{"id":16835442,"url":"https://github.com/defuse/gadgetrie","last_synced_at":"2025-08-12T21:07:47.974Z","repository":{"id":11496722,"uuid":"13972731","full_name":"defuse/gadgetrie","owner":"defuse","description":"A simple gadget finder for Return Oriented Programming","archived":false,"fork":false,"pushed_at":"2014-04-17T17:01:53.000Z","size":228,"stargazers_count":4,"open_issues_count":3,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-06-03T19:03:35.150Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/defuse.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-10-30T00:20:16.000Z","updated_at":"2024-04-28T15:45:52.000Z","dependencies_parsed_at":"2022-09-23T22:51:09.670Z","dependency_job_id":null,"html_url":"https://github.com/defuse/gadgetrie","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/defuse/gadgetrie","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/defuse%2Fgadgetrie","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/defuse%2Fgadgetrie/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/defuse%2Fgadgetrie/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/defuse%2Fgadgetrie/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/defuse","download_url":"https://codeload.github.com/defuse/gadgetrie/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/defuse%2Fgadgetrie/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270135073,"owners_count":24533203,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-12T02:00:09.011Z","response_time":80,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-13T12:10:18.910Z","updated_at":"2025-08-12T21:07:47.944Z","avatar_url":"https://github.com/defuse.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"gadgetrie\n=========\n\nGadetrie, pronounced \"gadgetry\", is a simple ROP gadget finder, written in C.\nIt is small and simple, but complete. It finds all possible gadgets in the\nexecutable segment(s) of a program and shows them to you. It doesn't do anything\nfancy like constructing a payload for you, it's just a gadget finder.\n\nIt only supports 32-bit ELF binaries.\n\nLicense\n-------\n\nThis software uses the MIT license. See the LICENSE file.\n\nThe following paragraph justifies the choice of license and does not have any\naffect on the copyright of this software.\n\nI normally use the GPL v3, but in this case I chose the MIT license over the GPL\nbecause this code is most likely to be used by researchers. I don't want to\nforce researchers to GPL their much larger project in order to use my code. They\nknow what's best for their project, and that might not be a GNU license.\nI believe that any responsible scientifically-minded researcher will do their\nbest to keep the code open even when they don't have to.\n\nHow it Works\n------------\n\n### Unintended Instructions\n\nOn the x86, instructions are variable-length, and don't have to be aligned, so\nit's possible to find \"unintended\" instructions in machine code by starting the\ndisassembly at a different offset.\n\nConsider this sequence of bytes:\n\n    05 5A 59 5B 58 C3\n\nIf we start disassembling at the first byte, we find out that this is the\nsequence of instructions:\n\n    05 5A 59 5B 58      | ADD EAX, 0x585B595A\n    C3                  | RET\n\nHowever, if we skip the first byte, 0x05, and start disassembling at the second\nbyte, 0x5A, we get something different:\n\n    05                  | (skipped)\n    5A                  | POP EDX\n    59                  | POP ECX \n    5B                  | POP EBX\n    58                  | POP EAX\n    C3                  | RET\n\nThe programmer wrote an instruction to add a value to EAX, but its machine code\ncan be interpreted in a different ways to reveal different instructions. We have\nto take this into account when searching for gadgets, since these unintended\ninstructions might prove useful.\n\n### Search Algorithm\n\nWe're interested in finding sequences of instructions that end in a return\ninstruction (RET). These sequences are called gadgets. On x86, this instruction\nis encoded as a single byte 0xC3.\n\nTo find gadgets in a corpus of machine code, we first search for all return\ninstructions (0xC3 bytes). Then, for each return instruction, we work backwards\nto enumerate the instructions before it. Since x86 instructions are\nvariable-length, we don't know how long the instruction before the return is, so\nwe try all possible lengths. We start at 1 byte, and go up to the maximum length\nof an x86 instruction, which is 15 bytes. \n\nEven if we find, say, a two-byte instruction before the return, we will keep\ngoing and check for 3+ byte instructions, because those extra bytes might reveal\ndifferent unintended instructions before the return. We always check up to the\nmaximum length of 15 bytes. Each time we find an instruction before the return,\nwe add it to a list.\n\nThen, for each instruction before the return, we apply the same process\nrecursively. We now want to find the instructions before the instruction before\nthe return. As we do this, we build a tree of instructions that come before the\nreturn.\n\nThe root of the tree is the return instruction itself, its children are the\ninstructions that come directly before the return by looking at different\ninterpretations of the machine code, and their children are the instructions\nthat come directly before them, also by looking at different interpretations of\nthe machine code.\n\nThis continues until we've found up to 5 instructions before the return.\n\nSo far we have only looked at the instructions coming before a single return. In\na body of machine code, there will be many return instructions, so the next step\nis to combine them all into one tree. This is done by keeping one big tree\nholding all of the sequences of instructions found before a return. Whenever we\nfind a sequence of instructions before a return, we check if it is already in\nthe tree. If not, we add it into the tree.\n\nWhen the process is finished, we have one huge tree of instructions, whose root\nis a return, and whose branches represent all of the gadgets available in the\nprogram code. As we build the tree, we keep in the nodes the address at which\nthe sequence starts, so from the tree, we can find where the gadgets start.\n\nFor example, if we searched the following bytes for gadgets, we would get the\nfollowing tree.\n\n    Address:    0  1  2  3  4  5  6  7\n    Code:       05 5A 59 5B 58 C3 50 C3\n                                ^     ^   (returns)\n    Tree:\n                +-----------+\n                | RET (5,7) |\n                +----+------+\n                     |\n             .-------+-----.-------------------.\n            /               \\                   \\\n    +------+-------+     +---+---------+      +--+----------------------+\n    | PUSH EAX (6) |     | POP EAX (4) |      | ADD EAX, 0x585B595A (0) |\n    +------+-------+     +------+------+      +-------------------------+\n                                |\n                         +------+------+\n                         | POP EBX (3) |\n                         +------+------+\n                                |    \n                         +------+------+\n                         | POP ECX (2) |\n                         +------+------+\n                                |    \n                         +------+------+\n                         | POP EDX (1) |\n                         +-------------+\n\n### Credit\n\nThe algorithm used here was presented in \"Return Oriented Programming: Systems,\nLanguages, and Applications\" by Ryan Roemer, Erik Buchanan, Hovav Shacham, and\nStefan Savage from UCSD.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdefuse%2Fgadgetrie","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdefuse%2Fgadgetrie","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdefuse%2Fgadgetrie/lists"}