├── .gitignore ├── Changelog.txt ├── LICENSE ├── backup.cpp ├── backup.hpp ├── clist.cpp ├── clist.hpp ├── diff.cpp ├── diff.hpp ├── display.cpp ├── display.hpp ├── hash.cpp ├── hash.hpp ├── makefile ├── options.cpp ├── options.hpp ├── os.hpp ├── parser.cpp ├── parser.hpp ├── patchdiff.cpp ├── patchdiff.hpp ├── pchart.cpp ├── pchart.hpp ├── pgraph.cpp ├── pgraph.hpp ├── ppc.cpp ├── ppc.hpp ├── precomp.cpp ├── precomp.hpp ├── sig.cpp ├── sig.hpp ├── system.cpp ├── system.hpp ├── unix_fct.cpp ├── unix_fct.hpp ├── vs ├── .gitignore ├── ida_64_override.props ├── ida_base.props ├── patchdiff3.sln ├── patchdiff3.vcxproj └── patchdiff3.vcxproj.filters ├── win_fct.cpp ├── win_fct.hpp ├── x86.cpp └── x86.hpp /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.sln.docstates 8 | 9 | # Build results 10 | [Dd]ebug/ 11 | [Dd]ebugPublic/ 12 | [Rr]elease/ 13 | [Rr]eleases/ 14 | x64/ 15 | x86/ 16 | build/ 17 | bld/ 18 | [Bb]in/ 19 | [Oo]bj/ 20 | 21 | # Roslyn cache directories 22 | *.ide/ 23 | 24 | # MSTest test Results 25 | [Tt]est[Rr]esult*/ 26 | [Bb]uild[Ll]og.* 27 | 28 | #NUNIT 29 | *.VisualState.xml 30 | TestResult.xml 31 | 32 | # Build Results of an ATL Project 33 | [Dd]ebugPS/ 34 | [Rr]eleasePS/ 35 | dlldata.c 36 | 37 | *_i.c 38 | *_p.c 39 | *_i.h 40 | *.ilk 41 | *.meta 42 | *.obj 43 | *.pch 44 | *.pdb 45 | *.pgc 46 | *.pgd 47 | *.rsp 48 | *.sbr 49 | *.tlb 50 | *.tli 51 | *.tlh 52 | *.tmp 53 | *.tmp_proj 54 | *.log 55 | *.vspscc 56 | *.vssscc 57 | .builds 58 | *.pidb 59 | *.svclog 60 | *.scc 61 | 62 | # Chutzpah Test files 63 | _Chutzpah* 64 | 65 | # Visual C++ cache files 66 | ipch/ 67 | *.aps 68 | *.ncb 69 | *.opensdf 70 | *.sdf 71 | *.cachefile 72 | 73 | # Visual Studio profiler 74 | *.psess 75 | *.vsp 76 | *.vspx 77 | 78 | # TFS 2012 Local Workspace 79 | $tf/ 80 | 81 | # Guidance Automation Toolkit 82 | *.gpState 83 | 84 | # ReSharper is a .NET coding add-in 85 | _ReSharper*/ 86 | *.[Rr]e[Ss]harper 87 | *.DotSettings.user 88 | 89 | # JustCode is a .NET coding addin-in 90 | .JustCode 91 | 92 | # TeamCity is a build add-in 93 | _TeamCity* 94 | 95 | # DotCover is a Code Coverage Tool 96 | *.dotCover 97 | 98 | # NCrunch 99 | _NCrunch_* 100 | .*crunch*.local.xml 101 | 102 | # MightyMoose 103 | *.mm.* 104 | AutoTest.Net/ 105 | 106 | # Web workbench (sass) 107 | .sass-cache/ 108 | 109 | # Installshield output folder 110 | [Ee]xpress/ 111 | 112 | # DocProject is a documentation generator add-in 113 | DocProject/buildhelp/ 114 | DocProject/Help/*.HxT 115 | DocProject/Help/*.HxC 116 | DocProject/Help/*.hhc 117 | DocProject/Help/*.hhk 118 | DocProject/Help/*.hhp 119 | DocProject/Help/Html2 120 | DocProject/Help/html 121 | 122 | # Click-Once directory 123 | publish/ 124 | 125 | # Publish Web Output 126 | *.[Pp]ublish.xml 127 | *.azurePubxml 128 | # TODO: Comment the next line if you want to checkin your web deploy settings 129 | # but database connection strings (with potential passwords) will be unencrypted 130 | *.pubxml 131 | *.publishproj 132 | 133 | # NuGet Packages 134 | *.nupkg 135 | # The packages folder can be ignored because of Package Restore 136 | **/packages/* 137 | # except build/, which is used as an MSBuild target. 138 | !**/packages/build/ 139 | # If using the old MSBuild-Integrated Package Restore, uncomment this: 140 | #!**/packages/repositories.config 141 | 142 | # Windows Azure Build Output 143 | csx/ 144 | *.build.csdef 145 | 146 | # Windows Store app package directory 147 | AppPackages/ 148 | 149 | # Others 150 | sql/ 151 | *.Cache 152 | ClientBin/ 153 | [Ss]tyle[Cc]op.* 154 | ~$* 155 | *~ 156 | *.dbmdl 157 | *.dbproj.schemaview 158 | *.pfx 159 | *.publishsettings 160 | node_modules/ 161 | 162 | # RIA/Silverlight projects 163 | Generated_Code/ 164 | 165 | # Backup & report files from converting an old project file 166 | # to a newer Visual Studio version. Backup files are not needed, 167 | # because we have git ;-) 168 | _UpgradeReport_Files/ 169 | Backup*/ 170 | UpgradeLog*.XML 171 | UpgradeLog*.htm 172 | 173 | # SQL Server files 174 | *.mdf 175 | *.ldf 176 | 177 | # Business Intelligence projects 178 | *.rdl.data 179 | *.bim.layout 180 | *.bim_*.settings 181 | 182 | # Microsoft Fakes 183 | FakesAssemblies/ 184 | -------------------------------------------------------------------------------- /Changelog.txt: -------------------------------------------------------------------------------- 1 | PatchDiff v2.0.10a: 2 | 3 | * Uses idaq.exe on Windows as idag.exe is not always present anymore (IDA 6.1 Standard?) 4 | 5 | PatchDiff v2.0.10: 6 | 7 | * Fixes idc issue with IDA 6.1 8 | * Fixes Unix support (tested on Fedora 15 32bit) 9 | 10 | PatchDiff v2.0.9: 11 | 12 | * Improves 'direct jump' detection (better compiler change detection in the next version) 13 | * Fixes tmp file issue with IDA 5.7 14 | 15 | PatchDiff v2.0.8: 16 | 17 | * Adds Flag/Unflag feature for the 'matched' list to keep track of analyzed functions 18 | 19 | 20 | PatchDiff v2.0.7: 21 | 22 | * Properly fixes an issue where a int -> to unsigned int would not be detected 23 | * Adds dock support to display graphs (IDA >= 5.6) 24 | 25 | 26 | PatchDiff v2.0.6: 27 | 28 | * Switchs to graph call for checksum instead of instruction frequency 29 | * Removes invalid C++ classes/structs flagged as functions 30 | 31 | 32 | PatchDiff v2.0.5: 33 | 34 | * Adds string references to the signature 35 | * Fixes IPC close when option is disabled 36 | 37 | 38 | PatchDiff v2.0.4: 39 | 40 | * Requires at least IDA 5.2 41 | * Adds save backup results to IDB 42 | * Adds Unmatch/Set match/Switch match submenus 43 | * Adds "pipe" support to keep second IDA instance open 44 | - menu Options/PatchDiff3 to disable/enable it per IDB 45 | - registry HKLM\SOFTWARE\Tenable\PatchDiff3 IPC (DWORD) for the default setting 46 | * Uses demangled function names 47 | * Ignores duplicated names 48 | 49 | 50 | PatchDiff v2.0.3: 51 | 52 | * Adds support for C++ classes in the signature engine (improves results against c++ targets) 53 | * No longer relies on IDA code refs (due to bad references) 54 | * x86: merges inc reg and dec reg to one instruction 55 | * x86: handles jmp $2/$5 56 | * x86: stops block tracing on int3 57 | * Bugfix: Does not try to display graphs that IDA can't handle 58 | 59 | 60 | PatchDiff v2.0.2: 61 | 62 | * Adds support for IDA 5.1 63 | * Excludes data ref with segment reference from crc 64 | * Adds PPC optimization module 65 | * Relies on IDA to identify opcode for non optimized CPUs 66 | * Adds display graph option for unmatched functions 67 | * Adds x86 rep/repe/repne 16 bit compiler change optimization 68 | * Improves edge double click handling 69 | 70 | 71 | PatchDiff v2.0.1: 72 | 73 | * Increases the size of the command buffer (for long IDB paths) 74 | * Synchronizes graphs on edge double-click 75 | * Adds line address in the graph if the option is set in IDA 76 | * Fixes graph block matching to produce much better results 77 | * Uses %a for address 78 | 79 | 80 | PatchDiff v2.0.0: 81 | 82 | * Initial public release 83 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /backup.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Patchdiff3 3 | Portions (C) 2014 - 2014 namreeb (patchdiff@namreeb.org) 4 | Portions (C) 2010 - 2011 Nicolas Pouvesle 5 | Portions (C) 2007 - 2009 Tenable Network Security, Inc. 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License version 2 as 9 | published by the Free Software Foundation. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | 21 | #include "precomp.hpp" 22 | 23 | #include "sig.hpp" 24 | #include "diff.hpp" 25 | #include "options.hpp" 26 | #include "backup.hpp" 27 | 28 | 29 | static void buffer_serialize_data(char * buf, size_t blen, size_t * pos, void * data, size_t dsize) 30 | { 31 | if ( (*pos + dsize) > blen) 32 | { 33 | *pos = blen; 34 | return; 35 | } 36 | 37 | memcpy(buf+*pos, data, dsize); 38 | *pos += dsize; 39 | } 40 | 41 | 42 | static void buffer_unserialize_data(char * buf, size_t blen, size_t * pos, void * data, size_t dsize) 43 | { 44 | if ( (*pos + dsize) > blen) 45 | { 46 | *pos = blen; 47 | return; 48 | } 49 | 50 | memcpy(data, buf+*pos, dsize); 51 | *pos += dsize; 52 | } 53 | 54 | 55 | static void buffer_serialize_ea(char * buf, size_t blen, size_t * pos, ea_t ea) 56 | { 57 | buffer_serialize_data(buf, blen, pos, &ea, sizeof(ea)); 58 | } 59 | 60 | 61 | static void buffer_serialize_bool(char * buf, size_t blen, size_t * pos, bool b) 62 | { 63 | buffer_serialize_data(buf, blen, pos, &b, sizeof(b)); 64 | } 65 | 66 | 67 | static void buffer_serialize_char(char * buf, size_t blen, size_t * pos, char c) 68 | { 69 | buffer_serialize_data(buf, blen, pos, &c, sizeof(c)); 70 | } 71 | 72 | 73 | static void buffer_serialize_int(char * buf, size_t blen, size_t * pos, int i) 74 | { 75 | buffer_serialize_data(buf, blen, pos, &i, sizeof(i)); 76 | } 77 | 78 | 79 | static void buffer_serialize_long(char * buf, size_t blen, size_t * pos, unsigned long l) 80 | { 81 | buffer_serialize_data(buf, blen, pos, &l, sizeof(l)); 82 | } 83 | 84 | 85 | static void buffer_serialize_size(char * buf, size_t blen, size_t * pos, size_t size) 86 | { 87 | buffer_serialize_data(buf, blen, pos, &size, sizeof(size)); 88 | } 89 | 90 | 91 | static void buffer_unserialize_ea(char * buf, size_t blen, size_t * pos, ea_t * ea) 92 | { 93 | buffer_unserialize_data(buf, blen, pos, ea, sizeof(*ea)); 94 | } 95 | 96 | 97 | static void buffer_unserialize_bool(char * buf, size_t blen, size_t * pos, bool * b) 98 | { 99 | buffer_unserialize_data(buf, blen, pos, b, sizeof(*b)); 100 | } 101 | 102 | 103 | static void buffer_unserialize_char(char * buf, size_t blen, size_t * pos, char * c) 104 | { 105 | buffer_unserialize_data(buf, blen, pos, c, sizeof(*c)); 106 | } 107 | 108 | 109 | static void buffer_unserialize_int(char * buf, size_t blen, size_t * pos, int * i) 110 | { 111 | buffer_unserialize_data(buf, blen, pos, i, sizeof(*i)); 112 | } 113 | 114 | 115 | static void buffer_unserialize_long(char * buf, size_t blen, size_t * pos, unsigned long * l) 116 | { 117 | buffer_unserialize_data(buf, blen, pos, l, sizeof(*l)); 118 | } 119 | 120 | 121 | static void buffer_unserialize_size(char * buf, size_t blen, size_t * pos, size_t * size) 122 | { 123 | buffer_unserialize_data(buf, blen, pos, size, sizeof(*size)); 124 | } 125 | 126 | 127 | /*------------------------------------------------*/ 128 | /* function : buffer_serialize_string */ 129 | /* description: Serializes a string */ 130 | /*------------------------------------------------*/ 131 | 132 | static void buffer_serialize_string(char * buf, size_t blen, size_t * pos, char * s) 133 | { 134 | size_t len; 135 | 136 | len = strlen(s) + 1; 137 | if ( (*pos + len) > blen) 138 | { 139 | *pos = blen; 140 | return; 141 | } 142 | 143 | memcpy(buf+*pos, s, len); 144 | *pos += len; 145 | } 146 | 147 | 148 | /*------------------------------------------------*/ 149 | /* function : buffer_unserialize_string */ 150 | /* description: Unserializes a string */ 151 | /*------------------------------------------------*/ 152 | 153 | static void buffer_unserialize_string(char * buf, size_t blen, size_t * pos, char ** s) 154 | { 155 | *s = qstrdup(buf+*pos); 156 | *pos += strlen(*s) + 1; 157 | } 158 | 159 | 160 | /*------------------------------------------------*/ 161 | /* function : singleton_serialize */ 162 | /* description: Serializes a signature */ 163 | /*------------------------------------------------*/ 164 | 165 | static size_t singleton_serialize(char * buf, size_t blen, psig_t * s, int nfile) 166 | { 167 | size_t pos = 0; 168 | fref_t * fref = NULL; 169 | int num, i; 170 | 171 | buffer_serialize_ea(buf, blen, &pos, s->startEA); 172 | 173 | buffer_serialize_int(buf, blen, &pos, s->mtype); 174 | 175 | buffer_serialize_int(buf, blen, &pos, s->id_crc); 176 | buffer_serialize_int(buf, blen, &pos, nfile); 177 | 178 | buffer_serialize_long(buf, blen, &pos, s->sig); 179 | buffer_serialize_long(buf, blen, &pos, s->hash); 180 | buffer_serialize_long(buf, blen, &pos, s->crc_hash); 181 | buffer_serialize_long(buf, blen, &pos, s->str_hash); 182 | buffer_serialize_int(buf, blen, &pos, s->flag); 183 | buffer_serialize_long(buf, blen, &pos, s->lines); 184 | 185 | num= 0; 186 | if (s->srefs) 187 | { 188 | fref = s->srefs->list; 189 | num = s->srefs->num; 190 | } 191 | 192 | buffer_serialize_int(buf, blen, &pos, num); 193 | for (i=0; iea); 196 | buffer_serialize_int(buf, blen, &pos, fref->type); 197 | 198 | fref = fref->next; 199 | } 200 | 201 | if (nfile == 2) 202 | { 203 | if (!strncmp(s->name, "sub_", 4)) 204 | { 205 | buffer_serialize_char(buf, blen, &pos, 0); 206 | } 207 | else 208 | { 209 | buffer_serialize_char(buf, blen, &pos, 1); 210 | buffer_serialize_string(buf, blen, &pos, s->name); 211 | } 212 | } 213 | 214 | return pos; 215 | } 216 | 217 | 218 | /*------------------------------------------------*/ 219 | /* function : singleton_unserialize */ 220 | /* description: Serializes a signature */ 221 | /*------------------------------------------------*/ 222 | 223 | static size_t singleton_unserialize(char * buf, size_t blen, psig_t ** s, int version) 224 | { 225 | char tmp[512]; 226 | size_t pos = 0; 227 | char c; 228 | int num, i; 229 | ea_t ea; 230 | int type; 231 | 232 | *s = sig_init(); 233 | if (!(*s)) return 0; 234 | 235 | buffer_unserialize_ea(buf, blen, &pos, &(*s)->startEA); 236 | 237 | buffer_unserialize_int(buf, blen, &pos, &(*s)->mtype); 238 | 239 | buffer_unserialize_int(buf, blen, &pos, &(*s)->id_crc); 240 | buffer_unserialize_int(buf, blen, &pos, &(*s)->nfile); 241 | 242 | buffer_unserialize_long(buf, blen, &pos, &(*s)->sig); 243 | buffer_unserialize_long(buf, blen, &pos, &(*s)->hash); 244 | buffer_unserialize_long(buf, blen, &pos, &(*s)->crc_hash); 245 | 246 | if (version >= 2) 247 | buffer_unserialize_long(buf, blen, &pos, &(*s)->str_hash); 248 | if (version >= 3) 249 | buffer_unserialize_int(buf, blen, &pos, &(*s)->flag); 250 | 251 | buffer_unserialize_long(buf, blen, &pos, &(*s)->lines); 252 | 253 | buffer_unserialize_int(buf, blen, &pos, &num); 254 | for (i=0; infile == 2) 264 | { 265 | buffer_unserialize_char(buf, blen, &pos, &c); 266 | 267 | if (c == 1) 268 | buffer_unserialize_string(buf, blen, &pos, &(*s)->name); 269 | else 270 | { 271 | qsnprintf(tmp, sizeof(tmp), "sub_%a", (*s)->startEA); 272 | sig_set_name((*s), tmp); 273 | } 274 | } 275 | else 276 | { 277 | pget_func_name((*s)->startEA, tmp, sizeof(tmp)); 278 | sig_set_name(*s, tmp); 279 | } 280 | 281 | return pos; 282 | } 283 | 284 | 285 | /*------------------------------------------------*/ 286 | /* function : pair_serialize */ 287 | /* description: Serializes a signature and the */ 288 | /* matched signature */ 289 | /*------------------------------------------------*/ 290 | 291 | static size_t pair_serialize(char * buf, size_t blen, psig_t * s) 292 | { 293 | size_t len; 294 | 295 | len = singleton_serialize(buf, blen, s, 1); 296 | len += singleton_serialize(buf+len, blen-len, s->msig, 2); 297 | 298 | return len; 299 | } 300 | 301 | 302 | /*------------------------------------------------*/ 303 | /* function : pair_unserialize */ 304 | /* description: Unserializes a signature and the */ 305 | /* matched signature */ 306 | /*------------------------------------------------*/ 307 | 308 | static size_t pair_unserialize(char * buf, size_t blen, psig_t ** s, int version) 309 | { 310 | size_t len; 311 | 312 | len = singleton_unserialize(buf, blen, s, version); 313 | len += singleton_unserialize(buf+len, blen-len, &(*s)->msig, version); 314 | 315 | (*s)->msig->msig = (*s); 316 | 317 | return len; 318 | } 319 | 320 | 321 | /*------------------------------------------------*/ 322 | /* function : backup_save_list */ 323 | /* description: Backups result list inside a */ 324 | /* netnode */ 325 | /*------------------------------------------------*/ 326 | 327 | static void backup_save_list(char * node_name, slist_t * sl) 328 | { 329 | char buf[5000]; 330 | size_t i; 331 | size_t len; 332 | netnode node; 333 | 334 | if (!sl) return; 335 | 336 | node.create(node_name); 337 | 338 | for (i=0; inum; i++) 339 | { 340 | nodeidx_t nidx = node.altval(i); 341 | if (nidx != 0) 342 | { 343 | msg("backup failed: netnode already exists !!\n"); 344 | return; 345 | } 346 | 347 | netnode n(nidx); 348 | 349 | n.create(); 350 | node.altset(i, n); 351 | 352 | if (sl->sigs[i]->msig != NULL) 353 | len = pair_serialize(buf, sizeof(buf), sl->sigs[i]); 354 | else 355 | len = singleton_serialize(buf, sizeof(buf), sl->sigs[i], sl->sigs[i]->nfile); 356 | 357 | n.setblob(buf, len, 0, 'P'); 358 | } 359 | } 360 | 361 | 362 | /*------------------------------------------------*/ 363 | /* function : backup_load_list */ 364 | /* description: Loads result list from a netnode */ 365 | /*------------------------------------------------*/ 366 | 367 | static bool backup_load_list(char * node_name, slist_t * sl, int type, int version) 368 | { 369 | char buf[5000]; 370 | size_t i; 371 | size_t len; 372 | netnode node; 373 | nodeidx_t nidx; 374 | 375 | if (!sl) return true; 376 | 377 | node.create(node_name); 378 | 379 | for (i=0; iorg_num; i++) 380 | { 381 | nidx = node.altval(i); 382 | if (nidx == BADNODE) 383 | { 384 | msg("backup failed: netnode does not exist !!\n"); 385 | return false; 386 | } 387 | 388 | netnode n(nidx); 389 | 390 | len = sizeof(buf); 391 | if (!n.getblob(buf, &len, 0, 'P')) 392 | { 393 | msg("backup failed: netnode blob does not exist !!\n"); 394 | return false; 395 | } 396 | 397 | if (type) 398 | pair_unserialize(buf, len, &sl->sigs[i], version); 399 | else 400 | singleton_unserialize(buf, len, &sl->sigs[i], version); 401 | } 402 | 403 | sl->num = sl->org_num; 404 | 405 | return true; 406 | } 407 | 408 | 409 | /*------------------------------------------------*/ 410 | /* function : backup_free_node */ 411 | /* description: Removes node from the IDB */ 412 | /*------------------------------------------------*/ 413 | 414 | static void backup_free_node(char * node_name, size_t size) 415 | { 416 | netnode node; 417 | size_t i; 418 | 419 | node.create(node_name); 420 | 421 | for (i=0; imlist ? eng->mlist->org_num : 0); 441 | backup_free_node("$ pdiff2_identical", eng->ilist ? eng->ilist->org_num : 0); 442 | backup_free_node("$ pdiff2_unmatched", eng->ulist ? eng->ulist->org_num : 0); 443 | 444 | backup_free_node("$ pdiff2_eng", 1); 445 | } 446 | 447 | 448 | /*------------------------------------------------*/ 449 | /* function : backup_save_eng */ 450 | /* description:Saves engine data inside a netnode */ 451 | /*------------------------------------------------*/ 452 | 453 | static void backup_save_eng(char * node_name, deng_t * eng) 454 | { 455 | char buf[1000]; 456 | char * file; 457 | size_t pos = 0; 458 | netnode node; 459 | size_t msize, isize, usize; 460 | 461 | node.create(node_name); 462 | 463 | nodeidx_t nidx = node.altval(0); 464 | if (nidx != 0) 465 | { 466 | backup_cleanup(eng); 467 | node.create(node_name); 468 | 469 | nidx = node.altval(0); 470 | if (nidx != 0) 471 | { 472 | msg("backup eng failed: netnode already exists !!\n"); 473 | return; 474 | } 475 | } 476 | 477 | netnode n(nidx); 478 | 479 | n.create(); 480 | node.altset(0, n); 481 | 482 | msize = isize = usize = 0; 483 | if (eng->mlist) 484 | { 485 | file = eng->mlist->file; 486 | msize = eng->mlist->num; 487 | } 488 | if (eng->ilist) 489 | { 490 | file = eng->ilist->file; 491 | isize = eng->ilist->num; 492 | } 493 | if (eng->ulist) 494 | { 495 | file = eng->ulist->file; 496 | usize = eng->ulist->num; 497 | } 498 | 499 | buffer_serialize_int(buf, sizeof(buf), &pos, PDIFF_BACKUP_VERSION); 500 | buffer_serialize_string(buf, sizeof(buf), &pos, file); 501 | buffer_serialize_size(buf, sizeof(buf), &pos, msize); 502 | buffer_serialize_size(buf, sizeof(buf), &pos, isize); 503 | buffer_serialize_size(buf, sizeof(buf), &pos, usize); 504 | buffer_serialize_bool(buf, sizeof(buf), &pos, eng->opt->ipc); 505 | 506 | n.setblob(buf, pos, 0, 'P'); 507 | } 508 | 509 | 510 | /*------------------------------------------------*/ 511 | /* function : backup_load_file */ 512 | /* description:Loads engine data inside a netnode */ 513 | /*------------------------------------------------*/ 514 | 515 | static deng_t * backup_load_eng(char * node_name, options_t * opt, int * version) 516 | { 517 | char buf[1000]; 518 | deng_t * eng; 519 | char * file = NULL; 520 | size_t blen, pos = 0; 521 | netnode node; 522 | size_t msize, isize, usize; 523 | 524 | node.create(node_name); 525 | 526 | nodeidx_t nidx = node.altval(0); 527 | if (nidx == 0) 528 | return NULL; 529 | 530 | netnode n(nidx); 531 | 532 | blen = sizeof(buf); 533 | n.getblob(buf, &blen, 0, 'P'); 534 | if (!blen) 535 | return NULL; 536 | 537 | eng = (deng_t *)qalloc(sizeof(*eng)); 538 | if (!eng) 539 | return NULL; 540 | 541 | eng->magic = 0x0BADF00D; 542 | eng->wnum = 0; 543 | eng->opt = opt; 544 | msize = isize = usize = 0; 545 | 546 | buffer_unserialize_int(buf, sizeof(buf), &pos, version); 547 | buffer_unserialize_string(buf, sizeof(buf), &pos, &file); 548 | buffer_unserialize_size(buf, sizeof(buf), &pos, &msize); 549 | buffer_unserialize_size(buf, sizeof(buf), &pos, &isize); 550 | buffer_unserialize_size(buf, sizeof(buf), &pos, &usize); 551 | buffer_unserialize_bool(buf, sizeof(buf), &pos, &eng->opt->ipc); 552 | 553 | // no need to save that in the IDB 554 | eng->opt->save_db = true; 555 | 556 | eng->mlist = siglist_init(msize, file); 557 | eng->ilist = siglist_init(isize, file); 558 | eng->ulist = siglist_init(usize, file); 559 | 560 | return eng; 561 | } 562 | 563 | 564 | /*------------------------------------------------*/ 565 | /* function : backup_save_results */ 566 | /* description: Saves diff results inside the */ 567 | /* IDB */ 568 | /*------------------------------------------------*/ 569 | 570 | void backup_save_results(deng_t * eng) 571 | { 572 | backup_save_eng("$ pdiff2_eng", eng); 573 | 574 | backup_save_list("$ pdiff2_matched", eng->mlist); 575 | backup_save_list("$ pdiff2_identical", eng->ilist); 576 | backup_save_list("$ pdiff2_unmatched", eng->ulist); 577 | } 578 | 579 | 580 | /*------------------------------------------------*/ 581 | /* function : backup_load_results */ 582 | /* description: Loads diff results from the IDB */ 583 | /*------------------------------------------------*/ 584 | 585 | int backup_load_results(deng_t ** eng, options_t * opt) 586 | { 587 | int ret; 588 | int version; 589 | 590 | if (*eng) 591 | { 592 | ret = askbuttons_c("Reuse", "Refresh", "Cancel", 1, 593 | "Previous diff results have been found. Please specify the action to perform."); 594 | 595 | if (ret == 0) 596 | { 597 | diff_engine_free(*eng); 598 | *eng = NULL; 599 | } 600 | 601 | return ret; 602 | } 603 | 604 | 605 | *eng = backup_load_eng("$ pdiff2_eng", opt, &version); 606 | if (!(*eng)) return 0; 607 | 608 | ret = askbuttons_c("Reuse", "Refresh", "Cancel", 1, 609 | "Previous diff results have been found. Please specify the action to perform."); 610 | 611 | if (ret != 1) goto error; 612 | 613 | msg("Loading backup results... "); 614 | if (!backup_load_list("$ pdiff2_matched", (*eng)->mlist, 1, version)) goto error; 615 | if (!backup_load_list("$ pdiff2_identical", (*eng)->ilist, 1, version)) goto error; 616 | if (!backup_load_list("$ pdiff2_unmatched", (*eng)->ulist, 0, version)) goto error; 617 | msg("done.\n"); 618 | 619 | return ret; 620 | 621 | error: 622 | diff_engine_free(*eng); 623 | *eng = NULL; 624 | 625 | return ret; 626 | } 627 | -------------------------------------------------------------------------------- /backup.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Patchdiff3 3 | Portions (C) 2014 - 2014 namreeb (patchdiff@namreeb.org) 4 | Portions (C) 2010 - 2011 Nicolas Pouvesle 5 | Portions (C) 2007 - 2009 Tenable Network Security, Inc. 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License version 2 as 9 | published by the Free Software Foundation. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | 21 | #pragma once 22 | 23 | #include "sig.hpp" 24 | 25 | // 1: first format 26 | // 2: adds str hash 27 | #define PDIFF_BACKUP_VERSION 3 28 | 29 | void backup_save_results(deng_t *); 30 | int backup_load_results(deng_t **, options_t *); 31 | -------------------------------------------------------------------------------- /clist.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Patchdiff3 3 | Portions (C) 2014 - 2014 namreeb (patchdiff@namreeb.org) 4 | Portions (C) 2010 - 2011 Nicolas Pouvesle 5 | Portions (C) 2007 - 2009 Tenable Network Security, Inc. 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License version 2 as 9 | published by the Free Software Foundation. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | 21 | #include "precomp.hpp" 22 | 23 | #include "sig.hpp" 24 | #include "hash.hpp" 25 | 26 | /*------------------------------------------------*/ 27 | /* function : clist_init */ 28 | /* description: Initializes a chained list of */ 29 | /* signatures */ 30 | /*------------------------------------------------*/ 31 | 32 | clist_t * clist_init(slist_t * l) 33 | { 34 | clist_t * cl; 35 | dpsig_t * ds, * prev; 36 | size_t i; 37 | 38 | cl = (clist_t *)qalloc(sizeof(*cl)); 39 | if (!cl) return NULL; 40 | 41 | cl->num = l->num; 42 | cl->sigs = NULL; 43 | cl->nmatch = 0; 44 | cl->msigs = NULL; 45 | 46 | prev = NULL; 47 | 48 | for(i=0; inum; i++) 49 | { 50 | ds = (dpsig_t *)qalloc(sizeof(*ds)); 51 | ds->prev = prev; 52 | ds->next = NULL; 53 | ds->removed = false; 54 | ds->sig = l->sigs[i]; 55 | 56 | if (prev) 57 | prev->next = ds; 58 | else 59 | cl->sigs = ds; 60 | 61 | prev = ds; 62 | } 63 | 64 | cl->pos = cl->sigs; 65 | 66 | return cl; 67 | } 68 | 69 | 70 | /*------------------------------------------------*/ 71 | /* function : clist_insert */ 72 | /* description: Inserts sig in sorted list */ 73 | /*------------------------------------------------*/ 74 | 75 | int clist_insert(clist_t * cl, psig_t * s) 76 | { 77 | dpsig_t * ds, * prev, * cur; 78 | int ret; 79 | 80 | ds = (dpsig_t *)qalloc(sizeof(*ds)); 81 | if (!ds) return -1; 82 | 83 | ds->sig = s; 84 | ds->prev = NULL; 85 | ds->next = NULL; 86 | ds->removed = false; 87 | 88 | prev = NULL; 89 | cur = cl->sigs; 90 | while (cur) 91 | { 92 | // sig_compare is reversed 93 | ret = sig_compare(&s, &cur->sig) ; 94 | if (!ret && cur->sig->startEA == s->startEA) 95 | return -1; 96 | 97 | if (ret <= 0) 98 | break; 99 | 100 | prev = cur; 101 | cur = cur->next; 102 | } 103 | 104 | ds->prev = prev; 105 | ds->next = cur; 106 | 107 | if (!prev) 108 | cl->sigs = ds; 109 | else 110 | prev->next = ds; 111 | 112 | if (cur) cur->prev = ds; 113 | 114 | cl->num++; 115 | 116 | return 0; 117 | } 118 | 119 | /*------------------------------------------------*/ 120 | /* function : clist_insert_dsig */ 121 | /* description: Inserts dsig in matched list */ 122 | /*------------------------------------------------*/ 123 | 124 | static int clist_insert_dsig(clist_t * cl, dpsig_t * ds) 125 | { 126 | dpsig_t * prev, * cur; 127 | int ret; 128 | 129 | ds->prev = NULL; 130 | ds->next = NULL; 131 | ds->removed = true; 132 | 133 | prev = NULL; 134 | cur = cl->msigs; 135 | while (cur) 136 | { 137 | // sig_compare is reversed 138 | ret = sig_compare(&ds->sig, &cur->sig) ; 139 | if (!ret && cur->sig->startEA == ds->sig->startEA) 140 | return -1; 141 | 142 | if (ret <= 0) 143 | break; 144 | 145 | prev = cur; 146 | cur = cur->next; 147 | } 148 | 149 | ds->prev = prev; 150 | ds->next = cur; 151 | 152 | if (!prev) 153 | cl->msigs= ds; 154 | else 155 | prev->next = ds; 156 | 157 | if (cur) cur->prev = ds; 158 | 159 | cl->nmatch++; 160 | 161 | return 0; 162 | } 163 | 164 | 165 | 166 | /*------------------------------------------------*/ 167 | /* function : clist_init */ 168 | /* description: Initializes a chained list of */ 169 | /* signatures with a list of xrefs */ 170 | /*------------------------------------------------*/ 171 | 172 | clist_t * clist_init_from_refs(hpsig_t * hsig, frefs_t * refs) 173 | { 174 | clist_t * cl; 175 | fref_t * fl; 176 | psig_t * sig; 177 | 178 | cl = (clist_t *)qalloc(sizeof(*cl)); 179 | if (!cl) return NULL; 180 | 181 | cl->num = 0; 182 | cl->nmatch = 0; 183 | cl->sigs = NULL; 184 | cl->pos = NULL; 185 | cl->msigs = NULL; 186 | 187 | if (!refs) return cl; 188 | 189 | fl = refs->list; 190 | 191 | while(fl) 192 | { 193 | sig = hash_find_ea(hsig, fl->ea); 194 | if (sig && sig_get_matched_type(sig) == DIFF_UNMATCHED) 195 | clist_insert(cl, sig); 196 | 197 | fl = fl->next; 198 | } 199 | 200 | cl->pos = cl->sigs; 201 | 202 | return cl; 203 | } 204 | 205 | 206 | /*------------------------------------------------*/ 207 | /* function : clist_remove */ 208 | /* description: Removes element from list */ 209 | /*------------------------------------------------*/ 210 | 211 | void clist_remove(clist_t * cl, dpsig_t * ds) 212 | { 213 | if (ds->removed == true) 214 | return; 215 | 216 | if (ds->prev == NULL) 217 | cl->sigs = ds->next; 218 | else 219 | ds->prev->next = ds->next; 220 | 221 | if (ds->next != NULL) 222 | ds->next->prev = ds->prev; 223 | 224 | clist_insert_dsig(cl, ds); 225 | } 226 | 227 | 228 | /*------------------------------------------------*/ 229 | /* function : clist_reset */ 230 | /* description: Resets list position */ 231 | /*------------------------------------------------*/ 232 | 233 | void clist_reset(clist_t * cl) 234 | { 235 | cl->pos = cl->sigs; 236 | } 237 | 238 | -------------------------------------------------------------------------------- /clist.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Patchdiff3 3 | Portions (C) 2014 - 2014 namreeb (patchdiff@namreeb.org) 4 | Portions (C) 2010 - 2011 Nicolas Pouvesle 5 | Portions (C) 2007 - 2009 Tenable Network Security, Inc. 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License version 2 as 9 | published by the Free Software Foundation. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | 21 | #pragma once 22 | 23 | #include "sig.hpp" 24 | #include "hash.hpp" 25 | 26 | clist_t * clist_init(slist_t *); 27 | int clist_insert(clist_t *, psig_t *); 28 | clist_t * clist_init_from_refs(hpsig_t *, frefs_t *); 29 | void clist_remove(clist_t *, dpsig_t *); 30 | void clist_reset(clist_t *); 31 | -------------------------------------------------------------------------------- /diff.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Patchdiff3 3 | Portions (C) 2014 - 2014 namreeb (patchdiff@namreeb.org) 4 | Portions (C) 2010 - 2011 Nicolas Pouvesle 5 | Portions (C) 2007 - 2009 Tenable Network Security, Inc. 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License version 2 as 9 | published by the Free Software Foundation. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | 21 | #include "precomp.hpp" 22 | 23 | #include "hash.hpp" 24 | #include "sig.hpp" 25 | #include "diff.hpp" 26 | #include "clist.hpp" 27 | #include "display.hpp" 28 | #include "backup.hpp" 29 | #include "options.hpp" 30 | 31 | 32 | /*------------------------------------------------*/ 33 | /* function : diff_init_hash */ 34 | /* description: Initializes a hash structure and */ 35 | /* creates successor xrefs */ 36 | /*------------------------------------------------*/ 37 | 38 | static hpsig_t * diff_init_hash(slist_t * sl) 39 | { 40 | fref_t * fref; 41 | psig_t * sig; 42 | hpsig_t * h; 43 | size_t i; 44 | 45 | h = hash_init(sl->num); 46 | if (!h) return NULL; 47 | 48 | for(i=0; inum; i++) 49 | { 50 | if (hash_add_ea(h, sl->sigs[i]) < 0) 51 | { 52 | hash_free(h); 53 | return NULL; 54 | } 55 | } 56 | // adds xrefs 57 | for(i=0; inum; i++) 58 | { 59 | if (sl->sigs[i]->srefs) 60 | { 61 | fref = sl->sigs[i]->srefs->list; 62 | while (fref) 63 | { 64 | if (!fref->rtype) 65 | { 66 | sig = hash_find_ea(h, fref->ea); 67 | if (sig) 68 | sig_add_pref(sig, sl->sigs[i]->startEA, fref->type, DO_NOT_CHECK_REF); 69 | } 70 | 71 | fref = fref->next; 72 | } 73 | } 74 | 75 | if (sl->sigs[i]->prefs) 76 | { 77 | fref = sl->sigs[i]->prefs->list; 78 | while (fref) 79 | { 80 | if (!fref->rtype) 81 | { 82 | sig = hash_find_ea(h, fref->ea); 83 | if (sig) 84 | sig_add_sref(sig, sl->sigs[i]->startEA, fref->type, DO_NOT_CHECK_REF); 85 | } 86 | 87 | fref = fref->next; 88 | } 89 | } 90 | } 91 | 92 | return h; 93 | } 94 | 95 | 96 | /*------------------------------------------------*/ 97 | /* function : slist_init_crefs */ 98 | /* description: Initializes slist crefs */ 99 | /*------------------------------------------------*/ 100 | 101 | static int slist_init_crefs(slist_t * l) 102 | { 103 | hpsig_t * h = NULL; 104 | clist_t * cl1, * cl2; 105 | size_t i; 106 | 107 | h = diff_init_hash(l); 108 | if(!h) return -1; 109 | 110 | for (i=0; inum; i++) 111 | { 112 | cl1 = clist_init_from_refs(h, sig_get_preds(l->sigs[i])); 113 | cl2 = clist_init_from_refs(h, sig_get_succs(l->sigs[i])); 114 | sig_set_crefs(l->sigs[i], SIG_PRED, cl1); 115 | sig_set_crefs(l->sigs[i], SIG_SUCC, cl2); 116 | } 117 | 118 | return 0; 119 | } 120 | 121 | 122 | /*------------------------------------------------*/ 123 | /* function : diff_engine_initialize */ 124 | /* description: Initializes engine structures */ 125 | /*------------------------------------------------*/ 126 | 127 | static deng_t * diff_engine_initialize(slist_t * l1, slist_t * l2, options_t * opt) 128 | { 129 | deng_t * eng; 130 | 131 | if (slist_init_crefs(l1) != 0) return NULL; 132 | if (slist_init_crefs(l2) != 0) return NULL; 133 | 134 | eng = (deng_t *)qalloc(sizeof(*eng)); 135 | if (!eng) return NULL; 136 | 137 | eng->magic = 0x0BADF00D; 138 | eng->wnum = 0; 139 | 140 | eng->identical = 0; 141 | eng->matched = 0; 142 | eng->unmatched = l1->num + l2->num; 143 | 144 | eng->opt = opt; 145 | 146 | return eng; 147 | } 148 | 149 | 150 | /*------------------------------------------------*/ 151 | /* function : diff_engine_initialize */ 152 | /* description: Initializes engine structures */ 153 | /*------------------------------------------------*/ 154 | 155 | void diff_engine_free(deng_t * eng) 156 | { 157 | if (eng->ilist) siglist_free(eng->ilist); 158 | if (eng->mlist) siglist_free(eng->mlist); 159 | if (eng->ulist) siglist_free(eng->ulist); 160 | 161 | qfree(eng); 162 | } 163 | 164 | 165 | /*------------------------------------------------*/ 166 | /* function : sig_equal */ 167 | /* description: Checks if 2 sigs are equal */ 168 | /*------------------------------------------------*/ 169 | 170 | bool sig_equal(psig_t * s1, psig_t * s2, int type) 171 | { 172 | if (s1->sig != s2->sig || s1->hash != s2->hash) 173 | return false; 174 | 175 | if (type == DIFF_EQUAL_SIG_HASH_CRC_STR) 176 | { 177 | if (s1->str_hash != s2->str_hash) 178 | return false; 179 | } 180 | 181 | if (type <= DIFF_EQUAL_SIG_HASH_CRC) 182 | { 183 | if (s1->crc_hash != s2->crc_hash) 184 | return false; 185 | } 186 | 187 | return true; 188 | } 189 | 190 | 191 | /*------------------------------------------------*/ 192 | /* function : sig_name_equal */ 193 | /* description: Checks if 2 sig names are equal */ 194 | /*------------------------------------------------*/ 195 | 196 | static bool sig_name_equal(psig_t * s1, psig_t * s2) 197 | { 198 | if (!strncmp(s1->name, "sub_", 4) || strcmp(s1->name, s2->name)) 199 | return false; 200 | 201 | return true; 202 | } 203 | 204 | /*------------------------------------------------*/ 205 | /* function : clist_equal_match */ 206 | /* description: Checks if all the elements of a */ 207 | /* clist match */ 208 | /*------------------------------------------------*/ 209 | 210 | static bool clist_equal_match(clist_t * cl1, clist_t * cl2) 211 | { 212 | dpsig_t * s1, * s2; 213 | size_t i; 214 | 215 | if (!cl1 || !cl2 || cl1->nmatch == 0 || cl2->nmatch == 0) 216 | return false; 217 | 218 | if (cl1->nmatch != cl2->nmatch) 219 | return false; 220 | 221 | s1 = cl1->msigs; 222 | s2 = cl2->msigs; 223 | 224 | for (i=0; inmatch; i++) 225 | { 226 | if ((sig_get_matched_type(s1->sig) == DIFF_UNMATCHED) || (s1->sig->msig->startEA != s2->sig->startEA)) 227 | return false; 228 | 229 | s1 = s1->next; 230 | s2 = s2->next; 231 | } 232 | 233 | return true; 234 | } 235 | 236 | 237 | /*------------------------------------------------*/ 238 | /* function : clist_almost_equal_match */ 239 | /* description: Checks if at lest one element of a*/ 240 | /* clist match */ 241 | /*------------------------------------------------*/ 242 | 243 | static bool clist_almost_equal_match(clist_t * cl1, clist_t * cl2) 244 | { 245 | dpsig_t * s1, * s2; 246 | size_t i, k; 247 | 248 | if (!cl1 || !cl2 || cl1->nmatch == 0 || cl2->nmatch == 0) 249 | return false; 250 | 251 | if (cl1->nmatch != cl2->nmatch) 252 | return false; 253 | 254 | s1 = cl1->msigs; 255 | 256 | 257 | for (i=0; inmatch; i++) 258 | { 259 | s2 = cl2->msigs; 260 | 261 | for (k=0; knmatch; k++) 262 | { 263 | if (s1->sig->msig->startEA == s2->sig->startEA) 264 | return true; 265 | 266 | s2 = s2->next; 267 | } 268 | 269 | s1 = s1->next; 270 | } 271 | 272 | return false; 273 | } 274 | 275 | 276 | /*------------------------------------------------*/ 277 | /* function : clist_get_unique_sig */ 278 | /* description: Returns first unique signature in */ 279 | /* list starting at ds */ 280 | /* note: changes ds if ds already matched */ 281 | /*------------------------------------------------*/ 282 | 283 | static dpsig_t * clist_get_unique_sig(clist_t * cl, dpsig_t ** ds, int type) 284 | { 285 | dpsig_t * ptr, * tmp; 286 | 287 | if (!*ds) return NULL; 288 | ptr = *ds; 289 | 290 | // do not keep the current signature if not unique 291 | while (ptr) 292 | { 293 | if (sig_get_matched_type(ptr->sig) != DIFF_UNMATCHED) 294 | { 295 | if (ptr == *ds) 296 | { 297 | *ds = ptr->next; 298 | if (!*ds) return NULL; 299 | } 300 | 301 | tmp = ptr->next; 302 | clist_remove(cl, ptr); 303 | ptr = tmp; 304 | } 305 | else 306 | { 307 | if (!ptr->next) break; 308 | 309 | if (type == DIFF_NEQUAL_SUCC) 310 | { 311 | if (sig_equal(ptr->sig, (*ds)->sig, type) && sig_equal(ptr->next->sig, (*ds)->sig, type)) 312 | return NULL; 313 | 314 | if (( (!sig_equal(ptr->next->sig, (*ds)->sig, type) && (!ptr->prev || !sig_equal(ptr->prev->sig, (*ds)->sig, type))) || !clist_equal_match((*ds)->sig->cs, ptr->next->sig->cs)) && ptr->sig->cs->nmatch > 0 && ptr->sig->cs->num == ptr->sig->cs->nmatch) 315 | break; 316 | } 317 | else if (type == DIFF_NEQUAL_PRED) 318 | { 319 | if (sig_equal(ptr->sig, (*ds)->sig, type) && sig_equal(ptr->next->sig, (*ds)->sig, type)) 320 | return NULL; 321 | 322 | if (( (!sig_equal(ptr->next->sig, (*ds)->sig, type) && (!ptr->prev || !sig_equal(ptr->prev->sig, (*ds)->sig, type))) || !clist_equal_match((*ds)->sig->cp, ptr->next->sig->cp)) && ptr->sig->cp->nmatch > 0 && ptr->sig->cp->num == ptr->sig->cp->nmatch) 323 | break; 324 | } 325 | else if (type == DIFF_EQUAL_NAME) 326 | { 327 | if (!sig_equal(ptr->next->sig, (*ds)->sig, type) || !sig_name_equal((*ds)->sig, ptr->next->sig)) 328 | break; 329 | } 330 | else if (type == DIFF_NEQUAL_STR) 331 | { 332 | bool b = false; 333 | tmp = *ds; 334 | 335 | if (ptr->sig->str_hash != 0) 336 | { 337 | // slow: need to improve 338 | while (tmp) 339 | { 340 | if (tmp->sig->startEA != ptr->sig->startEA && tmp->sig->str_hash == ptr->sig->str_hash) 341 | { 342 | b = true; 343 | break; 344 | } 345 | 346 | tmp = tmp->next; 347 | } 348 | 349 | if (!b) 350 | break; 351 | } 352 | } 353 | else 354 | { 355 | bool b = sig_equal(ptr->next->sig, (*ds)->sig, type); 356 | if (!b) break; 357 | } 358 | 359 | ptr = ptr->next; 360 | } 361 | } 362 | 363 | return ptr; 364 | } 365 | 366 | /*------------------------------------------------*/ 367 | /* function : clist_get_best_sig */ 368 | /* description: Returns best unique signature in */ 369 | /* list */ 370 | /* note: position pointer is incremented to the */ 371 | /* next signature in the list */ 372 | /*------------------------------------------------*/ 373 | 374 | static dpsig_t * clist_get_best_sig(clist_t * cl, int type) 375 | { 376 | dpsig_t * best, * ptr; 377 | 378 | best = cl->pos; 379 | 380 | ptr = clist_get_unique_sig(cl, &best, type); 381 | 382 | // no more signature 383 | if (!best) return NULL; 384 | 385 | if (ptr == best) 386 | { 387 | cl->pos = best->next; 388 | return best; 389 | } 390 | 391 | cl->pos = ptr; 392 | return clist_get_best_sig(cl, type); 393 | } 394 | 395 | 396 | /*------------------------------------------------*/ 397 | /* function : clist_get_eq_sig */ 398 | /* description: Returns signature if sig presents */ 399 | /* in list and unique */ 400 | /*------------------------------------------------*/ 401 | 402 | static dpsig_t * clist_get_eq_sig(clist_t * cl, dpsig_t * dsig, int type) 403 | { 404 | dpsig_t * ds, * ptr; 405 | bool b2, b1 = sig_is_class(dsig->sig); 406 | 407 | ds = cl->sigs; 408 | while (ds) 409 | { 410 | if (type == DIFF_NEQUAL_SUCC) 411 | { 412 | ptr = clist_get_unique_sig(cl, &ds, type); 413 | if (!ds || !ptr) return NULL; 414 | 415 | b2 = sig_is_class(ptr->sig); 416 | if (b1 ^ b2) return NULL; 417 | 418 | if (clist_equal_match(ptr->sig->cs, dsig->sig->cs)) 419 | { 420 | if (ptr->next && (ptr->next->sig->sig == ptr->sig->sig || clist_equal_match(ptr->next->sig->cs, dsig->sig->cs))) 421 | return NULL; 422 | 423 | return ptr; 424 | } 425 | } 426 | else if (type == DIFF_NEQUAL_PRED ) 427 | { 428 | ptr = clist_get_unique_sig(cl, &ds, type); 429 | if (!ds || !ptr) return NULL; 430 | 431 | b2 = sig_is_class(ptr->sig); 432 | if (b1 ^ b2) return NULL; 433 | 434 | if (clist_equal_match(ptr->sig->cp, dsig->sig->cp)) 435 | { 436 | if (ptr->next && (ptr->next->sig->sig == ptr->sig->sig || clist_equal_match(ptr->next->sig->cp, dsig->sig->cp))) 437 | return NULL; 438 | 439 | return ptr; 440 | } 441 | } 442 | else if (type == DIFF_EQUAL_NAME) 443 | { 444 | ptr = clist_get_unique_sig(cl, &ds, type); 445 | if (!ds || !ptr) return NULL; 446 | 447 | if (sig_name_equal(ptr->sig, dsig->sig)) 448 | return ptr; 449 | } 450 | else if (type == DIFF_NEQUAL_STR) 451 | { 452 | ptr = clist_get_unique_sig(cl, &ds, type); 453 | if (!ds || !ptr) return NULL; 454 | 455 | if (ptr->sig->str_hash != 0 && ptr->sig->str_hash == dsig->sig->str_hash) 456 | return ptr; 457 | } 458 | else 459 | { 460 | if (sig_equal(ds->sig, dsig->sig, type)) 461 | { 462 | ptr = clist_get_unique_sig(cl, &ds, type); 463 | 464 | if (!ds) return NULL; 465 | 466 | if (ptr != ds || !sig_equal(ds->sig, dsig->sig, type)) 467 | return NULL; 468 | 469 | return ds; 470 | } 471 | else if (ds->sig->sig < dsig->sig->sig) 472 | { 473 | return NULL; 474 | } 475 | } 476 | 477 | ds = ds->next; 478 | } 479 | 480 | return NULL; 481 | } 482 | 483 | 484 | static void clist_update_crefs(clist_t * cl, dpsig_t * ds, int type) 485 | { 486 | dpsig_t * tmp, * next; 487 | dpsig_t * tmp2, * next2; 488 | clist_t * tcl; 489 | 490 | tmp = cl->sigs; 491 | while(tmp) 492 | { 493 | next = tmp->next; 494 | 495 | if (type == SIG_SUCC) 496 | tcl = tmp->sig->cs; 497 | else 498 | tcl = tmp->sig->cp; 499 | 500 | tmp2 = tcl->sigs; 501 | while(tmp2) 502 | { 503 | next2 = tmp2->next; 504 | 505 | if (tmp2->sig->startEA == ds->sig->startEA) 506 | clist_remove(tcl, tmp2); 507 | 508 | tmp2 = next2; 509 | } 510 | 511 | tmp = next; 512 | } 513 | } 514 | 515 | 516 | static void clist_update_and_remove(clist_t * cl, dpsig_t * ds) 517 | { 518 | if (ds->removed) 519 | return; 520 | 521 | clist_update_crefs(ds->sig->cp, ds, SIG_SUCC); 522 | clist_update_crefs(ds->sig->cs, ds, SIG_PRED); 523 | 524 | clist_remove(cl, ds); 525 | } 526 | 527 | 528 | /*------------------------------------------------*/ 529 | /* function : diff_run */ 530 | /* description: Runs binary analysis */ 531 | /*------------------------------------------------*/ 532 | 533 | static int diff_run(deng_t * eng, clist_t * cl1, clist_t * cl2, int min_type, int max_type, bool pclass) 534 | { 535 | dpsig_t * dsig, * dsig2; 536 | int changed = 0; 537 | int type = min_type; 538 | int mtype = max_type; 539 | bool b; 540 | 541 | if (pclass && max_type > DIFF_EQUAL_SIG_HASH) 542 | mtype = DIFF_EQUAL_SIG_HASH; 543 | 544 | do 545 | { 546 | clist_reset(cl1); 547 | clist_reset(cl2); 548 | 549 | changed = 0; 550 | while ( (dsig = clist_get_best_sig(cl1, type)) != NULL) 551 | { 552 | clist_reset(cl2); 553 | dsig2 = clist_get_eq_sig(cl2, dsig, type); 554 | if (dsig2) 555 | { 556 | sig_set_matched_sig(dsig->sig, dsig2->sig, type); 557 | 558 | eng->unmatched -= 2; 559 | if (dsig->sig->hash2 == dsig2->sig->hash2 || sig_equal(dsig->sig, dsig2->sig, DIFF_EQUAL_SIG_HASH)) 560 | eng->identical++; 561 | else 562 | eng->matched++; 563 | 564 | changed = 1; 565 | 566 | clist_update_and_remove(cl1, dsig); 567 | clist_update_and_remove(cl2, dsig2); 568 | 569 | b = sig_is_class(dsig->sig); 570 | 571 | // string matching is not 100% reliable so we only match on crc/hash 572 | if (mtype == DIFF_NEQUAL_STR) 573 | b = true; 574 | 575 | diff_run(eng, sig_get_crefs(dsig->sig, SIG_PRED), sig_get_crefs(dsig2->sig, SIG_PRED), min_type, max_type, b); 576 | diff_run(eng, sig_get_crefs(dsig->sig, SIG_SUCC), sig_get_crefs(dsig2->sig, SIG_SUCC), min_type, max_type, b); 577 | 578 | } 579 | } 580 | 581 | if (changed == 0) 582 | type++; 583 | } while(type <= mtype); 584 | 585 | return 0; 586 | } 587 | 588 | 589 | /*------------------------------------------------*/ 590 | /* function : generate_diff */ 591 | /* description: Generates binary diff */ 592 | /*------------------------------------------------*/ 593 | 594 | int generate_diff(deng_t ** d, slist_t * l1, slist_t * l2, char * file, bool display, options_t * opt) 595 | { 596 | int ret; 597 | clist_t * cl1, * cl2; 598 | int un1, un2, idf, mf; 599 | deng_t * eng; 600 | 601 | eng = diff_engine_initialize(l1, l2, opt); 602 | if (eng == NULL) 603 | return -1; 604 | 605 | cl1 = clist_init(l1); 606 | cl2 = clist_init(l2); 607 | 608 | if (file) 609 | ret = diff_run(eng, cl1, cl2, DIFF_EQUAL_NAME, DIFF_NEQUAL_STR, false); 610 | else 611 | { 612 | ret = diff_run(eng, cl1, cl2, DIFF_EQUAL_SIG_HASH_CRC, DIFF_EQUAL_SIG_HASH, false); 613 | ret = diff_run(eng, cl1, cl2, DIFF_NEQUAL_PRED, DIFF_NEQUAL_STR, false); 614 | } 615 | 616 | if (display) 617 | { 618 | eng->mlist = siglist_init(eng->matched, file); 619 | eng->ulist = siglist_init(eng->unmatched, file); 620 | eng->ilist = siglist_init(eng->identical, file); 621 | 622 | un1 = un2 = idf = mf = 0; 623 | 624 | for (size_t i=0; inum; i++) 625 | { 626 | if (sig_is_class(l1->sigs[i])) 627 | { 628 | sig_free(l1->sigs[i]); 629 | continue; 630 | } 631 | 632 | if (sig_get_matched_type(l1->sigs[i]) == DIFF_UNMATCHED) 633 | { 634 | sig_set_nfile(l1->sigs[i], 1); 635 | siglist_add(eng->ulist, l1->sigs[i]); 636 | un1++; 637 | } 638 | else 639 | { 640 | if (l1->sigs[i]->hash2 == l1->sigs[i]->msig->hash2 || sig_equal(l1->sigs[i], l1->sigs[i]->msig, DIFF_EQUAL_SIG_HASH)) 641 | { 642 | siglist_add(eng->ilist, l1->sigs[i]); 643 | idf++; 644 | } 645 | else 646 | { 647 | siglist_add(eng->mlist, l1->sigs[i]); 648 | mf++; 649 | } 650 | } 651 | } 652 | 653 | for (size_t i=0; inum; i++) 654 | { 655 | if (sig_is_class(l2->sigs[i])) 656 | { 657 | sig_free(l2->sigs[i]); 658 | continue; 659 | } 660 | 661 | if (sig_get_matched_type(l2->sigs[i]) == DIFF_UNMATCHED) 662 | { 663 | sig_set_nfile(l2->sigs[i], 2); 664 | siglist_add(eng->ulist, l2->sigs[i]); 665 | un2++; 666 | } 667 | } 668 | 669 | 670 | msg("Identical functions: %d\n", idf); 671 | msg("Matched functions: %d\n", mf); 672 | msg("Unmatched functions 1: %d\n", un1); 673 | msg("Unmatched functions 2: %d\n", un2); 674 | display_results(eng); 675 | } 676 | 677 | if (d) 678 | *d = eng; 679 | 680 | return 0; 681 | } 682 | 683 | -------------------------------------------------------------------------------- /diff.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Patchdiff3 3 | Portions (C) 2014 - 2014 namreeb (patchdiff@namreeb.org) 4 | Portions (C) 2010 - 2011 Nicolas Pouvesle 5 | Portions (C) 2007 - 2009 Tenable Network Security, Inc. 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License version 2 as 9 | published by the Free Software Foundation. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | 21 | #pragma once 22 | 23 | #include "sig.hpp" 24 | #include "hash.hpp" 25 | #include "options.hpp" 26 | 27 | 28 | #define DIFF_EQUAL_NAME 0 29 | #define DIFF_EQUAL_SIG_HASH_CRC 1 30 | #define DIFF_EQUAL_SIG_HASH_CRC_STR 2 31 | #define DIFF_EQUAL_SIG_HASH 3 32 | #define DIFF_NEQUAL_PRED 4 33 | #define DIFF_NEQUAL_SUCC 5 34 | #define DIFF_NEQUAL_STR 6 35 | #define DIFF_MANUAL 7 36 | 37 | 38 | struct dengine 39 | { 40 | int magic; 41 | int matched; 42 | int unmatched; 43 | int identical; 44 | slist_t * mlist; 45 | slist_t * ulist; 46 | slist_t * ilist; 47 | options_t * opt; 48 | int wnum; 49 | }; 50 | 51 | typedef struct dengine deng_t; 52 | 53 | 54 | int generate_diff(deng_t **, slist_t *, slist_t *, char *, bool, options_t *); 55 | void diff_engine_free(deng_t *); 56 | bool sig_equal(psig_t *, psig_t *, int); 57 | -------------------------------------------------------------------------------- /display.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Patchdiff3 3 | Portions (C) 2014 - 2014 namreeb (patchdiff@namreeb.org) 4 | Portions (C) 2010 - 2011 Nicolas Pouvesle 5 | Portions (C) 2007 - 2009 Tenable Network Security, Inc. 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License version 2 as 9 | published by the Free Software Foundation. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | 21 | #include "precomp.hpp" 22 | 23 | #include "diff.hpp" 24 | #include "display.hpp" 25 | #include "os.hpp" 26 | #include "parser.hpp" 27 | #include "pgraph.hpp" 28 | #include "options.hpp" 29 | #include "system.hpp" 30 | 31 | 32 | static uint32 idaapi sizer_dlist(slist_t *sl) 33 | { 34 | if (sl) 35 | return sl->num; 36 | 37 | return 0; 38 | } 39 | 40 | 41 | static uint32 idaapi sizer_match(void *obj) 42 | { 43 | deng_t * d = (deng_t *)obj; 44 | 45 | return sizer_dlist(d ? d->mlist : NULL); 46 | } 47 | 48 | 49 | static uint32 idaapi sizer_identical(void *obj) 50 | { 51 | deng_t * d = (deng_t *)obj; 52 | 53 | return sizer_dlist(d ? d->ilist : NULL); 54 | } 55 | 56 | 57 | static uint32 idaapi sizer_unmatch(void *obj) 58 | { 59 | deng_t * d = (deng_t *)obj; 60 | 61 | return sizer_dlist(d ? d->ulist : NULL); 62 | } 63 | 64 | 65 | static void idaapi close_window(void *obj) 66 | { 67 | deng_t * d = (deng_t *)obj; 68 | 69 | d->wnum--; 70 | if (!d->wnum) 71 | ipc_close(); 72 | 73 | return; 74 | } 75 | 76 | 77 | /*------------------------------------------------*/ 78 | /* function : ui_access_sig */ 79 | /* description: Compensates for the zero index */ 80 | /* indicating the header row and performs */ 81 | /* bounds checking in debug */ 82 | /*------------------------------------------------*/ 83 | 84 | static psig_t *ui_access_sig(slist_t *sl, uint32 n) 85 | { 86 | #ifdef _DEBUG 87 | if (!sl || n == 0 || n > sl->num) 88 | error("ui attempted to access siglist out-of-bounds: %p %x\n", sl, n - 1); 89 | else 90 | #endif 91 | return sl->sigs[n - 1]; 92 | } 93 | 94 | 95 | static void idaapi desc_dlist(slist_t * sl,uint32 n,char * const *arrptr) 96 | { 97 | int i; 98 | 99 | /* header */ 100 | if (n == 0) 101 | { 102 | for (i = 0; i < qnumber (header_match); i++) 103 | qsnprintf(arrptr[i], MAXSTR, "%s", header_match[i]); 104 | } 105 | else 106 | { 107 | psig_t *sig = ui_access_sig(sl, n); 108 | qsnprintf(arrptr[0], MAXSTR, "%u", sig->mtype); 109 | qsnprintf(arrptr[1], MAXSTR, "%s", sig->name); 110 | qsnprintf(arrptr[2], MAXSTR, "%s", sig->msig->name); 111 | qsnprintf(arrptr[3], MAXSTR, "%a", sig->startEA); 112 | qsnprintf(arrptr[4], MAXSTR, "%a", sig->msig->startEA); 113 | qsnprintf(arrptr[5], MAXSTR, "%c", sig->id_crc ? '+' : '-'); 114 | qsnprintf(arrptr[6], MAXSTR, "%a", sig->crc_hash); 115 | qsnprintf(arrptr[7], MAXSTR, "%a", sig->msig->crc_hash); 116 | } 117 | } 118 | 119 | 120 | /*------------------------------------------------*/ 121 | /* function : desc_match */ 122 | /* description: Fills matched list */ 123 | /*------------------------------------------------*/ 124 | 125 | static void idaapi desc_match(void *obj,uint32 n,char * const *arrptr) 126 | { 127 | deng_t * d = (deng_t *)obj; 128 | 129 | desc_dlist(d ? d->mlist : NULL, n, arrptr); 130 | } 131 | 132 | 133 | /*------------------------------------------------*/ 134 | /* function : desc_identical */ 135 | /* description: Fills identical list */ 136 | /*------------------------------------------------*/ 137 | 138 | static void idaapi desc_identical(void *obj,uint32 n,char * const *arrptr) 139 | { 140 | deng_t * d = (deng_t *)obj; 141 | 142 | desc_dlist(d ? d->ilist : NULL, n, arrptr); 143 | } 144 | 145 | 146 | /*------------------------------------------------*/ 147 | /* function : desc_unmatch */ 148 | /* description: Fills unmatched list */ 149 | /*------------------------------------------------*/ 150 | 151 | static void idaapi desc_unmatch(void *obj,uint32 n,char * const *arrptr) 152 | { 153 | int i; 154 | 155 | /* header */ 156 | if (n == 0) 157 | { 158 | for (i = 0; i < qnumber (header_unmatch); i++) 159 | qsnprintf(arrptr[i], MAXSTR, "%s", header_unmatch[i]); 160 | } 161 | else 162 | { 163 | psig_t *sig = ui_access_sig(((deng_t *)obj)->ulist, n); 164 | qsnprintf(arrptr[0], MAXSTR, "%u", sig->nfile); 165 | qsnprintf(arrptr[1], MAXSTR, "%s", sig->name); 166 | qsnprintf(arrptr[2], MAXSTR, "%a", sig->startEA); 167 | qsnprintf(arrptr[3], MAXSTR, "%.8X", sig->sig); 168 | qsnprintf(arrptr[4], MAXSTR, "%.8X", sig->hash); 169 | qsnprintf(arrptr[5], MAXSTR, "%.8X", sig->crc_hash); 170 | } 171 | } 172 | 173 | 174 | static void idaapi enter_list(slist_t * sl,uint32 n) 175 | { 176 | jumpto(ui_access_sig(sl, n)->startEA); 177 | os_copy_to_clipboard(NULL); 178 | } 179 | 180 | 181 | /*------------------------------------------------*/ 182 | /* function : enter_match */ 183 | /* description: Jumps to code for element n in */ 184 | /* matched list */ 185 | /*------------------------------------------------*/ 186 | 187 | static void idaapi enter_match(void *obj,uint32 n) 188 | { 189 | enter_list(((deng_t *)obj)->mlist, n); 190 | } 191 | 192 | 193 | /*------------------------------------------------*/ 194 | /* function : enter_match */ 195 | /* description: Jumps to code for element n in */ 196 | /* identical list */ 197 | /*------------------------------------------------*/ 198 | 199 | static void idaapi enter_identical(void *obj,uint32 n) 200 | { 201 | enter_list(((deng_t *)obj)->ilist, n); 202 | } 203 | 204 | 205 | /*------------------------------------------------*/ 206 | /* function : enter_match */ 207 | /* description: Jumps to code for element n in */ 208 | /* unmatched list */ 209 | /*------------------------------------------------*/ 210 | 211 | static void idaapi enter_unmatch(void *obj,uint32 n) 212 | { 213 | psig_t *sig = ui_access_sig(((deng_t *)obj)->ulist, n); 214 | 215 | if (sig->nfile == 1) 216 | jumpto(sig->startEA); 217 | else 218 | os_copy_to_clipboard(NULL); 219 | } 220 | 221 | 222 | static uint32 idaapi graph_list(slist_t * sl,uint32 n, options_t * opt) 223 | { 224 | slist_t * sl1 = NULL; 225 | slist_t * sl2 = NULL; 226 | 227 | msg ("parsing second function...\n"); 228 | sl2 = parse_second_fct(ui_access_sig(sl, n)->msig->startEA, sl->file, opt); 229 | if (!sl2) 230 | { 231 | msg("Error: FCT2 parsing failed.\n"); 232 | return 0; 233 | } 234 | 235 | msg ("parsing first function...\n"); 236 | sl1 = parse_fct(ui_access_sig(sl, n)->startEA, dto.graph.s_showpref); 237 | if (!sl1) 238 | { 239 | msg("Error: FCT1 parsing failed.\n"); 240 | siglist_free(sl2); 241 | return 0; 242 | } 243 | 244 | sl1->sigs[0]->nfile = 1; 245 | sl2->sigs[0]->nfile = 2; 246 | 247 | msg ("diffing functions...\n"); 248 | generate_diff(NULL, sl1, sl2, NULL, false, NULL); 249 | 250 | pgraph_display(sl1, sl2); 251 | 252 | msg ("done!\n"); 253 | return 1; 254 | } 255 | 256 | 257 | /*------------------------------------------------*/ 258 | /* function : graph_match */ 259 | /* description: Draws graph from element n in */ 260 | /* matched list */ 261 | /*------------------------------------------------*/ 262 | 263 | static void idaapi graph_match(void *obj,uint32 n) 264 | { 265 | slist_t * sl = ((deng_t *)obj)->mlist; 266 | options_t * opt = ((deng_t *)obj)->opt; 267 | 268 | graph_list(sl, n, opt); 269 | 270 | return; 271 | } 272 | 273 | 274 | /*------------------------------------------------*/ 275 | /* function : graph_identical */ 276 | /* description: Draws graph from element n in */ 277 | /* identical list */ 278 | /*------------------------------------------------*/ 279 | 280 | static void idaapi graph_identical(void *obj,uint32 n) 281 | { 282 | slist_t * sl = ((deng_t *)obj)->ilist; 283 | options_t * opt = ((deng_t *)obj)->opt; 284 | 285 | graph_list(sl, n, opt); 286 | 287 | return; 288 | } 289 | 290 | 291 | /*------------------------------------------------*/ 292 | /* function : graph_unmatch */ 293 | /* description: Draws graph from element n in */ 294 | /* unmatched list */ 295 | /*------------------------------------------------*/ 296 | 297 | static void idaapi graph_unmatch(void *obj,uint32 n) 298 | { 299 | slist_t * sl = NULL, * tmp = ((deng_t *)obj)->ulist; 300 | 301 | if (ui_access_sig(tmp, n)->nfile == 2) 302 | { 303 | msg ("parsing second function...\n"); 304 | sl = parse_second_fct(ui_access_sig(tmp, n)->startEA, tmp->file, ((deng_t *)obj)->opt); 305 | if (!sl) 306 | { 307 | msg("Error: FCT2 parsing failed.\n"); 308 | return; 309 | } 310 | 311 | sl->sigs[0]->nfile = 2; 312 | } 313 | else 314 | { 315 | msg ("parsing first function...\n"); 316 | sl = parse_fct(ui_access_sig(tmp, n)->startEA, dto.graph.s_showpref); 317 | if (!sl) 318 | { 319 | msg("Error: FCT1 parsing failed.\n"); 320 | return; 321 | } 322 | 323 | sl->sigs[0]->nfile = 1; 324 | } 325 | 326 | pgraph_display_one(sl); 327 | 328 | msg ("done!\n"); 329 | return; 330 | } 331 | 332 | 333 | static uint32 idaapi res_unmatch(deng_t * d,uint32 n, int type) 334 | { 335 | slist_t * sl; 336 | 337 | if (type == 0) 338 | sl = d->ilist; 339 | else 340 | sl = d->mlist; 341 | 342 | psig_t *sig = ui_access_sig(sl, n); 343 | 344 | sig->nfile = 1; 345 | sig->msig->nfile = 2; 346 | 347 | siglist_add(d->ulist, sig); 348 | siglist_add(d->ulist, sig->msig); 349 | 350 | sig->msig->msig = NULL; 351 | sig->msig = NULL; 352 | 353 | siglist_remove(sl, n - 1); 354 | 355 | refresh_chooser(title_unmatch); 356 | 357 | return 1; 358 | } 359 | 360 | 361 | /*------------------------------------------------*/ 362 | /* function : res_iunmatch */ 363 | /* description: Unmatches element n from identical*/ 364 | /* list */ 365 | /*------------------------------------------------*/ 366 | 367 | static uint32 idaapi res_iunmatch(void *obj,uint32 n) 368 | { 369 | return res_unmatch((deng_t *)obj, n, 0); 370 | } 371 | 372 | 373 | /*------------------------------------------------*/ 374 | /* function : res_munmatch */ 375 | /* description: Unmatches element n from matched */ 376 | /* list */ 377 | /*------------------------------------------------*/ 378 | 379 | static uint32 idaapi res_munmatch(void *obj,uint32 n) 380 | { 381 | return res_unmatch((deng_t *)obj, n, 1); 382 | } 383 | 384 | 385 | /*------------------------------------------------*/ 386 | /* function : propagate_match */ 387 | /* description: Propagates new matched result if */ 388 | /* option is set in dialog box */ 389 | /*------------------------------------------------*/ 390 | 391 | void propagate_match(deng_t * eng, psig_t * s1, psig_t * s2, int options) 392 | { 393 | size_t i; 394 | deng_t * d = NULL; 395 | slist_t * l1, * l2; 396 | 397 | if (options) 398 | { 399 | show_wait_box ("PatchDiff is in progress ..."); 400 | 401 | l1 = siglist_init(eng->ulist->num, eng->ulist->file); 402 | l2 = siglist_init(eng->ulist->num, eng->ulist->file); 403 | 404 | for (i=0; iulist->num; i++) 405 | if (!eng->ulist->sigs[i]->msig) 406 | { 407 | if (eng->ulist->sigs[i]->nfile == 1) 408 | siglist_add(l1, eng->ulist->sigs[i]); 409 | else 410 | siglist_add(l2, eng->ulist->sigs[i]); 411 | } 412 | 413 | generate_diff(&d, l1, l2, eng->ulist->file, false, NULL); 414 | 415 | siglist_partial_free(l1); 416 | siglist_partial_free(l2); 417 | 418 | hide_wait_box(); 419 | } 420 | 421 | i = 0; 422 | while (iulist->num) 423 | { 424 | s1 = eng->ulist->sigs[i]; 425 | s2 = s1->msig; 426 | 427 | if (!s2) 428 | i++; 429 | else 430 | { 431 | if (s1->nfile == 1) 432 | { 433 | if (sig_equal(s1, s2, DIFF_EQUAL_SIG_HASH)) 434 | siglist_add(eng->ilist, s1); 435 | else 436 | siglist_add(eng->mlist, s1); 437 | } 438 | 439 | siglist_remove(eng->ulist, i); 440 | } 441 | } 442 | } 443 | 444 | 445 | /*------------------------------------------------*/ 446 | /* function : res_match */ 447 | /* description: Matches 2 elements from unmatched */ 448 | /* list */ 449 | /*------------------------------------------------*/ 450 | 451 | static uint32 idaapi res_match(void *obj,uint32 n) 452 | { 453 | deng_t * eng = (deng_t *)obj; 454 | psig_t * s1, * s2; 455 | int option; 456 | ea_t ea = BADADDR; 457 | size_t i; 458 | 459 | const char format[] = 460 | "STARTITEM 0\n" 461 | 462 | "Set Match\n" 463 | "\n\n" 464 | 465 | "Options :\n" 466 | ">\n\n" 467 | ; 468 | 469 | option = 1; 470 | if (AskUsingForm_c(format, &ea, &option)) 471 | { 472 | s1 = ui_access_sig(eng->ulist, n); 473 | 474 | for (i=0; iulist->num; i++) 475 | { 476 | s2 = eng->ulist->sigs[i]; 477 | 478 | if (s2->startEA != ea || (s2->nfile == s1->nfile)) 479 | continue; 480 | 481 | sig_set_matched_sig(s1, s2, DIFF_MANUAL); 482 | propagate_match(eng, s1, s2, option); 483 | 484 | refresh_chooser(title_match); 485 | refresh_chooser(title_identical); 486 | 487 | return 1; 488 | } 489 | 490 | warning("Address '%a' is not valid.", ea); 491 | return 0; 492 | } 493 | 494 | return 1; 495 | } 496 | 497 | 498 | /*------------------------------------------------*/ 499 | /* function : res_mtoi */ 500 | /* description: Switches element n from matched */ 501 | /* to identical list */ 502 | /*------------------------------------------------*/ 503 | 504 | static uint32 idaapi res_mtoi(void *obj,uint32 n) 505 | { 506 | deng_t * d = (deng_t *)obj; 507 | psig_t *sig = ui_access_sig(d->mlist, n); 508 | 509 | sig->mtype = sig->msig->mtype = DIFF_MANUAL; 510 | 511 | siglist_add(d->ilist, sig); 512 | siglist_remove(d->mlist, n - 1); 513 | 514 | refresh_chooser(title_identical); 515 | 516 | return 1; 517 | } 518 | 519 | 520 | /*------------------------------------------------*/ 521 | /* function : res_itom */ 522 | /* description: Switches element n from identical */ 523 | /* to matched list */ 524 | /*------------------------------------------------*/ 525 | 526 | static uint32 idaapi res_itom(void *obj,uint32 n) 527 | { 528 | deng_t * d = (deng_t *)obj; 529 | psig_t *sig = ui_access_sig(d->ilist, n); 530 | 531 | sig->mtype = sig->msig->mtype = DIFF_MANUAL; 532 | 533 | siglist_add(d->mlist, sig); 534 | siglist_remove(d->ilist, n - 1); 535 | 536 | refresh_chooser(title_match); 537 | 538 | return 1; 539 | } 540 | 541 | 542 | /*------------------------------------------------*/ 543 | /* function : res_flagged */ 544 | /* description: Sets element as flagged/unflagged */ 545 | /*------------------------------------------------*/ 546 | 547 | static uint32 idaapi res_flagged(void *obj,uint32 n) 548 | { 549 | psig_t *sig = ui_access_sig(((deng_t *)obj)->mlist, n); 550 | 551 | sig->flag = !sig->flag; 552 | 553 | refresh_chooser(title_match); 554 | 555 | return 1; 556 | } 557 | 558 | 559 | static void transfer_sym(psig_t *sig) 560 | { 561 | psig_t *rhs = sig->msig; 562 | sig_set_name(sig, rhs->name); 563 | set_name(sig->startEA, rhs->name, SN_NOCHECK | SN_NON_AUTO); 564 | } 565 | 566 | 567 | static uint32 idaapi transfer_sym_match(void *obj, uint32 n) 568 | { 569 | psig_t *sig = ui_access_sig(((deng_t *)obj)->mlist, n); 570 | 571 | transfer_sym(sig); 572 | 573 | return 1; 574 | } 575 | 576 | 577 | static uint32 idaapi transfer_sym_identical(void *obj, uint32 n) 578 | { 579 | psig_t *sig = ui_access_sig(((deng_t *)obj)->ilist, n); 580 | 581 | transfer_sym(sig); 582 | 583 | return 1; 584 | } 585 | 586 | /*------------------------------------------------*/ 587 | /* function : display_matched */ 588 | /* description: Displays matched list */ 589 | /*------------------------------------------------*/ 590 | 591 | static void display_matched(deng_t * eng) 592 | { 593 | choose2(CH_ATTRS, 594 | -1, -1, -1, -1, // position is determined by Windows 595 | eng, // pass the created function list to the window 596 | qnumber(header_match),// number of columns 597 | widths_match, // widths of columns 598 | sizer_match, // function that returns number of lines 599 | desc_match, // function that generates a line 600 | title_match, // window title 601 | -1, // use the default icon for the window 602 | 1, // position the cursor on the first line 603 | NULL, // "kill" callback 604 | NULL, // "new" callback 605 | NULL, // "update" callback 606 | graph_match, // "edit" callback 607 | enter_match, // function to call when the user pressed Enter 608 | close_window, // function to call when the window is closed 609 | popup_match, // use default popup menu items 610 | NULL); 611 | 612 | eng->wnum++; 613 | 614 | add_chooser_command(title_match, "Unmatch", res_munmatch, 0, -1, CHOOSER_POPUP_MENU | CHOOSER_MENU_EDIT); 615 | add_chooser_command(title_match, "Set as identical", res_mtoi, 0, -1, CHOOSER_POPUP_MENU | CHOOSER_MENU_EDIT); 616 | add_chooser_command(title_match, "Flag/unflag", res_flagged, 0, -1, CHOOSER_POPUP_MENU | CHOOSER_MENU_EDIT); 617 | add_chooser_command(title_match, "Import Symbol", transfer_sym_match, 0, -1, CHOOSER_POPUP_MENU | CHOOSER_MENU_EDIT); 618 | } 619 | 620 | 621 | /*------------------------------------------------*/ 622 | /* function : display_identical */ 623 | /* description: Displays identical list */ 624 | /*------------------------------------------------*/ 625 | 626 | static void display_identical(deng_t * eng) 627 | { 628 | choose2(0, 629 | -1, -1, -1, -1, // position is determined by Windows 630 | eng, // pass the created function list to the window 631 | qnumber(header_match),// number of columns 632 | widths_match, // widths of columns 633 | sizer_identical, // function that returns number of lines 634 | desc_identical, // function that generates a line 635 | title_identical, // window title 636 | -1, // use the default icon for the window 637 | 1, // position the cursor on the first line 638 | NULL, // "kill" callback 639 | NULL, // "new" callback 640 | NULL, // "update" callback 641 | graph_identical, // "edit" callback 642 | enter_identical, // function to call when the user pressed Enter 643 | close_window, // function to call when the window is closed 644 | popup_match, // use default popup menu items 645 | NULL); 646 | 647 | eng->wnum++; 648 | 649 | add_chooser_command(title_identical, "Unmatch", res_iunmatch, 0, -1, CHOOSER_POPUP_MENU | CHOOSER_MENU_EDIT); 650 | add_chooser_command(title_identical, "Set as matched", res_itom, 0, -1, CHOOSER_POPUP_MENU | CHOOSER_MENU_EDIT); 651 | add_chooser_command(title_identical, "Import Symbol", transfer_sym_identical, 0, -1, CHOOSER_POPUP_MENU | CHOOSER_MENU_EDIT); 652 | } 653 | 654 | 655 | /*------------------------------------------------*/ 656 | /* function : display_unmatched */ 657 | /* description: Displays unmatched list */ 658 | /*------------------------------------------------*/ 659 | 660 | static void display_unmatched(deng_t * eng) 661 | { 662 | choose2(0, 663 | -1, -1, -1, -1, // position is determined by Windows 664 | eng, // pass the created function list to the window 665 | qnumber(header_unmatch),// number of columns 666 | widths_unmatch, // widths of columns 667 | sizer_unmatch, // function that returns number of lines 668 | desc_unmatch, // function that generates a line 669 | title_unmatch, // window title 670 | -1, // use the default icon for the window 671 | 1, // position the cursor on the first line 672 | NULL, // "kill" callback 673 | NULL, // "new" callback 674 | NULL, // "update" callback 675 | graph_unmatch, // "edit" callback 676 | enter_unmatch, // function to call when the user pressed Enter 677 | close_window, // function to call when the window is closed 678 | popup_unmatch, // use default popup menu items 679 | NULL); // use the same icon for all lines 680 | 681 | eng->wnum++; 682 | 683 | add_chooser_command(title_unmatch, "Set match", res_match, 0, -1, CHOOSER_POPUP_MENU | CHOOSER_MENU_EDIT); 684 | } 685 | 686 | 687 | /*------------------------------------------------*/ 688 | /* function : ui_callback */ 689 | /* description: Catchs lists to change bg color */ 690 | /*------------------------------------------------*/ 691 | 692 | int idaapi ui_callback(void * data, int event_id, va_list va) 693 | { 694 | if ( event_id == ui_get_chooser_item_attrs ) 695 | { 696 | void * co = va_arg(va, void *); 697 | uint32 n = va_arg(va, uint32); 698 | chooser_item_attrs_t *attrs = va_arg(va, chooser_item_attrs_t *); 699 | if (attrs != NULL) 700 | { 701 | deng_t * d = (deng_t *)co; 702 | if (d && d->magic == 0x0BADF00D && n > 0) 703 | if (ui_access_sig(d->mlist, n)->flag == 1) 704 | attrs->color = 0x908070; 705 | } 706 | } 707 | 708 | return 0; 709 | } 710 | 711 | 712 | /*------------------------------------------------*/ 713 | /* function : display_results */ 714 | /* description: Displays diff results */ 715 | /*------------------------------------------------*/ 716 | 717 | void display_results(deng_t * eng) 718 | { 719 | hook_to_notification_point(HT_UI, ui_callback, NULL); 720 | 721 | display_matched(eng); 722 | display_unmatched(eng); 723 | display_identical(eng); 724 | } 725 | -------------------------------------------------------------------------------- /display.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Patchdiff3 3 | Portions (C) 2014 - 2014 namreeb (patchdiff@namreeb.org) 4 | Portions (C) 2010 - 2011 Nicolas Pouvesle 5 | Portions (C) 2007 - 2009 Tenable Network Security, Inc. 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License version 2 as 9 | published by the Free Software Foundation. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "diff.hpp" 23 | 24 | 25 | // column widths 26 | static const int widths_match[] = { 5, 32, 32, 16, 16, 4, 16, 16 }; 27 | static const int widths_unmatch[] = { 5, 32, 16, 8, 8, 8}; 28 | 29 | // column headers 30 | static const char *header_match[] = 31 | { 32 | "Engine", 33 | "Function 1", 34 | "Function 2", 35 | "Address 1", 36 | "Address 2", 37 | "CRC", 38 | "CRC1", 39 | "CRC2" 40 | }; 41 | 42 | static const char *header_unmatch[] = 43 | { 44 | "File", 45 | "Function name", 46 | "Function address", 47 | "Sig", 48 | "Hash", 49 | "CRC" 50 | }; 51 | 52 | static const char * popup_null = "\0\0\0\0"; 53 | 54 | static const char * popup_match[] = 55 | { 56 | popup_null, 57 | popup_null, 58 | "Display Graphs", 59 | NULL, 60 | }; 61 | 62 | static const char * popup_unmatch[] = 63 | { 64 | popup_null, 65 | popup_null, 66 | "Display Graph", 67 | NULL, 68 | }; 69 | 70 | 71 | static const char* title_match = "Matched Functions"; 72 | static const char* title_unmatch = "Unmatched Functions"; 73 | static const char* title_identical = "Identical Functions"; 74 | 75 | 76 | void display_results(deng_t *); 77 | 78 | int idaapi ui_callback(void * data, int event_id, va_list va); 79 | 80 | -------------------------------------------------------------------------------- /hash.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Patchdiff3 3 | Portions (C) 2014 - 2014 namreeb (patchdiff@namreeb.org) 4 | Portions (C) 2010 - 2011 Nicolas Pouvesle 5 | Portions (C) 2007 - 2009 Tenable Network Security, Inc. 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License version 2 as 9 | published by the Free Software Foundation. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | 21 | #include "precomp.hpp" 22 | 23 | #include "hash.hpp" 24 | #include "sig.hpp" 25 | 26 | 27 | /*------------------------------------------------*/ 28 | /* function : hash_init */ 29 | /* description: Initializes hash table to NULL */ 30 | /*------------------------------------------------*/ 31 | 32 | hpsig_t * hash_init(size_t num) 33 | { 34 | unsigned int i; 35 | hpsig_t * hsig; 36 | static unsigned int primes[] = { 67, 251, 509, 1021, 2039, 4093, 8191, 16381, 32749, 65521, 131071, 262139, 524287, 1048573, 2097143 }; 37 | 38 | for (i=0; i < ((sizeof(primes) / sizeof(unsigned int)) - 1); i++) 39 | if (primes[i] > (num/3)) break; 40 | 41 | hsig = (hpsig_t *)qalloc(sizeof(*hsig)); 42 | if (!hsig) return NULL; 43 | 44 | hsig->max_hash = primes[i]; 45 | hsig->table = (hsignature_t **) qalloc(hsig->max_hash * sizeof(*hsig->table)); 46 | if (!hsig->table) 47 | { 48 | qfree(hsig); 49 | return NULL; 50 | } 51 | 52 | for (i = 0; i < hsig->max_hash; i++) 53 | hsig->table[i] = NULL; 54 | 55 | return hsig; 56 | } 57 | 58 | 59 | /*------------------------------------------------*/ 60 | /* function : hash_mk_ea */ 61 | /* description: Creates hash value */ 62 | /*------------------------------------------------*/ 63 | 64 | unsigned int hash_mk_ea(hpsig_t * htable, ea_t val) 65 | { 66 | char * ptr; 67 | unsigned int h = 0; 68 | int i; 69 | 70 | ptr = (char *) &val; 71 | 72 | for (i=0; i> 6 ); 77 | } 78 | 79 | h += ( h << 3); 80 | h ^= ( h >> 11 ); 81 | h += ( h >> 15 ); 82 | 83 | return h % htable->max_hash; 84 | } 85 | 86 | 87 | /*------------------------------------------------*/ 88 | /* function : hash_add_ea */ 89 | /* description: Adds element to the hash table */ 90 | /*------------------------------------------------*/ 91 | 92 | int hash_add_ea (hpsig_t * htable, psig_t * sig) 93 | { 94 | int id = hash_mk_ea(htable, sig->startEA); 95 | hsignature_t * hsig = NULL; 96 | 97 | hsig = (hsignature_t *)qalloc(sizeof(*hsig)); 98 | if (!hsig) return -1; 99 | 100 | hsig->sig = sig; 101 | hsig->next = htable->table[id]; 102 | htable->table[id] = hsig; 103 | 104 | return 0; 105 | } 106 | 107 | 108 | /*------------------------------------------------*/ 109 | /* function : hash_find_ea */ 110 | /* description: Finds element in the hash table */ 111 | /*------------------------------------------------*/ 112 | 113 | psig_t * hash_find_ea (hpsig_t * htable, ea_t ea) 114 | { 115 | if (ea == BADADDR) 116 | return NULL; 117 | 118 | int id = hash_mk_ea(htable, ea); 119 | hsignature_t * hsig; 120 | 121 | hsig = htable->table[id]; 122 | 123 | while (hsig != NULL) 124 | { 125 | if (hsig->sig->startEA == ea) 126 | return hsig->sig; 127 | 128 | hsig = hsig->next; 129 | } 130 | 131 | return NULL; 132 | } 133 | 134 | 135 | /*------------------------------------------------*/ 136 | /* function : hash_free */ 137 | /* description: Frees hash table */ 138 | /*------------------------------------------------*/ 139 | 140 | void hash_free (hpsig_t * htable) 141 | { 142 | unsigned int i; 143 | hsignature_t * hsig, * tmp; 144 | 145 | for (i = 0; i < htable->max_hash; i++) 146 | { 147 | hsig = htable->table[i]; 148 | 149 | while (hsig != NULL) 150 | { 151 | tmp = hsig->next; 152 | qfree (hsig); 153 | 154 | hsig = tmp; 155 | } 156 | } 157 | 158 | qfree(htable); 159 | } 160 | 161 | -------------------------------------------------------------------------------- /hash.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Patchdiff3 3 | Portions (C) 2014 - 2014 namreeb (patchdiff@namreeb.org) 4 | Portions (C) 2010 - 2011 Nicolas Pouvesle 5 | Portions (C) 2007 - 2009 Tenable Network Security, Inc. 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License version 2 as 9 | published by the Free Software Foundation. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | 21 | #pragma once 22 | 23 | #include "sig.hpp" 24 | 25 | 26 | typedef struct hsignature * phsignature; 27 | 28 | struct hsignature 29 | { 30 | psig_t * sig; 31 | phsignature next; 32 | }; 33 | 34 | typedef struct hsignature hsignature_t; 35 | 36 | struct hsig 37 | { 38 | unsigned int max_hash; 39 | hsignature_t ** table ; 40 | }; 41 | 42 | typedef struct hsig hpsig_t; 43 | 44 | 45 | hpsig_t * hash_init(size_t); 46 | unsigned int hash_mk_ea(hpsig_t *, ea_t); 47 | int hash_add_ea (hpsig_t *, psig_t *); 48 | psig_t * hash_find_ea (hpsig_t *, ea_t); 49 | void hash_free (hpsig_t *); 50 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | PROC=patchdiff 2 | O1=backup 3 | O2=clist 4 | O3=hash 5 | O4=diff 6 | O5=ppc 7 | O6=x86 8 | O7=options 9 | O8=parser 10 | O9=pchart 11 | O10=pgraph 12 | O11=sig 13 | O12=system 14 | O13=display 15 | O14=unix_fct 16 | 17 | __CFLAGS=-m32 18 | __LFLAGS=-m32 19 | __PIC__ = 1 20 | 21 | include ../plugin.unx 22 | 23 | # MAKEDEP dependency list ------------------ 24 | $(F)backup$(O) : $(I)ida.hpp sig.hpp diff.hpp options.hpp backup.hpp \ 25 | backup.cpp 26 | $(F)clist$(O) : $(I)ida.hpp sig.hpp hash.hpp clist.hpp clist.cpp 27 | $(F)diff$(O) : $(I)ida.hpp $(I)idp.hpp $(I)graph.hpp $(I)kernwin.hpp \ 28 | diff.hpp sig.hpp os.hpp clist.hpp display.hpp backup.hpp \ 29 | options.hpp hash.hpp diff.cpp 30 | $(F)display$(O) : $(I)ida.hpp $(I)idp.hpp $(I)graph.hpp $(I)kernwin.hpp \ 31 | diff.hpp system.hpp os.hpp parser.hpp pgraph.hpp \ 32 | options.hpp display.hpp display.cpp 33 | $(F)hash$(O) : $(I)ida.hpp sig.hpp hash.hpp hash.cpp 34 | $(F)options$(O) : $(I)ida.hpp $(I)kernwin.hpp system.hpp options.hpp \ 35 | options.cpp 36 | $(F)parser$(O) : $(I)ida.hpp $(I)pro.h $(I)funcs.hpp $(I)fpro.h \ 37 | $(I)diskio.hpp $(I)kernwin.hpp parser.hpp sig.hpp \ 38 | os.hpp pchart.hpp system.hpp display.cpp 39 | $(F)patchdiff$(O) : $(I)ida.hpp $(I)loader.hpp $(I)kernwin.hpp \ 40 | $(I)diskio.hpp $(I)idp.hpp $(I)auto.hpp parser.hpp sig.hpp\ 41 | patchdiff.hpp diff.hpp backup.hpp display.hpp options.hpp \ 42 | system.hpp patchdiff.cpp 43 | $(F)pchart$(O) : $(I)ida.hpp $(I)pro.h $(I)funcs.hpp \ 44 | $(I)gdl.hpp $(I)xref.hpp pchart.hpp patchdiff.hpp \ 45 | x86.hpp pchart.cpp 46 | $(F)pgraph$(O) : $(I)ida.hpp $(I)idp.hpp $(I)graph.hpp $(I)kernwin.hpp \ 47 | sig.hpp diff.hpp pgraph.hpp pgraph.cpp 48 | $(F)ppc$(O) : $(I)ida.hpp $(I)bytes.hpp $(I)kernwin.hpp patchdiff.hpp \ 49 | ppc.hpp ppc.cpp 50 | $(F)sig$(O) : $(I)pro.h $(I)ida.hpp $(I)xref.hpp $(I)gdl.hpp \ 51 | $(I)bytes.hpp $(I)funcs.hpp $(I)kernwin.hpp $(I)fpro.h \ 52 | $(I)diskio.hpp $(I)name.hpp $(I)ua.hpp $(I)demangle.hpp \ 53 | $(I)graph.hpp sig.hpp x86.hpp ppc.hpp patchdiff.hpp \ 54 | pchart.hpp sig.cpp 55 | $(F)system$(O) : $(I)ida.hpp $(I)pro.h $(I)fpro.h $(I)diskio.hpp \ 56 | $(I)kernwin.hpp sig.hpp system.hpp options.hpp os.hpp \ 57 | system.cpp 58 | $(F)unix_fct(O) : $(I)ida.hpp $(I)kernwin.hpp $(I)system.hpp \ 59 | unix_fct.hpp unix_fct.cpp 60 | $(F)x86$(O) : $(I)ida.hpp $(I)bytes.hpp $(I)kernwin.hpp patchdiff.hpp \ 61 | x86.hpp x86.cpp 62 | -------------------------------------------------------------------------------- /options.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Patchdiff3 3 | Portions (C) 2014 - 2014 namreeb (patchdiff@namreeb.org) 4 | Portions (C) 2010 - 2011 Nicolas Pouvesle 5 | Portions (C) 2007 - 2009 Tenable Network Security, Inc. 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License version 2 as 9 | published by the Free Software Foundation. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | 21 | #include "precomp.hpp" 22 | 23 | #include "options.hpp" 24 | #include "system.hpp" 25 | 26 | 27 | static bool idaapi pdiff_menu_callback(void *ud) 28 | { 29 | ushort option = 0, prev = 0; 30 | options_t * opt = (options_t *)ud; 31 | 32 | const char format[] = 33 | "STARTITEM 0\n" 34 | 35 | "PatchDiff3 options\n" 36 | "<##Settings #>\n" 37 | "<#Uses 'pipe' with the second IDA instance to speed up graph display#Keep second IDB open :C>\n" 38 | "<#Saves PatchDiff3 results into the current IDB#Save results to IDB :C>>\n\n" 39 | ; 40 | 41 | option |= opt->ipc ? 1 : 0; 42 | option |= opt->save_db ? 2 : 0; 43 | prev = opt->ipc; 44 | 45 | if (AskUsingForm_c(format, &option)) 46 | { 47 | opt->ipc = !!(option & 1); 48 | opt->save_db = !!(option & 2); 49 | 50 | if (prev && !option) 51 | ipc_close(); 52 | } 53 | 54 | return true; 55 | } 56 | 57 | 58 | options_t * options_init() 59 | { 60 | options_t * opt; 61 | int ipc, db; 62 | 63 | opt = (options_t *)qalloc(sizeof(*opt)); 64 | if (!opt) return NULL; 65 | 66 | if (system_get_pref("IPC", (void *)&ipc, SPREF_INT)) 67 | opt->ipc = !!ipc; 68 | else 69 | opt->ipc = true; 70 | 71 | if (system_get_pref("DB", (void *)&db, SPREF_INT)) 72 | opt->save_db = !!db; 73 | else 74 | opt->save_db = true; 75 | 76 | add_menu_item("Options/", "PatchDiff3", NULL, SETMENU_APP, pdiff_menu_callback, opt); 77 | 78 | return opt; 79 | } 80 | 81 | 82 | void options_close(options_t * opt) 83 | { 84 | del_menu_item("Options/PatchDiff3"); 85 | if (opt) qfree(opt); 86 | } 87 | 88 | 89 | bool options_use_ipc(options_t * opt) 90 | { 91 | return opt->ipc; 92 | } 93 | 94 | 95 | bool options_save_db(options_t * opt) 96 | { 97 | return opt->save_db; 98 | } 99 | -------------------------------------------------------------------------------- /options.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Patchdiff3 3 | Portions (C) 2014 - 2014 namreeb (patchdiff@namreeb.org) 4 | Portions (C) 2010 - 2011 Nicolas Pouvesle 5 | Portions (C) 2007 - 2009 Tenable Network Security, Inc. 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License version 2 as 9 | published by the Free Software Foundation. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | 21 | #pragma once 22 | 23 | struct p_options 24 | { 25 | bool ipc; // inter process communication 26 | bool save_db; 27 | }; 28 | 29 | typedef struct p_options options_t; 30 | 31 | 32 | options_t * options_init(); 33 | bool options_use_ipc(options_t *); 34 | bool options_save_db(options_t *); 35 | void options_close(options_t *); 36 | -------------------------------------------------------------------------------- /os.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Patchdiff3 3 | Portions (C) 2014 - 2014 namreeb (patchdiff@namreeb.org) 4 | Portions (C) 2010 - 2011 Nicolas Pouvesle 5 | Portions (C) 2007 - 2009 Tenable Network Security, Inc. 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License version 2 as 9 | published by the Free Software Foundation. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #ifdef _WINDOWS 23 | #include "win_fct.hpp" 24 | #else 25 | #include "unix_fct.hpp" 26 | #endif 27 | -------------------------------------------------------------------------------- /parser.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Patchdiff3 3 | Portions (C) 2014 - 2014 namreeb (patchdiff@namreeb.org) 4 | Portions (C) 2010 - 2011 Nicolas Pouvesle 5 | Portions (C) 2007 - 2009 Tenable Network Security, Inc. 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License version 2 as 9 | published by the Free Software Foundation. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | 21 | #include "precomp.hpp" 22 | 23 | #include "parser.hpp" 24 | #include "sig.hpp" 25 | #include "os.hpp" 26 | #include "pchart.hpp" 27 | #include "system.hpp" 28 | 29 | /*------------------------------------------------*/ 30 | /* function : parse_idb */ 31 | /* description: generates a list of signatures for*/ 32 | /* the current idb */ 33 | /*------------------------------------------------*/ 34 | 35 | slist_t * parse_idb() 36 | { 37 | slist_t * sl; 38 | psig_t * sig; 39 | size_t fct_num, i; 40 | qvector class_l; 41 | 42 | fct_num = get_func_qty(); 43 | 44 | sl = siglist_init(fct_num, NULL); 45 | if (!sl) return NULL; 46 | 47 | for (i=0; isig == 0 || sig->lines <= 1) 54 | sig_free(sig); 55 | else 56 | siglist_add(sl, sig); 57 | } 58 | } 59 | 60 | if (!siglist_realloc(sl, class_l.size())) 61 | { 62 | siglist_free(sl); 63 | return NULL; 64 | } 65 | 66 | for (i=0; inproper, NULL); 104 | if (!sl) return NULL; 105 | 106 | for (i=0; inproper; i++) 107 | { 108 | memset(opcodes, '\0', sizeof(opcodes)); 109 | sig = sig_init(); 110 | if (!sig) 111 | { 112 | siglist_free(sl); 113 | delete fchart; 114 | return NULL; 115 | } 116 | 117 | sig_set_start(sig, fchart->blocks[i].startEA); 118 | sig_set_name(sig, buf); 119 | 120 | for (k=0; knsucc(i); k++) 121 | sig_add_sref(sig, fchart->blocks[i].succ[k].ea, fchart->blocks[i].succ[k].type, CHECK_REF); 122 | 123 | sig_add_block(sig, opcodes, fchart->blocks[i].startEA, fchart->blocks[i].endEA, 1, options); 124 | 125 | sig_calc_sighash(sig, opcodes, 1); 126 | 127 | siglist_add(sl, sig); 128 | } 129 | 130 | siglist_sort(sl); 131 | delete fchart; 132 | 133 | return sl; 134 | } 135 | 136 | 137 | /*------------------------------------------------*/ 138 | /* function : parse_second_idb */ 139 | /* description: generates a list of signatures for*/ 140 | /* another idb */ 141 | /*------------------------------------------------*/ 142 | 143 | slist_t * parse_second_idb(char ** file, options_t * opt) 144 | { 145 | char ext[10]; 146 | 147 | qsnprintf(ext, sizeof(ext), ".%s", IDB_EXT); 148 | 149 | *file = askfile_c(0, ext, "IDA Database"); 150 | if (!*file) return NULL; 151 | 152 | return system_parse_idb(BADADDR, *file, opt); 153 | } 154 | 155 | 156 | /*------------------------------------------------*/ 157 | /* function : parse_second_fct */ 158 | /* description: generates a list of signatures for*/ 159 | /* another fct */ 160 | /*------------------------------------------------*/ 161 | 162 | slist_t * parse_second_fct(ea_t ea, char * file, options_t * opt) 163 | { 164 | return system_parse_idb(ea, file, opt); 165 | } 166 | -------------------------------------------------------------------------------- /parser.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Patchdiff3 3 | Portions (C) 2014 - 2014 namreeb (patchdiff@namreeb.org) 4 | Portions (C) 2010 - 2011 Nicolas Pouvesle 5 | Portions (C) 2007 - 2009 Tenable Network Security, Inc. 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License version 2 as 9 | published by the Free Software Foundation. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | 21 | #pragma once 22 | 23 | #include "sig.hpp" 24 | #include "options.hpp" 25 | 26 | slist_t * parse_idb(); 27 | slist_t * parse_second_idb(char **, options_t *); 28 | slist_t * parse_fct(ea_t, char); 29 | slist_t * parse_second_fct(ea_t, char *, options_t *); 30 | -------------------------------------------------------------------------------- /patchdiff.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Patchdiff3 3 | Portions (C) 2014 - 2014 namreeb (patchdiff@namreeb.org) 4 | Portions (C) 2010 - 2011 Nicolas Pouvesle 5 | Portions (C) 2007 - 2009 Tenable Network Security, Inc. 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License version 2 as 9 | published by the Free Software Foundation. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | 21 | #include "precomp.hpp" 22 | 23 | #include "sig.hpp" 24 | #include "parser.hpp" 25 | #include "patchdiff.hpp" 26 | #include "diff.hpp" 27 | #include "backup.hpp" 28 | #include "display.hpp" 29 | #include "options.hpp" 30 | #include "system.hpp" 31 | 32 | extern plugin_t PLUGIN; 33 | extern char *exename; 34 | 35 | deng_t * d_engine; 36 | cpu_t patchdiff_cpu; 37 | options_t * d_opt; 38 | 39 | 40 | static int idaapi init(void) 41 | { 42 | if (!strcmp(inf.procName, "metapc")) 43 | { 44 | if (inf.is_64bit()) 45 | patchdiff_cpu = CPU_X8664; 46 | else 47 | patchdiff_cpu = CPU_X8632; 48 | } 49 | else if (!strcmp(inf.procName, "PPC")) 50 | { 51 | patchdiff_cpu = CPU_PPC; 52 | } 53 | else 54 | patchdiff_cpu = CPU_DEFAULT; 55 | 56 | d_engine = NULL; 57 | 58 | // handle IPC 59 | ipc_init(NULL, 0, 0); 60 | 61 | d_opt = options_init(); 62 | if (!d_opt) 63 | return PLUGIN_SKIP; 64 | 65 | return PLUGIN_OK; 66 | } 67 | 68 | static void idaapi term(void) 69 | { 70 | if (d_engine) 71 | { 72 | if (options_save_db(d_opt)) 73 | backup_save_results(d_engine); 74 | diff_engine_free(d_engine); 75 | unhook_from_notification_point(HT_UI, ui_callback); 76 | } 77 | 78 | ipc_close(); 79 | options_close(d_opt); 80 | } 81 | 82 | 83 | static void run_first_instance() 84 | { 85 | char * file; 86 | slist_t * sl1 = NULL; 87 | slist_t * sl2 = NULL; 88 | int ret; 89 | 90 | msg ("\n---------------------------------------------------\n" 91 | "PatchDiff Plugin v2.0.10\n" 92 | "Copyright (c) 2010-2011, Nicolas Pouvesle\n" 93 | "Copyright (C) 2007-2009, Tenable Network Security, Inc\n" 94 | "---------------------------------------------------\n\n"); 95 | 96 | ret = backup_load_results(&d_engine, d_opt); 97 | if (ret == 1) 98 | { 99 | display_results(d_engine); 100 | return; 101 | } 102 | else if (ret == -1) 103 | { 104 | return; 105 | } 106 | 107 | show_wait_box ("PatchDiff is in progress ..."); 108 | 109 | msg ("Scanning for functions ...\n"); 110 | 111 | msg ("parsing second idb...\n"); 112 | sl2 = parse_second_idb(&file, d_opt); 113 | if (!sl2) 114 | { 115 | msg("Error: IDB2 parsing cancelled or failed.\n"); 116 | hide_wait_box(); 117 | return; 118 | } 119 | 120 | msg ("parsing first idb...\n"); 121 | sl1 = parse_idb (); 122 | if (!sl1) 123 | { 124 | msg("Error: IDB1 parsing failed.\n"); 125 | siglist_free(sl2); 126 | hide_wait_box(); 127 | return; 128 | } 129 | 130 | msg ("diffing...\n"); 131 | generate_diff(&d_engine, sl1, sl2, file, true, d_opt); 132 | 133 | msg ("done!\n"); 134 | hide_wait_box(); 135 | 136 | if (sl1) siglist_partial_free(sl1); 137 | if (sl2) siglist_partial_free(sl2); 138 | } 139 | 140 | 141 | static void run_second_instance(const char * options) 142 | { 143 | slist_t * sl; 144 | char file[QMAXPATH]; 145 | ea_t ea = BADADDR; 146 | unsigned char opt = 0; 147 | long id; 148 | unsigned int v; 149 | bool cont; 150 | char tmp[QMAXPATH*4]; 151 | 152 | qsscanf(options, "%u:%a:%u:%s", &id, &ea, &v, file); 153 | opt = (unsigned char)v; 154 | 155 | if (id) 156 | { 157 | if (ipc_init(file, 2, id)) 158 | { 159 | do 160 | { 161 | cont = ipc_recv_cmd(tmp, sizeof(tmp)); 162 | if (cont) 163 | { 164 | run_second_instance(tmp); 165 | ipc_recv_cmd_end(); 166 | } 167 | 168 | }while(cont); 169 | } 170 | } 171 | else 172 | { 173 | if (ea == BADADDR) 174 | { 175 | sl = parse_idb (); 176 | } 177 | else 178 | sl = parse_fct(ea, opt); 179 | 180 | if (!sl) return; 181 | 182 | siglist_save(sl, file); 183 | 184 | siglist_free(sl); 185 | } 186 | } 187 | 188 | 189 | static void idaapi run(int arg) 190 | { 191 | const char * options = NULL; 192 | 193 | autoWait(); 194 | 195 | options = get_plugin_options("patchdiff3"); 196 | 197 | if (options == NULL) 198 | run_first_instance(); 199 | else 200 | run_second_instance(options); 201 | } 202 | 203 | 204 | char comment[] = "w00t"; 205 | char help[] = "A Binary Difference Analysis plugin module\n"; 206 | char wanted_name[] = "PatchDiff3"; 207 | char wanted_hotkey[] = "Ctrl-8"; 208 | 209 | plugin_t PLUGIN = 210 | { 211 | IDP_INTERFACE_VERSION, 212 | PLUGIN_MOD | PLUGIN_FIX, 213 | init, 214 | term, 215 | run, 216 | comment, 217 | help, 218 | wanted_name, 219 | wanted_hotkey 220 | }; 221 | -------------------------------------------------------------------------------- /patchdiff.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Patchdiff3 3 | Portions (C) 2014 - 2014 namreeb (patchdiff@namreeb.org) 4 | Portions (C) 2010 - 2011 Nicolas Pouvesle 5 | Portions (C) 2007 - 2009 Tenable Network Security, Inc. 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License version 2 as 9 | published by the Free Software Foundation. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | 21 | #pragma once 22 | 23 | enum pcpu_type 24 | { 25 | CPU_DEFAULT, 26 | CPU_X8632, 27 | CPU_X8664, 28 | CPU_PPC 29 | }; 30 | 31 | typedef enum pcpu_type cpu_t; 32 | -------------------------------------------------------------------------------- /pchart.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Patchdiff3 3 | Portions (C) 2014 - 2014 namreeb (patchdiff@namreeb.org) 4 | Portions (C) 2010 - 2011 Nicolas Pouvesle 5 | Portions (C) 2007 - 2009 Tenable Network Security, Inc. 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License version 2 as 9 | published by the Free Software Foundation. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | 21 | #include "precomp.hpp" 22 | 23 | #include "pchart.hpp" 24 | #include "patchdiff.hpp" 25 | #include "x86.hpp" 26 | 27 | using namespace std; 28 | 29 | extern cpu_t patchdiff_cpu; 30 | 31 | 32 | ea_t get_fake_jump(ea_t ea) 33 | { 34 | switch(patchdiff_cpu) 35 | { 36 | case CPU_X8632: 37 | case CPU_X8664: 38 | return x86_get_fake_jump(ea); 39 | default: 40 | return BADADDR; 41 | } 42 | } 43 | 44 | 45 | bool is_end_block(ea_t ea) 46 | { 47 | switch(patchdiff_cpu) 48 | { 49 | case CPU_X8632: 50 | case CPU_X8664: 51 | return x86_is_end_block(ea); 52 | default: 53 | return false; 54 | } 55 | } 56 | 57 | ea_t get_direct_jump(ea_t ea) 58 | { 59 | xrefblk_t xb; 60 | cref_t cr; 61 | flags_t f = getFlags(ea); 62 | bool b = xb.first_from(ea, XREF_FAR); 63 | if (!b) return BADADDR; 64 | 65 | cr = (cref_t)xb.type; 66 | if (!xb.iscode || !(cr == fl_JF || cr == fl_JN || cr == fl_F) || (f & FF_JUMP)) return BADADDR; 67 | 68 | switch(patchdiff_cpu) 69 | { 70 | case CPU_X8632: 71 | case CPU_X8664: 72 | if (x86_is_direct_jump(ea)) return xb.to; 73 | default: 74 | return BADADDR; 75 | } 76 | } 77 | 78 | 79 | bool pflow_chart_t::getJump(func_t * fct, qvector & list, pbasic_block_t & bl) 80 | { 81 | xrefblk_t xb; 82 | cref_t cr; 83 | bool b, j, flow; 84 | qvector tmp; 85 | qvector::iterator pos; 86 | ea_t tea, ea = bl.endEA, end, jaddr; 87 | flags_t f; 88 | size_t k; 89 | int type = 0; 90 | int cond; 91 | 92 | j = flow = false; 93 | 94 | end = get_item_end(ea); 95 | 96 | b = xb.first_from(ea, XREF_ALL); 97 | f = getFlags(ea); 98 | cond = x86_is_cond_jump_pos(ea); 99 | 100 | while (b) 101 | { 102 | cr = (cref_t)xb.type; 103 | if (xb.iscode && (cr == fl_JF || cr == fl_JN || cr == fl_F)) 104 | { 105 | pedge_t ed; 106 | 107 | if (cr == fl_JF || cr == fl_JN) 108 | { 109 | j = true; 110 | type = 1; 111 | } 112 | else if (! (f & FF_JUMP)) 113 | { 114 | flow = true; 115 | type = 2; 116 | } 117 | 118 | if (patchdiff_cpu == CPU_X8632 || patchdiff_cpu == CPU_X8664 || get_func_chunknum(fct, xb.to) >= 0) 119 | { 120 | jaddr = get_direct_jump(xb.to); 121 | if (jaddr == BADADDR) 122 | ed.ea = xb.to; 123 | else 124 | ed.ea = jaddr; 125 | 126 | ed.type = type; 127 | 128 | pos = tmp.end(); 129 | 130 | if (patchdiff_cpu == CPU_X8632 || patchdiff_cpu == CPU_X8664) 131 | { 132 | if ( (cond == 1 && cr == fl_F) || (cond == 2 && cr != fl_F) ) 133 | pos = tmp.begin(); 134 | } 135 | else if (ed.ea == end) 136 | pos = tmp.begin(); 137 | 138 | assert(ed.type != 0); 139 | 140 | tmp.insert(pos, ed); 141 | } 142 | } 143 | 144 | b = xb.next_from(); 145 | } 146 | 147 | tea = get_fake_jump(ea); 148 | if (tea != BADADDR) 149 | { 150 | pedge_t ed; 151 | 152 | j = true; 153 | ed.ea = tea; 154 | ed.type = 1; 155 | } 156 | 157 | if (j) 158 | { 159 | for (k=0; k::iterator it; 185 | 186 | for (it=blocks.begin(); itstartEA == ea) 189 | return true; 190 | 191 | if (ea > it->startEA && ea < it->endEA) 192 | { 193 | pbasic_block_t bl; 194 | pedge_t ed; 195 | 196 | bl.startEA = ea; 197 | bl.endEA = it->endEA; 198 | bl.succ = it->succ; 199 | 200 | it->endEA = ea; 201 | it->succ.clear(); 202 | 203 | ed.ea = ea; 204 | ed.type = 3; 205 | it->succ.push_back(ed); 206 | 207 | blocks.push_back(bl); 208 | 209 | return true; 210 | } 211 | } 212 | 213 | 214 | return false; 215 | } 216 | 217 | 218 | pflow_chart_t::pflow_chart_t(func_t * fct) 219 | { 220 | ea_t ea; 221 | qvector to_trace; 222 | bool cont; 223 | flags_t f; 224 | 225 | to_trace.push_back(fct->startEA); 226 | 227 | while (!to_trace.empty()) 228 | { 229 | ea = to_trace.front(); 230 | to_trace.erase(to_trace.begin()); 231 | 232 | if (check_address(ea)) 233 | continue; 234 | 235 | pbasic_block_t bl; 236 | 237 | bl.startEA = ea; 238 | bl.endEA = ea; 239 | cont = true; 240 | 241 | while(cont) 242 | { 243 | ea = bl.endEA; 244 | f = getFlags(ea); 245 | 246 | if ( (!isFlow(f) && (ea != bl.startEA)) || !isCode(f) ) 247 | break; 248 | 249 | if ( check_address(ea) ) 250 | { 251 | pedge_t ed; 252 | 253 | ed.ea = ea; 254 | ed.type = 3; 255 | 256 | bl.succ.push_back(ed); 257 | break; 258 | } 259 | 260 | if ( getJump(fct, to_trace, bl) ) 261 | cont = false; 262 | 263 | if ( is_end_block(ea) ) 264 | break; 265 | 266 | bl.endEA = get_item_end(ea); 267 | } 268 | 269 | blocks.push_back(bl); 270 | } 271 | 272 | nproper = blocks.size(); 273 | } 274 | -------------------------------------------------------------------------------- /pchart.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Patchdiff3 3 | Portions (C) 2014 - 2014 namreeb (patchdiff@namreeb.org) 4 | Portions (C) 2010 - 2011 Nicolas Pouvesle 5 | Portions (C) 2007 - 2009 Tenable Network Security, Inc. 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License version 2 as 9 | published by the Free Software Foundation. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | 21 | #pragma once 22 | 23 | #include "precomp.hpp" 24 | 25 | struct pedge_t 26 | { 27 | ea_t ea; 28 | int type; 29 | }; 30 | 31 | struct pbasic_block_t : public area_t 32 | { 33 | qvector succ; // list of node successors 34 | qvector pred; // list of node predecessors 35 | }; 36 | 37 | class pflow_chart_t 38 | { 39 | private: 40 | bool check_address(ea_t ea); 41 | bool getJump(func_t * fct, qvector & list, pbasic_block_t & bl); 42 | 43 | public: 44 | typedef qvector blocks_t; 45 | blocks_t blocks; 46 | int nproper; 47 | 48 | idaapi pflow_chart_t(func_t *_pfn); 49 | 50 | int idaapi nsucc(int node) const { return int(blocks[node].succ.size()); } 51 | int idaapi succ(int node, int i) const 52 | { 53 | int k; 54 | 55 | for (k=0; k. 18 | */ 19 | 20 | 21 | #include "precomp.hpp" 22 | 23 | #include "pgraph.hpp" 24 | #include "sig.hpp" 25 | #include "diff.hpp" 26 | 27 | 28 | static int find_node(slist_t * sl, ea_t ea) 29 | { 30 | size_t i; 31 | 32 | for(i=0; inum; i++) 33 | if (sl->sigs[i]->startEA == ea) 34 | return i; 35 | 36 | return -1; 37 | } 38 | 39 | 40 | /*------------------------------------------------*/ 41 | /* function : menu_callback */ 42 | /* description: Menu callback */ 43 | /*------------------------------------------------*/ 44 | 45 | static bool idaapi menu_callback(void *ud) 46 | { 47 | int node; 48 | slist_t * sl = (slist_t *)ud; 49 | 50 | if (sl && sl->sigs && sl->sigs[0]->nfile == 1) 51 | { 52 | node = viewer_get_curnode(sl->gv); 53 | if (node >= 0) 54 | jumpto(sl->sigs[node]->startEA); 55 | } 56 | 57 | return true; 58 | } 59 | 60 | 61 | /*------------------------------------------------*/ 62 | /* function : graph_callback */ 63 | /* description: Graph callback */ 64 | /*------------------------------------------------*/ 65 | 66 | static int idaapi graph_callback(void * ud, int code, va_list va) 67 | { 68 | int result = 0; 69 | 70 | switch ( code ) 71 | { 72 | case grcode_layout_calculated: 73 | { 74 | mutable_graph_t *g = va_arg(va, mutable_graph_t *); 75 | slist_t * sl = (slist_t *)ud; 76 | 77 | if (sl->num != g->size()) 78 | { 79 | warning("Graph layout is too complex to be displayed.\n"); 80 | g->reset(); 81 | } 82 | } 83 | break; 84 | 85 | case grcode_changed_current: 86 | { 87 | graph_viewer_t *v = va_arg (va, graph_viewer_t *); 88 | int node = va_argi(va, int); 89 | 90 | if (node != -1) 91 | { 92 | slist_t * sl = (slist_t *)ud; 93 | sl->dclk = true; 94 | } 95 | } 96 | break; 97 | 98 | case grcode_clicked: 99 | { 100 | slist_t * sl = (slist_t *)ud; 101 | sl->dclk = false; 102 | } 103 | break; 104 | 105 | case grcode_dblclicked: 106 | { 107 | graph_viewer_t *v = va_arg(va, graph_viewer_t *); 108 | selection_item_t *s = va_arg(va, selection_item_t *); 109 | slist_t * sl = (slist_t *)ud; 110 | 111 | if ( s && s->is_node) 112 | { 113 | viewer_center_on(v, s->node); 114 | 115 | if (sl->sigs[s->node]->msig != NULL && sl->msl->gv != NULL) 116 | viewer_center_on(sl->msl->gv, find_node(sl->msl, sl->sigs[s->node]->matchedEA)); 117 | 118 | sl->dclk = false; 119 | } 120 | else if ( sl->dclk || s ) 121 | { 122 | int node; 123 | 124 | node = viewer_get_curnode(v); 125 | 126 | if (sl->sigs[node]->msig != NULL && sl->msl->gv != NULL) 127 | viewer_center_on(sl->msl->gv, find_node(sl->msl, sl->sigs[node]->matchedEA)); 128 | 129 | sl->dclk = false; 130 | } 131 | } 132 | break; 133 | 134 | case grcode_user_refresh: 135 | { 136 | mutable_graph_t *g = va_arg(va, mutable_graph_t *); 137 | slist_t * sl = (slist_t *)ud; 138 | 139 | if ( g->empty() ) 140 | g->resize(sl->num); 141 | 142 | for(size_t i = 0; i< sl->num; i++) 143 | { 144 | fref_t * fref; 145 | 146 | if (sl->sigs[i]->srefs) 147 | { 148 | fref = sl->sigs[i]->srefs->list; 149 | while(fref) 150 | { 151 | int pos = find_node(sl, fref->ea); 152 | 153 | if (pos != -1) 154 | { 155 | edge_info_t ed; 156 | if (fref->type == 3) 157 | ed.color = 0xff0000; 158 | else if (fref->type == 2) 159 | ed.color = 0x0000ff; 160 | else 161 | ed.color = 0x006400; 162 | 163 | g->add_edge(i, pos, &ed); 164 | } 165 | 166 | fref = fref->next; 167 | } 168 | } 169 | } 170 | 171 | result = 1; 172 | } 173 | break; 174 | 175 | case grcode_user_text: 176 | { 177 | mutable_graph_t *g = va_arg(va, mutable_graph_t *); 178 | int node = va_arg(va, int); 179 | const char **text = va_arg(va, const char **); 180 | bgcolor_t *bgcolor = va_arg(va, bgcolor_t *); 181 | 182 | slist_t * sl = (slist_t *)ud; 183 | 184 | *text = sl->sigs[node]->dl.lines; 185 | 186 | if ( bgcolor != NULL ) 187 | { 188 | *bgcolor = 0xFFFFFFFF; 189 | 190 | if (!sl->unique) 191 | { 192 | if (sl->sigs[node]->mtype == DIFF_UNMATCHED) 193 | *bgcolor = 0xcccccc; 194 | else if (sl->sigs[node]->sig != sl->sigs[node]->msig->sig) 195 | *bgcolor = 0x33cc; 196 | else if (sl->sigs[node]->id_crc) 197 | *bgcolor = 0x8cb4d2; 198 | } 199 | } 200 | result = 1; 201 | qnotused(g); 202 | } 203 | break; 204 | 205 | case grcode_destroyed: 206 | { 207 | slist_t * sl = (slist_t *)ud; 208 | 209 | sl->gv = NULL; 210 | } 211 | break; 212 | } 213 | 214 | return result; 215 | } 216 | 217 | 218 | template 219 | void create_form_name(char (&dst)[len], slist_t *sl, int num) 220 | { 221 | qsnprintf(dst, len, "IDB%d: %s", num, sl->sigs[0]->name); 222 | } 223 | 224 | 225 | /*------------------------------------------------*/ 226 | /* function : pgraph_create */ 227 | /* description: Creates s function graph */ 228 | /* returns: true if the form was newly created */ 229 | /*------------------------------------------------*/ 230 | 231 | static bool pgraph_create(slist_t *sl, int num) 232 | { 233 | HWND hwnd = NULL; 234 | char form_name[512]; 235 | char node_name[512]; 236 | TForm *form; 237 | bool form_is_new = true; 238 | 239 | create_form_name(form_name, sl, num); 240 | qsnprintf(node_name, sizeof(node_name), "$ %s", form_name); 241 | 242 | form = find_tform(form_name); 243 | 244 | netnode id; 245 | bool already_existed = !id.create(node_name); 246 | if (form && already_existed) 247 | { 248 | form_is_new = false; 249 | switchto_tform(form, true); 250 | sl->gv = get_graph_viewer(form); 251 | } 252 | else 253 | { 254 | form = create_tform(form_name, &hwnd); 255 | if (hwnd) 256 | { 257 | sl->gv = create_graph_viewer(form, id, graph_callback, sl, 0); 258 | open_tform(form, FORM_TAB|FORM_MENU|FORM_QWIDGET); 259 | if (sl->gv) 260 | { 261 | viewer_fit_window(sl->gv); 262 | viewer_add_menu_item(sl->gv, "Jump to code", menu_callback, sl, NULL, 0); 263 | } 264 | } 265 | } 266 | 267 | return form_is_new; 268 | } 269 | 270 | 271 | /*------------------------------------------------*/ 272 | /* function : pgraph_display */ 273 | /* description: Displays function graph */ 274 | /*------------------------------------------------*/ 275 | 276 | void pgraph_display(slist_t * sl1, slist_t * sl2) 277 | { 278 | graph_viewer_t *gv = NULL; 279 | 280 | sl1->msl = sl2; 281 | sl2->msl = sl1; 282 | 283 | sl1->unique = sl2->unique = false; 284 | 285 | bool sl1_new_form = pgraph_create(sl1, 1); 286 | bool sl2_new_form = pgraph_create(sl2, 2); 287 | if ((sl1_new_form || sl2_new_form) && 288 | sl1->gv && sl2->gv) 289 | { 290 | // Only perform the docking for forms that were just created 291 | char buf[512], buf2[512]; 292 | create_form_name(buf, sl1, 1); 293 | create_form_name(buf2, sl2, 2); 294 | set_dock_pos(buf2, buf, DP_RIGHT); 295 | } 296 | } 297 | 298 | 299 | void pgraph_display_one(slist_t * sl) 300 | { 301 | sl->msl = NULL; 302 | sl->unique = true; 303 | 304 | pgraph_create(sl, sl->sigs[0]->nfile); 305 | } 306 | -------------------------------------------------------------------------------- /pgraph.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Patchdiff3 3 | Portions (C) 2014 - 2014 namreeb (patchdiff@namreeb.org) 4 | Portions (C) 2010 - 2011 Nicolas Pouvesle 5 | Portions (C) 2007 - 2009 Tenable Network Security, Inc. 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License version 2 as 9 | published by the Free Software Foundation. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | 21 | #pragma once 22 | 23 | #include "sig.hpp" 24 | 25 | typedef struct node_list * pnode_list; 26 | 27 | struct node_list 28 | { 29 | uval_t id; 30 | slist_t * sl; 31 | pnode_list next; 32 | }; 33 | 34 | typedef struct node_list nlist_t; 35 | 36 | 37 | struct graph_list 38 | { 39 | int num; 40 | nlist_t * sl; 41 | 42 | }; 43 | 44 | typedef struct graph_list glist_t; 45 | 46 | 47 | void pgraph_display(slist_t *, slist_t *); 48 | void pgraph_display_one(slist_t *); 49 | -------------------------------------------------------------------------------- /ppc.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Patchdiff3 3 | Portions (C) 2014 - 2014 namreeb (patchdiff@namreeb.org) 4 | Portions (C) 2010 - 2011 Nicolas Pouvesle 5 | Portions (C) 2007 - 2009 Tenable Network Security, Inc. 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License version 2 as 9 | published by the Free Software Foundation. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | 21 | #include "precomp.hpp" 22 | 23 | #include "ppc.hpp" 24 | #include "patchdiff.hpp" 25 | 26 | extern cpu_t patchdiff_cpu; 27 | 28 | 29 | /*------------------------------------------------*/ 30 | /* function : ppc_is_nop */ 31 | /* arguments: unsigned char _byte */ 32 | /* description: detects if instruction is a nop */ 33 | /* (mr rA, rA) */ 34 | /*------------------------------------------------*/ 35 | 36 | bool ppc_is_nop (unsigned char _byte, ea_t ea) 37 | { 38 | unsigned char s, a, b, rc; 39 | unsigned short v; 40 | unsigned long l; 41 | 42 | _byte = get_byte(ea) >> 2; 43 | 44 | // or rS, rA, rB 45 | if (_byte == 31) 46 | { 47 | v = get_word(ea); 48 | s = (v >> 5) & 0x1F; 49 | a = v & 0x1F; 50 | 51 | if (s == a) 52 | { 53 | v = get_word(ea+2); 54 | 55 | b = v >> 11; 56 | rc = v & 1; 57 | v = (v >> 1) & 0x3FF; 58 | 59 | if (b == s && v == 444 && !rc) 60 | return true; 61 | } 62 | } 63 | // nop: ori 0,0,0 64 | else if (_byte == 24) 65 | { 66 | l = get_long(ea); 67 | if (l == 0x60000000) 68 | return true; 69 | } 70 | 71 | return false; 72 | } 73 | 74 | 75 | /*------------------------------------------------*/ 76 | /* function : ppc_remove_instr */ 77 | /* arguments: unsigned char byte, ea_t ea */ 78 | /* description: Returns true is the instruction */ 79 | /* must be ignored */ 80 | /*------------------------------------------------*/ 81 | 82 | bool ppc_remove_instr(unsigned char byte, ea_t ea) 83 | { 84 | if (ppc_is_nop(byte, ea)) 85 | return true; 86 | 87 | /* 88 | // if not addi (li) 89 | if (byte != 14) 90 | return false; 91 | 92 | // removes li, rD, 0 (addi rD, rA, 0 with rA == 0) 93 | b = get_byte(ea+1) & 0x1F; 94 | if (!b) 95 | { 96 | s = get_word(ea+2); 97 | if (s == 0) 98 | return true; 99 | } 100 | */ 101 | 102 | return false; 103 | } 104 | 105 | /*------------------------------------------------*/ 106 | /* function : ppc_get_byte */ 107 | /* arguments: unsigned char _byte */ 108 | /* description: Returns opcode */ 109 | /*------------------------------------------------*/ 110 | 111 | unsigned char ppc_get_byte(ea_t ea) 112 | { 113 | unsigned char byte; 114 | unsigned short v; 115 | 116 | byte = get_byte(ea) >> 2; 117 | 118 | if (byte == 31) 119 | { 120 | v = get_word(ea+2); 121 | v = (v >> 1) & 0xFF; 122 | if (v < 65) v += 65; 123 | 124 | byte = (unsigned char)v; 125 | } 126 | 127 | 128 | return byte; 129 | } 130 | -------------------------------------------------------------------------------- /ppc.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Patchdiff3 3 | Portions (C) 2014 - 2014 namreeb (patchdiff@namreeb.org) 4 | Portions (C) 2010 - 2011 Nicolas Pouvesle 5 | Portions (C) 2007 - 2009 Tenable Network Security, Inc. 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License version 2 as 9 | published by the Free Software Foundation. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "precomp.hpp" 23 | 24 | unsigned char ppc_get_byte(ea_t); 25 | bool ppc_remove_instr(unsigned char, ea_t); 26 | 27 | -------------------------------------------------------------------------------- /precomp.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Patchdiff3 3 | Portions (C) 2014 - 2014 namreeb (patchdiff@namreeb.org) 4 | Portions (C) 2010 - 2011 Nicolas Pouvesle 5 | Portions (C) 2007 - 2009 Tenable Network Security, Inc. 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License version 2 as 9 | published by the Free Software Foundation. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | 21 | #include "precomp.hpp" 22 | -------------------------------------------------------------------------------- /precomp.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Patchdiff3 3 | Portions (C) 2014 - 2014 namreeb (patchdiff@namreeb.org) 4 | Portions (C) 2010 - 2011 Nicolas Pouvesle 5 | Portions (C) 2007 - 2009 Tenable Network Security, Inc. 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License version 2 as 9 | published by the Free Software Foundation. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | 21 | #pragma once 22 | 23 | #include 24 | #include 25 | 26 | #define NO_OBSOLETE_FUNCS 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | 44 | // The graph API spams "forcing value to bool" warnings... 45 | #pragma warning(push) 46 | #pragma warning(disable: 4800) 47 | #include 48 | #pragma warning(pop) 49 | 50 | static_assert(IDA_SDK_VERSION >= 610, "This plugin expects IDA SDK 6.1 or later"); 51 | -------------------------------------------------------------------------------- /sig.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Patchdiff3 3 | Portions (C) 2014 - 2014 namreeb (patchdiff@namreeb.org) 4 | Portions (C) 2010 - 2011 Nicolas Pouvesle 5 | Portions (C) 2007 - 2009 Tenable Network Security, Inc. 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License version 2 as 9 | published by the Free Software Foundation. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | 21 | #pragma once 22 | 23 | #include "precomp.hpp" 24 | 25 | #define DIFF_UNMATCHED -1 26 | 27 | #define CLASS_SIG 0xACDCACDC 28 | 29 | #define SIG_PRED 1 30 | #define SIG_SUCC 2 31 | 32 | #define CHECK_REF 0 33 | #define DO_NOT_CHECK_REF 1 34 | 35 | #ifdef _WINDOWS 36 | #define OS_CDECL __cdecl 37 | #else 38 | #define OS_CDECL 39 | #endif 40 | 41 | typedef struct signature psig_t; 42 | typedef struct dc_sig * pdc_sig; 43 | 44 | struct dc_sig 45 | { 46 | psig_t * sig; 47 | bool removed; 48 | pdc_sig prev; 49 | pdc_sig next; 50 | }; 51 | 52 | typedef struct dc_sig dpsig_t; 53 | 54 | struct c_list 55 | { 56 | size_t num; 57 | dpsig_t * pos; // position in sigs list 58 | dpsig_t * sigs; // chained list 59 | 60 | size_t nmatch; // number of matched element 61 | dpsig_t * msigs; // matched list 62 | }; 63 | 64 | typedef struct c_list clist_t; 65 | 66 | 67 | 68 | typedef struct fct_ref * pfct_ref; 69 | 70 | struct fct_ref 71 | { 72 | ea_t ea; 73 | int type; 74 | char rtype; 75 | pfct_ref next; 76 | }; 77 | 78 | typedef struct fct_ref fref_t; 79 | 80 | struct fct_refs 81 | { 82 | int num; 83 | fref_t * list; 84 | }; 85 | 86 | typedef struct fct_refs frefs_t; 87 | 88 | struct dline 89 | { 90 | int num; 91 | int available; 92 | char * lines; 93 | }; 94 | 95 | typedef struct dline dline_t; 96 | 97 | typedef struct signature * psignature; 98 | 99 | struct signature 100 | { 101 | char * name; 102 | ea_t startEA; 103 | ea_t matchedEA; 104 | int mtype; 105 | psignature msig; 106 | int node; 107 | int id_crc; 108 | int nfile; 109 | int type; 110 | int flag; 111 | unsigned long sig; 112 | unsigned long hash; 113 | unsigned long hash2; 114 | unsigned long crc_hash; 115 | unsigned long str_hash; 116 | unsigned long lines; 117 | frefs_t * prefs; 118 | frefs_t * srefs; 119 | clist_t * cp; 120 | clist_t * cs; 121 | dline_t dl; 122 | }; 123 | 124 | 125 | typedef struct sig_list * psig_list; 126 | 127 | struct sig_list 128 | { 129 | size_t num; 130 | size_t org_num; 131 | char * file; 132 | bool dclk; 133 | graph_viewer_t *gv; 134 | bool unique; 135 | psig_list msl; 136 | psig_t ** sigs; 137 | }; 138 | 139 | typedef struct sig_list slist_t; 140 | 141 | 142 | void siglist_free(slist_t *); 143 | void siglist_partial_free(slist_t *); 144 | int siglist_save(slist_t *, const char *); 145 | slist_t * siglist_load(const char *); 146 | slist_t * siglist_init(size_t, char *); 147 | psig_t * sig_generate(size_t, qvector &); 148 | psig_t * sig_class_generate(ea_t); 149 | void clist_free(clist_t *); 150 | void siglist_free(slist_t **); 151 | bool siglist_realloc(slist_t *, size_t); 152 | void siglist_add(slist_t *, psig_t *); 153 | void siglist_remove(slist_t *, size_t); 154 | void siglist_sort(slist_t *); 155 | ea_t sig_get_start(psig_t * ); 156 | void sig_set_nfile(psig_t *, int); 157 | void sig_set_matched_sig(psig_t *, psig_t *, int); 158 | psig_t * sig_get_matched_sig(psig_t *); 159 | void sig_set_matched_ea(psig_t *, ea_t); 160 | ea_t sig_get_matched_ea(psig_t *); 161 | int sig_get_matched_type(psig_t *); 162 | frefs_t * sig_get_preds(psig_t *); 163 | frefs_t * sig_get_succs(psig_t *); 164 | int sig_add_pref(psig_t *, ea_t, int, char); 165 | int sig_add_sref(psig_t *, ea_t, int, char); 166 | clist_t * sig_get_crefs(psig_t *, int); 167 | void sig_set_crefs(psig_t *, int, clist_t *); 168 | int OS_CDECL sig_compare(const void *, const void *); 169 | psig_t * sig_init(); 170 | int sig_add_block(psig_t *, short *, ea_t, ea_t, bool, char); 171 | void sig_set_start(psig_t *, ea_t); 172 | void sig_set_name(psig_t *, const char *); 173 | int sig_calc_sighash(psig_t *, short *, int); 174 | void sig_free(psig_t *); 175 | bool sig_is_class(psig_t *); 176 | char * pget_func_name(ea_t, char *, size_t); 177 | -------------------------------------------------------------------------------- /system.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Patchdiff3 3 | Portions (C) 2014 - 2014 namreeb (patchdiff@namreeb.org) 4 | Portions (C) 2010 - 2011 Nicolas Pouvesle 5 | Portions (C) 2007 - 2009 Tenable Network Security, Inc. 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License version 2 as 9 | published by the Free Software Foundation. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | 21 | #include "precomp.hpp" 22 | 23 | #include "sig.hpp" 24 | #include "system.hpp" 25 | #include "options.hpp" 26 | #include "os.hpp" 27 | 28 | 29 | // global variable to keep IPC state 30 | ipc_config_t ipcc; 31 | 32 | 33 | /*------------------------------------------------*/ 34 | /* function : generate_idc_file */ 35 | /* description: generates an idc file to launch */ 36 | /* second plugin instance in batch */ 37 | /* mode */ 38 | /*------------------------------------------------*/ 39 | 40 | static int generate_idc_file(char * file) 41 | { 42 | FILE * fp; 43 | 44 | fp = qfopen(file, "w+"); 45 | if (!fp) return -1; 46 | 47 | qfwrite(fp, PATCHDIFF_IDC, strlen(PATCHDIFF_IDC)); 48 | qfclose(fp); 49 | 50 | return 0; 51 | } 52 | 53 | 54 | /*------------------------------------------------*/ 55 | /* function : system_execute_second_instance */ 56 | /* description: Executes another IDA instance */ 57 | /*------------------------------------------------*/ 58 | 59 | static int system_execute_second_instance(char * idc, ea_t ea, char * file, bool close, long id, void * data) 60 | { 61 | char path[QMAXPATH*4]; 62 | char cmd[QMAXPATH*4]; 63 | 64 | if (!getsysfile(path, sizeof(path), IDA_EXEC, NULL)) 65 | return -1; 66 | 67 | if (generate_idc_file(idc)) 68 | return -1; 69 | 70 | qsnprintf(cmd, sizeof(cmd), "%s -A -S\"%s\" -Opatchdiff3:%u:%a:%u:\"%s\" \"%s\"", 71 | path, 72 | idc, 73 | id, 74 | ea, 75 | dto.graph.s_showpref, 76 | idc, 77 | file 78 | ); 79 | 80 | return os_execute_command(cmd, close, data); 81 | } 82 | 83 | 84 | /*------------------------------------------------*/ 85 | /* function : ipc_init */ 86 | /* description: Inits interprocess communication */ 87 | /* between 2 IDA instances */ 88 | /*------------------------------------------------*/ 89 | 90 | bool ipc_init(char * file, int type, long id) 91 | { 92 | bool ret; 93 | long pid; 94 | char tmpname[QMAXPATH]; 95 | 96 | if (type == 0) 97 | { 98 | ipcc.init = false; 99 | ipcc.data = NULL; 100 | } 101 | else if (!ipcc.init) 102 | { 103 | if (type == 1) 104 | { 105 | 106 | pid = os_get_pid(); 107 | ret = os_ipc_init(&ipcc.data, pid, IPC_SERVER); 108 | if (!ret) 109 | return false; 110 | 111 | os_tempnam(tmpname, sizeof(tmpname), ".idc"); 112 | if (system_execute_second_instance(tmpname, BADADDR, file, false, pid, ipcc.data) != 0) 113 | { 114 | ipc_close(); 115 | return false; 116 | } 117 | } 118 | else 119 | { 120 | ret = os_ipc_init(&ipcc.data, id, IPC_CLIENT); 121 | if (!ret) 122 | return false; 123 | } 124 | 125 | ipcc.init = true; 126 | } 127 | 128 | return true; 129 | } 130 | 131 | 132 | /*------------------------------------------------*/ 133 | /* function : ipc_close */ 134 | /* description: Closes interprocess communication */ 135 | /* between 2 IDA instances */ 136 | /*------------------------------------------------*/ 137 | 138 | void ipc_close() 139 | { 140 | if (!ipcc.init) return; 141 | 142 | os_ipc_close(ipcc.data); 143 | 144 | ipcc.data = NULL; 145 | ipcc.init = false; 146 | } 147 | 148 | 149 | /*------------------------------------------------*/ 150 | /* function : ipc_send_cmd */ 151 | /* description: Executes command on the remote */ 152 | /* IDA instance */ 153 | /*------------------------------------------------*/ 154 | 155 | static bool ipc_send_cmd(char * cmd) 156 | { 157 | idata_t d; 158 | 159 | d.cmd = IPC_DATA; 160 | qstrncpy(d.data, cmd, sizeof(d.data)); 161 | 162 | if (!os_ipc_send(ipcc.data, IPC_SERVER, &d)) 163 | return false; 164 | 165 | if (!os_ipc_recv(ipcc.data, IPC_SERVER, &d) || d.cmd != IPC_DONE) 166 | return false; 167 | 168 | return true; 169 | } 170 | 171 | 172 | 173 | /*------------------------------------------------*/ 174 | /* function : ipc_recv_cmd */ 175 | /* description: Receives command to execute */ 176 | /*------------------------------------------------*/ 177 | 178 | bool ipc_recv_cmd(char * buf, size_t blen) 179 | { 180 | bool ret; 181 | idata_t d; 182 | size_t len; 183 | 184 | memset(d.data, '\0', sizeof(d.data)); 185 | 186 | ret = os_ipc_recv(ipcc.data, IPC_CLIENT, &d); 187 | if (!ret) 188 | return false; 189 | 190 | if (d.cmd != IPC_DATA) 191 | return false; 192 | 193 | len = strlen(d.data) + 1; 194 | if (len > blen) 195 | len = blen; 196 | 197 | memcpy(buf, d.data, len); 198 | 199 | return true; 200 | } 201 | 202 | 203 | /*------------------------------------------------*/ 204 | /* function : ipc_recv_cmd_end */ 205 | /* description: Acknowledges end of command */ 206 | /*------------------------------------------------*/ 207 | 208 | bool ipc_recv_cmd_end() 209 | { 210 | idata_t d; 211 | 212 | d.cmd = IPC_DONE; 213 | 214 | return os_ipc_send(ipcc.data, IPC_CLIENT, &d); 215 | } 216 | 217 | 218 | /*------------------------------------------------*/ 219 | /* function : ipc_execute_second_instance */ 220 | /* description: Sends command to the second IDA */ 221 | /* instance */ 222 | /*------------------------------------------------*/ 223 | 224 | static void ipc_execute_second_instance(char * idc, ea_t ea, char * file) 225 | { 226 | char cmd[QMAXPATH*4]; 227 | 228 | if (!ipc_init(file, 1, 0)) 229 | return; 230 | 231 | qsnprintf(cmd, sizeof(cmd), "%u:%a:%u:%s", 232 | 0, 233 | ea, 234 | dto.graph.s_showpref, 235 | idc 236 | ); 237 | 238 | ipc_send_cmd(cmd); 239 | } 240 | 241 | 242 | /*------------------------------------------------*/ 243 | /* function : system_parse_idb */ 244 | /* description: generates a list of signatures for*/ 245 | /* another idb */ 246 | /*------------------------------------------------*/ 247 | 248 | slist_t * system_parse_idb(ea_t ea, char * file, options_t * opt) 249 | { 250 | slist_t * sl = NULL; 251 | char tmpname[QMAXPATH]; 252 | 253 | os_tempnam(tmpname, sizeof(tmpname), ".idc"); 254 | 255 | if (!options_use_ipc(opt)) 256 | system_execute_second_instance(tmpname, ea, file, true, 0, NULL); 257 | else 258 | ipc_execute_second_instance(tmpname, ea, file); 259 | 260 | sl = siglist_load(tmpname); 261 | os_unlink(tmpname); 262 | 263 | return sl; 264 | } 265 | 266 | 267 | /*------------------------------------------------*/ 268 | /* function : system_get_pref */ 269 | /* description: Gets global system preference */ 270 | /*------------------------------------------------*/ 271 | 272 | bool system_get_pref(char * name, void * data, int type) 273 | { 274 | if (type == SPREF_INT) 275 | { 276 | return os_get_pref_int(name, (int *)data); 277 | } 278 | 279 | return false; 280 | } 281 | 282 | -------------------------------------------------------------------------------- /system.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Patchdiff3 3 | Portions (C) 2014 - 2014 namreeb (patchdiff@namreeb.org) 4 | Portions (C) 2010 - 2011 Nicolas Pouvesle 5 | Portions (C) 2007 - 2009 Tenable Network Security, Inc. 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License version 2 as 9 | published by the Free Software Foundation. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | 21 | #pragma once 22 | 23 | #include "sig.hpp" 24 | #include "options.hpp" 25 | 26 | #define PATCHDIFF_IDC "#include \n\nstatic main (void)\n{\n RunPlugin (\"patchdiff3\", 1);\n Exit(1);\n}\n" 27 | 28 | #define SPREF_INT 1 29 | 30 | #define IPC_DATA 0 31 | #define IPC_DONE 1 32 | #define IPC_END 3 33 | 34 | #define IPC_SERVER 1 35 | #define IPC_CLIENT 2 36 | 37 | 38 | struct ipc_config 39 | { 40 | long init; 41 | void * data; 42 | }; 43 | 44 | typedef struct ipc_config ipc_config_t; 45 | 46 | struct idata 47 | { 48 | long cmd; 49 | char data[256]; 50 | }; 51 | 52 | typedef struct idata idata_t; 53 | 54 | 55 | bool system_get_pref(char *, void *, int); 56 | slist_t * system_parse_idb(ea_t, char *, options_t *); 57 | 58 | bool ipc_init(char *, int, long); 59 | void ipc_close(); 60 | bool ipc_recv_cmd(char *, size_t); 61 | bool ipc_recv_cmd_end(); 62 | -------------------------------------------------------------------------------- /unix_fct.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Patchdiff3 3 | Portions (C) 2014 - 2014 namreeb (patchdiff@namreeb.org) 4 | Portions (C) 2010 Nicolas Pouvesle 5 | Portions (C) 2007 - 2009 Tenable Network Security, Inc. 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License version 2 as 9 | published by the Free Software Foundation. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | #include 26 | #include 27 | 28 | #include "unix_fct.hpp" 29 | #include "system.hpp" 30 | 31 | 32 | struct ipc_data 33 | { 34 | int spipe; 35 | int rpipe; 36 | char *sname; 37 | char *rname; 38 | pid_t pid; 39 | }; 40 | 41 | typedef struct ipc_data ipc_data_t; 42 | 43 | 44 | /*------------------------------------------------*/ 45 | /* function : create_process */ 46 | /* description: fork/exec */ 47 | /*------------------------------------------------*/ 48 | 49 | pid_t create_process(char * cmd) 50 | { 51 | pid_t pid; 52 | char * argv[4]; 53 | 54 | pid = fork(); 55 | if (pid == 0) 56 | { 57 | argv[0] = "/bin/sh"; 58 | argv[1] = "-c"; 59 | argv[2] = cmd; 60 | argv[3] = NULL; 61 | 62 | execvp(argv[0], argv); 63 | exit(EXIT_FAILURE); 64 | } 65 | 66 | return pid; 67 | } 68 | 69 | 70 | /*------------------------------------------------*/ 71 | /* function : os_execute_command */ 72 | /* description: Executes a command by creating a */ 73 | /* new process */ 74 | /*------------------------------------------------*/ 75 | 76 | int os_execute_command(char * cmd, bool close, void * data) 77 | { 78 | ipc_data_t * id = (ipc_data_t *)data; 79 | int ret = -1; 80 | int status; 81 | pid_t pid; 82 | 83 | pid = create_process(cmd); 84 | if (pid == -1) return -1; 85 | 86 | if (close) 87 | { 88 | /* we wait until the process finished (IE: sig file is generated) */ 89 | if (waitpid(pid, &status, 0) == -1) 90 | return -1; 91 | } 92 | else 93 | id->pid = pid; 94 | 95 | return 0; 96 | } 97 | 98 | 99 | /*------------------------------------------------*/ 100 | /* function : os_check_process */ 101 | /* description: checks process state */ 102 | /*------------------------------------------------*/ 103 | 104 | bool os_check_process(pid_t pid) 105 | { 106 | if (kill(pid, 0) == 0) 107 | return true; 108 | 109 | return false; 110 | } 111 | 112 | 113 | /*------------------------------------------------*/ 114 | /* function : os_copy_to_clipboard */ 115 | /* description: Copies data to clipboard */ 116 | /*------------------------------------------------*/ 117 | 118 | void os_copy_to_clipboard(char * data) 119 | { 120 | } 121 | 122 | 123 | /*------------------------------------------------*/ 124 | /* function : os_get_pid */ 125 | /* description: Returns process ID */ 126 | /*------------------------------------------------*/ 127 | 128 | long os_get_pid() 129 | { 130 | return (long)getpid(); 131 | } 132 | 133 | 134 | /*------------------------------------------------*/ 135 | /* function : os_unlink */ 136 | /* description: removes a link to a file */ 137 | /*------------------------------------------------*/ 138 | 139 | int os_unlink(const char * path) 140 | { 141 | return unlink(path); 142 | } 143 | 144 | 145 | /*------------------------------------------------*/ 146 | /* function : os_tempnam */ 147 | /* description: returns a temporary file name */ 148 | /*------------------------------------------------*/ 149 | 150 | void os_tempnam(char * data, size_t size, char * suffix) 151 | { 152 | char * str; 153 | 154 | str = tempnam(NULL, NULL); 155 | qsnprintf(data, size, "%s%s", str, suffix); 156 | } 157 | 158 | 159 | /*------------------------------------------------*/ 160 | /* function : os_ipc_send */ 161 | /* description: Sends data on pipe */ 162 | /*------------------------------------------------*/ 163 | 164 | bool os_ipc_send(void * data, int type, idata_t * d) 165 | { 166 | ipc_data_t * id = (ipc_data_t *)data; 167 | ssize_t num; 168 | 169 | num = write(id->spipe, d, sizeof(*d)); 170 | if (num > 0) return true; 171 | 172 | return false; 173 | } 174 | 175 | 176 | /*------------------------------------------------*/ 177 | /* function : os_ipc_recv */ 178 | /* description: Receives data on pipe */ 179 | /*------------------------------------------------*/ 180 | 181 | bool os_ipc_recv(void * data, int type, idata_t * d) 182 | { 183 | ipc_data_t * id = (ipc_data_t *)data; 184 | fd_set rfds, efds; 185 | struct timeval tv; 186 | int ret; 187 | 188 | tv.tv_sec = 0; 189 | tv.tv_usec = 1000; 190 | 191 | if (id->pid) 192 | { 193 | while (1) 194 | { 195 | FD_ZERO(&rfds); 196 | FD_SET(id->rpipe, &rfds); 197 | 198 | FD_ZERO(&efds); 199 | FD_SET(id->rpipe, &efds); 200 | 201 | ret = select(id->rpipe+1, &rfds, NULL, &efds, &tv); 202 | if (ret > 0 && FD_ISSET(id->rpipe, &rfds)) 203 | break; 204 | 205 | if (ret < 0 || (ret > 0 && FD_ISSET(id->rpipe, &efds)) || !os_check_process(id->pid)) 206 | return false; 207 | } 208 | } 209 | else 210 | { 211 | FD_ZERO(&rfds); 212 | FD_SET(id->rpipe, &rfds); 213 | 214 | FD_ZERO(&efds); 215 | FD_SET(id->rpipe, &efds); 216 | 217 | ret = select(id->rpipe+1, &rfds, NULL, &efds, NULL); 218 | if (!(ret > 0 && FD_ISSET(id->rpipe, &rfds))) 219 | return false; 220 | } 221 | 222 | read(id->rpipe, d, sizeof(*d)); 223 | 224 | return true; 225 | } 226 | 227 | 228 | /*------------------------------------------------*/ 229 | /* function : os_ipc_init */ 230 | /* description: Inits interprocess communication */ 231 | /*------------------------------------------------*/ 232 | 233 | bool os_ipc_init(void ** data, long pid, int type) 234 | { 235 | char sname[512]; 236 | char rname[512]; 237 | ipc_data_t * id; 238 | 239 | id = (ipc_data_t *)qalloc(sizeof(*id)); 240 | if (!id) 241 | return false; 242 | 243 | memset(id, '\0', sizeof(*id)); 244 | 245 | qsnprintf(sname, sizeof(sname), "/tmp/pdiff2spipe%u", pid); 246 | qsnprintf(rname, sizeof(rname), "/tmp/pdiff2rpipe%u", pid); 247 | 248 | id->sname = qstrdup(sname); 249 | id->rname = qstrdup(rname); 250 | 251 | if (type == IPC_SERVER) 252 | { 253 | mkfifo(sname, 0666); 254 | id->spipe = open(sname, O_RDWR|O_NONBLOCK); 255 | if (id->spipe == -1) goto error; 256 | 257 | mkfifo(rname, 0666); 258 | id->rpipe = open(rname, O_RDWR|O_NONBLOCK); 259 | if (id->rpipe == -1) goto error; 260 | } 261 | else 262 | { 263 | id->spipe = open(rname, O_WRONLY); 264 | if (id->spipe == -1) goto error; 265 | 266 | id->rpipe = open(sname, O_RDONLY); 267 | if (id->rpipe == -1) goto error; 268 | } 269 | 270 | *data = (void *)id; 271 | return true; 272 | 273 | error: 274 | if (id->spipe) close(id->spipe); 275 | if (id->rpipe) close(id->rpipe); 276 | qfree(id); 277 | return false; 278 | } 279 | 280 | 281 | /*------------------------------------------------*/ 282 | /* function : os_ipc_close */ 283 | /* description: Closes IPC */ 284 | /*------------------------------------------------*/ 285 | 286 | bool os_ipc_close(void * data) 287 | { 288 | ipc_data_t * id = (ipc_data_t *)data; 289 | 290 | if (id->spipe) close(id->spipe); 291 | if (id->rpipe) close(id->rpipe); 292 | 293 | os_unlink(id->sname); 294 | os_unlink(id->rname); 295 | return true; 296 | } 297 | 298 | 299 | /*------------------------------------------------*/ 300 | /* function : os_get_pref_int */ 301 | /* description: Gets system preferences (integer) */ 302 | /*------------------------------------------------*/ 303 | 304 | bool os_get_pref_int(char * name, int * i) 305 | { 306 | *i = 0; 307 | return false; 308 | } 309 | -------------------------------------------------------------------------------- /unix_fct.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Patchdiff3 3 | Portions (C) 2014 - 2014 namreeb (patchdiff@namreeb.org) 4 | Portions (C) 2010 Nicolas Pouvesle 5 | Portions (C) 2007 - 2009 Tenable Network Security, Inc. 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License version 2 as 9 | published by the Free Software Foundation. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "system.hpp" 23 | 24 | #ifdef __EA64__ 25 | #define IDA_EXEC "idaq64" 26 | #else 27 | #define IDA_EXEC "idaq" 28 | #endif 29 | 30 | 31 | // Preference functions 32 | bool os_get_pref_int(char *, int *); 33 | 34 | // System functions 35 | int os_execute_command(char *, bool, void *); 36 | void os_copy_to_clipboard(char *); 37 | long os_get_pid(); 38 | int os_unlink(const char *path); 39 | void os_tempnam(char *, size_t, char *); 40 | 41 | // Shared memory functions 42 | bool os_ipc_send(void *, int, idata_t *); 43 | bool os_ipc_recv(void *, int, idata_t *); 44 | bool os_ipc_init(void **, long, int); 45 | bool os_ipc_close(void *); 46 | -------------------------------------------------------------------------------- /vs/.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.sln.docstates 8 | 9 | # Build results 10 | [Dd]ebug/ 11 | [Dd]ebugPublic/ 12 | [Rr]elease/ 13 | [Rr]eleases/ 14 | x64/ 15 | x86/ 16 | build/ 17 | bld/ 18 | [Bb]in/ 19 | [Oo]bj/ 20 | 21 | # Roslyn cache directories 22 | *.ide/ 23 | 24 | # MSTest test Results 25 | [Tt]est[Rr]esult*/ 26 | [Bb]uild[Ll]og.* 27 | 28 | #NUNIT 29 | *.VisualState.xml 30 | TestResult.xml 31 | 32 | # Build Results of an ATL Project 33 | [Dd]ebugPS/ 34 | [Rr]eleasePS/ 35 | dlldata.c 36 | 37 | *_i.c 38 | *_p.c 39 | *_i.h 40 | *.ilk 41 | *.meta 42 | *.obj 43 | *.pch 44 | *.pdb 45 | *.pgc 46 | *.pgd 47 | *.rsp 48 | *.sbr 49 | *.tlb 50 | *.tli 51 | *.tlh 52 | *.tmp 53 | *.tmp_proj 54 | *.log 55 | *.vspscc 56 | *.vssscc 57 | .builds 58 | *.pidb 59 | *.svclog 60 | *.scc 61 | 62 | # Chutzpah Test files 63 | _Chutzpah* 64 | 65 | # Visual C++ cache files 66 | ipch/ 67 | *.aps 68 | *.ncb 69 | *.opensdf 70 | *.sdf 71 | *.cachefile 72 | 73 | # Visual Studio profiler 74 | *.psess 75 | *.vsp 76 | *.vspx 77 | 78 | # TFS 2012 Local Workspace 79 | $tf/ 80 | 81 | # Guidance Automation Toolkit 82 | *.gpState 83 | 84 | # ReSharper is a .NET coding add-in 85 | _ReSharper*/ 86 | *.[Rr]e[Ss]harper 87 | *.DotSettings.user 88 | 89 | # JustCode is a .NET coding addin-in 90 | .JustCode 91 | 92 | # TeamCity is a build add-in 93 | _TeamCity* 94 | 95 | # DotCover is a Code Coverage Tool 96 | *.dotCover 97 | 98 | # NCrunch 99 | _NCrunch_* 100 | .*crunch*.local.xml 101 | 102 | # MightyMoose 103 | *.mm.* 104 | AutoTest.Net/ 105 | 106 | # Web workbench (sass) 107 | .sass-cache/ 108 | 109 | # Installshield output folder 110 | [Ee]xpress/ 111 | 112 | # DocProject is a documentation generator add-in 113 | DocProject/buildhelp/ 114 | DocProject/Help/*.HxT 115 | DocProject/Help/*.HxC 116 | DocProject/Help/*.hhc 117 | DocProject/Help/*.hhk 118 | DocProject/Help/*.hhp 119 | DocProject/Help/Html2 120 | DocProject/Help/html 121 | 122 | # Click-Once directory 123 | publish/ 124 | 125 | # Publish Web Output 126 | *.[Pp]ublish.xml 127 | *.azurePubxml 128 | # TODO: Comment the next line if you want to checkin your web deploy settings 129 | # but database connection strings (with potential passwords) will be unencrypted 130 | *.pubxml 131 | *.publishproj 132 | 133 | # NuGet Packages 134 | *.nupkg 135 | # The packages folder can be ignored because of Package Restore 136 | **/packages/* 137 | # except build/, which is used as an MSBuild target. 138 | !**/packages/build/ 139 | # If using the old MSBuild-Integrated Package Restore, uncomment this: 140 | #!**/packages/repositories.config 141 | 142 | # Windows Azure Build Output 143 | csx/ 144 | *.build.csdef 145 | 146 | # Windows Store app package directory 147 | AppPackages/ 148 | 149 | # Others 150 | sql/ 151 | *.Cache 152 | ClientBin/ 153 | [Ss]tyle[Cc]op.* 154 | ~$* 155 | *~ 156 | *.dbmdl 157 | *.dbproj.schemaview 158 | *.pfx 159 | *.publishsettings 160 | node_modules/ 161 | 162 | # RIA/Silverlight projects 163 | Generated_Code/ 164 | 165 | # Backup & report files from converting an old project file 166 | # to a newer Visual Studio version. Backup files are not needed, 167 | # because we have git ;-) 168 | _UpgradeReport_Files/ 169 | Backup*/ 170 | UpgradeLog*.XML 171 | UpgradeLog*.htm 172 | 173 | # SQL Server files 174 | *.mdf 175 | *.ldf 176 | 177 | # Business Intelligence projects 178 | *.rdl.data 179 | *.bim.layout 180 | *.bim_*.settings 181 | 182 | # Microsoft Fakes 183 | FakesAssemblies/ 184 | -------------------------------------------------------------------------------- /vs/ida_64_override.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | .p64 7 | 8 | 9 | 10 | __EA64__;%(PreprocessorDefinitions) 11 | 12 | 13 | $(IDASDK_DIR)lib\x86_win_vc_64 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /vs/ida_base.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | .plw 7 | <_PropertySheetDisplayName>ida_base 8 | false 9 | 10 | 11 | 12 | $(IDASDK_DIR)include;%(AdditionalIncludeDirectories) 13 | __NT__;__IDP__;%(PreprocessorDefinitions) 14 | MultiThreadedDebug 15 | Use 16 | precomp.hpp 17 | 18 | 19 | $(IDASDK_DIR)lib\x86_win_vc_32;%(AdditionalLibraryDirectories) 20 | ida.lib;%(AdditionalDependencies) 21 | /EXPORT:PLUGIN %(AdditionalOptions) 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /vs/patchdiff3.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.21005.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "patchdiff3", "patchdiff3.vcxproj", "{CD825DE7-06F6-482D-82FE-3D20B1B04228}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Win32 = Debug|Win32 11 | Debug64|Win32 = Debug64|Win32 12 | Release|Win32 = Release|Win32 13 | Release64|Win32 = Release64|Win32 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {CD825DE7-06F6-482D-82FE-3D20B1B04228}.Debug|Win32.ActiveCfg = Debug|Win32 17 | {CD825DE7-06F6-482D-82FE-3D20B1B04228}.Debug|Win32.Build.0 = Debug|Win32 18 | {CD825DE7-06F6-482D-82FE-3D20B1B04228}.Debug64|Win32.ActiveCfg = Debug64|Win32 19 | {CD825DE7-06F6-482D-82FE-3D20B1B04228}.Debug64|Win32.Build.0 = Debug64|Win32 20 | {CD825DE7-06F6-482D-82FE-3D20B1B04228}.Release|Win32.ActiveCfg = Release|Win32 21 | {CD825DE7-06F6-482D-82FE-3D20B1B04228}.Release|Win32.Build.0 = Release|Win32 22 | {CD825DE7-06F6-482D-82FE-3D20B1B04228}.Release64|Win32.ActiveCfg = Release64|Win32 23 | {CD825DE7-06F6-482D-82FE-3D20B1B04228}.Release64|Win32.Build.0 = Release64|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /vs/patchdiff3.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug64 6 | Win32 7 | 8 | 9 | Debug 10 | Win32 11 | 12 | 13 | Release64 14 | Win32 15 | 16 | 17 | Release 18 | Win32 19 | 20 | 21 | 22 | {CD825DE7-06F6-482D-82FE-3D20B1B04228} 23 | Win32Proj 24 | patchdiff3 25 | 26 | 27 | 28 | DynamicLibrary 29 | true 30 | v100 31 | MultiByte 32 | 33 | 34 | DynamicLibrary 35 | true 36 | v100 37 | MultiByte 38 | 39 | 40 | DynamicLibrary 41 | false 42 | v100 43 | true 44 | MultiByte 45 | 46 | 47 | DynamicLibrary 48 | false 49 | v100 50 | true 51 | MultiByte 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | true 77 | 78 | 79 | true 80 | 81 | 82 | false 83 | 84 | 85 | false 86 | 87 | 88 | 89 | 90 | 91 | Level3 92 | Disabled 93 | WIN32;_DEBUG;_WINDOWS;_USRDLL;PATCHDIFF3_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) 94 | 95 | 96 | Windows 97 | true 98 | /EXPORT:PLUGIN %(AdditionalOptions) 99 | 100 | 101 | 102 | 103 | 104 | 105 | Level3 106 | Disabled 107 | WIN32;_DEBUG;_WINDOWS;_USRDLL;PATCHDIFF3_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) 108 | 109 | 110 | Windows 111 | true 112 | /EXPORT:PLUGIN %(AdditionalOptions) 113 | 114 | 115 | 116 | 117 | Level3 118 | 119 | 120 | MaxSpeed 121 | true 122 | true 123 | WIN32;NDEBUG;_WINDOWS;_USRDLL;PATCHDIFF3_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) 124 | 125 | 126 | Windows 127 | true 128 | true 129 | true 130 | /EXPORT:PLUGIN %(AdditionalOptions) 131 | 132 | 133 | 134 | 135 | Level3 136 | 137 | 138 | MaxSpeed 139 | true 140 | true 141 | WIN32;NDEBUG;_WINDOWS;_USRDLL;PATCHDIFF3_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) 142 | 143 | 144 | Windows 145 | true 146 | true 147 | true 148 | /EXPORT:PLUGIN %(AdditionalOptions) 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | true 169 | true 170 | true 171 | true 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | Create 190 | Create 191 | Create 192 | Create 193 | 194 | 195 | 196 | 197 | true 198 | true 199 | true 200 | true 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | -------------------------------------------------------------------------------- /vs/patchdiff3.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | Header Files 32 | 33 | 34 | Header Files 35 | 36 | 37 | Header Files 38 | 39 | 40 | Header Files 41 | 42 | 43 | Header Files 44 | 45 | 46 | Header Files 47 | 48 | 49 | Header Files 50 | 51 | 52 | Header Files 53 | 54 | 55 | Header Files 56 | 57 | 58 | Header Files 59 | 60 | 61 | Header Files 62 | 63 | 64 | Header Files 65 | 66 | 67 | Header Files 68 | 69 | 70 | Header Files 71 | 72 | 73 | 74 | 75 | Source Files 76 | 77 | 78 | Source Files 79 | 80 | 81 | Source Files 82 | 83 | 84 | Source Files 85 | 86 | 87 | Source Files 88 | 89 | 90 | Source Files 91 | 92 | 93 | Source Files 94 | 95 | 96 | Source Files 97 | 98 | 99 | Source Files 100 | 101 | 102 | Source Files 103 | 104 | 105 | Source Files 106 | 107 | 108 | Source Files 109 | 110 | 111 | Source Files 112 | 113 | 114 | Source Files 115 | 116 | 117 | Source Files 118 | 119 | 120 | Source Files 121 | 122 | 123 | Source Files 124 | 125 | 126 | 127 | 128 | Resource Files 129 | 130 | 131 | 132 | 133 | Resource Files 134 | 135 | 136 | -------------------------------------------------------------------------------- /win_fct.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Patchdiff3 3 | Portions (C) 2014 - 2014 namreeb (patchdiff@namreeb.org) 4 | Portions (C) 2010 - 2011 Nicolas Pouvesle 5 | Portions (C) 2007 - 2009 Tenable Network Security, Inc. 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License version 2 as 9 | published by the Free Software Foundation. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | 21 | // Must be included before idp.hpp 22 | #include 23 | #include "precomp.hpp" 24 | 25 | #include "win_fct.hpp" 26 | #include "system.hpp" 27 | 28 | 29 | struct ipc_data 30 | { 31 | HANDLE shared; 32 | idata_t * memory; 33 | HANDLE slock; 34 | HANDLE rlock; 35 | HANDLE process; 36 | }; 37 | 38 | typedef struct ipc_data ipc_data_t; 39 | 40 | 41 | 42 | /*------------------------------------------------*/ 43 | /* function : os_execute_command */ 44 | /* description: Executes a command by creating a */ 45 | /* new process */ 46 | /*------------------------------------------------*/ 47 | 48 | int os_execute_command(char * cmd, bool close, void * data) 49 | { 50 | STARTUPINFO si; 51 | PROCESS_INFORMATION pi; 52 | int ret = -1; 53 | ipc_data_t * id = (ipc_data_t *)data; 54 | 55 | ZeroMemory( &si, sizeof(STARTUPINFO) ); 56 | si.cb = sizeof(STARTUPINFO); 57 | si.hStdError = GetStdHandle(STD_ERROR_HANDLE); 58 | si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); 59 | si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); 60 | si.dwFlags |= STARTF_USESTDHANDLES; 61 | 62 | if (CreateProcess( 63 | NULL, 64 | cmd, // command line 65 | NULL, // process security 66 | NULL, // thread security 67 | FALSE, // inherit handles-yes 68 | 0, // creation flags 69 | NULL, // environment block 70 | NULL, // current directory 71 | &si, // startup info 72 | &pi)) // process info (out) 73 | { 74 | if (close) 75 | { 76 | /* we wait until the process finished (IE: sig file is generated) */ 77 | if (WaitForSingleObject( pi.hProcess, INFINITE ) == WAIT_OBJECT_0) 78 | ret = 0; 79 | 80 | CloseHandle(pi.hProcess); 81 | } 82 | else 83 | { 84 | id->process = pi.hProcess; 85 | ret = 0; 86 | } 87 | 88 | CloseHandle(pi.hThread); 89 | } 90 | 91 | return ret; 92 | } 93 | 94 | 95 | /*------------------------------------------------*/ 96 | /* function : os_check_process */ 97 | /* description: checks process state */ 98 | /*------------------------------------------------*/ 99 | 100 | static bool os_check_process(void * handle) 101 | { 102 | DWORD exitcode; 103 | 104 | if (GetExitCodeProcess((HANDLE)handle, &exitcode) && exitcode == STILL_ACTIVE) 105 | return true; 106 | 107 | return false; 108 | } 109 | 110 | 111 | /*------------------------------------------------*/ 112 | /* function : os_copy_to_clipboard */ 113 | /* description: Copies data to clipboard */ 114 | /*------------------------------------------------*/ 115 | 116 | void os_copy_to_clipboard(char * data) 117 | { 118 | } 119 | 120 | 121 | /*------------------------------------------------*/ 122 | /* function : os_get_pid */ 123 | /* description: Returns process ID */ 124 | /*------------------------------------------------*/ 125 | 126 | long os_get_pid() 127 | { 128 | return (long)GetCurrentProcessId(); 129 | } 130 | 131 | 132 | /*------------------------------------------------*/ 133 | /* function : os_unlink */ 134 | /* description: removes a link to a file */ 135 | /*------------------------------------------------*/ 136 | 137 | int os_unlink(const char * path) 138 | { 139 | return _unlink(path); 140 | } 141 | 142 | 143 | /*------------------------------------------------*/ 144 | /* function : os_tempnam */ 145 | /* description: returns a temporary file name */ 146 | /*------------------------------------------------*/ 147 | 148 | void os_tempnam(char * data, size_t size, char * suffix) 149 | { 150 | char tmp[MAX_PATH]; 151 | char name[MAX_PATH]; 152 | 153 | GetTempPath(sizeof(tmp), tmp); 154 | GetTempFileName(tmp, NULL, 0, name); 155 | qsnprintf(data, size, "%s%s", name, (suffix) ? suffix: ""); 156 | } 157 | 158 | 159 | /*------------------------------------------------*/ 160 | /* function : os_ipc_send */ 161 | /* description: Sends data on pipe */ 162 | /*------------------------------------------------*/ 163 | 164 | bool os_ipc_send(void * data, int type, idata_t * d) 165 | { 166 | ipc_data_t * id = (ipc_data_t *)data; 167 | HANDLE lock; 168 | 169 | memcpy(id->memory, d, sizeof(*id->memory)); 170 | 171 | lock = (type == IPC_SERVER) ? id->slock : id->rlock; 172 | 173 | return SetEvent(lock) == TRUE; 174 | } 175 | 176 | 177 | /*------------------------------------------------*/ 178 | /* function : os_ipc_recv */ 179 | /* description: Receives data on pipe */ 180 | /*------------------------------------------------*/ 181 | 182 | bool os_ipc_recv(void * data, int type, idata_t * d) 183 | { 184 | ipc_data_t * id = (ipc_data_t *)data; 185 | HANDLE lock; 186 | DWORD ret; 187 | 188 | lock = (type == IPC_SERVER) ? id->rlock : id->slock; 189 | 190 | if (id->process) 191 | { 192 | while (1) 193 | { 194 | ret = WaitForSingleObject((HANDLE)lock, 1000); 195 | 196 | if (ret == WAIT_OBJECT_0) 197 | break; 198 | 199 | if (ret != WAIT_TIMEOUT || !os_check_process(id->process)) 200 | return false; 201 | } 202 | } 203 | else 204 | { 205 | if (WaitForSingleObject((HANDLE)lock, INFINITE) != WAIT_OBJECT_0) 206 | return false; 207 | } 208 | 209 | memcpy(d, id->memory, sizeof(*d)); 210 | 211 | return true; 212 | } 213 | 214 | 215 | /*------------------------------------------------*/ 216 | /* function : os_ipc_init */ 217 | /* description: Inits interprocess communication */ 218 | /*------------------------------------------------*/ 219 | 220 | bool os_ipc_init(void ** data, long pid, int type) 221 | { 222 | char name[512]; 223 | ipc_data_t * id; 224 | 225 | id = (ipc_data_t *)qalloc(sizeof(*id)); 226 | if (!id) 227 | return false; 228 | 229 | memset(id, '\0', sizeof(*id)); 230 | 231 | qsnprintf(name, sizeof(name), "pdiff2_slock%u", pid); 232 | id->slock = CreateEvent(NULL, false, false, name); 233 | if (!id->slock) 234 | goto error; 235 | 236 | qsnprintf(name, sizeof(name), "pdiff2_rlock%u", pid); 237 | id->rlock = CreateEvent(NULL, false, false, name); 238 | if (!id->rlock) 239 | goto error; 240 | 241 | qsnprintf(name, sizeof(name), "pdiff2_sharedmemory%u", pid); 242 | if (type == IPC_SERVER) 243 | { 244 | id->shared = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(idata_t), name); 245 | if (!id->shared) 246 | goto error; 247 | } 248 | else 249 | { 250 | id->shared = OpenFileMapping(FILE_MAP_ALL_ACCESS,false,name); 251 | if (!id->shared) 252 | goto error; 253 | } 254 | 255 | id->memory = (idata_t *)MapViewOfFile(id->shared, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(idata_t)); 256 | if (!id->memory) 257 | goto error; 258 | 259 | *data = (void *)id; 260 | return true; 261 | 262 | error: 263 | if (id->slock) CloseHandle(id->slock); 264 | if (id->rlock) CloseHandle(id->rlock); 265 | if (id->shared) CloseHandle(id->shared); 266 | qfree(id); 267 | return false; 268 | } 269 | 270 | 271 | /*------------------------------------------------*/ 272 | /* function : os_ipc_close */ 273 | /* description: Closes IPC */ 274 | /*------------------------------------------------*/ 275 | 276 | bool os_ipc_close(void * data) 277 | { 278 | ipc_data_t * id = (ipc_data_t *)data; 279 | 280 | if (id->slock) {SetEvent(id->slock); CloseHandle(id->slock);} 281 | if (id->rlock) {SetEvent(id->rlock); CloseHandle(id->rlock);} 282 | if (id->memory) UnmapViewOfFile((void *)id->memory); 283 | if (id->shared) CloseHandle(id->shared); 284 | if (id->process) CloseHandle(id->process); 285 | 286 | return true; 287 | } 288 | 289 | 290 | /*------------------------------------------------*/ 291 | /* function : os_get_pref_int */ 292 | /* description: Gets system preferences (integer) */ 293 | /*------------------------------------------------*/ 294 | 295 | bool os_get_pref_int(char * name, int * i) 296 | { 297 | HKEY key; 298 | DWORD type; 299 | DWORD size; 300 | int tmp; 301 | long ret; 302 | 303 | ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Tenable\\PatchDiff3", 0, KEY_READ, &key); 304 | if (ret != ERROR_SUCCESS) 305 | return false; 306 | 307 | size = sizeof(tmp); 308 | ret = RegQueryValueEx(key, name, NULL, &type, (LPBYTE)&tmp, &size); 309 | RegCloseKey(key); 310 | 311 | if (ret != ERROR_SUCCESS || type != REG_DWORD) 312 | return false; 313 | 314 | *i = tmp; 315 | return true; 316 | } 317 | -------------------------------------------------------------------------------- /win_fct.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Patchdiff3 3 | Portions (C) 2014 - 2014 namreeb (patchdiff@namreeb.org) 4 | Portions (C) 2010 - 2011 Nicolas Pouvesle 5 | Portions (C) 2007 - 2009 Tenable Network Security, Inc. 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License version 2 as 9 | published by the Free Software Foundation. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | 21 | #pragma once 22 | 23 | #include "system.hpp" 24 | 25 | #ifdef __EA64__ 26 | #define IDA_EXEC "idaq64.exe" 27 | #else 28 | #define IDA_EXEC "idaq.exe" 29 | #endif 30 | 31 | 32 | // Preference functions 33 | bool os_get_pref_int(char *, int *); 34 | 35 | // System functions 36 | int os_execute_command(char *, bool, void *); 37 | void os_copy_to_clipboard(char *); 38 | long os_get_pid(); 39 | int os_unlink(const char *path); 40 | void os_tempnam(char *, size_t, char *); 41 | 42 | // Shared memory functions 43 | bool os_ipc_send(void *, int, idata_t *); 44 | bool os_ipc_recv(void *, int, idata_t *); 45 | bool os_ipc_init(void **, long, int); 46 | bool os_ipc_close(void *); 47 | -------------------------------------------------------------------------------- /x86.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Patchdiff3 3 | Portions (C) 2014 - 2014 namreeb (patchdiff@namreeb.org) 4 | Portions (C) 2010 - 2011 Nicolas Pouvesle 5 | Portions (C) 2007 - 2009 Tenable Network Security, Inc. 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License version 2 as 9 | published by the Free Software Foundation. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | 21 | #include "precomp.hpp" 22 | 23 | #include "x86.hpp" 24 | #include "patchdiff.hpp" 25 | 26 | extern cpu_t patchdiff_cpu; 27 | 28 | 29 | /*------------------------------------------------*/ 30 | /* function : x86_is_rex_prefix */ 31 | /* arguments: unsigned char val */ 32 | /* description: detects if instruction is a Rex */ 33 | /* prefix */ 34 | /*------------------------------------------------*/ 35 | 36 | bool x86_is_rex_prefix(unsigned char val) 37 | { 38 | if (val >= 0x40 && val <= 0x4F) 39 | return true; 40 | 41 | return false; 42 | } 43 | 44 | 45 | /*------------------------------------------------*/ 46 | /* function : x86_is_push_register */ 47 | /* arguments: unsigned char val */ 48 | /* description: detects if instruction is push reg*/ 49 | /*------------------------------------------------*/ 50 | 51 | bool x86_is_push_register (unsigned char val) 52 | { 53 | switch (val) 54 | { 55 | case 0x50: // push eax 56 | case 0x51: // push ecx 57 | case 0x52: // push edx 58 | case 0x53: // push ebx 59 | case 0x54: // push esp 60 | case 0x55: // push ebp 61 | case 0x56: // push esi 62 | case 0x57: // push edi 63 | return 1; 64 | 65 | default: 66 | return 0; 67 | } 68 | } 69 | 70 | /*------------------------------------------------*/ 71 | /* function : x86_is_pop_register */ 72 | /* arguments: unsigned char val */ 73 | /* description: detects if instruction is pop reg */ 74 | /*------------------------------------------------*/ 75 | 76 | bool x86_is_pop_register (unsigned char val) 77 | { 78 | switch (val) 79 | { 80 | case 0x58: // pop eax 81 | case 0x59: // pop ecx 82 | case 0x5A: // pop edx 83 | case 0x5B: // pop ebx 84 | case 0x5C: // pop esp 85 | case 0x5D: // pop ebp 86 | case 0x5E: // pop esi 87 | case 0x5F: // pop edi 88 | return 1; 89 | 90 | default: 91 | return 0; 92 | } 93 | } 94 | 95 | 96 | /*------------------------------------------------*/ 97 | /* function : x86_is_inc_register */ 98 | /* arguments: unsigned char val */ 99 | /* description: detects if instruction is inc reg */ 100 | /*------------------------------------------------*/ 101 | 102 | bool x86_is_inc_register (unsigned char val) 103 | { 104 | switch (val) 105 | { 106 | case 0x40: // inc eax 107 | case 0x41: // inc ecx 108 | case 0x42: // inc edx 109 | case 0x43: // inc ebx 110 | case 0x44: // inc esp 111 | case 0x45: // inc ebp 112 | case 0x46: // inc esi 113 | case 0x47: // inc edi 114 | return 1; 115 | 116 | default: 117 | return 0; 118 | } 119 | } 120 | 121 | /*------------------------------------------------*/ 122 | /* function : x86_is_dec_register */ 123 | /* arguments: unsigned char val */ 124 | /* description: detects if instruction is dec reg */ 125 | /*------------------------------------------------*/ 126 | 127 | bool x86_is_dec_register (unsigned char val) 128 | { 129 | switch (val) 130 | { 131 | case 0x48: // dec eax 132 | case 0x49: // dec ecx 133 | case 0x4A: // dec edx 134 | case 0x4B: // dec ebx 135 | case 0x4C: // dec esp 136 | case 0x4D: // dec ebp 137 | case 0x4E: // dec esi 138 | case 0x4F: // dec edi 139 | return 1; 140 | 141 | default: 142 | return 0; 143 | } 144 | } 145 | 146 | 147 | 148 | 149 | /*------------------------------------------------*/ 150 | /* function : is_nop */ 151 | /* arguments: unsigned char _byte */ 152 | /* description: detect if instruction is nop */ 153 | /* (nop, mov reg, reg, ...) */ 154 | /*------------------------------------------------*/ 155 | 156 | bool x86_is_nop (unsigned char _byte, ea_t ea) 157 | { 158 | unsigned char val; 159 | unsigned short val2; 160 | unsigned long val3; 161 | 162 | if (patchdiff_cpu == CPU_X8664 && x86_is_rex_prefix(_byte)) 163 | { 164 | ea++; 165 | _byte = get_byte(ea+1); 166 | } 167 | 168 | // mov reg, reg - xchg reg, reg 169 | if (_byte == 0x8A || _byte == 0x8B || _byte == 0x87 || _byte == 0x86) 170 | { 171 | val = get_byte(ea+1); 172 | if ( (val == 0xC0) || // mov eax, eax (al, al) 173 | (val == 0xC9) || // mov ecx, ecx 174 | (val == 0xDB) || // mov ebx, ebx 175 | (val == 0xD2) || // mov edx, edx 176 | (val == 0xF6) || // mov esi, esi 177 | (val == 0xFF) || // mov edi, edi 178 | (val == 0xE4) || // mov esp, esp 179 | (val == 0xED) ) // mov ebp, ebp 180 | return true; 181 | } 182 | if (_byte == 0x8D) 183 | { 184 | val = get_byte(ea+1); 185 | if ( (val == 0x00) || // lea eax, [eax] 186 | (val == 0x09) || // lea ecx, [ecx] 187 | (val == 0x42) || // lea edx, [edx] 188 | (val == 0x4b) || // lea ebx, [ebx] 189 | (val == 0x36) || // lea esi, [esi] 190 | (val == 0x3f) ) // lea edi, [edi] 191 | { 192 | return true; 193 | } 194 | else if ( (val == 0x40) || // lea eax, [eax+0] 195 | (val == 0x49) || // lea ecx, [ecx+0] 196 | (val == 0x52) || // lea edx, [edx+0] 197 | (val == 0x5b) || // lea ebx, [ebx+0] 198 | (val == 0x6d) || // lea ebp, [ebp+0] 199 | (val == 0x76) || // lea esi, [esi+0] 200 | (val == 0x7f) ) // lea edi, [edi+0] 201 | { 202 | val = get_byte(ea+2); 203 | if (val == 0x00) 204 | return true; 205 | } 206 | else if ( (val == 0x80) || // lea eax, [eax+0x00000000] 207 | (val == 0x89) || // lea ecx, [ecx+0x00000000] 208 | (val == 0x92) || // lea edx, [edx+0x00000000] 209 | (val == 0x9b) || // lea ebx, [ebx+0x00000000] 210 | (val == 0xad) || // lea ebp, [ebp+0x00000000] 211 | (val == 0xB6) || // lea esi, [esi+0x00000000] 212 | (val == 0xBf) ) // lea edi, [edi+0x00000000] 213 | { 214 | val3 = get_long(ea+2); 215 | if (val3 == 0x00) 216 | return true; 217 | } 218 | else if (val == 0xb4) 219 | { 220 | val = get_byte(ea+2); 221 | if (val == 0x26) 222 | { 223 | val3 = get_long(ea+3); 224 | if (val3 == 0x00) // lea esi, [esi+0x00000000] 225 | return true; 226 | } 227 | } 228 | else if (val == 0x24) 229 | { 230 | val = get_byte(ea+2); 231 | if (val == 0x24) // lea esp, [esp] 232 | return true; 233 | } 234 | else if (val == 0x64) 235 | { 236 | val2 = get_word(ea+2); 237 | if (val2 == 0x24) // lea esp, [esp+0] 238 | return true; 239 | } 240 | else if (val == 0xa4) 241 | { 242 | val = get_byte(ea+2); 243 | if (val == 0x24) 244 | { 245 | val3 = get_long(ea+3); 246 | if (val3 == 0x00) // lea esp, [esp+0x00000000] 247 | return true; 248 | } 249 | } 250 | } 251 | 252 | // nop 253 | if (_byte == 0x90) 254 | return true; 255 | 256 | return false; 257 | } 258 | 259 | 260 | /*------------------------------------------------*/ 261 | /* function : x86_remove_instr */ 262 | /* arguments: unsigned char byte, ea_t ea */ 263 | /* description: Returns true is the instruction */ 264 | /* must be ignored */ 265 | /*------------------------------------------------*/ 266 | 267 | bool x86_remove_instr(unsigned char byte, ea_t ea) 268 | { 269 | // removes nop 270 | if (x86_is_nop(byte, ea)) 271 | return true; 272 | 273 | return false; 274 | } 275 | 276 | 277 | /*------------------------------------------------*/ 278 | /* function : x86_convert_16bit_rep */ 279 | /* arguments: unsigned char val, instr address */ 280 | /* description: converts byte if instruction is a */ 281 | /* 16 bit rep/repe/repz/repne/repnz */ 282 | /* notes: detects changes like 66 F3 -> F3 66 */ 283 | /*------------------------------------------------*/ 284 | 285 | bool x86_convert_16bit_rep(unsigned char * byte, ea_t ea) 286 | { 287 | unsigned char byte2; 288 | 289 | if (*byte == 0x66) 290 | { 291 | byte2 = get_byte(ea+1); 292 | if (byte2 == 0xF3 || byte2 == 0xF2) 293 | { 294 | *byte = byte2; 295 | return true; 296 | } 297 | } 298 | 299 | return false; 300 | } 301 | 302 | 303 | /*------------------------------------------------*/ 304 | /* function : x86_convert_cond_jump */ 305 | /* arguments: unsigned char val, instr address */ 306 | /* description: converts byte if instruction is a */ 307 | /* conditionnal jump. If jnz returns */ 308 | /* jz, if jne return je, ... */ 309 | /*------------------------------------------------*/ 310 | 311 | bool x86_convert_cond_jump(unsigned char * byte, ea_t ea) 312 | { 313 | unsigned char byte2 = *byte; 314 | 315 | if (byte2 == 0x0F) 316 | { 317 | byte2 = get_byte(ea+1) - 0x10; 318 | } 319 | 320 | if (byte2 >= 0x70 && byte2 <= 0x7F) 321 | { 322 | switch (byte2) 323 | { 324 | case 0x77: // ja -> jb 325 | *byte = 0x72; 326 | break; 327 | case 0x73: // jae -> jbe 328 | *byte = 0x76; 329 | break; 330 | case 0x75: // jnz -> jz 331 | *byte = 0x74; 332 | break; 333 | case 0x7F: // jg -> jl 334 | *byte = 0x7C; 335 | break; 336 | case 0x7D: // jge -> jle 337 | *byte = 0x7E; 338 | break; 339 | case 0x71: // jno -> jo 340 | *byte = 0x70; 341 | break; 342 | case 0x7B: // jnp -> jp 343 | *byte = 0x7A; 344 | break; 345 | case 0x79: // jns -> js 346 | *byte = 0x78; 347 | break; 348 | default: 349 | *byte = byte2; 350 | } 351 | 352 | return true; 353 | } 354 | 355 | return false; 356 | } 357 | 358 | 359 | /*------------------------------------------------*/ 360 | /* function : x86_convert_cond_jump */ 361 | /* arguments: unsigned char val, instr address */ 362 | /* description: converts byte if instruction is a */ 363 | /* conditionnal jump. If jnz returns */ 364 | /* jz, if jne return je, ... */ 365 | /*------------------------------------------------*/ 366 | 367 | int x86_is_cond_jump_pos(ea_t ea) 368 | { 369 | unsigned char byte2 = get_byte(ea); 370 | 371 | if (byte2 == 0x0F) 372 | { 373 | byte2 = get_byte(ea+1) - 0x10; 374 | } 375 | 376 | if (byte2 >= 0x70 && byte2 <= 0x7F) 377 | { 378 | switch (byte2) 379 | { 380 | case 0x77: //ja 381 | case 0x72: //jb 382 | case 0x74: //jz 383 | case 0x7F: //jg 384 | case 0x7C: //jl 385 | case 0x70: //jo 386 | case 0x7A: //jp 387 | case 0x78: //js 388 | return 1; 389 | default: 390 | return 2; 391 | } 392 | } 393 | 394 | return 0; 395 | } 396 | 397 | 398 | /*------------------------------------------------*/ 399 | /* function : x86_get_fake_jump */ 400 | /* arguments: ea_t ea */ 401 | /* description: Returns jump for jump $5/$2 */ 402 | /*------------------------------------------------*/ 403 | 404 | ea_t x86_get_fake_jump(ea_t ea) 405 | { 406 | unsigned char byte; 407 | unsigned long l; 408 | 409 | byte = get_byte(ea); 410 | if (byte == 0xE9) 411 | { 412 | l = get_long(ea+1); 413 | if (l == 0) 414 | return get_item_end(ea); 415 | } 416 | else if (byte == 0xeb) 417 | { 418 | byte = get_byte(ea+1); 419 | if (byte == 0) 420 | return get_item_end(ea); 421 | } 422 | 423 | return BADADDR; 424 | } 425 | 426 | /*------------------------------------------------*/ 427 | /* function : x86_is_direct_jump */ 428 | /* arguments: ea_t ea */ 429 | /* description: Returns TRUE if a direct jump */ 430 | /*------------------------------------------------*/ 431 | 432 | bool x86_is_direct_jump(ea_t ea) 433 | { 434 | unsigned char byte; 435 | 436 | byte = get_byte(ea); 437 | switch (byte) 438 | { 439 | case 0xE9: 440 | case 0xEA: 441 | case 0xEB: 442 | case 0xFF: 443 | return true; 444 | default: 445 | return false; 446 | } 447 | 448 | return false; 449 | } 450 | 451 | 452 | /*------------------------------------------------*/ 453 | /* function : x86_is_end_block */ 454 | /* arguments: ea_t ea */ 455 | /* description: Returns true on int 3 */ 456 | /*------------------------------------------------*/ 457 | 458 | bool x86_is_end_block(ea_t ea) 459 | { 460 | if (get_byte(ea) == 0xCC) 461 | return true; 462 | 463 | return false; 464 | } 465 | 466 | 467 | /*------------------------------------------------*/ 468 | /* function : x86_get_byte */ 469 | /* arguments: unsigned char _byte */ 470 | /* description: Returns opcode */ 471 | /* note: convert push/pop registers and remove rex*/ 472 | /* prefix */ 473 | /*------------------------------------------------*/ 474 | 475 | unsigned char x86_get_byte(ea_t ea) 476 | { 477 | unsigned char byte; 478 | 479 | byte = get_byte(ea); 480 | 481 | if (patchdiff_cpu == CPU_X8664 && x86_is_rex_prefix(byte)) 482 | { 483 | ea++; 484 | byte = get_byte(ea); 485 | } 486 | 487 | if (x86_is_push_register (byte)) 488 | byte = 0x50; // push eax 489 | else if (x86_is_pop_register (byte)) 490 | byte = 0x58; // pop eax 491 | else if (x86_is_inc_register(byte)) 492 | byte = 0x40; // inc eax 493 | else if (x86_is_dec_register(byte)) 494 | byte = 0x48; // dec eax 495 | 496 | x86_convert_16bit_rep(&byte, ea); 497 | x86_convert_cond_jump(&byte, ea); 498 | 499 | return byte; 500 | } -------------------------------------------------------------------------------- /x86.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Patchdiff3 3 | Portions (C) 2014 - 2014 namreeb (patchdiff@namreeb.org) 4 | Portions (C) 2010 - 2011 Nicolas Pouvesle 5 | Portions (C) 2007 - 2009 Tenable Network Security, Inc. 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License version 2 as 9 | published by the Free Software Foundation. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "precomp.hpp" 23 | 24 | unsigned char x86_get_byte(ea_t); 25 | bool x86_remove_instr(unsigned char, ea_t); 26 | bool x86_is_end_block(ea_t); 27 | bool x86_is_direct_jump(ea_t ea); 28 | ea_t x86_get_fake_jump(ea_t); 29 | int x86_is_cond_jump_pos(ea_t); 30 | --------------------------------------------------------------------------------