├── .gitignore ├── LICENSE ├── README.md ├── examples ├── ais3_crackme │ ├── ais3_crackme │ └── ais3_crackme.py └── sharif7_rev50 │ ├── getit │ └── getit.py ├── r2angrdbg └── __init__.py ├── requirements.txt └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Visual Studio Code 2 | .vscode/ 3 | 4 | # Byte-compiled / optimized / DLL files 5 | __pycache__/ 6 | *.py[cod] 7 | *$py.class 8 | 9 | # C extensions 10 | *.so 11 | 12 | # Distribution / packaging 13 | .Python 14 | build/ 15 | develop-eggs/ 16 | dist/ 17 | downloads/ 18 | eggs/ 19 | .eggs/ 20 | lib/ 21 | lib64/ 22 | parts/ 23 | sdist/ 24 | var/ 25 | wheels/ 26 | *.egg-info/ 27 | .installed.cfg 28 | *.egg 29 | MANIFEST 30 | 31 | # PyInstaller 32 | # Usually these files are written by a python script from a template 33 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 34 | *.manifest 35 | *.spec 36 | 37 | # Installer logs 38 | pip-log.txt 39 | pip-delete-this-directory.txt 40 | 41 | # Unit test / coverage reports 42 | htmlcov/ 43 | .tox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | .hypothesis/ 51 | 52 | # Translations 53 | *.mo 54 | *.pot 55 | 56 | # Django stuff: 57 | *.log 58 | .static_storage/ 59 | .media/ 60 | local_settings.py 61 | 62 | # Flask stuff: 63 | instance/ 64 | .webassets-cache 65 | 66 | # Scrapy stuff: 67 | .scrapy 68 | 69 | # Sphinx documentation 70 | docs/_build/ 71 | 72 | # PyBuilder 73 | target/ 74 | 75 | # Jupyter Notebook 76 | .ipynb_checkpoints 77 | 78 | # pyenv 79 | .python-version 80 | 81 | # celery beat schedule file 82 | celerybeat-schedule 83 | 84 | # SageMath parsed files 85 | *.sage.py 86 | 87 | # Environments 88 | .env 89 | .venv 90 | env/ 91 | venv/ 92 | ENV/ 93 | env.bak/ 94 | venv.bak/ 95 | 96 | # Spyder project settings 97 | .spyderproject 98 | .spyproject 99 | 100 | # Rope project settings 101 | .ropeproject 102 | 103 | # mkdocs documentation 104 | /site 105 | 106 | # mypy 107 | .mypy_cache/ 108 | 109 | # Node 110 | 111 | .DS_Store 112 | node_modules/ 113 | dist/ 114 | npm-debug.log 115 | yarn-error.log 116 | 117 | # Editor directories and files 118 | .idea 119 | *.suo 120 | *.ntvs* 121 | *.njsproj 122 | *.sln 123 | 124 | # SQLite database 125 | *.sqlite3 126 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2018, Andrea Fioraldi 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # r2angrdbg 2 | 3 | Use angr inside the radare2 debugger. 4 | 5 | Create an angr state from the current debugger state. 6 | 7 | ## Install 8 | 9 | `pip install r2angrdbg` 10 | 11 | ## Usage 12 | 13 | r2angr implements the [angrdbg](https://github.com/andreafioraldi/angrdbg) API, you can use it after the call to `r2angrdbg.init` 14 | 15 | ```python 16 | import r2pipe 17 | import r2angrdbg 18 | 19 | r2 = r2pipe.open("stuff") 20 | r2angrdbg.init(r2) 21 | 22 | r2.cmd("l33t r2 cmd") 23 | 24 | sm = r2angrdbg.StateManager() 25 | # stuffs with angrdbg StateManager ... 26 | ``` 27 | 28 | see the [examples](https://github.com/andreafioraldi/r2angrdbg/tree/master/examples) folder. 29 | -------------------------------------------------------------------------------- /examples/ais3_crackme/ais3_crackme: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andreafioraldi/r2angrdbg/72cbd68a5b5b7e5802f2a67a66cb526aeba8374a/examples/ais3_crackme/ais3_crackme -------------------------------------------------------------------------------- /examples/ais3_crackme/ais3_crackme.py: -------------------------------------------------------------------------------- 1 | import r2pipe 2 | import r2angrdbg 3 | 4 | r2 = r2pipe.open("ais3_crackme") 5 | r2angrdbg.init(r2) 6 | 7 | r2.cmd("aaa") 8 | r2.cmd("ood DUMMY") 9 | r2.cmd("db 0x004005f9") 10 | r2.cmd("dc") 11 | 12 | sm = r2angrdbg.StateManager() 13 | key = sm.sim(sm["rax"], 100) 14 | argv1, size = sm.get_symbolic(key) 15 | initial_state = sm.get_state() 16 | 17 | initial_state.add_constraints(argv1.chop(8)[0] == b'a') 18 | initial_state.add_constraints(argv1.chop(8)[1] == b'i') 19 | initial_state.add_constraints(argv1.chop(8)[2] == b's') 20 | initial_state.add_constraints(argv1.chop(8)[3] == b'3') 21 | initial_state.add_constraints(argv1.chop(8)[4] == b'{') 22 | 23 | m = sm.simulation_manager() 24 | m.explore(find=0x00400602, avoid=0x0040060e) 25 | print(m) 26 | conc = sm.concretize(m.found[0]) 27 | for addr in conc: 28 | print ("0x%x ==> %s" % (addr, repr(conc[addr]))) 29 | 30 | sm.to_dbg(m.found[0]) 31 | 32 | print (r2.cmd("x 100 @ rax")) 33 | r2.cmd("dc") 34 | 35 | -------------------------------------------------------------------------------- /examples/sharif7_rev50/getit: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andreafioraldi/r2angrdbg/72cbd68a5b5b7e5802f2a67a66cb526aeba8374a/examples/sharif7_rev50/getit -------------------------------------------------------------------------------- /examples/sharif7_rev50/getit.py: -------------------------------------------------------------------------------- 1 | from r2angrdbg import * 2 | 3 | try: 4 | long 5 | bytes = str 6 | except: 7 | long = int 8 | 9 | r2 = r2pipe.open("getit") 10 | init(r2) 11 | 12 | set_memory_type(USE_CLE_MEMORY) 13 | 14 | r2.cmd("aaa") 15 | r2.cmd("ood") 16 | r2.cmd("db main") 17 | r2.cmd("dc") 18 | 19 | flag_addr = 0x6010e0 20 | stop_addr = 0x4008c8 21 | 22 | sm = StateManager() 23 | 24 | m = sm.simulation_manager() 25 | m.explore(find=stop_addr) 26 | 27 | flag = m.found[0].memory.load(flag_addr, 50) 28 | 29 | print(m.found[0].solver.eval(flag, cast_to=bytes)) 30 | -------------------------------------------------------------------------------- /r2angrdbg/__init__.py: -------------------------------------------------------------------------------- 1 | import r2pipe 2 | import base64 3 | import os 4 | 5 | from angrdbg import * 6 | 7 | 8 | class R2Debugger(Debugger): 9 | def __init__(self, r2): 10 | self.r2 = r2 11 | self.base_addr = None 12 | 13 | def _get_vmmap(self): 14 | dm = self.r2.cmdj("dmj") 15 | maps = [] 16 | for s in dm: 17 | start = s["addr"] 18 | end = s["addr_end"] 19 | mapperm = 0 20 | if "r" in s["perm"]: 21 | mapperm |= SEG_PROT_R 22 | if "w" in s["perm"]: 23 | mapperm |= SEG_PROT_W 24 | if "x" in s["perm"]: 25 | mapperm |= SEG_PROT_X 26 | maps += [(start, end, mapperm, s["name"])] 27 | return maps 28 | 29 | # ------------------------------------- 30 | def before_stateshot(self): 31 | self.vmmap = self._get_vmmap() 32 | 33 | for sec in self.r2.cmdj("iSj"): 34 | if sec["name"] == load_project().arch.got_section_name: 35 | self.got = (sec["vaddr"], sec["vaddr"] + sec["vsize"]) 36 | elif sec["name"] == ".plt": 37 | self.plt = (sec["vaddr"], sec["vaddr"] + sec["vsize"]) 38 | 39 | def after_stateshot(self, state): 40 | pass 41 | # ------------------------------------- 42 | 43 | def is_active(self): 44 | return self.r2.cmd("dm") != "" 45 | 46 | # ------------------------------------- 47 | def input_file(self): 48 | # path = self.r2.cmdj("dmj")[0]["file"] 49 | path = self.r2.cmdj("ij")['core']['file'] 50 | return open(path, "rb") 51 | 52 | def image_base(self): 53 | if self.base_addr is None: 54 | self.base_addr = int(self.r2.cmd("e bin.baddr"), 16) 55 | return self.base_addr 56 | 57 | # ------------------------------------- 58 | def get_byte(self, addr): 59 | try: 60 | return ord(base64.b64decode(self.r2.cmd("p6e 1 @ %d" % addr))) 61 | except BaseException: 62 | return None 63 | 64 | def get_word(self, addr): 65 | try: 66 | return struct.unpack( 67 | "= start and addr < end: 140 | return Segment(name, start, end, perms) 141 | return None 142 | 143 | def get_got(self): # return tuple(start_addr, end_addr) 144 | return self.got 145 | 146 | def get_plt(self): # return tuple(start_addr, end_addr) 147 | return self.plt 148 | 149 | # ------------------------------------- 150 | def resolve_name(self, name): # return None on fail 151 | try: 152 | modules = self.r2.cmdj("dmmj") 153 | for m in modules[1:]: 154 | addr = m["address"] 155 | lib = os.path.basename(m["name"]).split(".")[0].split("-")[0] 156 | o = self.r2.cmd("dmi* %s %s" % (lib, name)) 157 | for line in o.split("\n"): 158 | line = line.split() 159 | if len(line) < 4: 160 | continue 161 | if line[1] == name or line[3] == "sym."+name: 162 | return int(line[3], 16) 163 | except: 164 | pass 165 | return None 166 | 167 | 168 | def init(r2): 169 | register_debugger(R2Debugger(r2)) 170 | 171 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | angrdbg 2 | r2pipe 3 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | __author__ = "Andrea Fioraldi" 4 | __copyright__ = "Copyright 2017, Andrea Fioraldi" 5 | __license__ = "BSD 2-Clause" 6 | __email__ = "andreafioraldi@gmail.com" 7 | 8 | from setuptools import setup 9 | 10 | VER = "1.0.1" 11 | 12 | setup( 13 | name='r2angrdbg', 14 | version=VER, 15 | license=__license__, 16 | description='Use angr inside the radare2 debugger. Create an angr state from the current debugger state. ', 17 | author=__author__, 18 | author_email=__email__, 19 | url='https://github.com/andreafioraldi/r2angrdbg', 20 | download_url = 'https://github.com/andreafioraldi/r2angrdbg/archive/' + VER + '.tar.gz', 21 | package_dir={'r2angrdbg': 'r2angrdbg'}, 22 | packages=['r2angrdbg'], 23 | install_requires=['angrdbg'], 24 | ) 25 | --------------------------------------------------------------------------------