├── .gitignore ├── AUTHOR.txt ├── BUGS.txt ├── LICENSE.txt ├── README.txt ├── TODO.txt ├── jni ├── Android.mk ├── Application.mk └── src │ ├── banner.h │ ├── env1.c │ ├── env2.c │ ├── env3.c │ ├── fuzz_dyn.c │ ├── fuzz_hdr.c │ ├── fuzz_note.c │ ├── fuzz_pht.c │ ├── fuzz_rel.c │ ├── fuzz_sht.c │ ├── fuzz_strs.c │ ├── fuzz_sym.c │ ├── generators.c │ ├── lc_elf.h │ ├── logger.c │ ├── melkor.c │ ├── melkor.h │ ├── numbers.h │ └── print_envp_vars.c └── libs └── armeabi ├── env1 ├── env2 ├── env3 ├── melkor └── print_envp_vars /.gitignore: -------------------------------------------------------------------------------- 1 | obj/ 2 | -------------------------------------------------------------------------------- /AUTHOR.txt: -------------------------------------------------------------------------------- 1 | ~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ 2 | | -- AUTHOR -- | 3 | ~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ 4 | 5 | | Name: Alejandro Hernandez H. (nitr0us) 6 | | Twitter: http://twitter.com/nitr0usmx 7 | | Email: nitrousenador [at] gmail [dot] com 8 | | Website: http://www.brainoverflow.org 9 | | Blog: http://chatsubo-labs.blogspot.com 10 | | Location: 11 | 12 | . 13 | \'~~~-, 14 | \ '-,_ 15 | \ /\ `~'~''\ M E X I C O 16 | _\ \\ \/~\ 17 | \__ \\ \ 18 | \ \\. \ 19 | \ \ \ `~~ 20 | '\\ \. / 21 | / \ \ | 22 | \_\ \ | _.----, 23 | | \ ! / 24 | '._ \_ __/ _/ 25 | \_ ''--'' __/ 26 | \.__ | 27 | ''.__ __.._ o<-_\---- here ! 28 | '' './ ` 29 | -------------------------------------------------------------------------------- /BUGS.txt: -------------------------------------------------------------------------------- 1 | ~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ 2 | | -- BUGS -- | 3 | ~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ 4 | 5 | - No boundary checkings in the whole codebase. If a malformed ELF is 6 | supplied, it'll definitely segfault. 7 | 8 | It's supposed to be fed with non-malformed ELFs (templates), hence, 9 | you can use it as a test subject too ;-), fuzzing the fuzzer, 10 | meta-fuzzing, inception fuzzing, whatever... 11 | 12 | Bugs (overflows and off-by-one's) while treating strings and pointers 13 | with functions like strncpy(), strcat(), memcpy(), strlen(), etc. etc. 14 | 15 | - The data structures are adapted at compilation time based on the CPU 16 | where Melkor is running by checking the __i386__ and __x86_64__ macros, 17 | not by the ELF file to be used as a template (HDR.e_ident[EI_CLASS]). 18 | 19 | I've been through this before and I solved it by wrapping many data 20 | structures and assignations in macros to automatically adapt them 21 | based on the architecture detected in HDR.e_ident[EI_CLASS]. However, 22 | it adds more complexity to the code. You can see it at: 23 | http://www.brainoverflow.org/code/dissector.c 24 | 25 | So, if you want to fuzz a 32-bit ELF file, you need to compile and run 26 | Melkor in a 32-bit OS, and vice versa for 64-bit files. 27 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | ~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ 2 | | -- DESCRIPTION -- | 3 | ~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ 4 | 5 | Melkor - An ELF File Format Fuzzer 6 | 7 | Melkor, a fictional character from J. R. R. Tolkien's Middle-earth 8 | legendarium, was the first Dark Lord and master of Sauron. He's 9 | mentioned briefly in The Lord of the Rings and is known for: 10 | 11 | "... Melkor had captured a number of ELVES before the Valar 12 | attacked him, and he tortured and corrupted them, breeding the 13 | first Orcs." (http://en.wikipedia.org/wiki/Morgoth) 14 | 15 | "... Melkor was cunning and more filled with malice than ever. 16 | Seeing the bliss of the ELVES and remembering that it was for their 17 | sake that he was overthrown, Melkor desired above all things to 18 | corrupt them." (http://lotr.wikia.com/wiki/Melkor) 19 | 20 | "Orcs...This has been so from the day they were bred by Melkor from 21 | corrupted, tortured and mutilated ELVES that may also have been 22 | forced to breed with other unnatural abominations in the dominion 23 | of the Dark Powers." (http://lotr.wikia.com/wiki/Orcs) 24 | 25 | To honor his name, this piece of code takes an ELF, corrupts it and 26 | creates as much Orcs as you want. 27 | 28 | Melkor is a hybrid fuzzer (mutation-based and generation-based). 29 | It mutates the existing data in an ELF sample given to create orcs 30 | (malformed ELFs), however, it doesn't change values randomly (dumb 31 | fuzzing), instead, it fuzzes certain metadata with semi-valid values 32 | through the use of fuzzing rules (knowledge base). Written in C, 33 | Melkor is a very intuitive and easy-to-use fuzzer to find functional 34 | (and security) bugs in ELF parsers. 35 | 36 | The fuzzing rules were designed with the following inputs in mind: 37 | - ELF Specification violations 38 | * TIS ELF Specification 1.2 (May, 1995) 39 | * ELF-64 Object File Format 1.5 (May 1998) 40 | - Misc ideas & considerations 41 | - Parsing patterns in ELF software 42 | 43 | You will find the fuzzing rules in detail and some other schematics 44 | in the docs/ directory. 45 | 46 | 47 | 48 | ~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ 49 | | -- REQUIREMENTS -- | 50 | ~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ 51 | 52 | - make 53 | - gcc 54 | 55 | 56 | 57 | ~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ 58 | | -- COMPILATION & USAGE -- | 59 | ~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ 60 | The compilation is very straightforward, just type: 61 | $make 62 | 63 | It will create the file 'melkor', which is the fuzzer itself, and 64 | some other ELF files inside the templates/ folder, including normal 65 | ELF files such as a normal ELF executable, some shared libraries, 66 | an static ELF (standalone executable) and some others. 67 | 68 | By running melkor, a list of options will be shown and you will 69 | realize that it's very intuitive and easy-to-use. All you have to 70 | supply is the name of an ELF to be used as a template, which could 71 | be any of the ones inside the templates/ dir. 72 | 73 | Depending on what kind of software you want to test, you have to 74 | choose which metadata you want to fuzz. For example, if you want 75 | to test an OS loader, you probably might want to fuzz only the 76 | Program Header Table (-P) and/or the Dynamic Section (-D). On the 77 | other hand, perhaps you might want to fuzz the Section Header 78 | Table and the ELF Header to test any antivirus engine or debugger. 79 | Fuzzing the Symbols Tables (-s) and/or Relocations Tables (-R) on 80 | relocatable files (.o) or shared libraries (.so) to test compilers 81 | and/or linkers. The String Tables could be fuzzed as well (-Z). 82 | It's up to you to decide how badly you want to corrupt an ELF }:-) 83 | 84 | Once the orcs have been created inside the orcs_*/ dir, it's time 85 | to test them with the help of test_fuzzed.sh, where you can simply 86 | specify the name of the folder with the orcs to be run (OS loader 87 | testing) or add an extra parameter to specify which program (and 88 | its parameters) you'd like to test against every malformed ELF 89 | within the orcs folder. This script has the option to fuzz some 90 | environment variables (defined as fuzzing rules as well). 91 | Showing logs with #dmesg after running the script could be useful 92 | to identify which program/library crashed and where that crash was. 93 | Some examples are shown running the script without parameters. 94 | 95 | If you want test the malformed ELFs (orcs) automatically on Windows 96 | environment, there is included a batch script (win_test_fuzzed.bat) 97 | with almost the same functionality of the script for *NIX. 98 | 99 | Happy Fuzzing ! 100 | 101 | 102 | ~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ 103 | | -- DIRS -- | 104 | ~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ 105 | 106 | - docs/ Contains related documentation such as the detailed 107 | list of fuzzing rules as well as the list of ELF 108 | metadata dependencies. 109 | 110 | - templates/ It has some ELF files compiled at the same time than 111 | melkor and could be used to feed melkor: 112 | foo.c -> foo.o (ELF object)-> foo (ELF executable) 113 | foo.c -> foo_static (ELF static executable) 114 | libfoo.c -> libfoo.so (ELF shared object) 115 | and some others. Type "$make templ" to see in detail 116 | which other ELF templates are created. 117 | 118 | - orcs_*/ Will contain the malformed ELF files (based on the 119 | given template file) created after the fuzzing process. 120 | 121 | - src/ Melkor source code. 122 | 123 | 124 | 125 | ~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ 126 | | -- BUGS -- | 127 | ~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ 128 | 129 | Please read BUGS.txt 130 | 131 | 132 | 133 | ~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ 134 | | -- CONTACT -- | 135 | ~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ 136 | 137 | Name: Alejandro Hernandez H. [nitr0us] 138 | Twitter: http://twitter.com/nitr0usmx 139 | Email: nitrousenador [at] gmail [dot] com 140 | Website: http://www.brainoverflow.org 141 | Blog: http://chatsubo-labs.blogspot.com 142 | 143 | 144 | 145 | ~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ 146 | | -- IN MEMORIAL -- | 147 | ~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ 148 | 149 | This project is dedicated to the memory of one of my best friends, 150 | Aaron Alba. 151 | 152 | 153 | 154 | ~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ 155 | | -- LICENSE -- | 156 | ~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ 157 | 158 | Melkor - An ELF File Format Fuzzer 159 | Copyright (C) 2014 Alejandro Hernandez H. (nitr0us) 160 | 161 | This program is free software: you can redistribute it and/or modify 162 | it under the terms of the GNU General Public License as published by 163 | the Free Software Foundation, either version 3 of the License, or 164 | (at your option) any later version. 165 | 166 | This program is distributed in the hope that it will be useful, 167 | but WITHOUT ANY WARRANTY; without even the implied warranty of 168 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 169 | GNU General Public License for more details. 170 | 171 | You should have received a copy of the GNU General Public License 172 | along with this program. If not, see . 173 | -------------------------------------------------------------------------------- /TODO.txt: -------------------------------------------------------------------------------- 1 | ~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ 2 | | -- TODO -- | 3 | ~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ 4 | 5 | - Fuzz the (symbol) Hash Table(s) (SHT_HASH | SHT_GNU_HASH) 6 | These rules are marked in red in docs/Melkor_Fuzzing_Rules.pdf 7 | 8 | - Fuzz the debug information (DWARF format) 9 | This rule is marked in orange in docs/Melkor_Fuzzing_Rules.pdf 10 | An example of a malformed DWARF payload can be seen at: 11 | http://www.exploit-db.com/exploits/23523/ 12 | 13 | - Smart fuzzing of SHT_REL or SHT_RELA based on the relocation scheme used 14 | More info: http://www.mindfruit.co.uk/2012/06/relocations-relocations.html 15 | 16 | - Fuzz uncommon data structs in /usr/include/elf.h such as Elf*_Syminfo, 17 | Elf*_Verdef, etc. 18 | 19 | - Port to *BSD 20 | -------------------------------------------------------------------------------- /jni/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | 3 | # Build malkor # 4 | include $(CLEAR_VARS) 5 | LOCAL_MODULE := melkor 6 | SRC := src 7 | LOCAL_SRC_FILES := $(SRC)/melkor.c $(SRC)/logger.c \ 8 | $(SRC)/fuzz_hdr.c $(SRC)/fuzz_sht.c \ 9 | $(SRC)/fuzz_pht.c $(SRC)/fuzz_sym.c \ 10 | $(SRC)/fuzz_dyn.c $(SRC)/fuzz_rel.c \ 11 | $(SRC)/fuzz_note.c $(SRC)/fuzz_strs.c \ 12 | $(SRC)/generators.c 13 | 14 | LOCAL_CFLAGS += -fPIE -ggdb -Wall -Wno-maybe-uninitialized -DDEBUG 15 | LOCAL_LDFLAGS += -fPIE -pie 16 | include $(BUILD_EXECUTABLE) 17 | 18 | # Build envtools # 19 | include $(CLEAR_VARS) 20 | LOCAL_MODULE := env1 21 | SRC := src 22 | LOCAL_SRC_FILES := $(SRC)/env1.c $(SRC)/generators.c 23 | 24 | LOCAL_CFLAGS += -fPIE -ggdb -Wall -DDEBUG 25 | LOCAL_LDFLAGS += -fPIE -pie 26 | include $(BUILD_EXECUTABLE) 27 | 28 | include $(CLEAR_VARS) 29 | LOCAL_MODULE := env2 30 | SRC := src 31 | LOCAL_SRC_FILES := $(SRC)/env2.c $(SRC)/generators.c 32 | 33 | LOCAL_CFLAGS += -fPIE -ggdb -Wall -DDEBUG 34 | LOCAL_LDFLAGS += -fPIE -pie 35 | include $(BUILD_EXECUTABLE) 36 | 37 | include $(CLEAR_VARS) 38 | LOCAL_MODULE := env3 39 | SRC := src 40 | LOCAL_SRC_FILES := $(SRC)/env3.c $(SRC)/generators.c 41 | 42 | LOCAL_CFLAGS += -fPIE -ggdb -Wall -DDEBUG 43 | LOCAL_LDFLAGS += -fPIE -pie 44 | include $(BUILD_EXECUTABLE) 45 | 46 | include $(CLEAR_VARS) 47 | LOCAL_MODULE := print_envp_vars 48 | SRC := src 49 | LOCAL_SRC_FILES := $(SRC)/print_envp_vars.c $(SRC)/generators.c 50 | 51 | LOCAL_CFLAGS += -fPIE -ggdb -Wall -DDEBUG 52 | LOCAL_LDFLAGS += -fPIE -pie 53 | include $(BUILD_EXECUTABLE) 54 | -------------------------------------------------------------------------------- /jni/Application.mk: -------------------------------------------------------------------------------- 1 | APP_PLATFORM := android-9 2 | -------------------------------------------------------------------------------- /jni/src/banner.h: -------------------------------------------------------------------------------- 1 | const char *logo = 2 | " | \n" 3 | " | M e l k o R "VERSION" - An ELF File Format Fuzzer \n" 4 | " | by nitr0us \n" 5 | " | \n" 6 | " '. ;' '; .' \n" 7 | " ;l, x, lc ;c' \n" 8 | " ,x; k; ol :o. \n" 9 | " dk. ;0. :0. ,k: \n" 10 | " .0k dO.,;0: .Ok \n" 11 | " .0O. cO: c dO. cOx \n" 12 | " .O0ocOo l .kk;xOd \n" 13 | " .OO00O; . ;O00Ox \n" 14 | " .cxkkkx:xkolkkkxo. \n" 15 | " 'kkkkkkxxxxxx' \n" 16 | " .xxxxxxxxxxxxx. \n" 17 | " .;;:xxxxxxxxxxxxo;;;. \n" 18 | " ..:dxxdo.ddddd:.. \n" 19 | " ddl:. .ldd: \n" 20 | " ldd. .ddl \n" 21 | " .cdlc. .ldc. \n" 22 | " :o. .o: \n" 23 | " ; ; \n"; 24 | 25 | 26 | const char *banners[] = { 27 | " \n" 28 | " .-. . . _ .-. \n" 29 | " .-. /|/| / / _ (_) )-. .-. \n" 30 | " `-' / ` | .-. / /-./ .-._. / \\ `-' \n" 31 | " .-. / | ./--'_ / / ) ( ) / ) .-. \n" 32 | " `-' .-' / | (__.' /_.- _/ \\ `-' .-/ `--' `-' \n" 33 | " (__.' `. (_/ `. \n" 34 | " `._) `._) \n", 35 | 36 | 37 | " ___ ___ ____ __ __ __ ___ ____ \n" 38 | " ||\\\\//|| || || || // // \\\\ || \\\\ \n" 39 | " << || \\/ || ||== || ||<< (( )) ||_// >>\n" 40 | " || || ||___ ||__| || \\\\ \\\\_// || \\\\ \n", 41 | 42 | 43 | "____ ___ ___ _ _ ______ ____ \n" 44 | "\\ \\ \\ _ | \\/ | | | | | | ___ \\ _ / / / \n" 45 | " \\ \\ \\ |_| | . . | ___ | | | | __ ___ | |_/ / |_| / / / \n" 46 | " \\ \\ \\ | |\\/| | / _ \\ | | | |/ / / _ \\ | / / / / \n" 47 | " \\ \\ \\ _ | | | | | __/ | | | < | (_) | | |\\ \\ _ / / / \n" 48 | " \\_\\_\\ |_| \\_| |_/ \\___| |_| |_|\\_\\ \\___/ \\_| \\_| |_| /_/_/ \n", 49 | 50 | 51 | "/\\/\\ _____ __ __ __________ /\\/\\ \n" 52 | "\\ \\ \\ / \\ ____ | | | | __ ____ \\______ \\ / / / \n" 53 | " \\ \\ \\ / \\ / \\ _/ __ \\ | | | |/ / / _ \\ | _/ / / / \n" 54 | " \\ \\ \\ / Y \\ \\ ___/ | |__ | < ( <_> ) | | \\ / / / \n" 55 | " \\ \\ \\ \\____|__ / \\___ > |____/ |__|_ \\ \\____/ |____|_ / / / / \n" 56 | " \\/\\/ \\/ \\/ \\/ \\/ \\/\\/ \n", 57 | 58 | 59 | "::: _______ _______ _ _ _____ ______ ::: \n" 60 | "::: | | | |______ | |____/ | | |_____/ ::: \n" 61 | "::: | | | |______ |_____ | \\_ |_____| | \\_ ::: \n" 62 | }; 63 | 64 | const char *elf_ascii[] = { 65 | " ..-.--.. \n" 66 | " ,','.-`.-.`. \n" 67 | " :.',;' `.\\. \n", 68 | " ||//----,-.--\\| <<--- %s\n", 69 | " \\`:|/-----`-'--||'/ \n" 70 | " \\\\|: |:' \n" 71 | " `|| \" \\ |! _________________________________\n", 72 | " |!| ;| / I'll be corrupted %5d times ! \\ \n", 73 | " !||:. -- /|! \\_________________________________/ \n" 74 | " /||!||:.___.|!||\\ \n" 75 | " /|!|||!| |!||!\\\\:. \n" 76 | " ,'//!||!||!`._.||!||,:\\\\\\\n" 77 | ": :: |!|||!| |!||! |!::\n" 78 | "| |! !||!|||`---!|!|| ||!|\n\n" 79 | }; 80 | -------------------------------------------------------------------------------- /jni/src/env1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Melkor - An ELF File Format Fuzzer 3 | * Copyright (C) 2014 Alejandro Hernandez H. (nitr0us) 4 | * 5 | * Mexico 6 | */ 7 | 8 | #include "melkor.h" 9 | 10 | int main() 11 | { 12 | char *env_LD_BIND_NOW; 13 | 14 | srand(getseed()); 15 | 16 | if(rand() % 2){ 17 | int r = rand(); 18 | 19 | if(r % 3 == 0) 20 | env_LD_BIND_NOW = "1"; 21 | else if(r % 3 == 1) 22 | env_LD_BIND_NOW = "on"; 23 | else 24 | env_LD_BIND_NOW = "off"; 25 | } else { 26 | unsigned short s = 8 + (rand() % 1024); 27 | unsigned short ndx = 0; 28 | 29 | env_LD_BIND_NOW = malloc(s); 30 | 31 | while(ndx < s) 32 | *(env_LD_BIND_NOW + ndx++) = 'A' + (rand() % ('Z' - 'A')); // Range of printable chars 'A'-'Z' 33 | } 34 | 35 | printf("%s", env_LD_BIND_NOW); 36 | 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /jni/src/env2.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Melkor - An ELF File Format Fuzzer 3 | * Copyright (C) 2014 Alejandro Hernandez H. (nitr0us) 4 | * 5 | * Mexico 6 | */ 7 | 8 | #include "melkor.h" 9 | 10 | #define BUFF_SIZE 2048 11 | 12 | int main(int argc, char *argv[], char *envp[]) 13 | { 14 | unsigned short cnt = 0, ndx; 15 | char *env_PATH, *path, env_paths[13][37]; // Only 13 paths taken from $PATH with 37 chars each one, enough to play with ... 16 | char *env_LD_LIBRARY_PATH = malloc(BUFF_SIZE); // Yeah yeah, I prefer to spend time writing this comment than checking the returned value by malloc() :D 17 | char *fuzzed_path; 18 | 19 | // Split $PATH 20 | env_PATH = getenv("PATH"); 21 | 22 | path = strtok(env_PATH, ":"); 23 | strncpy(env_paths[cnt], path, 37); 24 | env_paths[cnt++][36] = '\0'; 25 | 26 | while((path = strtok(NULL, ":")) != NULL && cnt < 13){ 27 | strncpy(env_paths[cnt], path, 37); 28 | env_paths[cnt++][36] = '\0'; 29 | } 30 | // Split 31 | 32 | srand(getseed()); 33 | 34 | // Overflows and off-by-one's section :D, exploit them ! 35 | *env_LD_LIBRARY_PATH = '\0'; 36 | while(strlen(env_LD_LIBRARY_PATH) < BUFF_SIZE){ 37 | if(rand() % 4 < 3){ // 75% chance of valid paths 38 | ndx = rand() % cnt; 39 | if(strlen(env_LD_LIBRARY_PATH) + strlen(env_paths[ndx]) < BUFF_SIZE) 40 | strcat(env_LD_LIBRARY_PATH, env_paths[ndx]); 41 | else 42 | break; 43 | } else { 44 | fuzzed_path = get_fuzzed_path(); 45 | 46 | if(strlen(env_LD_LIBRARY_PATH) + strlen(fuzzed_path) < BUFF_SIZE) 47 | strcat(env_LD_LIBRARY_PATH, fuzzed_path); 48 | else 49 | break; 50 | } 51 | 52 | if(strlen(env_LD_LIBRARY_PATH) + 1 < BUFF_SIZE) 53 | strcat(env_LD_LIBRARY_PATH, ":"); 54 | 55 | if(strlen(env_LD_LIBRARY_PATH) == BUFF_SIZE - 1) 56 | break; 57 | } 58 | 59 | printf("%s", env_LD_LIBRARY_PATH); 60 | 61 | free(env_LD_LIBRARY_PATH); 62 | 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /jni/src/env3.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Melkor - An ELF File Format Fuzzer 3 | * Copyright (C) 2014 Alejandro Hernandez H. (nitr0us) 4 | * 5 | * Mexico 6 | */ 7 | 8 | #include "melkor.h" 9 | 10 | #define BUFF_SIZE 1024 11 | 12 | static char *fuzz_paths[] = { 13 | "orcs_libfoo.so/", 14 | "../orcs_libfoo.so/", 15 | "./..../", 16 | ";/;;/", 17 | "/.so/", 18 | "~~//", 19 | "\\", 20 | "$/", 21 | }; 22 | 23 | int main(int argc, char *argv[], char *envp[]) 24 | { 25 | unsigned short ndx; 26 | char orcfname[strlen("orc_") + 16]; 27 | char *env_LD_PRELOAD = malloc(BUFF_SIZE); // Yeah yeah, I prefer to spend time writing this comment than checking the returned value by malloc() :D 28 | 29 | srand(getseed()); 30 | 31 | // Overflows and off-by-one's section :D, exploit them ! 32 | *env_LD_PRELOAD = '\0'; 33 | while(strlen(env_LD_PRELOAD) < BUFF_SIZE){ 34 | if(rand() % 2){ 35 | ndx = rand() % 2; // First two entries. Valid paths to ../orcs_libfoo.so/ in case libfoo.so has been already fuzzed 36 | if(strlen(env_LD_PRELOAD) + strlen(fuzz_paths[ndx]) < BUFF_SIZE) 37 | strcat(env_LD_PRELOAD, fuzz_paths[ndx]); 38 | else 39 | break; 40 | } else { 41 | ndx = 2 + (rand() % (sizeof(fuzz_paths) / sizeof(char *)) - 2); 42 | if(strlen(env_LD_PRELOAD) + strlen(fuzz_paths[ndx]) < BUFF_SIZE) 43 | strcat(env_LD_PRELOAD, fuzz_paths[ndx]); 44 | else 45 | break; 46 | } 47 | 48 | snprintf(orcfname, sizeof(orcfname), "orc_%.4d.so", 1 + rand() % 100); 49 | if(strlen(env_LD_PRELOAD) + strlen(orcfname) < BUFF_SIZE) 50 | strcat(env_LD_PRELOAD, orcfname); 51 | else 52 | break; 53 | 54 | if(rand() % 10 < 1) // Double .so extension 55 | if(strlen(env_LD_PRELOAD) + 3 < BUFF_SIZE) 56 | strcat(env_LD_PRELOAD, ".so"); 57 | 58 | if(strlen(env_LD_PRELOAD) + 1 < BUFF_SIZE) 59 | strcat(env_LD_PRELOAD, ":"); 60 | 61 | if(strlen(env_LD_PRELOAD) == BUFF_SIZE - 1) 62 | break; 63 | } 64 | 65 | printf("%s", env_LD_PRELOAD); 66 | 67 | free(env_LD_PRELOAD); 68 | 69 | return 0; 70 | } 71 | -------------------------------------------------------------------------------- /jni/src/fuzz_dyn.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Melkor - An ELF File Format Fuzzer 3 | * Copyright (C) 2014 Alejandro Hernandez H. (nitr0us) 4 | * 5 | * Mexico 6 | */ 7 | 8 | #include "melkor.h" 9 | 10 | #define N_RULES_DYN 18 // Total of fuzzing rules defined for this metadata type 11 | 12 | // Array of function pointers. Index zero won't be used. The fuzzing rules start from index 1 13 | func_ptr dyn[N_RULES_DYN + 1]; 14 | 15 | void initialize_dyn_funcs(void) __attribute__((constructor)); 16 | 17 | /* External vars */ 18 | extern FILE *logfp; 19 | extern unsigned int quiet; 20 | extern unsigned int like_a, like_b; 21 | extern unsigned int secnum; 22 | extern unsigned int entry; 23 | extern char *orcptr; 24 | extern Elf_Ehdr *orcHDR; 25 | extern Elf_Shdr *elfSHT, *orcSHT; 26 | extern Elf_Dyn *elfDYN, *orcDYN; 27 | extern Elf_Dyn *elfOrigDYN; 28 | extern Elf_Off linkstrtab_offset; 29 | 30 | void fuzz_dyn() 31 | { 32 | int rule; 33 | 34 | for(rule = 1; rule <= N_RULES_DYN; rule++) 35 | if((rand() % like_a) < like_b) 36 | if(dyn[rule]()){ 37 | printf(". "); 38 | debug("SHT[%d] DYN[%d] rule [%.2d] executed\n", secnum, entry, rule); 39 | fprintf(logfp, " | SHT[%d] DYN[%d] rule [%.2d] executed\n", secnum, entry, rule); 40 | } 41 | } 42 | 43 | int dyn1(void) 44 | { 45 | if(orcDYN->d_tag != DT_NEEDED && 46 | orcDYN->d_tag != DT_SONAME && 47 | orcDYN->d_tag != DT_RPATH) 48 | return 0; 49 | 50 | if(rand() % 3 == 0) 51 | return 0; 52 | 53 | orcDYN->d_un.d_val = rand() & 0x0fff; // 12-bit random offset 54 | 55 | fprintf(logfp, "(DYN[%d]->d_un.d_val = 0x"HEX")", entry, orcDYN->d_un.d_val); 56 | 57 | return 1; 58 | } 59 | 60 | int dyn2(void) 61 | { 62 | if(orcDYN->d_tag != DT_PLTRELSZ && 63 | orcDYN->d_tag != DT_RELSZ && 64 | orcDYN->d_tag != DT_RELASZ && 65 | orcDYN->d_tag != DT_STRSZ) 66 | return 0; 67 | 68 | if(rand() % 2) 69 | return 0; 70 | 71 | int r = rand(); 72 | 73 | if(r % 4 < 2) // 50% chance 74 | orcDYN->d_un.d_val = rand() & 0xff; 75 | else if(r % 4 == 2) 76 | orcDYN->d_un.d_val = getElf_Word(); 77 | else 78 | orcDYN->d_un.d_val = 0x00; 79 | 80 | fprintf(logfp, "(DYN[%d]->d_un.d_val = 0x"HEX")", entry, orcDYN->d_un.d_val); 81 | 82 | return 1; 83 | } 84 | 85 | int dyn3(void) 86 | { 87 | if(orcDYN->d_tag != DT_RELENT && 88 | orcDYN->d_tag != DT_RELAENT && 89 | orcDYN->d_tag != DT_SYMENT) 90 | return 0; 91 | 92 | if(rand() % 2) 93 | return 0; 94 | 95 | int r = rand(); 96 | 97 | if(r % 4 < 2) // 50% chance 98 | orcDYN->d_un.d_val = rand() & 0xff; 99 | else if(r % 4 == 2) 100 | orcDYN->d_un.d_val = getElf_Word(); 101 | else 102 | orcDYN->d_un.d_val = 0x00; 103 | 104 | fprintf(logfp, "(DYN[%d]->d_un.d_val = 0x"HEX")", entry, orcDYN->d_un.d_val); 105 | 106 | return 1; 107 | } 108 | 109 | int dyn4(void) 110 | { 111 | if(orcDYN->d_tag != DT_PLTGOT) 112 | return 0; 113 | 114 | if(rand() % 2) 115 | orcDYN->d_un.d_ptr = getElf_Addr(); 116 | else 117 | return 0; 118 | 119 | fprintf(logfp, "(DYN[%d]->d_un.d_val = 0x"HEX")", entry, orcDYN->d_un.d_val); 120 | 121 | return 1; 122 | } 123 | 124 | int dyn5(void) 125 | { 126 | if(orcDYN->d_tag != DT_HASH && 127 | orcDYN->d_tag != DT_GNU_HASH && 128 | orcDYN->d_tag != DT_SYMTAB) 129 | return 0; 130 | 131 | if(rand() % 2) 132 | orcDYN->d_un.d_ptr = getElf_Addr(); 133 | 134 | fprintf(logfp, "(DYN[%d]->d_un.d_val = 0x"HEX")", entry, orcDYN->d_un.d_val); 135 | 136 | return 1; 137 | } 138 | 139 | int dyn6(void) 140 | { 141 | if(orcDYN->d_tag != DT_INIT && 142 | orcDYN->d_tag != DT_FINI) 143 | return 0; 144 | 145 | int r = rand(); 146 | 147 | if(r % 3 == 0) 148 | orcDYN->d_un.d_ptr = getElf_Addr(); 149 | else if(r % 3 == 1) 150 | orcDYN->d_un.d_ptr = orcHDR->e_entry; // jmp to the original entrypoint 151 | else { 152 | if(orcDYN->d_tag == DT_INIT) 153 | orcDYN->d_un.d_ptr = get_d_ptr_by_d_tag(DT_FINI); 154 | else 155 | orcDYN->d_un.d_ptr = get_d_ptr_by_d_tag(DT_INIT); 156 | } 157 | 158 | fprintf(logfp, "(DYN[%d]->d_un.d_val = 0x"HEX")", entry, orcDYN->d_un.d_val); 159 | 160 | return 1; 161 | } 162 | 163 | int dyn7(void) 164 | { 165 | if(orcDYN->d_tag != DT_DEBUG) 166 | return 0; 167 | 168 | if(rand() % 2) 169 | return 0; 170 | 171 | if(rand() % 2) 172 | orcDYN->d_tag = DT_SYMBOLIC; 173 | else 174 | orcDYN->d_tag = DT_TEXTREL; 175 | 176 | fprintf(logfp, "(DYN[%d]->d_tag = 0x"HEX")", entry, orcDYN->d_tag); 177 | 178 | return 1; 179 | } 180 | 181 | int dyn8(void) 182 | { 183 | if(orcDYN->d_tag != DT_PLTREL) 184 | return 0; 185 | 186 | if(rand() % 2) 187 | return 0; 188 | 189 | #if defined(__i386__) || defined(__ANDROID_API__) 190 | Elf_Word d_val; 191 | #elif defined(__x86_64__) 192 | Elf_Xword d_val; 193 | #endif 194 | 195 | while((d_val = rand() % DT_NUM)) 196 | if(d_val != DT_REL && d_val != DT_RELA) 197 | break; 198 | 199 | orcDYN->d_un.d_val = d_val; 200 | 201 | fprintf(logfp, "(DYN[%d]->d_un.d_val = 0x"HEX")", entry, orcDYN->d_un.d_val); 202 | 203 | return 1; 204 | } 205 | 206 | int dyn9(void) 207 | { 208 | if(orcDYN->d_tag != DT_DEBUG) 209 | return 0; 210 | 211 | if(rand() % 2) 212 | return 0; 213 | 214 | orcDYN->d_tag = DT_BIND_NOW; 215 | 216 | fprintf(logfp, "(DYN[%d]->d_tag = 0x"HEX")", entry, orcDYN->d_tag); 217 | 218 | return 1; 219 | } 220 | 221 | int dyn10(void) 222 | { 223 | if(orcDYN->d_tag != DT_RPATH && 224 | orcDYN->d_tag != DT_RUNPATH) 225 | return 0; 226 | 227 | unsigned int s = strlen(orcptr + linkstrtab_offset + elfDYN->d_un.d_val); 228 | char *rpath = malloc(s); 229 | char *fuzzed_path; 230 | int fuzzed = 0; 231 | 232 | *rpath = '\0'; 233 | while(strlen(rpath) < s){ 234 | fuzzed_path = get_fuzzed_path(); 235 | 236 | if(strlen(rpath) + strlen(fuzzed_path) < s){ 237 | strcat(rpath, fuzzed_path); 238 | fuzzed = 1; 239 | } else 240 | break; 241 | 242 | if(strlen(rpath) + 1 < s) 243 | strcat(rpath, ":"); 244 | 245 | if(strlen(rpath) == s - 1) 246 | break; 247 | } 248 | 249 | if(!fuzzed) 250 | return 0; 251 | 252 | strncpy(orcptr + linkstrtab_offset + elfDYN->d_un.d_val, rpath, s); 253 | 254 | fprintf(logfp, "(DYN[%d]->(d_val + 0) = %s)", entry, orcptr + linkstrtab_offset + elfDYN->d_un.d_val); 255 | 256 | free(rpath); 257 | 258 | return 1; 259 | } 260 | 261 | int dyn11(void) 262 | { 263 | if(orcDYN->d_tag != DT_PLTREL) 264 | return 0; 265 | 266 | if(rand() % 2) 267 | return 0; 268 | 269 | #if defined(__i386__) || defined(__ANDROID_API__) 270 | orcDYN->d_un.d_val = DT_RELA; 271 | #elif defined(__x86_64__) 272 | orcDYN->d_un.d_val = DT_REL; 273 | #endif 274 | 275 | fprintf(logfp, "(DYN[%d]->d_un.d_val = 0x"HEX")", entry, orcDYN->d_un.d_val); 276 | 277 | return 1; 278 | } 279 | 280 | int dyn12(void) 281 | { 282 | if(orcDYN->d_tag != DT_PLTGOT) 283 | return 0; 284 | 285 | Elf_Section ndx; 286 | 287 | if(!(ndx = findSectionIndexByName(".got.plt"))) 288 | return 0; 289 | 290 | Elf_Addr *d_ptr = (void *) orcptr + elfSHT[ndx].sh_offset; 291 | 292 | if(rand() % 5 == 0) // 20% chance to modify the first entry, which is the address of _DYNAMIC[] 293 | *d_ptr++ = getElf_Addr(); 294 | else 295 | d_ptr++; 296 | 297 | *d_ptr++ = getElf_Addr(); 298 | *d_ptr++ = getElf_Addr(); 299 | 300 | d_ptr = (void *) orcptr + elfSHT[ndx].sh_offset; // Points back again to print the results 301 | 302 | fprintf(logfp, "(DYN[%d]->(d_un.d_ptr + 0) = 0x"HEX",", entry, *d_ptr++); 303 | fprintf(logfp, " (d_un.d_ptr + %d) = 0x"HEX",", (unsigned int) sizeof(Elf_Addr *), *d_ptr++); 304 | fprintf(logfp, " (d_un.d_ptr + %d) = 0x"HEX")", (unsigned int) sizeof(Elf_Addr *), *d_ptr); 305 | 306 | return 1; 307 | } 308 | 309 | int dyn13(void) 310 | { 311 | if(orcDYN->d_tag != DT_PLTRELSZ) 312 | return 0; 313 | 314 | if(rand() % 3 < 2) 315 | return 0; 316 | 317 | #if defined(__i386__) || defined(__ANDROID_API__) 318 | Elf_Sword d_tag; 319 | #elif defined(__x86_64__) 320 | Elf_Sxword d_tag; 321 | #endif 322 | 323 | if(rand() % 3 < 2){ 324 | while((d_tag = rand() % 0xff)) 325 | if(d_tag != DT_PLTRELSZ) 326 | break; 327 | } else 328 | #if defined(__i386__) || defined(__ANDROID_API__) 329 | d_tag = getElf_Word(); 330 | #elif defined(__x86_64__) 331 | d_tag = getElf_Xword(); 332 | #endif 333 | 334 | orcDYN->d_tag = d_tag; 335 | 336 | fprintf(logfp, "(DYN[%d]->d_tag = 0x"HEX")", entry, orcDYN->d_tag); 337 | 338 | return 1; 339 | } 340 | 341 | int dyn14(void) 342 | { 343 | if(orcDYN->d_tag != DT_RELASZ && 344 | orcDYN->d_tag != DT_RELSZ && 345 | orcDYN->d_tag != DT_RELAENT && 346 | orcDYN->d_tag != DT_RELENT) 347 | return 0; 348 | 349 | if(rand() % 4 < 3) 350 | return 0; 351 | 352 | #if defined(__i386__) || defined(__ANDROID_API__) 353 | Elf_Sword d_tag; 354 | #elif defined(__x86_64__) 355 | Elf_Sxword d_tag; 356 | #endif 357 | 358 | if(rand() % 3 < 2){ 359 | while((d_tag = rand() % 0xff)) 360 | if(d_tag != DT_RELASZ && 361 | d_tag != DT_RELSZ && 362 | d_tag != DT_RELAENT && 363 | d_tag != DT_RELENT) 364 | break; 365 | } else 366 | #if defined(__i386__) || defined(__ANDROID_API__) 367 | d_tag = getElf_Word(); 368 | #elif defined(__x86_64__) 369 | d_tag = getElf_Xword(); 370 | #endif 371 | 372 | orcDYN->d_tag = d_tag; 373 | 374 | fprintf(logfp, "(DYN[%d]->d_tag = 0x"HEX")", entry, orcDYN->d_tag); 375 | 376 | return 1; 377 | } 378 | 379 | int dyn15(void) 380 | { 381 | if(orcDYN->d_tag != DT_NULL) 382 | return 0; 383 | 384 | if(rand() % 5 < 3) // DT_NULL is fucking critical: is the end of _DYNAMIC[] 385 | return 0; 386 | 387 | #if defined(__i386__) || defined(__ANDROID_API__) 388 | Elf_Sword d_tag; 389 | #elif defined(__x86_64__) 390 | Elf_Sxword d_tag; 391 | #endif 392 | 393 | if(rand() % 3 < 2){ 394 | while((d_tag = rand() % 0xff)) 395 | if(d_tag != DT_NULL) 396 | break; 397 | } else 398 | #if defined(__i386__) || defined(__ANDROID_API__) 399 | d_tag = getElf_Word(); 400 | #elif defined(__x86_64__) 401 | d_tag = getElf_Xword(); 402 | #endif 403 | 404 | orcDYN->d_tag = d_tag; 405 | 406 | fprintf(logfp, "(DYN[%d]->d_tag = 0x"HEX")", entry, orcDYN->d_tag); 407 | 408 | return 1; 409 | } 410 | 411 | int dyn16(void) 412 | { 413 | if(orcDYN->d_tag != DT_INIT_ARRAY && 414 | orcDYN->d_tag != DT_FINI_ARRAY) 415 | return 0; 416 | 417 | if(rand() % 2) // Constructors & Destructors are cool 418 | return 0; 419 | 420 | Elf_Word array_size; 421 | Elf_Section ndx; 422 | 423 | if(orcDYN->d_tag == DT_INIT_ARRAY) 424 | array_size = get_d_val_by_d_tag(DT_INIT_ARRAYSZ); 425 | else 426 | array_size = get_d_val_by_d_tag(DT_FINI_ARRAYSZ); 427 | 428 | if(array_size <= sizeof(Elf_Addr *)) // There's more than the default functions 429 | return 0; 430 | 431 | if(orcDYN->d_tag == DT_INIT_ARRAY){ 432 | if(!(ndx = findSectionIndexByName(".init_array"))) 433 | return 0; 434 | } else { 435 | if(!(ndx = findSectionIndexByName(".fini_array"))) 436 | return 0; 437 | } 438 | 439 | Elf_Addr *d_ptr = (void *) orcptr + elfSHT[ndx].sh_offset; 440 | 441 | d_ptr++; 442 | 443 | *d_ptr = getElf_Addr(); // DT_(INIT|FINI)_ARRAY[1] 444 | 445 | d_ptr = (void *) orcptr + elfSHT[ndx].sh_offset; // Points back again to print the results 446 | 447 | fprintf(logfp, "(DYN[%d]->(d_un.d_ptr + 0) = 0x"HEX",", entry, *d_ptr++); 448 | fprintf(logfp, " (d_un.d_ptr + %d) = 0x"HEX")", (unsigned int) sizeof(Elf_Addr *), *d_ptr); 449 | 450 | return 1; 451 | } 452 | 453 | int dyn17(void) 454 | { 455 | if(orcDYN->d_tag != DT_INIT_ARRAYSZ && 456 | orcDYN->d_tag != DT_FINI_ARRAYSZ) 457 | return 0; 458 | 459 | if(rand() % 2) 460 | return 0; 461 | 462 | #if defined(__i386__) || defined(__ANDROID_API__) 463 | Elf_Word d_val; 464 | #elif defined(__x86_64__) 465 | Elf_Xword d_val; 466 | #endif 467 | 468 | if(rand() % 2){ 469 | while((d_val = rand() & 0xffff)) 470 | if(d_val % 4 != 0) 471 | break; 472 | } else { 473 | d_val = orcDYN->d_un.d_val; 474 | 475 | #if defined(__i386__) || defined(__ANDROID_API__) 476 | d_val += 8; // A ptr in 64-bit is 8 bytes. Add 8 to 32-bit ELF 477 | #elif defined(__x86_64__) 478 | d_val += 4; // Vice versa 479 | #endif 480 | } 481 | 482 | orcDYN->d_un.d_val = d_val; 483 | 484 | fprintf(logfp, "(DYN[%d]->d_un.d_val = 0x"HEX")", entry, orcDYN->d_un.d_val); 485 | 486 | return 1; 487 | } 488 | 489 | int dyn18(void) 490 | { 491 | if(rand() % 20 < 19) // d_tag is critical 492 | return 0; 493 | 494 | // d_tag is a Sword (Signed Word) 495 | if(rand() % 2){ // 50% chance to set d_tag to a negative number > 0x7fffffff 496 | #if defined(__x86_64__) 497 | if(rand() % 2) 498 | orcDYN->d_tag = 0x8000000000000000 + (rand() % 0x7fffffff); 499 | else 500 | #endif 501 | orcDYN->d_tag = 0x80000000 + (rand() % 0x7fffffff); 502 | } else { 503 | if(rand() % 3 < 2){ 504 | if(rand() % 2) 505 | orcDYN->d_tag = getElf_Word(); 506 | else 507 | orcDYN->d_tag = getElf_Xword(); 508 | } else { 509 | int r = rand(); 510 | 511 | if(r % 4 == 0) 512 | orcDYN->d_tag = DT_LOOS; 513 | else if(r % 4 == 1) 514 | orcDYN->d_tag = DT_HIOS; 515 | else if(r % 4 == 2) 516 | orcDYN->d_tag = DT_LOPROC; 517 | else 518 | orcDYN->d_tag = DT_HIPROC; 519 | } 520 | } 521 | 522 | fprintf(logfp, "(DYN[%d]->d_tag = 0x"HEX")", entry, orcDYN->d_tag); 523 | 524 | return 1; 525 | } 526 | 527 | 528 | Elf_Addr get_d_ptr_by_d_tag(Elf_Sword d_tag) 529 | { 530 | int k; 531 | Elf_Dyn *tmpDYN = elfOrigDYN; 532 | 533 | for(k = 0; k < orcSHT->sh_size / orcSHT->sh_entsize; k++, tmpDYN++) 534 | if(tmpDYN->d_tag == d_tag) 535 | return tmpDYN->d_un.d_ptr; 536 | 537 | return (Elf_Addr) NULL; 538 | } 539 | 540 | Elf_Word get_d_val_by_d_tag(Elf_Sword d_tag) 541 | { 542 | int k; 543 | Elf_Dyn *tmpDYN = elfOrigDYN; 544 | 545 | for(k = 0; k < orcSHT->sh_size / orcSHT->sh_entsize; k++, tmpDYN++) 546 | if(tmpDYN->d_tag == d_tag) 547 | return tmpDYN->d_un.d_val; 548 | 549 | return 0; 550 | } 551 | 552 | void initialize_dyn_funcs(void) 553 | { 554 | dyn[1] = &dyn1; 555 | dyn[2] = &dyn2; 556 | dyn[3] = &dyn3; 557 | dyn[4] = &dyn4; 558 | dyn[5] = &dyn5; 559 | dyn[6] = &dyn6; 560 | dyn[7] = &dyn7; 561 | dyn[8] = &dyn8; 562 | dyn[9] = &dyn9; 563 | dyn[10] = &dyn10; 564 | dyn[11] = &dyn11; 565 | dyn[12] = &dyn12; 566 | dyn[13] = &dyn13; 567 | dyn[14] = &dyn14; 568 | dyn[15] = &dyn15; 569 | dyn[16] = &dyn16; 570 | dyn[17] = &dyn17; 571 | dyn[18] = &dyn18; 572 | } 573 | -------------------------------------------------------------------------------- /jni/src/fuzz_hdr.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Melkor - An ELF File Format Fuzzer 3 | * Copyright (C) 2014 Alejandro Hernandez H. (nitr0us) 4 | * 5 | * Mexico 6 | */ 7 | 8 | #include "melkor.h" 9 | 10 | #define N_RULES_HDR 19 // Total of fuzzing rules defined for this metadata type 11 | 12 | // Array of function pointers. Index zero won't be used. The fuzzing rules start from index 1 13 | func_ptr hdr[N_RULES_HDR + 1]; 14 | 15 | void initialize_hdr_funcs(void) __attribute__((constructor)); 16 | 17 | /* External vars */ 18 | extern FILE *logfp; 19 | extern unsigned int mode; // Metadata to fuzz (parameters given in argv[]) 20 | extern unsigned int quiet; 21 | extern unsigned int like_a, like_b; 22 | extern Elf_Ehdr *elfHDR, *orcHDR; 23 | 24 | void fuzz_hdr() 25 | { 26 | int rule; 27 | 28 | for(rule = 1; rule <= N_RULES_HDR; rule++) 29 | if((rand() % like_a) < like_b) 30 | if(hdr[rule]()){ 31 | printf(". "); 32 | debug("HDR rule [%.2d] executed\n", rule); 33 | fprintf(logfp, " | HDR rule [%.2d] executed\n", rule); 34 | } 35 | } 36 | 37 | int hdr1(void) 38 | { 39 | if(mode & PHT) 40 | return 0; 41 | 42 | if(rand() % 2){ // 50% chance 43 | orcHDR->e_phoff = 0; 44 | orcHDR->e_phentsize = 0; 45 | fprintf(logfp, "(HDR->e_phoff = 0x00, e_phentsize = 0x00)"); 46 | } else { 47 | orcHDR->e_phnum = 0; 48 | fprintf(logfp, "(HDR->e_phnum = 0x00)"); 49 | } 50 | 51 | return 1; 52 | } 53 | 54 | int hdr2(void) 55 | { 56 | if(mode & SHT) 57 | return 0; 58 | 59 | if(rand() % 2){ // 50% chance 60 | orcHDR->e_shoff = 0; 61 | orcHDR->e_shentsize = 0; 62 | fprintf(logfp, "(HDR->e_shoff = 0x00, e_shentsize = 0x00)"); 63 | } else { 64 | orcHDR->e_shnum = 0; 65 | fprintf(logfp, "(HDR->e_shnum = 0x00)"); 66 | } 67 | 68 | return 1; 69 | } 70 | 71 | int hdr3(void) 72 | { 73 | Elf_Half e_type; 74 | 75 | if(rand() % 2) // 50% chance 76 | e_type = getElf_Half() % ET_NUM; 77 | else { 78 | if((rand() % 4) < 3){ // .5 * .75 = 37.5% chance 79 | while((e_type = (getElf_Half() % ET_HIPROC))) 80 | if(e_type >= 5 && e_type <= ET_HIPROC) 81 | break; 82 | } else // .5 * .25 = 12.5% chance 83 | e_type = 0; 84 | } 85 | 86 | orcHDR->e_type = e_type; 87 | 88 | fprintf(logfp, "(HDR->e_type = 0x%x)", orcHDR->e_type); 89 | 90 | return 1; 91 | } 92 | 93 | int hdr4(void) 94 | { 95 | if((rand() % 4) < 3){ // 75% chance 96 | while((orcHDR->e_machine = getElf_Half())) 97 | if(orcHDR->e_machine > 16) 98 | break; 99 | } else 100 | orcHDR->e_machine = 0; 101 | 102 | fprintf(logfp, "(HDR->e_machine = 0x%x)", orcHDR->e_machine); 103 | 104 | return 1; 105 | } 106 | 107 | int hdr5(void) 108 | { 109 | if((rand() % 4) < 3) // 75% chance 110 | orcHDR->e_entry = getElf_Addr(); 111 | else 112 | orcHDR->e_entry = 0; 113 | 114 | fprintf(logfp, "(HDR->e_entry = 0x"HEX")", orcHDR->e_entry); 115 | 116 | return 1; 117 | } 118 | 119 | int hdr6(void) 120 | { 121 | if(mode & PHT) 122 | return 0; 123 | 124 | orcHDR->e_phoff = getElf_Off(); 125 | fprintf(logfp, "(HDR->e_phoff = 0x"HEX")", orcHDR->e_phoff); 126 | 127 | return 1; 128 | } 129 | 130 | int hdr7(void) 131 | { 132 | orcHDR->e_ehsize = getElf_Half(); 133 | fprintf(logfp, "(HDR->e_ehsize = 0x%x)", orcHDR->e_ehsize); 134 | 135 | return 1; 136 | } 137 | 138 | int hdr8(void) 139 | { 140 | if(mode & PHT) 141 | return 0; 142 | 143 | if((rand() % 4) < 3){ // 75% chance 144 | orcHDR->e_phentsize = getElf_Half(); 145 | orcHDR->e_phnum = getElf_Half(); 146 | fprintf(logfp, "(HDR->e_phentsize = 0x%x,", orcHDR->e_phentsize); 147 | fprintf(logfp, " e_phnum = 0x%x)", orcHDR->e_phnum); 148 | } else { 149 | orcHDR->e_phentsize = 0; 150 | fprintf(logfp, "(HDR->e_phentsize = 0x00)"); 151 | } 152 | 153 | return 1; 154 | } 155 | 156 | int hdr9(void) 157 | { 158 | if((rand() % 4) < 3){ // 75% chance 159 | if(mode & SHT) 160 | return 0; 161 | 162 | orcHDR->e_shentsize = getElf_Half(); 163 | orcHDR->e_shnum = getElf_Half(); 164 | fprintf(logfp, "(HDR->e_shentsize = 0x%x,", orcHDR->e_shentsize); 165 | fprintf(logfp, " e_shnum = 0x%x)", orcHDR->e_shnum); 166 | } else { 167 | orcHDR->e_shentsize = 0; 168 | fprintf(logfp, "(HDR->e_shentsize = 0x00)"); 169 | } 170 | 171 | return 1; 172 | } 173 | 174 | int hdr10(void) 175 | { 176 | if(mode & (STRS | NOTE | DYN | SYM | REL)) 177 | return 0; 178 | 179 | if(mode & SHT) 180 | if(rand() % 3 < 2) 181 | return 0; 182 | 183 | if((rand() % 4) < 3) // 75% chance 184 | orcHDR->e_shstrndx = rand() % elfHDR->e_shnum; 185 | else { 186 | if(rand() % 2) 187 | orcHDR->e_shstrndx = getElf_Half(); 188 | else 189 | orcHDR->e_shstrndx = 0; 190 | } 191 | 192 | fprintf(logfp, "(HDR->e_shstrndx = 0x%x)", orcHDR->e_shstrndx); 193 | 194 | return 1; 195 | } 196 | 197 | int hdr11(void) 198 | { 199 | if((rand() % 4) < 3) // 75% chance 200 | orcHDR->e_ident[EI_CLASS] = (rand() & 0xff) + ELFCLASS64 + 1; 201 | else 202 | orcHDR->e_ident[EI_CLASS] = 0; 203 | 204 | fprintf(logfp, "(HDR->e_ident[EI_CLASS] = 0x%.2x)", orcHDR->e_ident[EI_CLASS]); 205 | 206 | return 1; 207 | } 208 | 209 | int hdr12(void) 210 | { 211 | if((rand() % 4) < 3) // 75% chance 212 | orcHDR->e_ident[EI_DATA] = (rand() & 0xff) + ELFDATA2MSB + 1; 213 | else 214 | orcHDR->e_ident[EI_DATA] = 0; 215 | 216 | fprintf(logfp, "(HDR->e_ident[EI_DATA] = 0x%.2x)", orcHDR->e_ident[EI_DATA]); 217 | 218 | return 1; 219 | } 220 | 221 | int hdr13(void) 222 | { 223 | if(rand() % 2){ 224 | orcHDR->e_version = getElf_Word() + EV_CURRENT + 1; 225 | orcHDR->e_ident[EI_VERSION] = (rand() & 0xff) + EV_CURRENT + 1; 226 | } else { 227 | orcHDR->e_version = 0; 228 | orcHDR->e_ident[EI_VERSION] = 0; 229 | } 230 | 231 | fprintf(logfp, "(HDR->e_version = 0x%x, e_ident[EI_VERSION] = 0x%.2x)", orcHDR->e_version, orcHDR->e_ident[EI_VERSION]); 232 | 233 | return 1; 234 | } 235 | 236 | int hdr14(void) 237 | { 238 | if(mode & SHT) 239 | return 0; 240 | 241 | orcHDR->e_shoff = getElf_Off(); 242 | orcHDR->e_shnum = getElf_Half(); 243 | orcHDR->e_shentsize = getElf_Half(); 244 | 245 | fprintf(logfp, "(HDR->e_shoff = 0x"HEX",", orcHDR->e_shoff); 246 | fprintf(logfp, " e_shnum = 0x%x,", orcHDR->e_shnum); 247 | fprintf(logfp, " e_shentsize = 0x%x)", orcHDR->e_shentsize); 248 | 249 | return 1; 250 | } 251 | 252 | int hdr15(void) 253 | { 254 | if(mode & SHT) 255 | return 0; 256 | 257 | orcHDR->e_shnum = SHN_LORESERVE; 258 | fprintf(logfp, "(HDR->e_shnum = 0x%x)", orcHDR->e_shnum); 259 | 260 | return 1; 261 | } 262 | 263 | int hdr16(void) 264 | { 265 | orcHDR->e_ident[EI_ABIVERSION] = rand() & 0xff; 266 | 267 | fprintf(logfp, "(HDR->e_ident[EI_ABIVERSION] = 0x%.2x)", orcHDR->e_ident[EI_ABIVERSION]); 268 | 269 | return 1; 270 | } 271 | 272 | int hdr17(void) 273 | { 274 | orcHDR->e_ident[EI_OSABI] = rand() & 0xff; 275 | 276 | fprintf(logfp, "(HDR->e_ident[EI_OSABI] = 0x%.2x)", orcHDR->e_ident[EI_OSABI]); 277 | 278 | return 1; 279 | } 280 | 281 | int hdr18(void) 282 | { 283 | if(rand() % 2) 284 | orcHDR->e_type = ET_LOOS + 1; 285 | else 286 | orcHDR->e_type = ET_HIOS; 287 | 288 | fprintf(logfp, "(HDR->e_type = 0x%x)", orcHDR->e_type); 289 | 290 | return 1; 291 | } 292 | 293 | int hdr19(void) 294 | { 295 | if(mode & PHT) 296 | return 0; 297 | 298 | orcHDR->e_phnum = 32; 299 | 300 | fprintf(logfp, "(HDR->e_phnum = 0x00)"); 301 | 302 | return 1; 303 | } 304 | 305 | void initialize_hdr_funcs(void) 306 | { 307 | hdr[1] = &hdr1; 308 | hdr[2] = &hdr2; 309 | hdr[3] = &hdr3; 310 | hdr[4] = &hdr4; 311 | hdr[5] = &hdr5; 312 | hdr[6] = &hdr6; 313 | hdr[7] = &hdr7; 314 | hdr[8] = &hdr8; 315 | hdr[9] = &hdr9; 316 | hdr[10] = &hdr10; 317 | hdr[11] = &hdr11; 318 | hdr[12] = &hdr12; 319 | hdr[13] = &hdr13; 320 | hdr[14] = &hdr14; 321 | hdr[15] = &hdr15; 322 | hdr[16] = &hdr16; 323 | hdr[17] = &hdr17; 324 | hdr[18] = &hdr18; 325 | hdr[19] = &hdr19; 326 | } 327 | -------------------------------------------------------------------------------- /jni/src/fuzz_note.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Melkor - An ELF File Format Fuzzer 3 | * Copyright (C) 2014 Alejandro Hernandez H. (nitr0us) 4 | * 5 | * Mexico 6 | */ 7 | 8 | #include "melkor.h" 9 | 10 | #define N_RULES_NOTE 4 // Total of fuzzing rules defined for this metadata type 11 | 12 | // Array of function pointers. Index zero won't be used. The fuzzing rules start from index 1 13 | func_ptr note[N_RULES_NOTE + 1]; 14 | 15 | void initialize_note_funcs(void) __attribute__((constructor)); 16 | 17 | /* External vars */ 18 | extern FILE *logfp; 19 | extern unsigned int quiet; 20 | extern unsigned int like_a, like_b; 21 | extern unsigned int secnum; 22 | extern unsigned int entry; 23 | extern Elf_Nhdr *elfNOTE, *orcNOTE; 24 | 25 | void fuzz_note() 26 | { 27 | int rule; 28 | 29 | for(rule = 1; rule <= N_RULES_NOTE; rule++) 30 | if((rand() % like_a) < like_b) 31 | if(note[rule]()){ 32 | printf(". "); 33 | debug("SHT[%d] NOTE[%d] rule [%.2d] executed\n", secnum, entry, rule); 34 | fprintf(logfp, " | SHT[%d] NOTE[%d] rule [%.2d] executed\n", secnum, entry, rule); 35 | } 36 | } 37 | 38 | int note1(void) 39 | { 40 | orcNOTE->n_namesz = getElf_Word(); 41 | 42 | fprintf(logfp, "(NOTE[%d]->n_namesz = 0x%x)", entry, orcNOTE->n_namesz); 43 | 44 | return 1; 45 | } 46 | 47 | int note2(void) 48 | { 49 | unsigned int ptr_offset = 0; 50 | char *fmt_ptr; 51 | 52 | fprintf(logfp, "(NOTE[%d] + %d (sizeof(Elf_Nhdr)) + ", entry, (int) sizeof(Elf_Nhdr)); 53 | 54 | if(rand() % 3 == 0) 55 | while(ptr_offset < elfNOTE->n_namesz){ // Trusting in n_namesz from the original ELF. This field in the Orc might be already fuzzed 56 | fmt_ptr = get_fmt_str(); 57 | 58 | memcpy((void *) orcNOTE + sizeof(Elf_Nhdr) + ptr_offset, fmt_ptr, strlen(fmt_ptr)); 59 | fprintf(logfp, "%d =%s, ", ptr_offset, fmt_ptr); 60 | 61 | ptr_offset += 4; 62 | } 63 | else 64 | while(ptr_offset < elfNOTE->n_namesz){ 65 | if(*((char *) orcNOTE + sizeof(Elf_Nhdr) + ptr_offset) != 0){ 66 | ptr_offset++; 67 | continue; 68 | } 69 | 70 | *((char *) orcNOTE + sizeof(Elf_Nhdr) + ptr_offset) = (rand() & 0x7f) + 0x80; // > 7-bit ASCII chars 71 | fprintf(logfp, "%d = %c (0x%.2x), ", ptr_offset, *((char *) orcNOTE + sizeof(Elf_Nhdr) + ptr_offset), *((char *) orcNOTE + sizeof(Elf_Nhdr) + ptr_offset) & 0xff); 72 | ptr_offset++; 73 | } 74 | 75 | fprintf(logfp, ")"); 76 | 77 | return 1; 78 | } 79 | 80 | int note3(void) 81 | { 82 | unsigned int cnt = 0; 83 | int *desc = (int *) ((void *) orcNOTE + sizeof(Elf_Nhdr) + elfNOTE->n_namesz); 84 | 85 | fprintf(logfp, "(NOTE[%d] + %d (sizeof(Elf_Nhdr)) + %d (elfNOTE->n_namesz) + ", entry, (int) sizeof(Elf_Nhdr), elfNOTE->n_namesz); 86 | 87 | while(cnt < elfNOTE->n_descsz){ // Trusting in n_descsz from the original ELF. This field in the Orc might be already fuzzed 88 | *desc = getElf_Word(); 89 | 90 | fprintf(logfp, "%d = 0x%x, ", cnt, *desc); 91 | 92 | desc++; 93 | cnt += sizeof(Elf_Word); 94 | } 95 | 96 | fprintf(logfp, ")"); 97 | 98 | orcNOTE->n_descsz = getElf_Word(); 99 | 100 | fprintf(logfp, "(NOTE[%d]->n_descsz = 0x%x)", entry, orcNOTE->n_descsz); 101 | 102 | return 1; 103 | } 104 | 105 | int note4(void) 106 | { 107 | if(rand() % 4 < 3) // Metadata in previous rules is used based upon n_type 108 | return 0; 109 | 110 | orcNOTE->n_type = 0x80000000 + (rand() % 0x7fffffff); 111 | 112 | fprintf(logfp, "(NOTE[%d]->n_type = 0x%x)", entry, orcNOTE->n_type); 113 | 114 | return 1; 115 | } 116 | 117 | void initialize_note_funcs(void) 118 | { 119 | note[1] = ¬e1; 120 | note[2] = ¬e2; 121 | note[3] = ¬e3; 122 | note[4] = ¬e4; 123 | } 124 | -------------------------------------------------------------------------------- /jni/src/fuzz_pht.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Melkor - An ELF File Format Fuzzer 3 | * Copyright (C) 2014 Alejandro Hernandez H. (nitr0us) 4 | * 5 | * Mexico 6 | */ 7 | 8 | #include "melkor.h" 9 | 10 | #define N_RULES_PHT 22 // Total of fuzzing rules defined for this metadata type 11 | 12 | // Array of function pointers. Index zero won't be used. The fuzzing rules start from index 1 13 | func_ptr pht[N_RULES_PHT + 1]; 14 | int ph = 0; // Program Header. Used inside the for() loop in fuzz_pht() and will be used in the rules 15 | 16 | void initialize_pht_funcs(void) __attribute__((constructor)); 17 | 18 | /* External vars */ 19 | extern FILE *logfp; 20 | extern unsigned int mode; // Metadata to fuzz (parameters given in argv[]) 21 | extern unsigned int quiet; 22 | extern unsigned int like_a, like_b; 23 | extern char *dirname_orcfname; 24 | extern char *orcptr; 25 | extern Elf_Ehdr *elfHDR; 26 | extern Elf_Ehdr *orcHDR; 27 | extern Elf_Phdr *elfPHT; 28 | extern Elf_Phdr *orcPHT; 29 | extern Elf_Phdr *orcOrigPHT; 30 | 31 | void fuzz_pht() 32 | { 33 | int rule; 34 | 35 | for(ph = 0; ph < orcHDR->e_phnum; ph++, orcPHT++) 36 | for(rule = 1; rule <= 18; rule++) // Rules from 19 will be executed outside the for() loop 37 | if((rand() % like_a) < like_b) 38 | if(pht[rule]()){ 39 | printf(". "); 40 | debug("PHT[%d] rule [%.2d] executed\n", ph, rule); 41 | fprintf(logfp, " | PHT[%d] rule [%.2d] executed\n", ph, rule); 42 | } 43 | 44 | for( ; rule <= N_RULES_PHT; rule++) 45 | if((rand() % like_a) < like_b) 46 | if(pht[rule]()){ 47 | printf(". "); 48 | debug("PHT rule [%.2d] executed\n", rule); 49 | fprintf(logfp, " | PHT rule [%.2d] executed\n", rule); 50 | } 51 | } 52 | 53 | int pht1(void) 54 | { 55 | if(orcPHT->p_type == PT_INTERP) 56 | return 0; 57 | 58 | if(orcPHT->p_type == PT_DYNAMIC) 59 | if(mode & DYN) 60 | return 0; 61 | 62 | if(orcPHT->p_type == PT_NOTE) 63 | if(mode & NOTE) 64 | return 0; 65 | 66 | if(rand() % 2) // p_type is a critical field 67 | return 0; 68 | 69 | Elf_Word p_type; 70 | 71 | if(rand() % 2){ // 50% chance 72 | while((p_type = rand() % PT_NUM)){ 73 | switch(p_type){ 74 | case PT_INTERP: 75 | continue; 76 | break; 77 | case PT_DYNAMIC: 78 | if(mode & DYN) 79 | continue; 80 | break; 81 | case PT_NOTE: 82 | if(mode & NOTE) 83 | continue; 84 | break; 85 | } 86 | 87 | break; 88 | } 89 | } else { 90 | if(rand() % 2) 91 | p_type = getElf_Word() + PT_NUM; 92 | else 93 | p_type = 0; 94 | } 95 | 96 | orcPHT->p_type = p_type; 97 | 98 | fprintf(logfp, "(PHT[%d]->p_type = 0x%x)", ph, orcPHT->p_type); 99 | 100 | return 1; 101 | } 102 | 103 | int pht2(void) 104 | { 105 | if(orcPHT->p_type == PT_INTERP) 106 | if(rand() % 5 < 4) // 80% chance 107 | return 0; 108 | 109 | if(orcPHT->p_type == PT_DYNAMIC) 110 | if(mode & DYN) 111 | return 0; 112 | 113 | if(orcPHT->p_type == PT_NOTE) 114 | if(mode & NOTE) 115 | return 0; 116 | 117 | Elf_Off p_offset; 118 | 119 | if(rand() % 3 < 2){ // 66.66% chance 120 | while((p_offset = getElf_Off())) 121 | if(p_offset % PAGESIZE == 0) 122 | break; 123 | } else { 124 | while((p_offset = getElf_Off())) 125 | if(p_offset % PAGESIZE != 0) 126 | break; 127 | } 128 | 129 | orcPHT->p_offset = p_offset; 130 | 131 | fprintf(logfp, "(PHT[%d]->p_offset = 0x"HEX")", ph, orcPHT->p_offset); 132 | 133 | return 1; 134 | } 135 | 136 | int pht3(void) 137 | { 138 | if(orcPHT->p_type == PT_INTERP) 139 | if(rand() % 5 < 4) // 80% chance 140 | return 0; 141 | 142 | if(orcPHT->p_type == PT_DYNAMIC) 143 | if(mode & DYN) 144 | return 0; 145 | 146 | if(orcPHT->p_type == PT_NOTE) 147 | if(mode & NOTE) 148 | return 0; 149 | 150 | Elf_Addr v, p; 151 | 152 | if(rand() % 2){ 153 | if(rand() % 3 < 2){ // .5 * .6666 = 33.33% chance 154 | v = orcPHT->p_vaddr; 155 | p = getElf_Addr(); 156 | } else { // 16.66% chance 157 | v = getElf_Addr(); 158 | p = orcPHT->p_paddr; 159 | } 160 | } else { 161 | if(rand() % 2){ // .5 * .5 = 25% chance 162 | while((v = getElf_Addr())) 163 | if(v % PAGESIZE == 0){ 164 | if(rand() % 2) 165 | p = v; 166 | else 167 | p = getElf_Addr(); 168 | break; 169 | } 170 | } else { // 25% chance 171 | while((v = getElf_Addr())) 172 | if(v % PAGESIZE != 0){ 173 | if(rand() % 2) 174 | p = v; 175 | else 176 | p = getElf_Addr(); 177 | break; 178 | } 179 | } 180 | } 181 | 182 | orcPHT->p_vaddr = v; 183 | orcPHT->p_paddr = p; 184 | 185 | fprintf(logfp, "(PHT[%d]->p_vaddr = 0x"HEX",", ph, orcPHT->p_vaddr); 186 | fprintf(logfp, " p_paddr = 0x"HEX")", orcPHT->p_paddr); 187 | 188 | return 1; 189 | } 190 | 191 | int pht4(void) 192 | { 193 | if(orcPHT->p_type == PT_INTERP) 194 | if(rand() % 5 < 4) // 80% chance 195 | return 0; 196 | 197 | if(orcPHT->p_type == PT_DYNAMIC) 198 | if(mode & DYN) 199 | return 0; 200 | 201 | if(orcPHT->p_type == PT_NOTE) 202 | if(mode & NOTE) 203 | return 0; 204 | 205 | #if defined(__i386__) || defined(__ANDROID_API__) 206 | Elf_Word p_memsz; 207 | #elif defined(__x86_64__) 208 | Elf_Xword p_memsz; 209 | #endif 210 | int r = rand(); 211 | 212 | if(r % 3 == 0){ 213 | orcPHT->p_filesz = 0; 214 | #if defined(__i386__) || defined(__ANDROID_API__) 215 | while((p_memsz = getElf_Word())) 216 | #elif defined(__x86_64__) 217 | while((p_memsz = getElf_Xword())) 218 | #endif 219 | if(p_memsz % PAGESIZE == 0){ 220 | orcPHT->p_memsz = p_memsz; 221 | break; 222 | } 223 | } else if(r % 3 == 1){ 224 | #if defined(__i386__) || defined(__ANDROID_API__) 225 | orcPHT->p_filesz = getElf_Word(); 226 | #elif defined(__x86_64__) 227 | orcPHT->p_filesz = getElf_Xword(); 228 | #endif 229 | orcPHT->p_memsz = 0; 230 | } else { 231 | if(rand() % 2){ 232 | orcPHT->p_filesz = 0; 233 | orcPHT->p_memsz = 0; 234 | } else 235 | orcPHT->p_memsz = getElf_Word(); 236 | } 237 | 238 | fprintf(logfp, "(PHT[%d]->p_filesz = 0x"HEX",", ph, orcPHT->p_filesz); 239 | fprintf(logfp, " p_memsz = 0x"HEX")", orcPHT->p_memsz); 240 | 241 | return 1; 242 | } 243 | 244 | int pht5(void) 245 | { 246 | if(rand() % 2){ 247 | if(rand() % 2) 248 | orcPHT->p_align = PAGESIZE - 1; 249 | else 250 | orcPHT->p_align = PAGESIZE + 1; 251 | } else 252 | #if defined(__i386__) || defined(__ANDROID_API__) 253 | orcPHT->p_align = getElf_Word(); 254 | #elif defined(__x86_64__) 255 | orcPHT->p_align = getElf_Xword(); 256 | #endif 257 | 258 | fprintf(logfp, "(PHT[%d]->p_align = 0x"HEX")", ph, orcPHT->p_align); 259 | 260 | return 1; 261 | } 262 | 263 | int pht6(void) 264 | { 265 | if(orcPHT->p_type == PT_INTERP) 266 | return 0; 267 | 268 | if(orcPHT->p_type == PT_DYNAMIC) 269 | if(mode & DYN) 270 | return 0; 271 | 272 | if(orcPHT->p_type == PT_NOTE) 273 | if(mode & NOTE) 274 | return 0; 275 | 276 | if(rand() % 2) // p_type is a critical field 277 | return 0; 278 | 279 | Elf_Word p_type; 280 | 281 | while((p_type = (getElf_Word() + PT_LOPROC))) 282 | if(p_type >= PT_LOPROC && p_type < PT_HIPROC) 283 | break; 284 | 285 | orcPHT->p_type = p_type; 286 | 287 | fprintf(logfp, "(PHT[%d]->p_type = 0x%x)", ph, orcPHT->p_type); 288 | 289 | return 1; 290 | } 291 | 292 | int pht7(void) 293 | { 294 | if(orcPHT->p_type == PT_INTERP) 295 | if(rand() % 5 < 4) // 80% chance 296 | return 0; 297 | 298 | if(orcPHT->p_type == PT_DYNAMIC) 299 | if(mode & DYN) 300 | return 0; 301 | 302 | if(orcPHT->p_type == PT_NOTE) 303 | if(mode & NOTE) 304 | return 0; 305 | 306 | #if defined(__i386__) || defined(__ANDROID_API__) 307 | Elf_Word p_filesz; 308 | #elif defined(__x86_64__) 309 | Elf_Xword p_filesz; 310 | #endif 311 | 312 | if(rand() % 3 < 2){ 313 | #if defined(__i386__) || defined(__ANDROID_API__) 314 | while((p_filesz = getElf_Word())) 315 | #elif defined(__x86_64__) 316 | while((p_filesz = getElf_Xword())) 317 | #endif 318 | if(p_filesz > orcPHT->p_memsz){ 319 | orcPHT->p_filesz = p_filesz; 320 | break; 321 | } 322 | } else 323 | #if defined(__i386__) || defined(__ANDROID_API__) 324 | orcPHT->p_filesz = getElf_Word(); 325 | #elif defined(__x86_64__) 326 | orcPHT->p_filesz = getElf_Xword(); 327 | #endif 328 | 329 | fprintf(logfp, "(PHT[%d]->p_filesz = 0x"HEX")", ph, orcPHT->p_filesz); 330 | 331 | return 1; 332 | } 333 | 334 | int pht8(void) 335 | { 336 | if(orcPHT->p_type != PT_NOTE) 337 | return 0; 338 | 339 | if(mode & NOTE) 340 | return 0; 341 | 342 | #if defined(__i386__) || defined(__ANDROID_API__) 343 | Elf_Word p_filesz; 344 | #elif defined(__x86_64__) 345 | Elf_Xword p_filesz; 346 | #endif 347 | 348 | while((p_filesz = getElf_Half())) 349 | if(p_filesz % sizeof(Elf_Word) != 0) 350 | break; 351 | 352 | orcPHT->p_filesz = p_filesz; 353 | 354 | fprintf(logfp, "(PHT[%d]->p_filesz = 0x"HEX")", ph, orcPHT->p_filesz); 355 | 356 | return 1; 357 | } 358 | 359 | int pht9(void) 360 | { 361 | if(orcPHT->p_type != PT_INTERP) 362 | return 0; 363 | 364 | if(rand() % 3 == 0) // p_type is a critical field 365 | return 0; 366 | 367 | Elf_Word p_type; 368 | int r = rand(); 369 | 370 | if(r % 4 == 0){ // 25% chance 371 | while((p_type = getElf_Word())){ 372 | switch(p_type){ 373 | case PT_INTERP: 374 | continue; 375 | break; 376 | case PT_DYNAMIC: 377 | if(mode & DYN) 378 | continue; 379 | break; 380 | case PT_NOTE: 381 | if(mode & NOTE) 382 | continue; 383 | break; 384 | } 385 | 386 | break; 387 | } 388 | 389 | orcPHT->p_type = p_type; 390 | 391 | fprintf(logfp, "(PHT[%d]->p_type = 0x%x)", ph, orcPHT->p_type); 392 | } else if(r % 4 == 1){ // 25% chance 393 | int k; 394 | Elf_Phdr *tmpPHT = elfPHT; 395 | 396 | for(k = 0; k < elfHDR->e_phnum; k++, tmpPHT++) 397 | if(tmpPHT->p_type == PT_INTERP){ 398 | strncpy(orcptr + tmpPHT->p_offset, dirname_orcfname, strlen(dirname_orcfname)); 399 | *(orcptr + tmpPHT->p_offset + strlen(dirname_orcfname)) = '\0'; 400 | 401 | fprintf(logfp, "(PHT[PT_INTERP] = %s)", orcptr + tmpPHT->p_offset); 402 | 403 | return 1; 404 | } 405 | 406 | return 0; // Not found 407 | } else if(ph > 0){ 408 | if(rand() % 2){ 409 | if(mode & DYN) 410 | if(orcOrigPHT[ph - 1].p_type == PT_DYNAMIC) 411 | return 0; 412 | 413 | if(mode & NOTE) 414 | if(orcOrigPHT[ph - 1].p_type == PT_NOTE) 415 | return 0; 416 | 417 | orcOrigPHT[ph - 1].p_type = PT_INTERP; 418 | 419 | fprintf(logfp, "(PHT[%d - 1]->p_type = 0x%x)", ph, orcOrigPHT[ph - 1].p_type); 420 | } else if(ph < (orcHDR->e_phnum - 1)){ 421 | if(mode & DYN) 422 | if(orcOrigPHT[ph + 1].p_type == PT_DYNAMIC) 423 | return 0; 424 | 425 | if(mode & NOTE) 426 | if(orcOrigPHT[ph + 1].p_type == PT_NOTE) 427 | return 0; 428 | 429 | orcOrigPHT[ph + 1].p_type = PT_INTERP; 430 | 431 | fprintf(logfp, "(PHT[%d + 1]->p_type = 0x%x)", ph, orcOrigPHT[ph + 1].p_type); 432 | } 433 | } else 434 | return 0; 435 | 436 | return 1; 437 | } 438 | 439 | int pht10(void) 440 | { 441 | if(rand() % 2) 442 | orcPHT->p_flags = getElf_Half(); 443 | else 444 | orcPHT->p_flags |= PF_MASKPROC; 445 | 446 | fprintf(logfp, "(PHT[%d]->p_flags = 0x%x)", ph, orcPHT->p_flags); 447 | 448 | return 1; 449 | } 450 | 451 | int pht11(void) 452 | { 453 | if(orcPHT->p_flags & PF_X) 454 | orcPHT->p_flags |= PF_W; 455 | else 456 | return 0; 457 | 458 | fprintf(logfp, "(PHT[%d]->p_flags = 0x%x)", ph, orcPHT->p_flags); 459 | 460 | return 1; 461 | } 462 | 463 | int pht12(void) 464 | { 465 | if(orcPHT->p_type != PT_DYNAMIC) 466 | return 0; 467 | 468 | if(mode & DYN) 469 | return 0; 470 | 471 | orcPHT->p_offset = getElf_Off(); 472 | orcPHT->p_vaddr = getElf_Addr(); 473 | 474 | fprintf(logfp, "(PHT[%d]->p_offset = 0x"HEX",", ph, orcPHT->p_offset); 475 | fprintf(logfp, " p_vaddr = 0x"HEX")", orcPHT->p_vaddr); 476 | 477 | return 1; 478 | } 479 | 480 | int pht13(void) 481 | { 482 | if(rand() % 2) // p_type is a critical field 483 | return 0; 484 | 485 | if(orcOrigPHT[orcHDR->e_phnum - 1].p_type != PT_NULL && 486 | orcOrigPHT[orcHDR->e_phnum - 1].p_type != PT_GNU_RELRO && 487 | orcOrigPHT[orcHDR->e_phnum - 1].p_type != PT_GNU_EH_FRAME && 488 | orcOrigPHT[orcHDR->e_phnum - 1].p_type != PT_GNU_STACK) 489 | return 0; 490 | 491 | orcOrigPHT[orcHDR->e_phnum - 1].p_type = PT_SHLIB; 492 | 493 | fprintf(logfp, "(PHT[%d - 1]->p_type = 0x%x)", orcHDR->e_phnum, orcOrigPHT[orcHDR->e_phnum - 1].p_type); 494 | 495 | return 1; 496 | } 497 | 498 | int pht14(void) 499 | { 500 | if(orcPHT->p_type != PT_NULL && 501 | orcPHT->p_type != PT_GNU_RELRO && 502 | orcPHT->p_type != PT_GNU_EH_FRAME && 503 | orcPHT->p_type != PT_GNU_STACK) 504 | return 0; 505 | 506 | if(rand() % 2) // p_type is a critical field 507 | return 0; 508 | 509 | if(rand() % 2) 510 | orcPHT->p_type = PT_LOOS; 511 | else 512 | orcPHT->p_type = PT_HIOS; 513 | 514 | fprintf(logfp, "(PHT[%d]->p_type = 0x%x)", ph, orcPHT->p_type); 515 | 516 | return 1; 517 | } 518 | 519 | int pht15(void) 520 | { 521 | orcPHT->p_flags |= PF_MASKOS; 522 | 523 | fprintf(logfp, "(PHT[%d]->p_flags = 0x%x)", ph, orcPHT->p_flags); 524 | 525 | return 1; 526 | } 527 | 528 | int pht16(void) 529 | { 530 | if(orcPHT->p_type != PT_PAX_FLAGS && 531 | orcPHT->p_type != PT_GNU_RELRO && 532 | orcPHT->p_type != PT_GNU_STACK) 533 | return 0; 534 | 535 | if(rand() % 3 == 0) 536 | orcPHT->p_offset = getElf_Off(); 537 | orcPHT->p_vaddr = getElf_Addr(); 538 | #if defined(__i386__) || defined(__ANDROID_API__) 539 | orcPHT->p_filesz = getElf_Word(); 540 | #elif defined(__x86_64__) 541 | orcPHT->p_filesz = getElf_Xword(); 542 | #endif 543 | #if defined(__i386__) || defined(__ANDROID_API__) 544 | orcPHT->p_memsz = getElf_Word(); 545 | #elif defined(__x86_64__) 546 | orcPHT->p_memsz = getElf_Xword(); 547 | #endif 548 | orcPHT->p_flags = getElf_Word(); 549 | #if defined(__i386__) || defined(__ANDROID_API__) 550 | orcPHT->p_align = getElf_Word(); 551 | #elif defined(__x86_64__) 552 | orcPHT->p_align = getElf_Xword(); 553 | #endif 554 | 555 | fprintf(logfp, "(PHT[%d]->p_offset = 0x"HEX",", ph, orcPHT->p_offset); 556 | fprintf(logfp, " p_vaddr = 0x"HEX",", orcPHT->p_vaddr); 557 | fprintf(logfp, " p_filesz = 0x"HEX",", orcPHT->p_filesz); 558 | fprintf(logfp, " p_memsz = 0x"HEX",", orcPHT->p_memsz); 559 | fprintf(logfp, " p_flags = 0x%x,", orcPHT->p_flags); 560 | fprintf(logfp, " p_align = 0x"HEX")", orcPHT->p_align); 561 | 562 | return 1; 563 | } 564 | 565 | int pht17(void) 566 | { 567 | if(orcPHT->p_type != PT_TLS) 568 | return 0; 569 | 570 | if(rand() % 3 == 0) 571 | orcPHT->p_offset = getElf_Off(); 572 | orcPHT->p_vaddr = getElf_Addr(); 573 | #if defined(__i386__) || defined(__ANDROID_API__) 574 | orcPHT->p_filesz = getElf_Word(); 575 | #elif defined(__x86_64__) 576 | orcPHT->p_filesz = getElf_Xword(); 577 | #endif 578 | #if defined(__i386__) || defined(__ANDROID_API__) 579 | orcPHT->p_memsz = getElf_Word(); 580 | #elif defined(__x86_64__) 581 | orcPHT->p_memsz = getElf_Xword(); 582 | #endif 583 | orcPHT->p_flags = getElf_Word(); 584 | #if defined(__i386__) || defined(__ANDROID_API__) 585 | orcPHT->p_align = getElf_Word(); 586 | #elif defined(__x86_64__) 587 | orcPHT->p_align = getElf_Xword(); 588 | #endif 589 | 590 | fprintf(logfp, "(PHT[%d]->p_offset = 0x"HEX",", ph, orcPHT->p_offset); 591 | fprintf(logfp, " p_vaddr = 0x"HEX",", orcPHT->p_vaddr); 592 | fprintf(logfp, " p_filesz = 0x"HEX",", orcPHT->p_filesz); 593 | fprintf(logfp, " p_memsz = 0x"HEX",", orcPHT->p_memsz); 594 | fprintf(logfp, " p_flags = 0x%x,", orcPHT->p_flags); 595 | fprintf(logfp, " p_align = 0x"HEX")", orcPHT->p_align); 596 | 597 | return 1; 598 | } 599 | 600 | int pht18(void) 601 | { 602 | if(orcPHT->p_type != PT_GNU_EH_FRAME) 603 | return 0; 604 | 605 | if(rand() % 3 == 0) 606 | orcPHT->p_offset = getElf_Off(); 607 | orcPHT->p_vaddr = getElf_Addr(); 608 | #if defined(__i386__) || defined(__ANDROID_API__) 609 | orcPHT->p_filesz = getElf_Word(); 610 | #elif defined(__x86_64__) 611 | orcPHT->p_filesz = getElf_Xword(); 612 | #endif 613 | #if defined(__i386__) || defined(__ANDROID_API__) 614 | orcPHT->p_memsz = getElf_Word(); 615 | #elif defined(__x86_64__) 616 | orcPHT->p_memsz = getElf_Xword(); 617 | #endif 618 | orcPHT->p_flags = getElf_Word(); 619 | #if defined(__i386__) || defined(__ANDROID_API__) 620 | orcPHT->p_align = getElf_Word(); 621 | #elif defined(__x86_64__) 622 | orcPHT->p_align = getElf_Xword(); 623 | #endif 624 | 625 | fprintf(logfp, "(PHT[%d]->p_offset = 0x"HEX",", ph, orcPHT->p_offset); 626 | fprintf(logfp, " p_vaddr = 0x"HEX",", orcPHT->p_vaddr); 627 | fprintf(logfp, " p_filesz = 0x"HEX",", orcPHT->p_filesz); 628 | fprintf(logfp, " p_memsz = 0x"HEX",", orcPHT->p_memsz); 629 | fprintf(logfp, " p_flags = 0x%x,", orcPHT->p_flags); 630 | fprintf(logfp, " p_align = 0x"HEX")", orcPHT->p_align); 631 | 632 | return 1; 633 | } 634 | 635 | int pht19(void) 636 | { 637 | int p, last_PT = -1; 638 | Elf_Phdr *tmpPHT = orcOrigPHT; 639 | int r = rand(); 640 | 641 | if(r % 3 == 0){ // 33.33% chance // Deletes the PT_PHDR from the PHT 642 | for(p = 0; p < orcHDR->e_phnum; p++, tmpPHT++) 643 | if(tmpPHT->p_type == PT_PHDR){ 644 | tmpPHT->p_type = getElf_Word(); 645 | 646 | fprintf(logfp, "(PHT[%d]->p_type = 0x%x)", p, tmpPHT->p_type); 647 | 648 | break; 649 | } 650 | } else if(r % 3 == 1){ // Create an extra PT_PHT right after the first one found in the PHT 651 | for(p = 0; p < orcHDR->e_phnum; p++, tmpPHT++) 652 | if(tmpPHT->p_type == PT_PHDR) 653 | last_PT = p; 654 | 655 | if(last_PT == -1) 656 | return 0; 657 | 658 | if(last_PT == (orcHDR->e_phnum - 1)){ // No more program headers 659 | if(mode & DYN) 660 | if(orcOrigPHT[last_PT].p_type == PT_DYNAMIC) 661 | return 0; 662 | 663 | if(mode & NOTE) 664 | if(orcOrigPHT[last_PT].p_type == PT_NOTE) 665 | return 0; 666 | 667 | orcOrigPHT[last_PT].p_type = PT_PHDR; 668 | 669 | fprintf(logfp, "(PHT[%d]->p_type = 0x%x)", last_PT, orcOrigPHT[last_PT].p_type); 670 | } else { // Set to PT_PHT right after the latest found 671 | if(mode & DYN) 672 | if(orcOrigPHT[last_PT + 1].p_type == PT_DYNAMIC) 673 | return 0; 674 | 675 | if(mode & NOTE) 676 | if(orcOrigPHT[last_PT + 1].p_type == PT_NOTE) 677 | return 0; 678 | 679 | orcOrigPHT[last_PT + 1].p_type = PT_PHDR; 680 | 681 | fprintf(logfp, "(PHT[%d + 1]->p_type = 0x%x)", last_PT, orcOrigPHT[last_PT + 1].p_type); 682 | } 683 | } else { // Set to PT_PHDR the latest entry in the PHT (after the PT_LOAD segments) 684 | if(mode & DYN) 685 | if(orcOrigPHT[orcHDR->e_phnum - 1].p_type == PT_DYNAMIC) 686 | return 0; 687 | 688 | if(mode & NOTE) 689 | if(orcOrigPHT[orcHDR->e_phnum - 1].p_type == PT_NOTE) 690 | return 0; 691 | 692 | orcOrigPHT[orcHDR->e_phnum - 1].p_type = PT_PHDR; 693 | 694 | fprintf(logfp, "(PHT[%d - 1]->p_type = 0x%x)", orcHDR->e_phnum, orcOrigPHT[orcHDR->e_phnum - 1].p_type); 695 | } 696 | 697 | return 1; 698 | } 699 | 700 | int pht20(void) 701 | { 702 | int a, b; 703 | Elf_Phdr swap; 704 | 705 | // Bubble sort algorithm to put the PT_LOAD segments in decreasing order based in their p_vaddr 706 | for(a = 0; a < orcHDR->e_phnum - 1; a++){ 707 | if(orcOrigPHT[a].p_type != PT_LOAD) 708 | continue; 709 | 710 | for(b = 0; b < orcHDR->e_phnum - 1 - a; b++){ 711 | if(orcOrigPHT[b].p_type != PT_LOAD) 712 | continue; 713 | 714 | if(orcOrigPHT[b].p_vaddr < orcOrigPHT[a].p_vaddr){ 715 | memcpy(&swap, &orcOrigPHT[b], sizeof(Elf_Phdr)); 716 | memcpy(&orcOrigPHT[b], &orcOrigPHT[b + 1], sizeof(Elf_Phdr)); 717 | memcpy(&orcOrigPHT[b + 1], &swap, sizeof(Elf_Phdr)); 718 | } 719 | } 720 | } 721 | 722 | fprintf(logfp, "(PHT[PT_LOAD].p_vaddr reordered [descending])"); 723 | 724 | return 1; 725 | } 726 | 727 | int pht21(void) 728 | { 729 | int p, last_INTERP = -1; 730 | Elf_Phdr swap, *tmpPHT = orcOrigPHT; 731 | 732 | for(p = 0; p < orcHDR->e_phnum; p++, tmpPHT++) 733 | if(tmpPHT->p_type == PT_INTERP) 734 | last_INTERP = p; 735 | 736 | if(last_INTERP == -1) 737 | return 0; 738 | 739 | memcpy(&swap, &orcOrigPHT[last_INTERP], sizeof(Elf_Phdr)); 740 | memcpy(&orcOrigPHT[last_INTERP], &orcOrigPHT[orcHDR->e_phnum - 1], sizeof(Elf_Phdr)); 741 | memcpy(&orcOrigPHT[orcHDR->e_phnum - 1], &swap, sizeof(Elf_Phdr)); 742 | 743 | fprintf(logfp, "(PHT[PT_INTERP] relocated to the end of the PHT. PHT[%d] is now PHT[%d])", orcHDR->e_phnum - 1, last_INTERP); 744 | 745 | return 1; 746 | } 747 | 748 | int pht22(void) 749 | { 750 | int p, found = 0; 751 | Elf_Phdr *tmpPHT = orcOrigPHT; 752 | 753 | for(p = 0; p < orcHDR->e_phnum; p++, tmpPHT++) 754 | if(tmpPHT->p_type == PT_DYNAMIC){ 755 | found++; 756 | break; 757 | } 758 | 759 | if(found){ 760 | if(mode & DYN) 761 | return 0; 762 | 763 | if(rand() % 2) // PT_DYNAMIC is important 764 | return 0; 765 | 766 | if(rand() % 3 == 0) 767 | tmpPHT->p_offset = getElf_Off(); 768 | tmpPHT->p_vaddr = getElf_Addr(); 769 | #if defined(__i386__) || defined(__ANDROID_API__) 770 | tmpPHT->p_filesz = getElf_Word(); 771 | #elif defined(__x86_64__) 772 | tmpPHT->p_filesz = getElf_Xword(); 773 | #endif 774 | #if defined(__i386__) || defined(__ANDROID_API__) 775 | tmpPHT->p_memsz = getElf_Word(); 776 | #elif defined(__x86_64__) 777 | tmpPHT->p_memsz = getElf_Xword(); 778 | #endif 779 | tmpPHT->p_flags = getElf_Word(); 780 | #if defined(__i386__) || defined(__ANDROID_API__) 781 | tmpPHT->p_align = getElf_Word(); 782 | #elif defined(__x86_64__) 783 | tmpPHT->p_align = getElf_Xword(); 784 | #endif 785 | 786 | fprintf(logfp, "(PHT[%d]->p_offset = 0x"HEX",", p, tmpPHT->p_offset); 787 | fprintf(logfp, " p_vaddr = 0x"HEX",", tmpPHT->p_vaddr); 788 | fprintf(logfp, " p_filesz = 0x"HEX",", tmpPHT->p_filesz); 789 | fprintf(logfp, " p_memsz = 0x"HEX",", tmpPHT->p_memsz); 790 | fprintf(logfp, " p_flags = 0x%x,", tmpPHT->p_flags); 791 | fprintf(logfp, " p_align = 0x"HEX")", tmpPHT->p_align); 792 | 793 | return 1; 794 | } else { 795 | tmpPHT = orcOrigPHT; 796 | 797 | for(p = 0; p < orcHDR->e_phnum; p++, tmpPHT++) 798 | if(tmpPHT->p_type == PT_NULL){ 799 | if(mode & DYN) 800 | return 0; 801 | 802 | tmpPHT->p_type = PT_DYNAMIC; 803 | 804 | fprintf(logfp, "(PHT[%d]->p_type = 0x%x)", p, tmpPHT->p_type); 805 | 806 | return 1; 807 | } 808 | 809 | tmpPHT = orcOrigPHT; 810 | 811 | // Less priority than overwriting a PT_NULL 812 | for(p = 0; p < orcHDR->e_phnum; p++, tmpPHT++) 813 | if(tmpPHT->p_type == PT_GNU_STACK){ 814 | if(mode & DYN) 815 | return 0; 816 | 817 | tmpPHT->p_type = PT_DYNAMIC; 818 | 819 | fprintf(logfp, "(PHT[%d]->p_type = 0x%x)", p, tmpPHT->p_type); 820 | 821 | return 1; 822 | } 823 | 824 | return 0; 825 | } 826 | } 827 | 828 | void initialize_pht_funcs(void) 829 | { 830 | pht[1] = &pht1; 831 | pht[2] = &pht2; 832 | pht[3] = &pht3; 833 | pht[4] = &pht4; 834 | pht[5] = &pht5; 835 | pht[6] = &pht6; 836 | pht[7] = &pht7; 837 | pht[8] = &pht8; 838 | pht[9] = &pht9; 839 | pht[10] = &pht10; 840 | pht[11] = &pht11; 841 | pht[12] = &pht12; 842 | pht[13] = &pht13; 843 | pht[14] = &pht14; 844 | pht[15] = &pht15; 845 | pht[16] = &pht16; 846 | pht[17] = &pht17; 847 | pht[18] = &pht18; 848 | pht[19] = &pht19; 849 | pht[20] = &pht20; 850 | pht[21] = &pht21; 851 | pht[22] = &pht22; 852 | } 853 | -------------------------------------------------------------------------------- /jni/src/fuzz_rel.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Melkor - An ELF File Format Fuzzer 3 | * Copyright (C) 2014 Alejandro Hernandez H. (nitr0us) 4 | * 5 | * Mexico 6 | */ 7 | 8 | #include "melkor.h" 9 | 10 | #define N_RULES_REL 3 // Total of fuzzing rules defined for this metadata type 11 | 12 | // Array of function pointers. Index zero won't be used. The fuzzing rules start from index 1 13 | func_ptr rel[N_RULES_REL + 1]; 14 | 15 | void initialize_rel_funcs(void) __attribute__((constructor)); 16 | 17 | /* External vars */ 18 | extern FILE *logfp; 19 | extern unsigned int quiet; 20 | extern unsigned int like_a, like_b; 21 | extern unsigned int secnum; 22 | extern unsigned int entry; 23 | extern Elf_Ehdr *orcHDR; 24 | extern Elf_Shdr *orcSHT; 25 | extern Elf_Rel *orcREL; 26 | extern Elf_Rela *orcRELA; 27 | 28 | void fuzz_rel() 29 | { 30 | int rule; 31 | 32 | for(rule = 1; rule <= N_RULES_REL; rule++) 33 | if((rand() % like_a) < like_b) 34 | if(rel[rule]()){ 35 | printf(". "); 36 | debug("SHT[%d] REL[%d] rule [%.2d] executed\n", secnum, entry, rule); 37 | fprintf(logfp, " | SHT[%d] REL[%d] rule [%.2d] executed\n", secnum, entry, rule); 38 | } 39 | } 40 | 41 | int rel1(void) 42 | { 43 | if(rand() % 3 < 2) 44 | return 0; 45 | 46 | if(orcHDR->e_type == ET_REL){ 47 | if(orcSHT->sh_type == SHT_REL) 48 | orcREL->r_offset = getElf_Half(); 49 | else 50 | orcRELA->r_offset = getElf_Half(); 51 | } else if(orcHDR->e_type == ET_EXEC || orcHDR->e_type == ET_DYN){ 52 | if(orcSHT->sh_type == SHT_REL) 53 | orcREL->r_offset = getElf_Addr(); 54 | else 55 | orcRELA->r_offset = getElf_Addr(); 56 | } else 57 | return 0; 58 | 59 | fprintf(logfp, "(REL[%d]->r_offset = 0x"HEX")", entry, orcSHT->sh_type == SHT_REL ? orcREL->r_offset : orcRELA->r_offset); 60 | 61 | return 1; 62 | } 63 | 64 | int rel2(void) 65 | { 66 | if(rand() % 3 < 2) 67 | return 0; 68 | 69 | if(rand() % 4 < 3){ // 75% chance to only change its related Symbol Table index 70 | Elf_Section sym_ndx; 71 | 72 | if(rand() % 2) 73 | sym_ndx = rand() % orcHDR->e_shnum; // A random but valid Symbol Table index within the SHT 74 | else 75 | sym_ndx = getElf_Section(); 76 | 77 | if(orcSHT->sh_type == SHT_REL) 78 | orcREL->r_info = ELF_R_INFO(sym_ndx, ELF_R_TYPE(orcREL->r_info)); 79 | else 80 | orcRELA->r_info = ELF_R_INFO(sym_ndx, ELF_R_TYPE(orcRELA->r_info)); 81 | } else { 82 | if(orcSHT->sh_type == SHT_REL) 83 | #if defined(__i386__) || defined(__ANDROID_API__) 84 | orcREL->r_info = getElf_Word(); 85 | #elif defined(__x86_64__) 86 | orcREL->r_info = getElf_Xword(); 87 | #endif 88 | else 89 | #if defined(__i386__) || defined(__ANDROID_API__) 90 | orcRELA->r_info = getElf_Word(); 91 | #elif defined(__x86_64__) 92 | orcRELA->r_info = getElf_Xword(); 93 | #endif 94 | } 95 | 96 | fprintf(logfp, "(REL[%d]->r_info = 0x"HEX")", entry, orcSHT->sh_type == SHT_REL ? orcREL->r_info : orcRELA->r_info); 97 | 98 | return 1; 99 | } 100 | 101 | int rel3(void) 102 | { 103 | if(orcSHT->sh_type == SHT_REL) 104 | return 0; 105 | 106 | if(rand() % 3 < 2) 107 | return 0; 108 | 109 | // r_addend is a Sword (Signed Word) 110 | if(rand() % 2){ // 75% chance to set r_addend to a negative number > 0x7fffffff 111 | #if defined(__x86_64__) 112 | if(rand() % 2) 113 | orcRELA->r_addend = 0x8000000000000000 + (rand() % 0x7fffffff); 114 | else 115 | #endif 116 | orcRELA->r_addend = 0x80000000 + (rand() % 0x7fffffff); 117 | } else { 118 | if(rand() % 2) 119 | orcRELA->r_addend = getElf_Word(); 120 | else 121 | orcRELA->r_addend = getElf_Xword(); 122 | } 123 | 124 | fprintf(logfp, "(REL[%d]->r_addend = 0x"HEX")", entry, orcRELA->r_addend); 125 | 126 | return 1; 127 | } 128 | 129 | void initialize_rel_funcs(void) 130 | { 131 | rel[1] = &rel1; 132 | rel[2] = &rel2; 133 | rel[3] = &rel3; 134 | } 135 | -------------------------------------------------------------------------------- /jni/src/fuzz_sht.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Melkor - An ELF File Format Fuzzer 3 | * Copyright (C) 2014 Alejandro Hernandez H. (nitr0us) 4 | * 5 | * Mexico 6 | */ 7 | 8 | #include "melkor.h" 9 | #include 10 | 11 | #define N_RULES_SHT 37 // Total of fuzzing rules defined for this metadata type 12 | 13 | // Array of function pointers. Index zero won't be used. The fuzzing rules start from index 1 14 | func_ptr sht[N_RULES_SHT + 1]; 15 | int sh = 0; // Section Header. Used inside the for() loop in fuzz_sht() and will be used in the rules 16 | 17 | void initialize_sht_funcs(void) __attribute__((constructor)); 18 | 19 | /* External vars */ 20 | extern FILE *logfp; 21 | extern unsigned int mode; // Metadata to fuzz (parameters given in argv[]) 22 | extern unsigned int quiet; 23 | extern unsigned int like_a, like_b; 24 | extern struct stat elfstatinfo; 25 | extern char *dirname_orcfname; 26 | extern char *elfptr, *orcptr; 27 | extern Elf_Ehdr *elfHDR; 28 | extern Elf_Ehdr *orcHDR; 29 | extern Elf_Shdr *elfSHT; 30 | extern Elf_Shdr *orcSHT; 31 | extern Elf_Shdr *orcOrigSHT; 32 | extern Elf_Off elfshstrtab_offset; 33 | 34 | void fuzz_sht() 35 | { 36 | int rule; 37 | 38 | for(sh = 0; sh < orcHDR->e_shnum; sh++, orcSHT++) 39 | for(rule = 1; rule <= N_RULES_SHT; rule++) 40 | if((rand() % like_a) < like_b) 41 | if(sht[rule]()){ 42 | printf(". "); 43 | debug("SHT[%d] rule [%.2d] executed\n", sh, rule); 44 | fprintf(logfp, " | SHT[%d] rule [%.2d] executed\n", sh, rule); 45 | } 46 | } 47 | 48 | int sht1(void) 49 | { 50 | // Metadata dependencies 51 | switch(orcSHT->sh_type){ 52 | case SHT_STRTAB: 53 | if(mode & STRS) 54 | if(rand() % 3 < 2) 55 | return 0; 56 | break; 57 | case SHT_NOTE: 58 | if(mode & NOTE) 59 | if(rand() % 3 < 2) 60 | return 0; 61 | break; 62 | case SHT_DYNAMIC: 63 | if(mode & DYN) 64 | if(rand() % 3 < 2) 65 | return 0; 66 | break; 67 | case SHT_SYMTAB: 68 | case SHT_DYNSYM: 69 | if(mode & SYM) 70 | if(rand() % 3 < 2) 71 | return 0; 72 | break; 73 | case SHT_RELA: 74 | case SHT_REL: 75 | if(mode & REL) 76 | if(rand() % 3 < 2) 77 | return 0; 78 | break; 79 | default: 80 | if(rand() % 2) 81 | return 0; 82 | } 83 | 84 | fuzzName(); 85 | 86 | fprintf(logfp, "(SHT[%d]->sh_name = 0x%x)", sh, orcSHT->sh_name); 87 | 88 | return 1; 89 | } 90 | 91 | int sht2(void) 92 | { 93 | if(rand() % 3 == 0) 94 | return 0; 95 | 96 | orcSHT->sh_addr = getElf_Addr(); 97 | 98 | fprintf(logfp, "(SHT[%d]->sh_addr = 0x"HEX")", sh, orcSHT->sh_addr); 99 | 100 | return 1; 101 | } 102 | 103 | int sht3(void) 104 | { 105 | // Metadata dependencies 106 | switch(orcSHT->sh_type){ 107 | case SHT_STRTAB: 108 | if(mode & STRS) 109 | return 0; 110 | break; 111 | case SHT_NOTE: 112 | if(mode & NOTE) 113 | return 0; 114 | break; 115 | case SHT_DYNAMIC: 116 | if(mode & DYN) 117 | return 0; 118 | break; 119 | case SHT_SYMTAB: 120 | case SHT_DYNSYM: 121 | if(mode & (SYM | REL)) // In REL, sh_offset of the symbol table will be needed 122 | return 0; 123 | break; 124 | case SHT_RELA: 125 | case SHT_REL: 126 | if(mode & REL) 127 | return 0; 128 | break; 129 | default: 130 | if(rand() % 5 < 4) // 80% chance 131 | return 0; 132 | } 133 | 134 | orcSHT->sh_offset = getElf_Off(); 135 | 136 | fprintf(logfp, "(SHT[%d]->sh_offset = 0x"HEX")", sh, orcSHT->sh_offset); 137 | 138 | return 1; 139 | } 140 | 141 | int sht4(void) 142 | { 143 | // Metadata dependencies 144 | switch(orcSHT->sh_type){ 145 | case SHT_STRTAB: 146 | if(mode & STRS) 147 | if(rand() % 2) // 50% chance 148 | return 0; 149 | break; 150 | case SHT_NOTE: 151 | if(mode & NOTE) 152 | if(rand() % 2) 153 | return 0; 154 | break; 155 | case SHT_DYNAMIC: 156 | if(mode & DYN) 157 | if(rand() % 4 < 3) 158 | return 0; 159 | break; 160 | case SHT_SYMTAB: 161 | case SHT_DYNSYM: 162 | if(mode & SYM) 163 | if(rand() % 4 < 3) 164 | return 0; 165 | break; 166 | case SHT_RELA: 167 | case SHT_REL: 168 | if(mode & REL) 169 | if(rand() % 4 < 3) 170 | return 0; 171 | break; 172 | default: 173 | if(rand() % 3 < 2) 174 | return 0; 175 | } 176 | 177 | fuzzSize(); 178 | 179 | fprintf(logfp, "(SHT[%d]->sh_size = 0x"HEX")", sh, orcSHT->sh_size); 180 | 181 | return 1; 182 | } 183 | 184 | int sht5(void) 185 | { 186 | fuzzAddrAlign(); 187 | 188 | fprintf(logfp, "(SHT[%d]->sh_addralign = 0x"HEX")", sh, orcSHT->sh_addralign); 189 | 190 | return 1; 191 | } 192 | 193 | int sht6(void) 194 | { 195 | // Metadata dependencies 196 | switch(orcSHT->sh_type){ 197 | case SHT_DYNAMIC: 198 | if(mode & DYN) 199 | if(rand() % 4 < 3) 200 | return 0; 201 | break; 202 | case SHT_SYMTAB: 203 | case SHT_DYNSYM: 204 | if(mode & SYM) 205 | if(rand() % 4 < 3) 206 | return 0; 207 | break; 208 | case SHT_RELA: 209 | case SHT_REL: 210 | if(mode & REL) 211 | if(rand() % 4 < 3) 212 | return 0; 213 | break; 214 | default: 215 | if(rand() % 2) 216 | return 0; 217 | } 218 | 219 | fuzzEntSize(); 220 | 221 | fprintf(logfp, "(SHT[%d]->sh_entsize = 0x"HEX")", sh, orcSHT->sh_entsize); 222 | 223 | return 1; 224 | } 225 | 226 | int sht7(void) 227 | { 228 | // Metadata dependencies 229 | switch(orcSHT->sh_type){ 230 | case SHT_STRTAB: 231 | if(mode & STRS) 232 | return 0; 233 | break; 234 | case SHT_NOTE: 235 | if(mode & NOTE) 236 | return 0; 237 | break; 238 | case SHT_DYNAMIC: 239 | if(mode & DYN) 240 | return 0; 241 | break; 242 | case SHT_SYMTAB: 243 | case SHT_DYNSYM: 244 | if(mode & (SYM | REL)) // In REL, sh_type of the symbol table will be needed 245 | return 0; 246 | break; 247 | case SHT_RELA: 248 | case SHT_REL: 249 | if(mode & REL) 250 | return 0; 251 | break; 252 | default: 253 | if(rand() % 4 < 3) 254 | return 0; 255 | } 256 | 257 | if(rand() % 4 < 3){ // 75% chance 258 | Elf_Word t; 259 | 260 | while((t = rand() % SHT_NUM)){ 261 | switch(t){ // Metadata dependencies 262 | case SHT_STRTAB: 263 | if(mode & STRS) 264 | continue; 265 | break; 266 | case SHT_NOTE: 267 | if(mode & NOTE) 268 | continue; 269 | break; 270 | case SHT_DYNAMIC: 271 | if(mode & DYN) 272 | continue; 273 | break; 274 | case SHT_SYMTAB: 275 | case SHT_DYNSYM: 276 | if(mode & (SYM | REL)) // In REL, sh_type of the symbol table will be needed 277 | continue; 278 | break; 279 | case SHT_REL: 280 | case SHT_RELA: 281 | if(mode & REL) 282 | continue; 283 | break; 284 | default: 285 | break; 286 | } 287 | 288 | break; 289 | } 290 | 291 | orcSHT->sh_type = t; 292 | } else 293 | orcSHT->sh_type = getElf_Word(); 294 | 295 | fprintf(logfp, "(SHT[%d]->sh_type = 0x%x)", sh, orcSHT->sh_type); 296 | 297 | return 1; 298 | } 299 | 300 | int sht8(void) 301 | { 302 | // Metadata dependencies 303 | switch(orcSHT->sh_type){ 304 | case SHT_STRTAB: 305 | if(mode & STRS) 306 | return 0; 307 | break; 308 | case SHT_NOTE: 309 | if(mode & NOTE) 310 | return 0; 311 | break; 312 | case SHT_DYNAMIC: 313 | if(mode & DYN) 314 | return 0; 315 | break; 316 | case SHT_SYMTAB: 317 | case SHT_DYNSYM: 318 | if(mode & (SYM | REL)) // In REL, sh_type of the symbol table will be needed 319 | return 0; 320 | break; 321 | case SHT_RELA: 322 | case SHT_REL: 323 | if(mode & REL) 324 | return 0; 325 | break; 326 | default: 327 | if(rand() % 5 < 4) // 80% chance 328 | return 0; 329 | } 330 | 331 | int r = rand(); 332 | 333 | if(r % 4 == 0) 334 | orcSHT->sh_type = SHT_LOPROC + 1; 335 | else if(r % 4 == 1) 336 | orcSHT->sh_type = SHT_HIPROC; 337 | else if(r % 4 == 2) 338 | orcSHT->sh_type = SHT_LOUSER + 1; 339 | else 340 | orcSHT->sh_type = SHT_HIUSER; 341 | 342 | fprintf(logfp, "(SHT[%d]->sh_type = 0x%x)", sh, orcSHT->sh_type); 343 | 344 | return 1; 345 | } 346 | 347 | int sht9(void) 348 | { 349 | if(orcSHT->sh_type != SHT_NULL) 350 | return 0; 351 | 352 | fuzzName(); 353 | fuzzSize(); 354 | fuzzEntSize(); 355 | orcSHT->sh_offset = getElf_Off(); 356 | 357 | fprintf(logfp, "(SHT[%d]->sh_name = 0x%x,", sh, orcSHT->sh_name); 358 | fprintf(logfp, " sh_offset = 0x"HEX",", orcSHT->sh_offset); 359 | fprintf(logfp, " sh_size = 0x"HEX",", orcSHT->sh_size); 360 | fprintf(logfp, " sh_entsize = 0x"HEX")", orcSHT->sh_entsize); 361 | 362 | return 1; 363 | } 364 | 365 | int sht10(void) 366 | { 367 | fuzzFlags(); 368 | 369 | fprintf(logfp, "(SHT[%d]->sh_flags = 0x"HEX")", sh, orcSHT->sh_flags); 370 | 371 | return 1; 372 | } 373 | int sht11(void) 374 | { 375 | if(orcSHT->sh_type != SHT_DYNAMIC && 376 | orcSHT->sh_type != SHT_HASH && 377 | orcSHT->sh_type != SHT_GNU_HASH) 378 | return 0; 379 | 380 | Elf_Word l; 381 | 382 | if(rand() % 2) 383 | orcSHT->sh_info = 1 + (rand() % (orcHDR->e_shnum - 1)); 384 | else 385 | orcSHT->sh_info = getElf_Word(); 386 | 387 | if(orcSHT->sh_type == SHT_DYNAMIC){ 388 | if(mode & DYN){ 389 | if(rand() % 2){ 390 | fprintf(logfp, "(SHT[%d]->sh_info = 0x%x)", sh, orcSHT->sh_info); 391 | 392 | return 1; 393 | } else { 394 | if(rand() % 4 < 3){ 395 | while((l = 1 + (rand() % (orcHDR->e_shnum - 1)))) 396 | if(orcOrigSHT[l].sh_type != SHT_STRTAB) 397 | break; 398 | } else 399 | l = (Elf_Word) getElf_Half(); 400 | 401 | orcSHT->sh_link = l; 402 | } 403 | } else { 404 | if(rand() % 2) 405 | orcSHT->sh_link = 1 + (rand() % (orcHDR->e_shnum - 1)); 406 | else 407 | orcSHT->sh_link = (Elf_Word) getElf_Half(); 408 | } 409 | } else { // HASH 410 | if(rand() % 4 < 3){ 411 | while((l = 1 + (rand() % (orcHDR->e_shnum - 1)))) 412 | if(orcOrigSHT[l].sh_type != SHT_SYMTAB && orcOrigSHT[l].sh_type != SHT_DYNSYM) 413 | break; 414 | } else 415 | l = (Elf_Word) getElf_Half(); 416 | 417 | orcSHT->sh_link = l; 418 | } 419 | 420 | fprintf(logfp, "(SHT[%d]->sh_link = 0x%x,", sh, orcSHT->sh_link); 421 | fprintf(logfp, " sh_info = 0x%x)", orcSHT->sh_info); 422 | 423 | return 1; 424 | } 425 | 426 | int sht12(void) 427 | { 428 | if(orcSHT->sh_type != SHT_REL && 429 | orcSHT->sh_type != SHT_RELA) 430 | return 0; 431 | 432 | Elf_Word l; 433 | 434 | if(mode & REL){ 435 | if(rand() % 2){ 436 | if(rand() % 2) 437 | orcSHT->sh_info = 1 + (rand() % (orcHDR->e_shnum - 1)); 438 | else 439 | orcSHT->sh_info = getElf_Word(); 440 | 441 | fprintf(logfp, "(SHT[%d]->sh_info = 0x%x)", sh, orcSHT->sh_info); 442 | 443 | return 1; 444 | } else 445 | return 0; 446 | } else { 447 | if(rand() % 4 < 3){ 448 | while((l = 1 + (rand() % (orcHDR->e_shnum - 1)))) 449 | if(orcOrigSHT[l].sh_type != SHT_SYMTAB && orcOrigSHT[l].sh_type != SHT_DYNSYM) 450 | break; 451 | } else 452 | l = (Elf_Word) getElf_Half(); 453 | 454 | orcSHT->sh_link = l; 455 | 456 | if(rand() % 2) 457 | orcSHT->sh_info = 1 + (rand() % (orcHDR->e_shnum - 1)); 458 | else 459 | orcSHT->sh_info = getElf_Word(); 460 | } 461 | 462 | fprintf(logfp, "(SHT[%d]->sh_link = 0x%x,", sh, orcSHT->sh_link); 463 | fprintf(logfp, " sh_info = 0x%x)", orcSHT->sh_info); 464 | 465 | return 1; 466 | } 467 | 468 | int sht13(void) 469 | { 470 | if(orcSHT->sh_type != SHT_SYMTAB && 471 | orcSHT->sh_type != SHT_DYNSYM) 472 | return 0; 473 | 474 | if(mode & REL) // In REL, sh_link is the associated symbol table 475 | if(rand() % 3 < 2) 476 | return 0; 477 | 478 | if(mode & SYM) 479 | if(rand() % 2) 480 | return 0; 481 | 482 | if(rand() % 2){ 483 | if(rand() % 2) 484 | orcSHT->sh_info = 1 + (rand() % (orcHDR->e_shnum - 1)); 485 | else 486 | orcSHT->sh_info = (Elf_Word) getElf_Half(); 487 | 488 | Elf_Word l; 489 | 490 | if(rand() % 4 < 3){ 491 | while((l = 1 + (rand() % (orcHDR->e_shnum - 1)))) 492 | if(orcOrigSHT[l].sh_type != SHT_STRTAB) 493 | break; 494 | } else 495 | l = (Elf_Word) getElf_Half(); 496 | 497 | orcSHT->sh_link = l; 498 | } else 499 | return 0; 500 | 501 | fprintf(logfp, "(SHT[%d]->sh_link = 0x%x,", sh, orcSHT->sh_link); 502 | fprintf(logfp, " sh_info = 0x%x)", orcSHT->sh_info); 503 | 504 | return 1; 505 | } 506 | 507 | int sht14(void) 508 | { 509 | if(orcSHT->sh_type != SHT_NOBITS) 510 | return 0; 511 | 512 | fuzzFlags(); 513 | fuzzSize(); 514 | 515 | fprintf(logfp, "(SHT[%d]->sh_flags = 0x"HEX",", sh, orcSHT->sh_flags); 516 | fprintf(logfp, " sh_size = 0x"HEX")", orcSHT->sh_size); 517 | 518 | return 1; 519 | } 520 | 521 | int sht15(void) 522 | { 523 | Elf_Section ndx; 524 | 525 | if(!(ndx = findSectionIndexByName(".data"))) 526 | return 0; 527 | 528 | // Return if not the current section header being fuzzed 529 | if(ndx != sh) 530 | return 0; 531 | 532 | if(rand() % 2){ 533 | if(rand() % 2){ 534 | Elf_Word t; 535 | 536 | while((t = rand() % SHT_NUM)){ 537 | switch(t){ 538 | case SHT_STRTAB: 539 | if(mode & STRS) 540 | continue; 541 | break; 542 | case SHT_NOTE: 543 | if(mode & NOTE) 544 | continue; 545 | break; 546 | case SHT_DYNAMIC: 547 | if(mode & DYN) 548 | continue; 549 | break; 550 | case SHT_SYMTAB: 551 | case SHT_DYNSYM: 552 | if(mode & (SYM | REL)) // In REL, sh_type of the symbol table will be needed 553 | continue; 554 | break; 555 | case SHT_REL: 556 | case SHT_RELA: 557 | if(mode & REL) 558 | continue; 559 | break; 560 | default: 561 | break; 562 | } 563 | 564 | break; 565 | } 566 | 567 | orcSHT->sh_type = t; 568 | } else 569 | orcSHT->sh_type = getElf_Word(); 570 | } 571 | 572 | fuzzFlags(); 573 | fuzzSize(); 574 | 575 | fprintf(logfp, "(SHT[%d]->sh_type = 0x%x,", sh, orcSHT->sh_type); 576 | fprintf(logfp, " sh_size = 0x"HEX",", orcSHT->sh_size); 577 | fprintf(logfp, " sh_flags = 0x"HEX")", orcSHT->sh_flags); 578 | 579 | return 1; 580 | } 581 | 582 | int sht16(void) 583 | { 584 | if(orcSHT->sh_type != SHT_HASH && 585 | orcSHT->sh_type != SHT_GNU_HASH) 586 | return 0; 587 | 588 | fuzzSize(); 589 | fuzzEntSize(); 590 | fuzzFlags(); 591 | fuzzAddrAlign(); 592 | 593 | fprintf(logfp, "(SHT[%d]->sh_size = 0x"HEX",", sh, orcSHT->sh_size); 594 | fprintf(logfp, " sh_flags = 0x"HEX",", orcSHT->sh_flags); 595 | fprintf(logfp, " sh_entsize = 0x"HEX",", orcSHT->sh_entsize); 596 | fprintf(logfp, " sh_addralign = 0x"HEX")", orcSHT->sh_addralign); 597 | 598 | return 1; 599 | } 600 | 601 | int sht17(void) 602 | { 603 | if(sh == 0) // Avoid the first entry of the SHT 604 | return 0; 605 | 606 | Elf_Section dar = findSectionIndexByName(".debug_aranges"); 607 | Elf_Section din = findSectionIndexByName(".debug_info"); 608 | Elf_Section dab = findSectionIndexByName(".debug_abbrev"); 609 | Elf_Section dli = findSectionIndexByName(".debug_line"); 610 | Elf_Section dst = findSectionIndexByName(".debug_str"); 611 | 612 | if(dar != sh && din != sh && dab != sh && dli != sh && dst != sh) 613 | return 0; 614 | 615 | if(rand() % 2){ 616 | if(rand() % 2){ 617 | Elf_Word t; 618 | 619 | while((t = rand() % SHT_NUM)){ 620 | switch(t){ 621 | case SHT_STRTAB: 622 | if(mode & STRS) 623 | continue; 624 | break; 625 | case SHT_NOTE: 626 | if(mode & NOTE) 627 | continue; 628 | break; 629 | case SHT_DYNAMIC: 630 | if(mode & DYN) 631 | continue; 632 | break; 633 | case SHT_SYMTAB: 634 | case SHT_DYNSYM: 635 | if(mode & (SYM | REL)) // In REL, sh_type of the symbol table will be needed 636 | continue; 637 | break; 638 | case SHT_REL: 639 | case SHT_RELA: 640 | if(mode & REL) 641 | continue; 642 | break; 643 | default: 644 | break; 645 | } 646 | 647 | break; 648 | } 649 | 650 | orcSHT->sh_type = t; 651 | } else 652 | orcSHT->sh_type = getElf_Word(); 653 | } 654 | 655 | fuzzFlags(); 656 | fuzzSize(); 657 | fuzzEntSize(); 658 | 659 | fprintf(logfp, "(SHT[%d]->sh_type = 0x%x,", sh, orcSHT->sh_type); 660 | fprintf(logfp, " sh_flags = 0x"HEX",", orcSHT->sh_flags); 661 | fprintf(logfp, " sh_size = 0x"HEX",", orcSHT->sh_size); 662 | fprintf(logfp, " sh_entsize = 0x"HEX")", orcSHT->sh_entsize); 663 | 664 | return 1; 665 | } 666 | 667 | int sht18(void) 668 | { 669 | if(orcSHT->sh_type != SHT_DYNAMIC) 670 | return 0; 671 | 672 | orcSHT->sh_flags &= ~SHF_ALLOC; 673 | orcSHT->sh_flags &= ~SHF_WRITE; 674 | 675 | fprintf(logfp, "(SHT[%d]->sh_flags = 0x"HEX")", sh, orcSHT->sh_flags); 676 | 677 | return 1; 678 | } 679 | 680 | int sht19(void) 681 | { 682 | if(sh == 0) // Avoid the first entry of the SHT 683 | return 0; 684 | 685 | Elf_Section rodata = findSectionIndexByName(".rodata"); 686 | Elf_Section rodata1 = findSectionIndexByName(".rodata1"); 687 | 688 | if(rodata != sh && rodata1 != sh) 689 | return 0; 690 | 691 | if(rand() % 2){ 692 | if(rand() % 2){ 693 | Elf_Word t; 694 | 695 | while((t = rand() % SHT_NUM)){ 696 | switch(t){ 697 | case SHT_STRTAB: 698 | if(mode & STRS) 699 | continue; 700 | break; 701 | case SHT_NOTE: 702 | if(mode & NOTE) 703 | continue; 704 | break; 705 | case SHT_DYNAMIC: 706 | if(mode & DYN) 707 | continue; 708 | break; 709 | case SHT_SYMTAB: 710 | case SHT_DYNSYM: 711 | if(mode & (SYM | REL)) // In REL, sh_type of the symbol table will be needed 712 | continue; 713 | break; 714 | case SHT_REL: 715 | case SHT_RELA: 716 | if(mode & REL) 717 | continue; 718 | break; 719 | default: 720 | break; 721 | } 722 | 723 | break; 724 | } 725 | 726 | orcSHT->sh_type = t; 727 | } else 728 | orcSHT->sh_type = getElf_Word(); 729 | } 730 | 731 | fuzzFlags(); 732 | fuzzSize(); 733 | fuzzEntSize(); 734 | 735 | fprintf(logfp, "(SHT[%d]->sh_type = 0x%x,", sh, orcSHT->sh_type); 736 | fprintf(logfp, " sh_flags = 0x"HEX",", orcSHT->sh_flags); 737 | fprintf(logfp, " sh_size = 0x"HEX",", orcSHT->sh_size); 738 | fprintf(logfp, " sh_entsize = 0x"HEX")", orcSHT->sh_entsize); 739 | 740 | return 1; 741 | } 742 | 743 | int sht20(void) 744 | { 745 | if(orcSHT->sh_type != SHT_NOTE) 746 | return 0; 747 | 748 | if(mode & NOTE) 749 | if(rand() % 2) 750 | return 0; 751 | 752 | #if defined(__i386__) || defined(__ANDROID_API__) 753 | Elf_Word s; 754 | #elif defined(__x86_64__) 755 | Elf_Xword s; 756 | #endif 757 | 758 | int r = rand(); 759 | 760 | if(r % 3 == 0) // If running in 64 bits, set a size modulo the 32-bits struct's size and viceversa 761 | s = sizeof(Elf_Nhdr); 762 | else if(r % 3 == 1){ 763 | while((s = rand() & 0x00ffffff)) 764 | if(s % 4 != 0) 765 | break; 766 | } else // Just the size of the header of the running platform 767 | s = sizeof(Elf_Nhdr); 768 | 769 | orcSHT->sh_size = s; 770 | 771 | fuzzFlags(); 772 | fuzzEntSize(); 773 | fuzzAddrAlign(); 774 | 775 | fprintf(logfp, "(SHT[%d]->sh_size = 0x"HEX",", sh, orcSHT->sh_size); 776 | fprintf(logfp, " sh_flags = 0x"HEX",", orcSHT->sh_flags); 777 | fprintf(logfp, " sh_entsize = 0x"HEX",", orcSHT->sh_entsize); 778 | fprintf(logfp, " sh_addralign = 0x"HEX")", orcSHT->sh_addralign); 779 | 780 | return 1; 781 | } 782 | 783 | int sht21(void) 784 | { 785 | if(orcSHT->sh_type != SHT_STRTAB) 786 | return 0; 787 | 788 | if(mode & STRS) 789 | if(rand() % 2) 790 | return 0; 791 | 792 | fuzzFlags(); 793 | fuzzSize(); 794 | fuzzEntSize(); 795 | fuzzAddrAlign(); 796 | 797 | fprintf(logfp, "(SHT[%d]->sh_size = 0x"HEX",", sh, orcSHT->sh_size); 798 | fprintf(logfp, " sh_flags = 0x"HEX",", orcSHT->sh_flags); 799 | fprintf(logfp, " sh_entsize = 0x"HEX",", orcSHT->sh_entsize); 800 | fprintf(logfp, " sh_addralign = 0x"HEX")", orcSHT->sh_addralign); 801 | 802 | return 1; 803 | } 804 | 805 | int sht22(void) 806 | { 807 | if(orcSHT->sh_type != SHT_SYMTAB && 808 | orcSHT->sh_type != SHT_DYNSYM) 809 | return 0; 810 | 811 | if(mode & SYM) 812 | if(rand() % 4 < 3) 813 | return 0; 814 | 815 | fuzzFlags(); 816 | fuzzSize(); 817 | fuzzEntSize(); 818 | fuzzAddrAlign(); 819 | 820 | fprintf(logfp, "(SHT[%d]->sh_size = 0x"HEX",", sh, orcSHT->sh_size); 821 | fprintf(logfp, " sh_flags = 0x"HEX",", orcSHT->sh_flags); 822 | fprintf(logfp, " sh_entsize = 0x"HEX",", orcSHT->sh_entsize); 823 | fprintf(logfp, " sh_addralign = 0x"HEX")", orcSHT->sh_addralign); 824 | 825 | return 1; 826 | } 827 | 828 | int sht23(void) 829 | { 830 | if(sh == 0) // Avoid the first entry of the SHT 831 | return 0; 832 | 833 | Elf_Section ndx; 834 | 835 | if(!(ndx = findSectionIndexByName(".text"))) 836 | return 0; 837 | 838 | // Return if not the current section header being fuzzed 839 | if(ndx != sh) 840 | return 0; 841 | 842 | if(rand() % 2){ 843 | Elf_Word t; 844 | 845 | while((t = rand() % SHT_NUM)){ 846 | switch(t){ 847 | case SHT_PROGBITS: 848 | continue; 849 | break; 850 | case SHT_STRTAB: 851 | if(mode & STRS) 852 | continue; 853 | break; 854 | case SHT_NOTE: 855 | if(mode & NOTE) 856 | continue; 857 | break; 858 | case SHT_DYNAMIC: 859 | if(mode & DYN) 860 | continue; 861 | break; 862 | case SHT_SYMTAB: 863 | case SHT_DYNSYM: 864 | if(mode & (SYM | REL)) // In REL, sh_type of the symbol table will be needed 865 | continue; 866 | break; 867 | case SHT_REL: 868 | case SHT_RELA: 869 | if(mode & REL) 870 | continue; 871 | break; 872 | default: 873 | break; 874 | } 875 | 876 | break; 877 | } 878 | 879 | orcSHT->sh_type = t; 880 | } else 881 | orcSHT->sh_type = getElf_Word(); 882 | 883 | int r = rand(); 884 | 885 | if(r % 3 == 0){ 886 | orcSHT->sh_flags &= ~SHF_ALLOC; 887 | orcSHT->sh_flags &= ~SHF_EXECINSTR; 888 | } else if(r % 3 == 1) 889 | orcSHT->sh_flags = getElf_Word(); 890 | else 891 | orcSHT->sh_flags = 0x00; 892 | 893 | fprintf(logfp, "(SHT[%d]->sh_type = 0x%x,", sh, orcSHT->sh_type); 894 | fprintf(logfp, " sh_flags = 0x"HEX")", orcSHT->sh_flags); 895 | 896 | return 1; 897 | } 898 | 899 | int sht24(void) 900 | { 901 | if(sh == 0) // Avoid the first entry of the SHT 902 | return 0; 903 | 904 | Elf_Section init = findSectionIndexByName(".init"); 905 | Elf_Section fini = findSectionIndexByName(".fini"); 906 | 907 | if(init != sh && fini != sh) 908 | return 0; 909 | 910 | if(rand() % 2){ 911 | Elf_Word t; 912 | 913 | while((t = rand() % SHT_NUM)){ 914 | switch(t){ 915 | case SHT_PROGBITS: 916 | continue; 917 | break; 918 | case SHT_STRTAB: 919 | if(mode & STRS) 920 | continue; 921 | break; 922 | case SHT_NOTE: 923 | if(mode & NOTE) 924 | continue; 925 | break; 926 | case SHT_DYNAMIC: 927 | if(mode & DYN) 928 | continue; 929 | break; 930 | case SHT_SYMTAB: 931 | case SHT_DYNSYM: 932 | if(mode & (SYM | REL)) // In REL, sh_type of the symbol table will be needed 933 | continue; 934 | break; 935 | case SHT_REL: 936 | case SHT_RELA: 937 | if(mode & REL) 938 | continue; 939 | break; 940 | default: 941 | break; 942 | } 943 | 944 | break; 945 | } 946 | 947 | orcSHT->sh_type = t; 948 | } else 949 | orcSHT->sh_type = getElf_Word(); 950 | 951 | int r = rand(); 952 | 953 | if(r % 3 == 0){ 954 | orcSHT->sh_flags &= ~SHF_ALLOC; 955 | orcSHT->sh_flags &= ~SHF_EXECINSTR; 956 | } else if(r % 3 == 1) 957 | orcSHT->sh_flags = getElf_Word(); 958 | else 959 | orcSHT->sh_flags = 0x00; 960 | 961 | fprintf(logfp, "(SHT[%d]->sh_type = 0x%x,", sh, orcSHT->sh_type); 962 | fprintf(logfp, " sh_flags = 0x"HEX")", orcSHT->sh_flags); 963 | 964 | return 1; 965 | } 966 | 967 | int sht25(void) 968 | { 969 | if(sh == 0) // Avoid the first entry of the SHT 970 | return 0; 971 | 972 | Elf_Section interp; 973 | 974 | if(!(interp = findSectionIndexByName(".interp"))) 975 | return 0; 976 | 977 | if(interp != sh) 978 | return 0; 979 | 980 | if(rand() % 2) 981 | orcSHT->sh_type = SHT_NULL; 982 | 983 | if(rand() % 2) 984 | orcSHT->sh_flags &= ~SHF_ALLOC; 985 | else 986 | orcSHT->sh_flags = 0x00; 987 | 988 | // Using the original sh_offset of the ELF. sh_offset in the ORC might be already fuzzed 989 | strncpy(orcptr + elfSHT[interp].sh_offset, dirname_orcfname, strlen(dirname_orcfname)); 990 | *(orcptr + elfSHT[interp].sh_offset + strlen(dirname_orcfname)) = '\0'; 991 | 992 | fprintf(logfp, "(SHT[%d]->sh_type = 0x%x,", sh, orcSHT->sh_type); 993 | fprintf(logfp, " sh_flags = 0x"HEX",", orcSHT->sh_flags); 994 | fprintf(logfp, " .interp = %s)", orcptr + elfSHT[interp].sh_offset); 995 | 996 | return 1; 997 | } 998 | 999 | int sht26(void) 1000 | { 1001 | if(sh == 0) // Avoid the first entry of the SHT 1002 | return 0; 1003 | 1004 | Elf_Section got = findSectionIndexByName(".got"); 1005 | 1006 | if(got != sh) 1007 | return 0; 1008 | 1009 | orcSHT->sh_flags &= ~SHF_WRITE; 1010 | 1011 | fprintf(logfp, "(SHT[%d]->sh_flags = 0x"HEX")", sh, orcSHT->sh_flags); 1012 | 1013 | return 1; 1014 | } 1015 | 1016 | int sht27(void) 1017 | { 1018 | if(sh == 0) // Avoid the first entry of the SHT 1019 | return 0; 1020 | 1021 | Elf_Section plt = findSectionIndexByName(".plt"); 1022 | 1023 | if(plt != sh) 1024 | return 0; 1025 | 1026 | if(rand() % 4 < 3){ // 75% chance 1027 | orcSHT->sh_flags &= ~SHF_EXECINSTR; 1028 | 1029 | fprintf(logfp, "(SHT[%d]->sh_flags = 0x"HEX")", sh, orcSHT->sh_flags); 1030 | 1031 | return 1; 1032 | } else { // Binary patch: the second jmp instruction in the PLT 1033 | unsigned int jmp_asm; 1034 | int r = rand(); 1035 | 1036 | // The 1st jmp in PLT is 6 bytes length in x86 and x86_64 1037 | *(orcptr + elfSHT[plt].sh_offset + 6) = 0xff; // jmp opcode 1038 | *(orcptr + elfSHT[plt].sh_offset + 7) = 0x25; // jmp opcode 1039 | 1040 | if(r % 4 == 0) // jmp to the original entrypoint 1041 | jmp_asm = (unsigned int) elfHDR->e_entry; 1042 | else if(r % 4 == 1){ // jmp to _init (".init".sh_addr) 1043 | Elf_Section init; 1044 | 1045 | if(!(init = findSectionIndexByName(".init"))) 1046 | return 0; 1047 | 1048 | jmp_asm = (unsigned int) elfSHT[init].sh_addr; 1049 | } else if(r % 4 == 2){ // jmp to _fini (".fini".sh_addr) 1050 | Elf_Section fini; 1051 | 1052 | if(!(fini = findSectionIndexByName(".fini"))) 1053 | return 0; 1054 | 1055 | jmp_asm = (unsigned int) elfSHT[fini].sh_addr; 1056 | } else { // jmp to a semi-random address 1057 | jmp_asm = (unsigned int) getElf_Addr(); 1058 | if(rand() % 2) 1059 | jmp_asm = SWAP32(jmp_asm); // little-endian conversion, just for phun ;D 1060 | } 1061 | 1062 | memcpy(orcptr + elfSHT[plt].sh_offset + 8, &jmp_asm, sizeof(jmp_asm)); 1063 | 1064 | fprintf(logfp, "(SHT[%d]->(sh_offset + 6) = jmp 0x%x)", sh, jmp_asm); 1065 | 1066 | return 1; 1067 | } 1068 | } 1069 | 1070 | int sht28(void) 1071 | { 1072 | if(orcSHT->sh_type != SHT_STRTAB) 1073 | return 0; 1074 | 1075 | if(sh == elfHDR->e_shstrndx) 1076 | return 0; 1077 | 1078 | if(rand() % 2){ 1079 | if(mode & STRS) 1080 | return 0; 1081 | 1082 | if(mode & REL) // If REL is fuzzed, the sh_offset of the string tab will be needed 1083 | if(rand() % 3 < 2) 1084 | return 0; 1085 | 1086 | orcSHT->sh_offset = elfstatinfo.st_size; // Pointing at the end of the file 1087 | orcSHT->sh_size = 0x1337; 1088 | } else { 1089 | if(mode & STRS) 1090 | if(rand() % 2) 1091 | return 0; 1092 | 1093 | orcSHT->sh_size = 0; 1094 | } 1095 | 1096 | fprintf(logfp, "(SHT[%d]->sh_offset = 0x"HEX",", sh, orcSHT->sh_offset); 1097 | fprintf(logfp, " sh_size = 0x"HEX")", orcSHT->sh_size); 1098 | 1099 | return 1; 1100 | } 1101 | 1102 | int sht29(void) 1103 | { 1104 | if(orcSHT->sh_type != SHT_HASH && 1105 | orcSHT->sh_type != SHT_GNU_HASH) 1106 | return 0; 1107 | 1108 | if(rand() % 4 < 3) 1109 | return 0; 1110 | 1111 | orcSHT->sh_type = getElf_Word(); 1112 | 1113 | fprintf(logfp, "(SHT[%d]->sh_type = 0x%x)", sh, orcSHT->sh_type); 1114 | 1115 | return 1; 1116 | } 1117 | 1118 | int sht30(void) 1119 | { 1120 | if(sh == 0) // Avoid the first entry of the SHT 1121 | return 0; 1122 | 1123 | // Metadata dependencies 1124 | switch(orcSHT->sh_type){ 1125 | case SHT_STRTAB: 1126 | if(mode & STRS) 1127 | if(rand() % 3 < 2) 1128 | return 0; 1129 | break; 1130 | case SHT_NOTE: 1131 | if(mode & NOTE) 1132 | if(rand() % 3 < 2) 1133 | return 0; 1134 | break; 1135 | case SHT_DYNAMIC: 1136 | if(mode & DYN) 1137 | if(rand() % 3 < 2) 1138 | return 0; 1139 | break; 1140 | case SHT_SYMTAB: 1141 | case SHT_DYNSYM: 1142 | if(mode & SYM) 1143 | if(rand() % 3 < 2) 1144 | return 0; 1145 | break; 1146 | case SHT_RELA: 1147 | case SHT_REL: 1148 | if(mode & REL) 1149 | if(rand() % 3 < 2) 1150 | return 0; 1151 | break; 1152 | default: 1153 | if(rand() % 4 < 3) 1154 | return 0; 1155 | } 1156 | 1157 | Elf_Section text = findSectionIndexByName(".text"); 1158 | Elf_Section data = findSectionIndexByName(".data"); 1159 | Elf_Section got = findSectionIndexByName(".got"); 1160 | Elf_Section bss = findSectionIndexByName(".bss"); 1161 | Elf_Section gotplt = findSectionIndexByName(".got.plt"); 1162 | 1163 | int r = rand(); 1164 | 1165 | if(r % 5 == 0){ 1166 | if(!text) 1167 | return 0; 1168 | 1169 | orcSHT->sh_name = elfSHT[text].sh_name; 1170 | } else if(r % 5 == 1){ 1171 | if(!data) 1172 | return 0; 1173 | 1174 | orcSHT->sh_name = elfSHT[data].sh_name; 1175 | } else if(r % 5 == 2){ 1176 | if(!got) 1177 | return 0; 1178 | 1179 | orcSHT->sh_name = elfSHT[got].sh_name; 1180 | } else if(r % 5 == 3){ 1181 | if(!bss) 1182 | return 0; 1183 | 1184 | orcSHT->sh_name = elfSHT[bss].sh_name; 1185 | } else { 1186 | if(!gotplt) 1187 | return 0; 1188 | 1189 | orcSHT->sh_name = elfSHT[gotplt].sh_name; 1190 | } 1191 | 1192 | fprintf(logfp, "(SHT[%d]->sh_name = 0x%x)", sh, orcSHT->sh_name); 1193 | 1194 | return 1; 1195 | } 1196 | 1197 | int sht31(void) 1198 | { 1199 | // Metadata dependencies 1200 | switch(orcSHT->sh_type){ 1201 | case SHT_STRTAB: 1202 | if(mode & STRS) 1203 | return 0; 1204 | break; 1205 | case SHT_NOTE: 1206 | if(mode & NOTE) 1207 | return 0; 1208 | break; 1209 | case SHT_DYNAMIC: 1210 | if(mode & DYN) 1211 | return 0; 1212 | break; 1213 | case SHT_SYMTAB: 1214 | case SHT_DYNSYM: 1215 | if(mode & (SYM | REL)) // In REL, sh_type of the symbol table will be needed 1216 | return 0; 1217 | break; 1218 | case SHT_RELA: 1219 | case SHT_REL: 1220 | if(mode & REL) 1221 | return 0; 1222 | break; 1223 | default: 1224 | if(rand() % 5 < 4) // 80% chance 1225 | return 0; 1226 | } 1227 | 1228 | if(rand() % 2) 1229 | orcSHT->sh_type = SHT_LOOS; 1230 | else 1231 | orcSHT->sh_type = SHT_HIOS; 1232 | 1233 | fprintf(logfp, "(SHT[%d]->sh_type = 0x%x)", sh, orcSHT->sh_type); 1234 | 1235 | return 1; 1236 | } 1237 | 1238 | int sht32(void) 1239 | { 1240 | orcSHT->sh_flags |= SHF_MASKOS; 1241 | 1242 | fprintf(logfp, "(SHT[%d]->sh_flags = 0x"HEX")", sh, orcSHT->sh_flags); 1243 | 1244 | return 1; 1245 | } 1246 | 1247 | int sht33(void) 1248 | { 1249 | // Metadata dependencies 1250 | switch(orcSHT->sh_type){ 1251 | case SHT_STRTAB: 1252 | if(mode & STRS) 1253 | return 0; 1254 | break; 1255 | case SHT_NOTE: 1256 | if(mode & NOTE) 1257 | return 0; 1258 | break; 1259 | case SHT_DYNAMIC: 1260 | if(mode & DYN) 1261 | return 0; 1262 | break; 1263 | case SHT_SYMTAB: 1264 | case SHT_DYNSYM: 1265 | if(mode & (SYM | REL)) // In REL, sh_type of the symbol table will be needed 1266 | return 0; 1267 | break; 1268 | case SHT_RELA: 1269 | case SHT_REL: 1270 | if(mode & REL) 1271 | return 0; 1272 | break; 1273 | default: 1274 | if(rand() % 5 < 4) // 80% chance 1275 | return 0; 1276 | } 1277 | 1278 | int r = rand(); 1279 | 1280 | if(r % 6 == 0) 1281 | orcSHT->sh_type = SHT_GNU_ATTRIBUTES; 1282 | else if(r % 6 == 1) 1283 | orcSHT->sh_type = SHT_GNU_HASH; 1284 | else if(r % 6 == 2) 1285 | orcSHT->sh_type = SHT_GNU_LIBLIST; 1286 | else if(r % 6 == 3) 1287 | orcSHT->sh_type = SHT_GNU_verdef; 1288 | else if(r % 6 == 4) 1289 | orcSHT->sh_type = SHT_GNU_verneed; 1290 | else 1291 | orcSHT->sh_type = SHT_GNU_versym; 1292 | 1293 | fprintf(logfp, "(SHT[%d]->sh_type = 0x%x)", sh, orcSHT->sh_type); 1294 | 1295 | return 1; 1296 | } 1297 | 1298 | int sht34(void) 1299 | { 1300 | int fuzzed = 0; 1301 | 1302 | if(orcSHT->sh_flags & SHF_WRITE){ 1303 | orcSHT->sh_flags &= ~SHF_ALLOC; 1304 | fuzzed++; 1305 | } 1306 | 1307 | if(orcSHT->sh_flags & SHF_EXECINSTR){ 1308 | orcSHT->sh_flags &= ~SHF_ALLOC; 1309 | fuzzed++; 1310 | } 1311 | 1312 | if(!fuzzed) 1313 | return 0; 1314 | 1315 | fprintf(logfp, "(SHT[%d]->sh_flags = 0x"HEX")", sh, orcSHT->sh_flags); 1316 | 1317 | return 1; 1318 | } 1319 | 1320 | int sht35(void) 1321 | { 1322 | if(sh == 0) // Avoid the first entry of the SHT 1323 | return 0; 1324 | 1325 | if(orcSHT->sh_type != SHT_INIT_ARRAY && 1326 | orcSHT->sh_type != SHT_FINI_ARRAY) 1327 | return 0; 1328 | 1329 | if(rand() % 2) 1330 | return 0; 1331 | 1332 | Elf_Addr addr; 1333 | int r = rand(); 1334 | 1335 | if(r % 4 == 0) // jmp to the original entrypoint 1336 | addr = elfHDR->e_entry; 1337 | else if(r % 4 == 1){ // jmp to _init (".init".sh_addr) 1338 | Elf_Section init; 1339 | 1340 | if(!(init = findSectionIndexByName(".init"))) 1341 | return 0; 1342 | 1343 | addr = elfSHT[init].sh_addr; 1344 | } else if(r % 4 == 2){ // jmp to _fini (".fini".sh_addr) 1345 | Elf_Section fini; 1346 | 1347 | if(!(fini = findSectionIndexByName(".fini"))) 1348 | return 0; 1349 | 1350 | addr = elfSHT[fini].sh_addr; 1351 | } else 1352 | addr = getElf_Addr(); 1353 | 1354 | memcpy(orcptr + elfSHT[sh].sh_offset, &addr, sizeof(addr)); 1355 | 1356 | fprintf(logfp, "(SHT[%d]->(sh_offset + 0) = 0x"HEX")", sh, addr); 1357 | 1358 | return 1; 1359 | } 1360 | 1361 | int sht36(void) 1362 | { 1363 | // Metadata dependencies 1364 | switch(orcSHT->sh_type){ 1365 | case SHT_STRTAB: 1366 | if(mode & STRS) 1367 | if(rand() % 2) // 50% chance 1368 | return 0; 1369 | break; 1370 | case SHT_NOTE: 1371 | if(mode & NOTE) 1372 | if(rand() % 2) 1373 | return 0; 1374 | break; 1375 | case SHT_DYNAMIC: 1376 | if(mode & DYN) 1377 | if(rand() % 4 < 3) 1378 | return 0; 1379 | break; 1380 | case SHT_SYMTAB: 1381 | case SHT_DYNSYM: 1382 | if(mode & SYM) 1383 | if(rand() % 4 < 3) 1384 | return 0; 1385 | break; 1386 | case SHT_RELA: 1387 | case SHT_REL: 1388 | if(mode & REL) 1389 | if(rand() % 4 < 3) 1390 | return 0; 1391 | break; 1392 | default: 1393 | if(rand() % 3 < 2) 1394 | return 0; 1395 | } 1396 | 1397 | orcSHT->sh_size++; 1398 | orcSHT->sh_entsize--; 1399 | 1400 | fprintf(logfp, "(SHT[%d]->sh_size = 0x"HEX",", sh, orcSHT->sh_size); 1401 | fprintf(logfp, " sh_entsize = 0x"HEX")", orcSHT->sh_entsize); 1402 | 1403 | return 1; 1404 | } 1405 | 1406 | int sht37(void) 1407 | { 1408 | if(sh == 0) // Avoid the first entry of the SHT 1409 | return 0; 1410 | 1411 | Elf_Section tbss = findSectionIndexByName(".tbss"); 1412 | Elf_Section tdata = findSectionIndexByName(".tdata"); 1413 | 1414 | if(!tbss && !tdata) 1415 | return 0; 1416 | 1417 | if(tbss != sh && tdata != sh) 1418 | return 0; 1419 | 1420 | int fuzzed = 0; 1421 | 1422 | if(tbss){ 1423 | orcOrigSHT[tbss].sh_flags &= ~SHF_TLS; 1424 | fuzzed++; 1425 | } 1426 | 1427 | if(tdata){ 1428 | orcOrigSHT[tdata].sh_flags &= ~SHF_TLS; 1429 | fuzzed++; 1430 | } 1431 | 1432 | if(!fuzzed) 1433 | return 0; 1434 | 1435 | if(tbss && tdata){ 1436 | fprintf(logfp, "(SHT[%d]->sh_flags = 0x"HEX",", tdata, orcOrigSHT[tdata].sh_flags); 1437 | fprintf(logfp, " SHT[%d]->sh_flags = 0x"HEX")", tbss, orcOrigSHT[tbss].sh_flags); 1438 | } else if(tbss) 1439 | fprintf(logfp, "(SHT[%d]->sh_flags = 0x"HEX")", tbss, orcOrigSHT[tbss].sh_flags); 1440 | else 1441 | fprintf(logfp, "(SHT[%d]->sh_flags = 0x"HEX")", tdata, orcOrigSHT[tdata].sh_flags); 1442 | 1443 | return 1; 1444 | } 1445 | 1446 | 1447 | // Will trust only in the original (unmodified) ELF data. 1448 | // Previous rules might already fuzzed sh_name and could SIGSEGV here is orc sh_name is used 1449 | Elf_Section findSectionIndexByName(char *name) 1450 | { 1451 | int k; 1452 | Elf_Shdr *tmpSHT = elfSHT; 1453 | 1454 | for(k = 0; k < elfHDR->e_shnum; k++, tmpSHT++) 1455 | if(strcmp(elfptr + elfshstrtab_offset + tmpSHT->sh_name, name) == 0) 1456 | return k; 1457 | 1458 | return SHT_NULL; // Zero 1459 | } 1460 | 1461 | void fuzzName() 1462 | { 1463 | if(rand() % 3 == 0){ 1464 | if(rand() % 2) 1465 | orcSHT->sh_name = getElf_Word(); 1466 | else 1467 | orcSHT->sh_name = getElf_Half(); 1468 | } else { 1469 | if(rand() % 3 == 0) 1470 | orcSHT->sh_name = 0x00; 1471 | else 1472 | orcSHT->sh_name = (rand() % 0xff); 1473 | } 1474 | } 1475 | 1476 | void fuzzSize() 1477 | { 1478 | if((rand() % 4) < 3){ // 75% chance 1479 | if(rand() % 2) 1480 | #if defined(__i386__) || defined(__ANDROID_API__) 1481 | orcSHT->sh_size = getElf_Word(); 1482 | #elif defined(__x86_64__) 1483 | orcSHT->sh_size = getElf_Xword(); 1484 | #endif 1485 | else 1486 | orcSHT->sh_size = getElf_Half(); 1487 | } else 1488 | orcSHT->sh_size = 0x00; 1489 | } 1490 | 1491 | void fuzzEntSize() 1492 | { 1493 | if((rand() % 4) < 3){ // 75% chance 1494 | if(rand() % 2) 1495 | #if defined(__i386__) || defined(__ANDROID_API__) 1496 | orcSHT->sh_entsize = getElf_Word(); 1497 | #elif defined(__x86_64__) 1498 | orcSHT->sh_entsize = getElf_Xword(); 1499 | else 1500 | orcSHT->sh_entsize = getElf_Half(); 1501 | #endif 1502 | } else 1503 | orcSHT->sh_entsize = 0x00; 1504 | } 1505 | 1506 | void fuzzFlags() 1507 | { 1508 | int r = rand(); 1509 | 1510 | if(r % 3 == 0){ 1511 | r = rand(); 1512 | 1513 | // Set SHF_x 1514 | if(r % 5 == 0) 1515 | orcSHT->sh_flags = (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR | SHF_TLS | SHF_MASKPROC); 1516 | else if(r % 5 == 1) 1517 | orcSHT->sh_flags |= SHF_WRITE; 1518 | else if(r % 5 == 2) 1519 | orcSHT->sh_flags |= SHF_ALLOC; 1520 | else if(r % 5 == 3) 1521 | orcSHT->sh_flags |= SHF_TLS; 1522 | else 1523 | orcSHT->sh_flags |= SHF_EXECINSTR; 1524 | } else if(r % 3 == 1){ 1525 | r = rand(); 1526 | 1527 | // Unset SHF_x 1528 | if(r % 5 == 0) 1529 | orcSHT->sh_flags = 0x00; 1530 | else if(r % 5 == 1) 1531 | orcSHT->sh_flags &= ~SHF_WRITE; 1532 | else if(r % 5 == 2) 1533 | orcSHT->sh_flags &= ~SHF_ALLOC; 1534 | else if(r % 5 == 3) 1535 | orcSHT->sh_flags &= ~SHF_TLS; 1536 | else 1537 | orcSHT->sh_flags &= ~SHF_EXECINSTR; 1538 | } else { 1539 | #if defined(__i386__) || defined(__ANDROID_API__) 1540 | orcSHT->sh_flags = getElf_Word(); 1541 | #elif defined(__x86_64__) 1542 | orcSHT->sh_flags = getElf_Xword(); 1543 | #endif 1544 | } 1545 | } 1546 | 1547 | void fuzzAddrAlign() 1548 | { 1549 | if(rand() % 2){ // 50% chance 1550 | #if defined(__i386__) || defined(__ANDROID_API__) 1551 | while((orcSHT->sh_addralign = getElf_Word())) 1552 | #elif defined(__x86_64__) 1553 | while((orcSHT->sh_addralign = getElf_Xword())) 1554 | #endif 1555 | // Bitwise: x & (x - 1) != 0 if x is NOT a power of 2 1556 | if((orcSHT->sh_addralign & (orcSHT->sh_addralign - 1)) != 0) 1557 | break; 1558 | } else { 1559 | if(rand() % 2) // 25% 1560 | orcSHT->sh_addralign = PAGESIZE - 1; 1561 | else // 25% 1562 | orcSHT->sh_addralign = PAGESIZE + 1; 1563 | } 1564 | } 1565 | 1566 | void initialize_sht_funcs(void) 1567 | { 1568 | sht[1] = &sht1; 1569 | sht[2] = &sht2; 1570 | sht[3] = &sht3; 1571 | sht[4] = &sht4; 1572 | sht[5] = &sht5; 1573 | sht[6] = &sht6; 1574 | sht[7] = &sht7; 1575 | sht[8] = &sht8; 1576 | sht[9] = &sht9; 1577 | sht[10] = &sht10; 1578 | sht[11] = &sht11; 1579 | sht[12] = &sht12; 1580 | sht[13] = &sht13; 1581 | sht[14] = &sht14; 1582 | sht[15] = &sht15; 1583 | sht[16] = &sht16; 1584 | sht[17] = &sht17; 1585 | sht[18] = &sht18; 1586 | sht[19] = &sht19; 1587 | sht[20] = &sht20; 1588 | sht[21] = &sht21; 1589 | sht[22] = &sht22; 1590 | sht[23] = &sht23; 1591 | sht[24] = &sht24; 1592 | sht[25] = &sht25; 1593 | sht[26] = &sht26; 1594 | sht[27] = &sht27; 1595 | sht[28] = &sht28; 1596 | sht[29] = &sht29; 1597 | sht[30] = &sht30; 1598 | sht[31] = &sht31; 1599 | sht[32] = &sht32; 1600 | sht[33] = &sht33; 1601 | sht[34] = &sht34; 1602 | sht[35] = &sht35; 1603 | sht[36] = &sht36; 1604 | sht[37] = &sht37; 1605 | } 1606 | -------------------------------------------------------------------------------- /jni/src/fuzz_strs.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Melkor - An ELF File Format Fuzzer 3 | * Copyright (C) 2014 Alejandro Hernandez H. (nitr0us) 4 | * 5 | * Mexico 6 | */ 7 | 8 | #include "melkor.h" 9 | 10 | #define N_RULES_STRS 3 // Total of fuzzing rules defined for this metadata type 11 | 12 | // Array of function pointers. Index zero won't be used. The fuzzing rules start from index 1 13 | func_ptr strs[N_RULES_STRS + 1]; 14 | 15 | void initialize_strs_funcs(void) __attribute__((constructor)); 16 | 17 | /* External vars */ 18 | extern FILE *logfp; 19 | extern unsigned int mode; // Metadata to fuzz (parameters given in argv[]) 20 | extern unsigned int quiet; 21 | extern unsigned int like_a, like_b; 22 | extern unsigned int secnum; 23 | extern char *orcSTRS; 24 | extern Elf_Shdr *orcSHT; 25 | 26 | void fuzz_strs() 27 | { 28 | int rule; 29 | 30 | for(rule = 1; rule <= N_RULES_STRS; rule++) 31 | if((rand() % like_a) < like_b) 32 | if(strs[rule]()){ 33 | printf(". "); 34 | debug("STRS[%d] rule [%.2d] executed\n", secnum, rule); 35 | fprintf(logfp, " | STRS[%d] rule [%.2d] executed\n", secnum, rule); 36 | } 37 | } 38 | 39 | int strs1(void) 40 | { 41 | if(mode & (SHT | NOTE | DYN | SYM | REL)) 42 | if(rand() % 3 < 2) 43 | return 0; 44 | 45 | unsigned int ptr_offset = (rand() % 15) + 1; // Avoid the first NULL byte (index 0) 46 | 47 | fprintf(logfp, "(STRS[%d]->sh_offset (0x%x) + ", secnum, (unsigned int) orcSHT->sh_offset); 48 | 49 | while(ptr_offset < orcSHT->sh_size - 1){ 50 | if(*(orcSTRS + ptr_offset) == 0){ 51 | ptr_offset += rand() % 15 + rand() % 15; 52 | continue; 53 | } 54 | 55 | *(orcSTRS + ptr_offset) = (rand() & 0x7f) + 0x80; // > 7-bit ASCII chars 56 | fprintf(logfp, "%d = %c (0x%.2x), ", ptr_offset, *(orcSTRS + ptr_offset), *(orcSTRS + ptr_offset) & 0xff); 57 | 58 | ptr_offset += rand() % 15 + rand() % 15; 59 | } 60 | 61 | fprintf(logfp, ")"); 62 | 63 | return 1; 64 | } 65 | 66 | int strs2(void) 67 | { 68 | if(mode & (SHT | NOTE | DYN | SYM | REL)) 69 | if(rand() % 3 < 2) 70 | return 0; 71 | 72 | fprintf(logfp, "(STRS[%d]->sh_offset (0x%x) + ", secnum, (unsigned int) orcSHT->sh_offset); 73 | 74 | if(rand() % 2){ 75 | unsigned int ptr_offset = 1; 76 | 77 | while(ptr_offset < orcSHT->sh_size - 1){ 78 | if(*(orcSTRS + ptr_offset) != 0){ 79 | ptr_offset += rand() % 5; 80 | continue; 81 | } 82 | 83 | *(orcSTRS + ptr_offset) = (rand() & 0x7f) + 0x80; // > 7-bit ASCII chars 84 | fprintf(logfp, "%d = %c (0x%.2x), ", ptr_offset, *(orcSTRS + ptr_offset), *(orcSTRS + ptr_offset) & 0xff); 85 | 86 | ptr_offset += rand() % 5; 87 | } 88 | } else { 89 | *(orcSTRS) = (rand() & 0x7f) + 0x80; // > 7-bit ASCII chars 90 | fprintf(logfp, "0 = %c (0x%.2x), ", *(orcSTRS), *(orcSTRS) & 0xff); 91 | 92 | *(orcSTRS + orcSHT->sh_size - 1) = (rand() & 0x7f) + 0x80; 93 | fprintf(logfp, "%d = %c (0x%.2x), ", (int) orcSHT->sh_size - 1, *(orcSTRS + orcSHT->sh_size - 1), *(orcSTRS + orcSHT->sh_size - 1) & 0xff); 94 | } 95 | 96 | fprintf(logfp, ")"); 97 | 98 | return 1; 99 | } 100 | 101 | int strs3(void) 102 | { 103 | if(mode & (SHT | NOTE | DYN | SYM | REL)) 104 | if(rand() % 3 < 2) 105 | return 0; 106 | 107 | unsigned int ptr_offset = rand() % 20; 108 | char *fmt_ptr; 109 | 110 | fprintf(logfp, "(STRS[%d]->sh_offset (0x%x) + ", secnum, (unsigned int) orcSHT->sh_offset); 111 | 112 | while(ptr_offset < orcSHT->sh_size - 2){ 113 | fmt_ptr = get_fmt_str(); 114 | 115 | memcpy(orcSTRS + ptr_offset, fmt_ptr, strlen(fmt_ptr)); 116 | fprintf(logfp, "%d =%s, ", ptr_offset, fmt_ptr); 117 | 118 | ptr_offset += rand() % 20 + rand() % 20; 119 | } 120 | 121 | fprintf(logfp, ")"); 122 | 123 | return 1; 124 | } 125 | 126 | void initialize_strs_funcs(void) 127 | { 128 | strs[1] = &strs1; 129 | strs[2] = &strs2; 130 | strs[3] = &strs3; 131 | } 132 | -------------------------------------------------------------------------------- /jni/src/fuzz_sym.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Melkor - An ELF File Format Fuzzer 3 | * Copyright (C) 2014 Alejandro Hernandez H. (nitr0us) 4 | * 5 | * Mexico 6 | */ 7 | 8 | #include "melkor.h" 9 | 10 | #define N_RULES_SYM 15 // Total of fuzzing rules defined for this metadata type 11 | 12 | // Array of function pointers. Index zero won't be used. The fuzzing rules start from index 1 13 | func_ptr sym[N_RULES_SYM + 1]; 14 | 15 | void initialize_sym_funcs(void) __attribute__((constructor)); 16 | 17 | /* External vars */ 18 | extern FILE *logfp; 19 | extern unsigned int mode; // Metadata to fuzz (parameters given in argv[]) 20 | extern unsigned int quiet; 21 | extern unsigned int like_a, like_b; 22 | extern unsigned int secnum; 23 | extern unsigned int entry; 24 | extern Elf_Ehdr *orcHDR; 25 | extern Elf_Sym *orcSYM; 26 | 27 | void fuzz_sym() 28 | { 29 | int rule; 30 | 31 | for(rule = 1; rule <= N_RULES_SYM; rule++) 32 | if((rand() % like_a) < like_b) 33 | if(sym[rule]()){ 34 | printf(". "); 35 | debug("SHT[%d] SYM[%d] rule [%.2d] executed\n", secnum, entry, rule); 36 | fprintf(logfp, " | SHT[%d] SYM[%d] rule [%.2d] executed\n", secnum, entry, rule); 37 | } 38 | } 39 | 40 | int sym1(void) 41 | { 42 | if(entry != STN_UNDEF) 43 | return 0; 44 | 45 | if(rand() % 2) 46 | return 0; 47 | 48 | #if defined(__i386__) || defined(__ANDROID_API__) 49 | orcSYM->st_size = getElf_Word(); 50 | #elif defined(__x86_64__) 51 | if(rand() % 3 < 2) 52 | orcSYM->st_size = getElf_Xword(); 53 | else 54 | orcSYM->st_size = getElf_Word(); 55 | #endif 56 | 57 | orcSYM->st_value = getElf_Addr(); 58 | orcSYM->st_info = rand() & 0xff; 59 | orcSYM->st_other = rand() & 0xff; 60 | 61 | if(rand() % 4 == 0) 62 | orcSYM->st_shndx = getElf_Section(); 63 | else 64 | orcSYM->st_shndx = rand() % orcHDR->e_shnum; 65 | 66 | if(rand() % 4 == 0) 67 | orcSYM->st_name = getElf_Word(); 68 | else 69 | orcSYM->st_name = rand() & 0xff; 70 | 71 | fprintf(logfp, "(SYM[%d]->st_value = 0x"HEX",", entry, orcSYM->st_value); 72 | fprintf(logfp, " st_size = 0x"HEX",", orcSYM->st_size); 73 | fprintf(logfp, " st_info = 0x%x,", orcSYM->st_info); 74 | fprintf(logfp, " st_other = 0x%x,", orcSYM->st_other); 75 | fprintf(logfp, " st_shndx = 0x%x,", orcSYM->st_shndx); 76 | fprintf(logfp, " st_name = 0x%x)", orcSYM->st_name); 77 | 78 | return 1; 79 | } 80 | 81 | int sym2(void) 82 | { 83 | if(rand() % 5 < 4) // 80% chance to return. The symbol name is important. 84 | return 0; 85 | 86 | if(mode & REL) 87 | if(rand() % 2) 88 | return 0; 89 | 90 | if(rand() % 4 == 0) 91 | orcSYM->st_name = getElf_Word(); 92 | else 93 | orcSYM->st_name = rand() & 0xff; 94 | 95 | fprintf(logfp, "(SYM[%d]->st_name = 0x%x)", entry, orcSYM->st_name); 96 | 97 | return 1; 98 | } 99 | 100 | int sym3(void) 101 | { 102 | if(rand() % 5 < 4) // 80% chance to return. st_value is fuzzed in other rules as well. 103 | return 0; 104 | 105 | if(rand() % 4 < 3) 106 | orcSYM->st_value = getElf_Addr(); 107 | else 108 | orcSYM->st_value = getElf_Word(); 109 | 110 | fprintf(logfp, "(SYM[%d]->st_value = 0x"HEX")", entry, orcSYM->st_value); 111 | 112 | return 1; 113 | } 114 | 115 | int sym4(void) 116 | { 117 | #if defined(__i386__) || defined(__ANDROID_API__) 118 | orcSYM->st_size = getElf_Word(); 119 | #elif defined(__x86_64__) 120 | if(rand() % 3 < 2) 121 | orcSYM->st_size = getElf_Xword(); 122 | else 123 | orcSYM->st_size = getElf_Word(); 124 | #endif 125 | 126 | fprintf(logfp, "(SYM[%d]->st_size = 0x"HEX")", entry, orcSYM->st_size); 127 | 128 | return 1; 129 | } 130 | 131 | int sym5(void) 132 | { 133 | if(rand() % 2) 134 | return 0; 135 | 136 | if(mode & REL) 137 | if(rand() % 2) 138 | return 0; 139 | 140 | if(rand() % 2) 141 | orcSYM->st_shndx = rand() % orcHDR->e_shnum; 142 | else { 143 | if(rand() % 2) 144 | orcSYM->st_shndx = getElf_Section(); 145 | else 146 | orcSYM->st_shndx = SHN_UNDEF; 147 | } 148 | 149 | fprintf(logfp, "(SYM[%d]->st_shndx = 0x%x)", entry, orcSYM->st_shndx); 150 | 151 | return 1; 152 | } 153 | 154 | int sym6(void) 155 | { 156 | if(ELF_ST_TYPE(orcSYM->st_info) != STT_SECTION) 157 | return 0; 158 | 159 | if(mode & REL) 160 | if(rand() % 2) 161 | return 0; 162 | 163 | unsigned char st_info; 164 | 165 | do 166 | st_info = ELF_ST_INFO(rand() & 0x0f, STT_SECTION); 167 | while(ELF_ST_BIND(st_info) == STB_LOCAL); 168 | 169 | orcSYM->st_info = st_info; 170 | 171 | fprintf(logfp, "(SYM[%d]->st_info = 0x%.2x)", entry, orcSYM->st_info); 172 | 173 | return 1; 174 | } 175 | 176 | int sym7(void) 177 | { 178 | if(ELF_ST_TYPE(orcSYM->st_info) != STT_FILE) 179 | return 0; 180 | 181 | if(mode & REL) 182 | if(rand() % 2) 183 | return 0; 184 | 185 | unsigned char st_info = orcSYM->st_info; 186 | Elf_Section st_shndx; 187 | 188 | if(rand() % 2) 189 | do 190 | st_info = ELF_ST_INFO(rand() & 0x0f, STT_FILE); 191 | while(ELF_ST_BIND(st_info) == STB_LOCAL); 192 | 193 | if(rand() % 4 < 3){ 194 | while((st_shndx = rand() % orcHDR->e_shnum)) 195 | if(st_shndx != SHN_ABS) 196 | break; 197 | } else 198 | while((st_shndx = getElf_Section())) 199 | if(st_shndx != SHN_ABS) 200 | break; 201 | 202 | orcSYM->st_info = st_info; 203 | orcSYM->st_shndx = st_shndx; 204 | 205 | fprintf(logfp, "(SYM[%d]->st_info = 0x%.2x,", entry, orcSYM->st_info); 206 | fprintf(logfp, " st_shndx = 0x%x)", orcSYM->st_shndx); 207 | 208 | return 1; 209 | } 210 | 211 | int sym8(void) 212 | { 213 | if(orcHDR->e_type != ET_REL || 214 | orcSYM->st_shndx != SHN_COMMON) 215 | return 0; 216 | 217 | Elf_Addr st_value; 218 | 219 | while((st_value = getElf_Addr())) 220 | if(st_value % 4 != 0) 221 | break; 222 | 223 | orcSYM->st_value = st_value; 224 | 225 | fprintf(logfp, "(SYM[%d]->st_value = 0x"HEX")", entry, orcSYM->st_value); 226 | 227 | return 1; 228 | } 229 | 230 | int sym9(void) 231 | { 232 | if(orcHDR->e_type != ET_REL || 233 | orcSYM->st_shndx == SHN_COMMON) 234 | return 0; 235 | 236 | if(rand() % 2) 237 | orcSYM->st_value = getElf_Off(); 238 | else 239 | orcSYM->st_value = getElf_Word(); 240 | 241 | fprintf(logfp, "(SYM[%d]->st_value = 0x"HEX")", entry, orcSYM->st_value); 242 | 243 | return 1; 244 | } 245 | 246 | int sym10(void) 247 | { 248 | if(orcHDR->e_type != ET_EXEC && 249 | orcHDR->e_type != ET_DYN) 250 | return 0; 251 | 252 | if(rand() % 5 < 4) 253 | return 0; 254 | 255 | orcSYM->st_value = getElf_Addr(); 256 | 257 | fprintf(logfp, "(SYM[%d]->st_value = 0x"HEX")", entry, orcSYM->st_value); 258 | 259 | return 1; 260 | } 261 | 262 | int sym11(void) 263 | { 264 | if(orcHDR->e_type != ET_EXEC && 265 | orcHDR->e_type != ET_DYN) 266 | return 0; 267 | 268 | if(rand() % 5 < 4) 269 | return 0; 270 | 271 | if(mode & REL) 272 | if(rand() % 2) 273 | return 0; 274 | 275 | if(rand() % 2) 276 | orcSYM->st_shndx = 1 + rand() % orcHDR->e_shnum; 277 | else 278 | orcSYM->st_shndx = (rand() % 10) + getElf_Section(); 279 | 280 | fprintf(logfp, "(SYM[%d]->st_shndx = 0x%x)", entry, orcSYM->st_shndx); 281 | 282 | return 1; 283 | } 284 | 285 | int sym12(void) 286 | { 287 | if(orcSYM->st_shndx != SHN_UNDEF) 288 | return 0; 289 | 290 | if(!orcSYM->st_value) 291 | return 0; 292 | 293 | orcSYM->st_value = getElf_Addr(); 294 | 295 | fprintf(logfp, "(SYM[%d]->st_value = 0x"HEX")", entry, orcSYM->st_value); 296 | 297 | return 1; 298 | } 299 | 300 | int sym13(void) 301 | { 302 | if(rand() % 4 < 3) 303 | return 0; 304 | 305 | if(mode & REL) 306 | if(rand() % 2) 307 | return 0; 308 | 309 | orcSYM->st_info = rand() & 0xff; 310 | 311 | fprintf(logfp, "(SYM[%d]->st_info = 0x%.2x)", entry, orcSYM->st_info); 312 | 313 | return 1; 314 | } 315 | 316 | int sym14(void) 317 | { 318 | if(rand() % 4 < 3) 319 | return 0; 320 | 321 | if(mode & REL) 322 | if(rand() % 2) 323 | return 0; 324 | 325 | orcSYM->st_info = ELF_ST_INFO(rand() % 2 ? STB_LOOS : STB_HIOS, rand() % 2 ? STT_LOOS : STT_HIOS); 326 | 327 | fprintf(logfp, "(SYM[%d]->st_info = 0x%.2x)", entry, orcSYM->st_info); 328 | 329 | return 1; 330 | } 331 | 332 | int sym15(void) 333 | { 334 | orcSYM->st_other = rand() & 0xff; 335 | 336 | fprintf(logfp, "(SYM[%d]->st_other = 0x%.2x)", entry, orcSYM->st_other); 337 | 338 | return 1; 339 | } 340 | 341 | void initialize_sym_funcs(void) 342 | { 343 | sym[1] = &sym1; 344 | sym[2] = &sym2; 345 | sym[3] = &sym3; 346 | sym[4] = &sym4; 347 | sym[5] = &sym5; 348 | sym[6] = &sym6; 349 | sym[7] = &sym7; 350 | sym[8] = &sym8; 351 | sym[9] = &sym9; 352 | sym[10] = &sym10; 353 | sym[11] = &sym11; 354 | sym[12] = &sym12; 355 | sym[13] = &sym13; 356 | sym[14] = &sym14; 357 | sym[15] = &sym15; 358 | } 359 | -------------------------------------------------------------------------------- /jni/src/generators.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Melkor - An ELF File Format Fuzzer 3 | * Copyright (C) 2014 Alejandro Hernandez H. (nitr0us) 4 | * 5 | * Mexico 6 | */ 7 | 8 | #include "melkor.h" 9 | #include "numbers.h" 10 | 11 | #include 12 | #include 13 | 14 | unsigned int getseed(void) 15 | { 16 | int fd; 17 | unsigned int seed; 18 | 19 | if((fd = open("/dev/urandom", O_RDONLY)) == -1){ 20 | perror("getseed(): open"); 21 | exit(EXIT_FAILURE); 22 | } 23 | 24 | read(fd, &seed, sizeof(seed)); 25 | 26 | close(fd); 27 | 28 | return seed; 29 | } 30 | 31 | Elf_Addr getElf_Addr(void) 32 | { 33 | Elf_Addr a; 34 | 35 | if(rand() % 2) 36 | // A key base address + 16 bits random offset 37 | a = (Elf_Addr) (key_Addr[rand() % (sizeof(key_Addr) / sizeof(Elf_Addr))] + (rand() & 0xffff)); 38 | else { 39 | if(rand() % 2){ 40 | int r = rand(); 41 | 42 | if(r % 3 == 0) 43 | a = (Elf_Addr) int_l33t[rand() % (sizeof(int_l33t) / sizeof(int))]; 44 | else if(r % 3 == 1) 45 | a = (Elf_Addr) int_b0f[rand() % (sizeof(int_b0f) / sizeof(int))]; 46 | else 47 | a = (Elf_Addr) common_b0f[rand() % (sizeof(common_b0f) / sizeof(int))]; 48 | } else 49 | a = (Elf_Addr) rand(); 50 | } 51 | 52 | return a; 53 | } 54 | 55 | Elf_Off getElf_Off(void) 56 | { 57 | Elf_Off o; 58 | int r = rand(); 59 | 60 | if(r % 5 == 0) // 20% chance 61 | o = (Elf_Off) (key_Addr[rand() % (sizeof(key_Addr) / sizeof(Elf_Addr))] + (rand() % 0xffff)); 62 | else if(r % 5 == 1) 63 | o = (Elf_Off) int_l33t[rand() % (sizeof(int_l33t) / sizeof(int))]; 64 | else if(r % 5 == 2) 65 | o = (Elf_Off) int_b0f[rand() % (sizeof(int_b0f) / sizeof(int))]; 66 | else if(r % 5 == 3) 67 | o = (Elf_Off) common_b0f[rand() % (sizeof(common_b0f) / sizeof(int))]; 68 | else 69 | o = (Elf_Off) rand(); 70 | 71 | return o; 72 | } 73 | 74 | Elf_Word getElf_Word(void) 75 | { 76 | Elf_Word w; 77 | int r = rand(); 78 | 79 | if(r % 3 == 0) // 33.33% chance 80 | w = (Elf_Word) int_l33t[rand() % (sizeof(int_l33t) / sizeof(int))]; 81 | else if(r % 3 == 1){ 82 | if(rand() % 2) 83 | w = (Elf_Word) int_b0f[rand() % (sizeof(int_b0f) / sizeof(int))]; 84 | else 85 | w = (Elf_Word) common_b0f[rand() % (sizeof(common_b0f) / sizeof(int))]; 86 | } else 87 | w = (Elf_Word) rand(); 88 | 89 | return w; 90 | } 91 | 92 | Elf_Xword getElf_Xword(void) 93 | { 94 | Elf_Xword xw; 95 | 96 | xw = getElf_Word(); 97 | xw = xw << 32 | getElf_Word(); 98 | 99 | return xw; 100 | } 101 | 102 | Elf_Half getElf_Half(void) 103 | { 104 | Elf_Half h; 105 | int r = rand(); 106 | 107 | if(r % 5 == 0) // 20% chance 108 | h = (Elf_Half) short_l33t[rand() % (sizeof(short_l33t) / sizeof(int))]; 109 | else if(r % 5 == 1) 110 | h = (Elf_Half) (int_b0f[rand() % 3] >> 16); // 0x7fff || 0xffff || 0x8000 111 | else if(r % 5 == 2) 112 | h = (Elf_Half) (int_b0f[(rand() % (sizeof(int_b0f) / sizeof(int))) + 3] >> 16); 113 | else if(r % 5 == 3) 114 | h = (Elf_Half) common_b0f[rand() % (sizeof(common_b0f) / sizeof(int))] >> 16; 115 | else 116 | h = (Elf_Half) rand(); 117 | 118 | return h; 119 | } 120 | 121 | Elf_Section getElf_Section(void) 122 | { 123 | Elf_Section s; 124 | 125 | if(rand() % 2) // 50% chance to return a small (valid?) value 126 | s = (Elf_Section) rand() % 0x20; 127 | else 128 | s = (Elf_Section) getElf_Half(); 129 | 130 | return s; 131 | } 132 | 133 | char *get_fmt_str(void) 134 | { 135 | char *fmt_ptr; 136 | 137 | fmt_ptr = (char *) fmt_strs[rand() % (sizeof(fmt_strs) / sizeof(char *))]; 138 | 139 | return fmt_ptr; 140 | } 141 | 142 | char *get_fuzzed_path(void) 143 | { 144 | char *fuzzed_path; 145 | 146 | fuzzed_path = (char *) fuzz_paths[rand() % (sizeof(fuzz_paths) / sizeof(char *))]; 147 | 148 | return fuzzed_path; 149 | } 150 | -------------------------------------------------------------------------------- /jni/src/logger.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Melkor - An ELF File Format Fuzzer 3 | * Copyright (C) 2014 Alejandro Hernandez H. (nitr0us) 4 | * 5 | * Mexico 6 | */ 7 | 8 | #include "melkor.h" 9 | 10 | FILE *start_logger(char *logfname, char *elfname) 11 | { 12 | FILE *fp; 13 | const char *log_line = " ~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~\n"; 14 | 15 | char log_title[strlen(logfname) + 100]; 16 | snprintf(log_title, sizeof(log_title), "| Log report for fuzzed files based on %-25s |\n", elfname); 17 | 18 | if(!(fp = fopen(logfname, "w"))){ 19 | perror("fopen"); 20 | exit(EXIT_FAILURE); 21 | } 22 | 23 | fputs(log_line, fp); 24 | fputs(log_title, fp); 25 | fputs(log_line, fp); 26 | fputs("\nHow to read this report:\n\n", fp); 27 | fputs("(Fuzzed Metadata) | Corresponding fuzzing rule (docs/Melkor_Fuzzing_Rules.pdf)\n\n", fp); 28 | fputs("SHT[N] REL[E] = Section Header N type is SHT_REL or SHT_RELA; Relocation entry E within that section was fuzzed.\n", fp); 29 | fputs("SHT[N] SYM[E] = Section Header N type is SHT_SYMTAB or SHT_DYNSYM; Symbol entry E within that section was fuzzed.\n", fp); 30 | fputs("SHT[N] DYN[E] = Section Header N type is SHT_DYNAMIC; Dynamic entry E within that section was fuzzed.\n", fp); 31 | fputs("SHT[N] NOTE[E] = Section Header N type is SHT_NOTE; Note entry E within that section was fuzzed.\n", fp); 32 | fputs("STRS[N] = Section Header N type is SHT_STRTAB; the String Table within that section was fuzzed.\n", fp); 33 | fputs("SHT[N] = Section Header N was fuzzed.\n", fp); 34 | fputs("PHT[N] = Program Header N was fuzzed.\n", fp); 35 | fputs("HDR = ELF Header was fuzzed.\n", fp); 36 | 37 | return fp; 38 | } 39 | 40 | void stop_logger(FILE *fp) 41 | { 42 | const char *log_footer = 43 | "\n\n ~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~\n" 44 | "| End of report. |\n" 45 | " ~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~\n"; 46 | 47 | fputs(log_footer, fp); 48 | 49 | fclose(fp); 50 | } 51 | -------------------------------------------------------------------------------- /jni/src/melkor.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Melkor - An ELF File Format Fuzzer 3 | * Copyright (C) 2014 Alejandro Hernandez H. (nitr0us) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * Mexico 19 | */ 20 | 21 | #include "melkor.h" 22 | #include "banner.h" 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | /* GLOBAL VARS */ 32 | FILE *logfp; 33 | struct stat elfstatinfo; 34 | unsigned int mode = 0; // Metadata to fuzz (parameters) 35 | unsigned int orcn = 0; // OrcN inside the for() loop. fuzz_* modules will use it through different loops 36 | unsigned int n = 5000; // Default for option -n 37 | unsigned int quiet = 0; // For quiet mode (-q). Default is not quiet [debug() output] 38 | unsigned int likelihood = 10; // Likelihood given in % of the execution of each rule in the main for() loop in fuzz_*.c. Default 10% 39 | unsigned int like_a = 10, like_b = 1; // Based upon the likelihood, these will be used for: rand() % like_a < like_b. Default values for 10% 40 | unsigned int secnum = 0; // Used in loops here but refered in fuzz_*.c as the section number 41 | unsigned int entry = 0; // Used in loops here but refered in fuzz_*.c as the entry number inside a section (for DYN, SYM, REL) 42 | char *dirname_orcfname; 43 | char *elfptr, *orcptr; 44 | char *elfSTRS, *orcSTRS; 45 | Elf_Ehdr *elfHDR, *orcHDR; 46 | Elf_Shdr *elfSHT, *orcSHT; 47 | Elf_Phdr *elfPHT, *orcPHT; 48 | Elf_Sym *elfSYM, *orcSYM; 49 | Elf_Dyn *elfDYN, *orcDYN; 50 | Elf_Rel *elfREL, *orcREL; 51 | Elf_Rela *elfRELA, *orcRELA; 52 | Elf_Nhdr *elfNOTE, *orcNOTE; 53 | Elf_Off elfshstrtab_offset = 0, orcshstrtab_offset = 0, linkstrtab_offset = 0; 54 | Elf_Shdr *orcOrigSHT; 55 | Elf_Phdr *orcOrigPHT; 56 | Elf_Dyn *elfOrigDYN; 57 | 58 | int main(int argc, char **argv) 59 | { 60 | int opt, elffd, orcfd, fuzzed_flag = 0, k = 0; 61 | char *elfname; 62 | Elf_Shdr elfshstrtab_section, orcshstrtab_section, linkstrtab_section; 63 | 64 | if(argc < 3) 65 | usage(argv[0]); 66 | 67 | while((opt = getopt(argc, argv, "aHSPsDRNZABqn:l:")) != EOF) 68 | switch(opt){ 69 | case 'a': 70 | mode |= AUTO; 71 | break; 72 | case 'H': 73 | mode |= HDR; 74 | break; 75 | case 'S': 76 | mode |= SHT; 77 | break; 78 | case 'P': 79 | mode |= PHT; 80 | break; 81 | case 's': 82 | mode |= SYM; 83 | break; 84 | case 'D': 85 | mode |= DYN; 86 | break; 87 | case 'R': 88 | mode |= REL; 89 | break; 90 | case 'N': 91 | mode |= NOTE; 92 | break; 93 | case 'Z': 94 | mode |= STRS; 95 | break; 96 | case 'A': 97 | mode |= ALL; 98 | break; 99 | case 'B': 100 | mode |= ALLB; 101 | break; 102 | case 'n': 103 | n = atoi(optarg); 104 | break; 105 | case 'l': 106 | likelihood = atoi(optarg); 107 | if(likelihood < 1 || likelihood > 100){ 108 | fprintf(stderr, "[!] Likelihood (-l) is given in %% and must be between 1 and 100\n"); 109 | exit(EXIT_FAILURE); 110 | } 111 | 112 | /* 113 | rand() % 20 < 1 = 5% 114 | rand() % 10 < 1 = 10% 115 | rand() % 5 < 1 = 20% 116 | rand() % 4 < 1 = 25% 117 | rand() % 3 < 1 = 33.33% 118 | rand() % 5 < 2 = 40% 119 | rand() % 2 < 1 = 50% 120 | rand() % 5 < 3 = 60% 121 | rand() % 3 < 2 = 66.66% 122 | rand() % 4 < 3 = 75% 123 | rand() % 5 < 4 = 80% 124 | rand() % 10 < 9 = 90% 125 | rand() % 1 < 1 = 100% 126 | */ 127 | if(likelihood <= 5){ 128 | like_a = 20; 129 | like_b = 1; 130 | } else if(likelihood <= 10){ 131 | like_a = 10; 132 | like_b = 1; 133 | } else if(likelihood <= 20){ 134 | like_a = 5; 135 | like_b = 1; 136 | } else if(likelihood <= 25){ 137 | like_a = 4; 138 | like_b = 1; 139 | } else if(likelihood <= 34){ 140 | like_a = 3; 141 | like_b = 1; 142 | } else if(likelihood <= 40){ 143 | like_a = 5; 144 | like_b = 2; 145 | } else if(likelihood <= 50){ 146 | like_a = 2; 147 | like_b = 1; 148 | } else if(likelihood <= 60){ 149 | like_a = 5; 150 | like_b = 3; 151 | } else if(likelihood <= 67){ 152 | like_a = 3; 153 | like_b = 2; 154 | } else if(likelihood <= 75){ 155 | like_a = 4; 156 | like_b = 3; 157 | } else if(likelihood <= 80){ 158 | like_a = 5; 159 | like_b = 4; 160 | } else if(likelihood <= 90){ 161 | like_a = 10; 162 | like_b = 9; 163 | } else if(likelihood <= 100){ 164 | like_a = 1; 165 | like_b = 1; 166 | } 167 | break; 168 | case 'q': 169 | quiet = 1; 170 | break; 171 | default: 172 | exit(EXIT_FAILURE); 173 | } 174 | 175 | if(argv[optind] == NULL){ 176 | fprintf(stderr, "[!] not supplied !\n"); 177 | exit(EXIT_FAILURE); 178 | } 179 | 180 | /* Separate the filename from the dirname. The same as basename() */ 181 | elfname = strrchr(argv[optind], '/'); 182 | if(!elfname) 183 | elfname = argv[optind]; 184 | else 185 | elfname = strrchr(argv[optind], '/') + 1; 186 | 187 | if((elffd = open(argv[optind], O_RDONLY)) == -1){ 188 | perror("open"); 189 | exit(EXIT_FAILURE); 190 | } 191 | 192 | if(!elf_identification(elffd)){ 193 | fprintf(stderr, "[!] '%s' is not an ELF file. Invalid magic number !\n", elfname); 194 | close(elffd); 195 | exit(EXIT_FAILURE); 196 | } 197 | 198 | if(fstat(elffd, &elfstatinfo) == -1){ 199 | perror("stat"); 200 | close(elffd); 201 | exit(EXIT_FAILURE); 202 | } 203 | 204 | if((elfptr = (char *) mmap(NULL, elfstatinfo.st_size, PROT_READ, MAP_SHARED, elffd, 0)) == MAP_FAILED){ 205 | perror("mmap"); 206 | close(elffd); 207 | exit(EXIT_FAILURE); 208 | } 209 | 210 | close(elffd); 211 | 212 | elfHDR = (Elf_Ehdr *) (elfptr); 213 | elfSHT = (Elf_Shdr *) (elfptr + elfHDR->e_shoff); 214 | elfPHT = (Elf_Phdr *) (elfptr + elfHDR->e_phoff); 215 | elfshstrtab_section = *(Elf_Shdr *) (elfSHT + elfHDR->e_shstrndx); 216 | elfshstrtab_offset = elfshstrtab_section.sh_offset; 217 | 218 | char dirname[strlen("orcs_") + strlen(elfname) + 1]; 219 | char orcfname[strlen("orc_") + 16]; 220 | char logfname[strlen("Report_") + strlen(elfname) + 5]; 221 | char *ext = ""; 222 | if(strcmp(elfname + strlen(elfname) - 2, ".o") == 0) 223 | ext = ".o"; 224 | if(strcmp(elfname + strlen(elfname) - 3, ".so") == 0) 225 | ext = ".so"; 226 | 227 | dirname_orcfname = malloc(sizeof(dirname) + sizeof(orcfname) + 2); 228 | 229 | snprintf(dirname, sizeof(dirname), "orcs_%s", elfname); 230 | snprintf(logfname, sizeof(logfname), "Report_%s.txt", elfname); 231 | 232 | if(mkdir(dirname, 0775) == -1) 233 | if(errno == EEXIST) 234 | printf("[!] Dir '%s' already exists. Files inside will be overwritten !\n", dirname); 235 | 236 | printf("%s", elf_ascii[0]); 237 | printf(elf_ascii[1], argv[optind]); 238 | printf("%s", elf_ascii[2]); 239 | printf(elf_ascii[3], n); 240 | printf("%s", elf_ascii[4]); 241 | 242 | if(mode & AUTO){ 243 | printf("[+] Automatic mode\n"); 244 | printf("[+] ELF type detected: "); 245 | 246 | switch(elfHDR->e_type){ 247 | case ET_NONE: 248 | printf("ET_NONE"); 249 | break; 250 | case ET_REL: 251 | printf("ET_REL"); 252 | break; 253 | case ET_EXEC: 254 | printf("ET_EXEC"); 255 | break; 256 | case ET_DYN: 257 | printf("ET_DYN"); 258 | break; 259 | case ET_CORE: 260 | printf("ET_CORE"); 261 | break; 262 | default: 263 | printf("Unknown e_type !\n"); 264 | printf("[+] All the metadata (except) the header will be fuzzed\n\n"); 265 | } 266 | 267 | if(elfHDR->e_type > 0 && elfHDR->e_type < 5){ 268 | printf("\n[+] Selecting the metadata to fuzz\n\n"); 269 | 270 | int metadata_by_e_type[5][8] = { 271 | /* HDR SHT PHT SYM DYN REL NOTE STRS */ 272 | /* ET_NONE */ { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }, // Untouched 273 | /* ET_REL */ { 0 , SHT, 0 , SYM, 0 , REL, 0 , STRS }, 274 | /* ET_EXEC */ { 0 , SHT, PHT, SYM, DYN, REL, NOTE, STRS }, 275 | /* ET_DYN */ { 0 , SHT, PHT, SYM, DYN, REL, NOTE, STRS }, 276 | /* ET_CORE */ { 0 , 0 , PHT, 0 , 0 , 0 , 0 , 0 }, 277 | }; 278 | 279 | for(k = 0; k < 8; k++) 280 | mode |= metadata_by_e_type[elfHDR->e_type][k]; 281 | } else { 282 | mode = ALLB; // All except the ELF header 283 | } 284 | } 285 | 286 | printf("[+] Detailed log for this session: '%s/%s' \n\n", dirname, logfname); 287 | 288 | printf("[+] The Likelihood of execution of each rule is: "); 289 | printf("Aprox. %d %% (rand() %% %d < %d)\n\n", likelihood, like_a, like_b); 290 | 291 | printf("[+] Press any key to start the fuzzing process...\n"); 292 | 293 | getchar(); 294 | 295 | chdir(dirname); 296 | 297 | logfp = start_logger(logfname, elfname); 298 | 299 | srand(getseed()); 300 | #ifndef __ANDROID_API__ 301 | PAGESIZE = getpagesize(); 302 | #endif 303 | 304 | for(orcn = 1; orcn <= n; orcn++){ 305 | snprintf(orcfname, sizeof(orcfname), "orc_%.4d%s", orcn, ext); 306 | snprintf(dirname_orcfname, sizeof(dirname) + sizeof(orcfname) + 2, "%s/%s", dirname, orcfname); 307 | 308 | if((orcfd = creat(orcfname, elfstatinfo.st_mode)) == -1){ 309 | perror("creat"); 310 | continue; 311 | } 312 | 313 | if(write(orcfd, elfptr, elfstatinfo.st_size) == -1){ 314 | perror("write"); 315 | continue; 316 | } 317 | 318 | close(orcfd); 319 | 320 | if((orcfd = open(orcfname, O_RDWR)) == -1){ 321 | perror("open"); 322 | continue; 323 | } 324 | 325 | if((orcptr = (char *) mmap(NULL, elfstatinfo.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, orcfd, 0)) == MAP_FAILED){ 326 | perror("mmap"); 327 | close(orcfd); 328 | continue; 329 | } 330 | 331 | orcHDR = (Elf_Ehdr *) (orcptr); 332 | orcOrigSHT = (Elf_Shdr *) (orcptr + orcHDR->e_shoff); 333 | orcOrigPHT = (Elf_Phdr *) (orcptr + orcHDR->e_phoff); 334 | orcshstrtab_section = *(Elf_Shdr *) (orcOrigSHT + orcHDR->e_shstrndx); 335 | orcshstrtab_offset = orcshstrtab_section.sh_offset; 336 | 337 | printf("\n=================================================================================\n"); 338 | printf("[+] Malformed ELF '%s':\n", orcfname); 339 | fprintf(logfp, "\n=================================================================================\n\n"); 340 | fprintf(logfp, "[+] Malformed ELF: '%s':\n\n", orcfname); 341 | 342 | if(mode & REL){ 343 | verifySHT(); 344 | orcSHT = orcOrigSHT; 345 | 346 | fuzzed_flag = 0; 347 | entry = 0; 348 | 349 | for(secnum = 0; secnum < orcHDR->e_shnum; secnum++, orcSHT++){ 350 | if(orcSHT->sh_type != SHT_REL && orcSHT->sh_type != SHT_RELA) 351 | continue; 352 | 353 | if(orcSHT->sh_size == 0) 354 | continue; 355 | 356 | if(orcSHT->sh_type == SHT_REL){ 357 | orcREL = (Elf_Rel *) (orcptr + orcSHT->sh_offset); 358 | } else { 359 | orcRELA = (Elf_Rela *) (orcptr + orcSHT->sh_offset); 360 | } 361 | 362 | printf("\n[+] Fuzzing the relocations section %s with %d %s entries\n", 363 | orcptr + orcshstrtab_offset + orcSHT->sh_name, (unsigned int) (orcSHT->sh_size / orcSHT->sh_entsize), 364 | orcSHT->sh_type == SHT_REL ? "SHT_REL" : "SHT_RELA"); 365 | fprintf(logfp, "\n[+] Fuzzing the relocations section %s with %d %s entries\n", 366 | orcptr + orcshstrtab_offset + orcSHT->sh_name, (unsigned int) (orcSHT->sh_size / orcSHT->sh_entsize), 367 | orcSHT->sh_type == SHT_REL ? "SHT_REL" : "SHT_RELA"); 368 | 369 | for(entry = 0; entry < orcSHT->sh_size / orcSHT->sh_entsize; entry++){ 370 | fuzz_rel(); 371 | 372 | fuzzed_flag = 1; 373 | 374 | if(orcSHT->sh_type == SHT_REL) 375 | orcREL++; 376 | else 377 | orcRELA++; 378 | } 379 | } 380 | 381 | if(!fuzzed_flag){ 382 | printf("\n[!] No SHT_REL nor SHT_RELA sections found!\n"); 383 | fprintf(logfp, "\n[!] No SHT_REL nor SHT_RELA sections found!\n"); 384 | } 385 | } 386 | 387 | if(mode & SYM){ 388 | verifySHT(); 389 | orcSHT = orcOrigSHT; 390 | 391 | fuzzed_flag = 0; 392 | entry = 0; 393 | 394 | for(secnum = 0; secnum < orcHDR->e_shnum; secnum++, orcSHT++){ 395 | if(orcSHT->sh_type != SHT_SYMTAB && orcSHT->sh_type != SHT_DYNSYM) 396 | continue; 397 | 398 | if(orcSHT->sh_size == 0) 399 | continue; 400 | 401 | linkstrtab_section = *(Elf_Shdr *) (orcptr + orcHDR->e_shoff + (orcSHT->sh_link * sizeof(Elf_Shdr))); 402 | linkstrtab_offset = linkstrtab_section.sh_offset; 403 | 404 | elfSYM = (Elf_Sym *) (elfptr + orcSHT->sh_offset); 405 | orcSYM = (Elf_Sym *) (orcptr + orcSHT->sh_offset); 406 | 407 | printf("\n[+] Fuzzing the Symbol Table %s with %d entries\n", 408 | orcptr + orcshstrtab_offset + orcSHT->sh_name, (unsigned int) (orcSHT->sh_size / orcSHT->sh_entsize)); 409 | fprintf(logfp, "\n[+] Fuzzing the Symbol Table %s with %d entries\n", 410 | orcptr + orcshstrtab_offset + orcSHT->sh_name, (unsigned int) (orcSHT->sh_size / orcSHT->sh_entsize)); 411 | 412 | for(entry = 0; entry < orcSHT->sh_size / orcSHT->sh_entsize; entry++, elfSYM++, orcSYM++){ 413 | fuzz_sym(); 414 | 415 | fuzzed_flag = 1; 416 | } 417 | } 418 | 419 | if(!fuzzed_flag){ 420 | printf("\n[!] No SHT_SYMTAB nor SHT_DYNSYM sections found!\n"); 421 | fprintf(logfp, "\n[!] No SHT_SYMTAB nor SHT_DYNSYM sections found!\n"); 422 | } 423 | } 424 | 425 | if(mode & DYN){ 426 | verifyPHT(); 427 | verifySHT(); 428 | orcSHT = orcOrigSHT; 429 | 430 | fuzzed_flag = 0; 431 | entry = 0; 432 | 433 | for(secnum = 0; secnum < orcHDR->e_shnum; secnum++, orcSHT++){ 434 | if(orcSHT->sh_type != SHT_DYNAMIC) 435 | continue; 436 | 437 | if(orcSHT->sh_size == 0) 438 | continue; 439 | 440 | linkstrtab_section = *(Elf_Shdr *) (orcptr + orcHDR->e_shoff + (orcSHT->sh_link * sizeof(Elf_Shdr))); 441 | linkstrtab_offset = linkstrtab_section.sh_offset; 442 | 443 | elfOrigDYN = (Elf_Dyn *) (elfptr + orcSHT->sh_offset); 444 | elfDYN = elfOrigDYN; 445 | orcDYN = (Elf_Dyn *) (orcptr + orcSHT->sh_offset); 446 | 447 | printf("\n[+] Fuzzing the Dynamic section %s with %d entries\n", 448 | orcptr + orcshstrtab_offset + orcSHT->sh_name, (unsigned int) (orcSHT->sh_size / orcSHT->sh_entsize)); 449 | fprintf(logfp, "\n[+] Fuzzing the Dynamic section %s with %d entries\n", 450 | orcptr + orcshstrtab_offset + orcSHT->sh_name, (unsigned int) (orcSHT->sh_size / orcSHT->sh_entsize)); 451 | 452 | for(entry = 0; entry < orcSHT->sh_size / orcSHT->sh_entsize; entry++, elfDYN++, orcDYN++){ 453 | fuzz_dyn(); 454 | 455 | fuzzed_flag = 1; 456 | 457 | if(elfDYN->d_tag == DT_NULL)// End of _DYNAMIC[]. Trust in elfDYN, orcDYN->d_tag = NULL might have been changed 458 | break; 459 | } 460 | } 461 | 462 | if(!fuzzed_flag){ 463 | printf("\n[!] No SHT_DYNAMIC section found!\n"); 464 | fprintf(logfp, "\n[!] No SHT_DYNAMIC section found!\n"); 465 | } 466 | } 467 | 468 | if(mode & NOTE){ 469 | verifySHT(); 470 | orcSHT = orcOrigSHT; 471 | 472 | fuzzed_flag = 0; 473 | entry = 0; 474 | 475 | for(secnum = 0; secnum < orcHDR->e_shnum; secnum++, orcSHT++){ 476 | if(orcSHT->sh_type != SHT_NOTE) 477 | continue; 478 | 479 | if(orcSHT->sh_size == 0) 480 | continue; 481 | 482 | printf("\n[+] Fuzzing the Note section %s with %d bytes\n", 483 | orcptr + orcshstrtab_offset + orcSHT->sh_name, (unsigned int) orcSHT->sh_size); 484 | fprintf(logfp, "\n[+] Fuzzing the Note section %s with %d bytes\n", 485 | orcptr + orcshstrtab_offset + orcSHT->sh_name, (unsigned int) orcSHT->sh_size); 486 | 487 | elfNOTE = (Elf_Nhdr *) (elfptr + orcSHT->sh_offset); 488 | orcNOTE = (Elf_Nhdr *) (orcptr + orcSHT->sh_offset); 489 | 490 | fuzz_note(); 491 | 492 | fuzzed_flag = 1; 493 | } 494 | 495 | if(!fuzzed_flag){ 496 | printf("\n[!] No SHT_NOTE section found!\n"); 497 | fprintf(logfp, "\n[!] No SHT_NOTE section found!\n"); 498 | } 499 | } 500 | 501 | if(mode & STRS){ 502 | verifySHT(); 503 | orcSHT = orcOrigSHT; 504 | 505 | fuzzed_flag = 0; 506 | 507 | for(secnum = 0; secnum < orcHDR->e_shnum; secnum++, orcSHT++){ 508 | if(orcSHT->sh_type != SHT_STRTAB) 509 | continue; 510 | 511 | // Metadata dependencies 512 | if(secnum == orcHDR->e_shstrndx) 513 | if(mode & (SHT | NOTE | DYN | SYM | REL)) 514 | if(rand() % 3 < 2) 515 | continue; 516 | 517 | if(orcSHT->sh_size == 0) 518 | continue; 519 | 520 | printf("\n[+] Fuzzing the String Table %s with %d bytes\n", 521 | orcptr + orcshstrtab_offset + orcSHT->sh_name, (unsigned int) orcSHT->sh_size); 522 | fprintf(logfp, "\n[+] Fuzzing the String Table %s with %d bytes\n", 523 | orcptr + orcshstrtab_offset + orcSHT->sh_name, (unsigned int) orcSHT->sh_size); 524 | 525 | orcSTRS = (char *) (orcptr + orcSHT->sh_offset); 526 | 527 | fuzz_strs(); 528 | 529 | fuzzed_flag = 1; 530 | } 531 | 532 | if(!fuzzed_flag){ 533 | printf("\n[!] No SHT_STRTAB section found!\n"); 534 | fprintf(logfp, "\n[!] No SHT_STRTAB section found!\n"); 535 | } 536 | } 537 | 538 | if(mode & SHT){ 539 | verifySHT(); 540 | orcSHT = orcOrigSHT; 541 | 542 | printf("\n[+] Fuzzing the Section Header Table with %d entries\n", orcHDR->e_shnum); 543 | fprintf(logfp, "\n[+] Fuzzing the Section Header Table with %d entries\n", orcHDR->e_shnum); 544 | 545 | fuzz_sht(); 546 | } 547 | 548 | if(mode & PHT){ 549 | verifyPHT(); 550 | orcPHT = orcOrigPHT; 551 | 552 | printf("\n[+] Fuzzing the Program Header Table with %d entries\n", orcHDR->e_phnum); 553 | fprintf(logfp, "\n[+] Fuzzing the Program Header Table with %d entries\n", orcHDR->e_phnum); 554 | 555 | fuzz_pht(); 556 | } 557 | 558 | if(mode & HDR){ 559 | printf("\n[+] Fuzzing the Elf Header\n"); 560 | fprintf(logfp, "\n[+] Fuzzing the Elf Header\n"); 561 | 562 | fuzz_hdr(); 563 | } 564 | 565 | // Reflect the changes in filesystem 566 | if(msync(orcptr, 0, MS_SYNC) == -1){ 567 | perror("msync"); 568 | munmap(orcptr, elfstatinfo.st_size); 569 | close(orcfd); 570 | continue; 571 | } 572 | 573 | munmap(orcptr, elfstatinfo.st_size); 574 | 575 | close(orcfd); 576 | 577 | usleep(20000); 578 | } 579 | 580 | stop_logger(logfp); 581 | 582 | printf("\n[+] Fuzzing process finished\n"); 583 | printf("[+] Orcs (malformed ELFs) saved in '%s/'\n", dirname); 584 | printf("[+] Detailed fuzzing report: '%s/%s'\n", dirname, logfname); 585 | 586 | munmap(elfptr, elfstatinfo.st_size); 587 | 588 | free(dirname_orcfname); 589 | 590 | exit(EXIT_SUCCESS); 591 | } 592 | 593 | void usage(const char *self) 594 | { 595 | banner(); 596 | 597 | printf("Usage: %s [-n num -l likelihood -q]\n", self); 598 | printf("\t:\n"); 599 | printf("\t\t-a Autodetect (fuzz according to e_type except -H [the header])\n"); 600 | printf("\t\t-H ELF header\n"); 601 | printf("\t\t-S Section Header Table\n"); 602 | printf("\t\t-P Program Header Table\n"); 603 | printf("\t\t-D Dynamic section\n"); 604 | printf("\t\t-s Symbols Table(s)\n"); 605 | printf("\t\t-R Relocations Table(s)\n"); 606 | printf("\t\t-N Notes section\n"); 607 | printf("\t\t-Z Strings Tables\n"); 608 | printf("\t\t-A All of the above (except -a [Autodetect])\n"); 609 | printf("\t\t-B All of the above (except -a [Autodetect] and -H [ELF Header])\n"); 610 | printf("\t-n Number of new fuzzed ELF files (orcs) to create (default: %d)\n", n); 611 | printf("\t-l Likelihood (given in %% from 1-100) of the execution of each fuzzing rule (default: %d%%)\n", likelihood); 612 | printf("\t-q Quiet mode (doesn't print to STDOUT every executed fuzzing rule)\n"); 613 | 614 | exit(EXIT_SUCCESS); 615 | } 616 | 617 | void banner() 618 | { 619 | srand(getseed()); 620 | 621 | printf("%s", logo); 622 | printf("%s", banners[rand() % 5]); 623 | 624 | putchar('\n'); 625 | } 626 | 627 | int elf_identification(int fd) 628 | { 629 | Elf_Ehdr header; 630 | 631 | if(read(fd, &header, sizeof(header)) == -1){ 632 | perror("elf_identification: read"); 633 | return 0; 634 | } 635 | 636 | return memcmp(&header.e_ident[EI_MAG0], ELFMAG, SELFMAG) == 0; 637 | } 638 | 639 | void verifySHT() 640 | { 641 | if(elfHDR->e_shoff == 0 || elfHDR->e_shnum == 0){ 642 | printf("[-] No Section Header Table found (necessary for fuzzing) !\n"); 643 | printf("[-] Quitting...\n"); 644 | munmap(elfptr, elfstatinfo.st_size); 645 | exit(EXIT_FAILURE); 646 | } 647 | } 648 | 649 | void verifyPHT() 650 | { 651 | if(elfHDR->e_phoff == 0 || elfHDR->e_phnum == 0){ 652 | printf("[-] No Program Header Table found (necessary for fuzzing) !\n"); 653 | printf("[-] Quitting...\n"); 654 | munmap(elfptr, elfstatinfo.st_size); 655 | exit(EXIT_FAILURE); 656 | } 657 | } 658 | -------------------------------------------------------------------------------- /jni/src/melkor.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #ifndef __ANDROID_API__ 5 | #include 6 | #else 7 | #include 8 | #include "lc_elf.h" 9 | #endif 10 | 11 | #define VERSION "v1.0" 12 | 13 | #define SWAP32(v) ((((v) & 0x000000ff) << 24) | \ 14 | (((v) & 0x0000ff00) << 8) | \ 15 | (((v) & 0x00ff0000) >> 8) | \ 16 | (((v) & 0xff000000) >> 24)) 17 | 18 | /* FUZZING MODES */ 19 | #define AUTO (1 << 0) // Autodetect (based on e_type) 20 | #define HDR (1 << 1) // Elf Header 21 | #define SHT (1 << 2) // Section Header Table 22 | #define PHT (1 << 3) // Program Header Table 23 | #define SYM (1 << 4) // Symbols Table 24 | #define DYN (1 << 5) // Dynamic info 25 | #define REL (1 << 6) // Relocation data 26 | #define NOTE (1 << 7) // Notes section 27 | #define STRS (1 << 8) // Strings in the file 28 | #define ALL (HDR | SHT | PHT | SYM | DYN | REL | NOTE | STRS) 29 | #define ALLB (SHT | PHT | SYM | DYN | REL | NOTE | STRS) 30 | 31 | 32 | /* -DDEBUG was deleted from CFLAGS in Makefile. 33 | Add -DDEBUG if you want to print extra info. 34 | */ 35 | #ifdef DEBUG 36 | #define debug(...) if(!quiet) printf(__VA_ARGS__) 37 | #else 38 | #define debug(...) // 39 | #endif 40 | 41 | 42 | /* Function pointer type 'func_ptr'. 43 | It will be used to create arrays of function pointers in fuzz_*.c 44 | */ 45 | typedef int (*func_ptr)(void); 46 | 47 | #ifndef __ANDROID_API__ 48 | int PAGESIZE; // Set at runtime with getpagesize() in melkor.c 49 | #endif 50 | 51 | #ifndef PT_GNU_STACK 52 | #define PT_GNU_STACK 0x6474e551 // Indicates executable stack 53 | #endif 54 | 55 | #ifndef PT_GNU_RELRO 56 | #define PT_GNU_RELRO 0x6474e552 // Read-only after relocation 57 | #endif 58 | 59 | #ifndef PT_PAX_FLAGS 60 | #define PT_PAX_FLAGS 0x65041580 // PAX Flags 61 | #endif 62 | 63 | // SHT_GNU_* 64 | #ifndef SHT_GNU_ATTRIBUTES 65 | #define SHT_GNU_ATTRIBUTES 0x6ffffff5 66 | #endif 67 | 68 | #ifndef SHT_GNU_HASH 69 | #define SHT_GNU_HASH 0x6ffffff6 70 | #endif 71 | 72 | #ifndef SHT_GNU_LIBLIST 73 | #define SHT_GNU_LIBLIST 0x6ffffff7 74 | #endif 75 | 76 | #ifndef SHT_GNU_verdef 77 | #define SHT_GNU_verdef 0x6ffffffd 78 | #endif 79 | 80 | #ifndef SHT_GNU_verneed 81 | #define SHT_GNU_verneed 0x6ffffffe 82 | #endif 83 | 84 | #ifndef SHT_GNU_versym 85 | #define SHT_GNU_versym 0x6fffffff 86 | #endif 87 | 88 | /* ELF STUFF */ 89 | /*** 32 - 64 BITS COMPAT ***/ 90 | #if defined(__i386__) /**** x86 ****/ 91 | // Data Types 92 | #define Elf_Half Elf32_Half 93 | #define Elf_Word Elf32_Word 94 | #define Elf_Sword Elf32_Sword 95 | #define Elf_Xword Elf32_Xword 96 | #define Elf_Sxword Elf32_Sxword 97 | #define Elf_Addr Elf32_Addr 98 | #define Elf_Off Elf32_Off 99 | #define Elf_Section Elf32_Section 100 | 101 | // Data Structs 102 | #define Elf_Ehdr Elf32_Ehdr 103 | #define Elf_Shdr Elf32_Shdr 104 | #define Elf_Sym Elf32_Sym 105 | #define Elf_Rel Elf32_Rel 106 | #define Elf_Rela Elf32_Rela 107 | #define Elf_Phdr Elf32_Phdr 108 | #define Elf_Dyn Elf32_Dyn 109 | #define Elf_Nhdr Elf32_Nhdr 110 | 111 | // Macros 112 | #define ELF_ST_TYPE ELF32_ST_TYPE 113 | #define ELF_ST_BIND ELF32_ST_BIND 114 | #define ELF_ST_INFO ELF32_ST_INFO 115 | #define ELF_ST_VISIBILITY ELF32_ST_VISIBILITY 116 | #define ELF_R_TYPE ELF32_R_TYPE 117 | #define ELF_R_SYM ELF32_R_SYM 118 | #define ELF_R_INFO ELF32_R_INFO 119 | 120 | #define HEX "%.8x" 121 | 122 | #elif defined(__x86_64__) /**** x86_64 ****/ 123 | // Data Types 124 | #define Elf_Half Elf64_Half 125 | #define Elf_Word Elf64_Word 126 | #define Elf_Sword Elf64_Sword 127 | #define Elf_Xword Elf64_Xword 128 | #define Elf_Sxword Elf64_Sxword 129 | #define Elf_Addr Elf64_Addr 130 | #define Elf_Off Elf64_Off 131 | #define Elf_Section Elf64_Section 132 | 133 | // Data Structs 134 | #define Elf_Ehdr Elf64_Ehdr 135 | #define Elf_Shdr Elf64_Shdr 136 | #define Elf_Sym Elf64_Sym 137 | #define Elf_Rel Elf64_Rel 138 | #define Elf_Rela Elf64_Rela 139 | #define Elf_Phdr Elf64_Phdr 140 | #define Elf_Dyn Elf64_Dyn 141 | #define Elf_Nhdr Elf64_Nhdr 142 | 143 | // Macros 144 | #define ELF_ST_TYPE ELF64_ST_TYPE 145 | #define ELF_ST_BIND ELF64_ST_BIND 146 | #define ELF_ST_INFO ELF64_ST_INFO 147 | #define ELF_ST_VISIBILITY ELF64_ST_VISIBILITY 148 | #define ELF_R_TYPE ELF64_R_TYPE 149 | #define ELF_R_SYM ELF64_R_SYM 150 | #define ELF_R_INFO ELF64_R_INFO 151 | 152 | #define HEX "%.16lx" 153 | 154 | #elif defined(__ANDROID_API__) /**** Android ****/ 155 | // Data Types 156 | #define Elf_Half Elf32_Half 157 | #define Elf_Word Elf32_Word 158 | #define Elf_Sword Elf32_Sword 159 | #define Elf_Xword Elf32_Xword 160 | #define Elf_Sxword Elf32_Sxword 161 | #define Elf_Addr Elf32_Addr 162 | #define Elf_Off Elf32_Off 163 | #define Elf_Section Elf32_Section 164 | 165 | // Data Structs 166 | #define Elf_Ehdr Elf32_Ehdr 167 | #define Elf_Shdr Elf32_Shdr 168 | #define Elf_Sym Elf32_Sym 169 | #define Elf_Rel Elf32_Rel 170 | #define Elf_Rela Elf32_Rela 171 | #define Elf_Phdr Elf32_Phdr 172 | #define Elf_Dyn Elf32_Dyn 173 | #define Elf_Nhdr Elf32_Nhdr 174 | 175 | // Macros 176 | #define ELF_ST_TYPE ELF32_ST_TYPE 177 | #define ELF_ST_BIND ELF32_ST_BIND 178 | #define ELF_ST_INFO ELF32_ST_INFO 179 | #define ELF_ST_VISIBILITY ELF32_ST_VISIBILITY 180 | #define ELF_R_TYPE ELF32_R_TYPE 181 | #define ELF_R_SYM ELF32_R_SYM 182 | #define ELF_R_INFO ELF32_R_INFO 183 | 184 | #define HEX "%.8x" 185 | #else 186 | #error "Unsupported arch !" 187 | #endif 188 | 189 | 190 | /* PROTOTYPES */ 191 | void usage(const char *); 192 | void banner(); 193 | int elf_identification(int); 194 | void verifySHT(void); 195 | void verifyPHT(void); 196 | 197 | FILE *start_logger(char *, char *); 198 | void stop_logger(FILE *); 199 | 200 | void fuzz_hdr(void); 201 | void fuzz_sht(void); 202 | void fuzz_pht(void); 203 | void fuzz_sym(void); 204 | void fuzz_dyn(void); 205 | void fuzz_rel(void); 206 | void fuzz_note(void); 207 | void fuzz_strs(void); 208 | 209 | unsigned int getseed(void); 210 | Elf_Addr getElf_Addr(void); 211 | Elf_Off getElf_Off(void); 212 | Elf_Word getElf_Word(void); 213 | Elf_Xword getElf_Xword(void); 214 | Elf_Half getElf_Half(void); 215 | Elf_Section getElf_Section(void); 216 | char *get_fmt_str(void); 217 | char *get_fuzzed_path(void); 218 | 219 | Elf_Section findSectionIndexByName(char *); 220 | void fuzzName(void); 221 | void fuzzSize(void); 222 | void fuzzEntSize(void); 223 | void fuzzFlags(void); 224 | void fuzzAddrAlign(void); 225 | 226 | Elf_Addr get_d_ptr_by_d_tag(Elf_Sword); 227 | Elf_Word get_d_val_by_d_tag(Elf_Sword); -------------------------------------------------------------------------------- /jni/src/numbers.h: -------------------------------------------------------------------------------- 1 | int int_l33t[] = { 2 | 0xB16B00B5, // ( * ) ( * ) 3 | 0x0DEFACED, 4 | 0XDEADFACE, 5 | 0xCAFED00D, 6 | 0xFEE1DEAD, 7 | 0x0D15EA5E, 8 | 0xDEADC0DE, 9 | 0xBAD0C0DE, 10 | 0xDEFECA7E, 11 | 0xDEFEC8ED, 12 | 0x600DCAFE, 13 | 0x00031337, 14 | }; 15 | 16 | short short_l33t[] = { 17 | 0xDEAD, 0xBABE, 18 | 0xCAFE, 0xF00D, 19 | 0xBEEF, 0xC0DE, 20 | 0xFACE, 0x0BAD, 21 | 0x1337, 0xD00D, 22 | 0x0FA6, 0xB00B, 23 | }; 24 | 25 | Elf_Addr key_Addr[] = { 26 | 0x00000000, // Zero page 27 | 0x00400000, 28 | 0x08048000, 29 | 0x40000000, // 1GB 30 | 0x80000000, // 2GB 31 | 0x81000000, 32 | 0xc0000000, // 3GB 33 | 0xc1000000, 34 | 0xd0000000, 35 | }; 36 | 37 | // Could be used as short by shifting 16 bits (E.g. int_b0f[0] >> 16 == 0x7fff) 38 | int int_b0f[] = { 39 | 0x7fffffff, // INT_MAX 40 | 0xffffffff, // UINT_MAX (-1 for signed vars) 41 | 0x80000000, // Negative value for signed vars (MSB = 1) 42 | 0xc0000000, 43 | 0xff00ff00, 44 | 0xffff0000, 45 | }; 46 | 47 | int common_b0f[] = { 48 | 0x41424344, // INC EAX; INC EBX; INC ECX; INC EDX 49 | 0x41414141, // INC EAX * 4 50 | 0x42424242, // INC EBX * 4 51 | 0x43434343, // INC ECX * 4 52 | 0x44444444, // INC EDX * 4 53 | 0x90909090, // NOP 54 | 0xcccccccc, // INT 3 55 | }; 56 | 57 | const char *fuzz_paths[] = { 58 | "orcs_libfoo.so/", 59 | "././../.././...", 60 | "/;;/;//..", 61 | "\\//\\//", 62 | "~/~~~//", 63 | "*/!/*", 64 | "$xX", 65 | ":::", 66 | "/#)", 67 | "$$", 68 | "//", 69 | "\\", 70 | "~", 71 | "*", 72 | "/", 73 | }; 74 | 75 | const char *fmt_strs[] = { 76 | " %x ", 77 | " %n ", 78 | " %p ", 79 | }; 80 | -------------------------------------------------------------------------------- /jni/src/print_envp_vars.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Melkor - An ELF File Format Fuzzer 3 | * Copyright (C) 2014 Alejandro Hernandez H. (nitr0us) 4 | * 5 | * Mexico 6 | */ 7 | 8 | #include 9 | #include 10 | 11 | int main(int argc, char *argv[], char *envp[]) 12 | { 13 | int index = 0; 14 | 15 | while(envp[index]) 16 | if(strstr(envp[index], "LD_")) 17 | printf("$%s\n\n", envp[index++]); 18 | else 19 | index++; 20 | 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /libs/armeabi/env1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anestisb/melkor-android/74d4ecd3719c21c92927c5a65bdf4318b547487d/libs/armeabi/env1 -------------------------------------------------------------------------------- /libs/armeabi/env2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anestisb/melkor-android/74d4ecd3719c21c92927c5a65bdf4318b547487d/libs/armeabi/env2 -------------------------------------------------------------------------------- /libs/armeabi/env3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anestisb/melkor-android/74d4ecd3719c21c92927c5a65bdf4318b547487d/libs/armeabi/env3 -------------------------------------------------------------------------------- /libs/armeabi/melkor: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anestisb/melkor-android/74d4ecd3719c21c92927c5a65bdf4318b547487d/libs/armeabi/melkor -------------------------------------------------------------------------------- /libs/armeabi/print_envp_vars: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anestisb/melkor-android/74d4ecd3719c21c92927c5a65bdf4318b547487d/libs/armeabi/print_envp_vars --------------------------------------------------------------------------------