{"id":19390657,"url":"https://github.com/mandiant/flare-bytecode_graph","last_synced_at":"2025-04-24T00:31:31.604Z","repository":{"id":146044525,"uuid":"57127314","full_name":"mandiant/flare-bytecode_graph","owner":"mandiant","description":null,"archived":true,"fork":false,"pushed_at":"2023-04-10T00:59:33.000Z","size":26,"stargazers_count":84,"open_issues_count":2,"forks_count":27,"subscribers_count":19,"default_branch":"master","last_synced_at":"2025-03-13T12:32:16.079Z","etag":null,"topics":["fireeye-flare"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mandiant.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-04-26T12:43:20.000Z","updated_at":"2024-08-16T22:13:30.000Z","dependencies_parsed_at":"2023-05-03T08:16:26.175Z","dependency_job_id":null,"html_url":"https://github.com/mandiant/flare-bytecode_graph","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mandiant%2Fflare-bytecode_graph","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mandiant%2Fflare-bytecode_graph/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mandiant%2Fflare-bytecode_graph/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mandiant%2Fflare-bytecode_graph/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mandiant","download_url":"https://codeload.github.com/mandiant/flare-bytecode_graph/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250539427,"owners_count":21447307,"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","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":["fireeye-flare"],"created_at":"2024-11-10T10:22:38.467Z","updated_at":"2025-04-24T00:31:31.588Z","avatar_url":"https://github.com/mandiant.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# bytecode_graph\n\nModule designed to modify Python bytecode. \nAllows instructions to be added or removed from a Python bytecode string. The modified bytecode can be refactored to correct offsets and produce a new functional code object. \n\nYou should use the same Python interpretor version as the bytecode being analyzed.\n\n## Example - Inserting NOP instructions\n\nThe following example inserts a NOP instruction after each instruction in the `Sample` function:\n\n```python\n\nimport bytecode_graph\nfrom dis import opmap\n\n\ndef Sample():\n    i = 2 + 2\n    if i == 4:\n        print \"2 + 2 = %d\" % i\n    else:\n        print \"oops\"\n\nprint bytecode_graph.disassemble(Sample.__code__)\nprint\nbcg = bytecode_graph.BytecodeGraph(Sample.__code__)\n\nnodes = [x for x in bcg.nodes()]\nfor n in nodes:\n    bc = bytecode_graph.Bytecode(0, chr(opmap['NOP']))\n    bcg.add_node(n, bc)\n\nnew_code = bcg.get_code()\nprint bytecode_graph.disassemble(new_code)\nprint\nexec new_code\n\nnodes = [x for x in bcg.nodes()]\nfor n in nodes:\n    if n.opcode == opmap['NOP']:\n        bcg.delete_node(n)\nnew_code = bcg.get_code()\nprint bytecode_graph.disassemble(new_code)\nexec new_code\n```\n\nDisassembly of `Sample()`:\n```\n          0 640500  LOAD_CONST          5 (4)\n          3 7d0000  STORE_FAST          0 (i)\n          6 7c0000  LOAD_FAST           0 (i)\n          9 640200  LOAD_CONST          2 (4)\n         12 6b0200  COMPARE_OP          2 (==)\n         15 721e00  POP_JUMP_IF_FALSE    30\n         18 640300  LOAD_CONST          3 ('2 + 2 = %d')\n         21 7c0000  LOAD_FAST           0 (i)\n         24 16      BINARY_MODULO  \n         25 47      PRINT_ITEM     \n         26 48      PRINT_NEWLINE  \n         27 6e0500  JUMP_FORWARD        5 (to 35)\n    \u003e\u003e   30 640400  LOAD_CONST          4 ('oops')\n         33 47      PRINT_ITEM     \n         34 48      PRINT_NEWLINE  \n    \u003e\u003e   35 640000  LOAD_CONST          0 (None)\n         38 53      RETURN_VALUE   \n```\n\nDisassembly of `Sample()` with NOPs:\n```\n          0 640500  LOAD_CONST          5 (4)\n          3 09      NOP            \n          4 7d0000  STORE_FAST          0 (i)\n          7 09      NOP            \n          8 7c0000  LOAD_FAST           0 (i)\n         11 09      NOP            \n         12 640200  LOAD_CONST          2 (4)\n         15 09      NOP            \n         16 6b0200  COMPARE_OP          2 (==)\n         19 09      NOP            \n         20 722a00  POP_JUMP_IF_FALSE    42\n         23 09      NOP            \n         24 640300  LOAD_CONST          3 ('2 + 2 = %d')\n         27 09      NOP            \n         28 7c0000  LOAD_FAST           0 (i)\n         31 09      NOP            \n         32 16      BINARY_MODULO  \n         33 09      NOP            \n         34 47      PRINT_ITEM     \n         35 09      NOP            \n         36 48      PRINT_NEWLINE  \n         37 09      NOP            \n         38 6e0900  JUMP_FORWARD        9 (to 50)\n         41 09      NOP            \n    \u003e\u003e   42 640400  LOAD_CONST          4 ('oops')\n         45 09      NOP            \n         46 47      PRINT_ITEM     \n         47 09      NOP            \n         48 48      PRINT_NEWLINE  \n         49 09      NOP            \n    \u003e\u003e   50 640000  LOAD_CONST          0 (None)\n         53 09      NOP            \n         54 53      RETURN_VALUE   \n         55 09      NOP    \n```\n\nOutput of running modified code object:\n```\n2 + 2 = 4\n```\n\nTo remove the NOPs append the following to the above example:\n```python\nnodes = [x for x in bcg.nodes()]\nfor n in nodes:\n    #verify opcode is NOP\n    if n.opcode == opmap['NOP']:\n        #remove instruction node from the graph\n        bcg.delete_node(n)\n        \n#create a new code object\nnew_code = bcg.get_code()\nbytecode_graph.disassemble(new_code)\nexec new_code\n```\n\nTo load code from a PYC file:\n```python\nimport bytecode_graph\nfrom dis import opmap\nimport sys\nimport marshal\n\n\npyc_file = open(sys.argv[1], \"rb\").read()\npyc = marshal.loads(pyc_file[8:])\n\nbytecode_graph.disassemble(pyc)\nprint\n\nbcg = bytecode_graph.BytecodeGraph(pyc)\n\nnodes = [x for x in bcg.nodes()]\nfor n in nodes:\n    bc = bytecode_graph.Bytecode(0, chr(opmap['NOP']))\n    bcg.add_node(n, bc)\n\nnew_code = bcg.get_code()\nbytecode_graph.disassemble(new_code)\nprint\n\nnodes = [x for x in bcg.nodes()]\nfor n in nodes:\n    if n.opcode == opmap['NOP']:\n        bcg.delete_node(n)\n\nnew_code = bcg.get_code()\nbytecode_graph.disassemble(new_code)\nprint\n```\n\nIt is also possible to create control flow diagrams using GraphViz. The disassembly within the graph can include the output from a simple peephole decompiler. This can be helpful when reviewing bytecode that fails to decompile.\n\n```python\nimport bytecode_graph\n\n\ndef Sample():\n    i = 2 + 2\n    if i == 4:\n        print \"2 + 2 = %d\" % i\n    else:\n        print \"oops\"\n\nbcg = bytecode_graph.BytecodeGraph(Sample.__code__)\n\ngraph = bytecode_graph.Render(bcg, Sample.__code__).dot()\n\ngraph.write_png('example_graph.png')\n\n```\n\n![Example_Graph](docs/example_graph.png?raw=true)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmandiant%2Fflare-bytecode_graph","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmandiant%2Fflare-bytecode_graph","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmandiant%2Fflare-bytecode_graph/lists"}