mirror of
https://github.com/trailofbits/manticore.git
synced 2026-10-12 02:23:44 +00:00
* py/missing-call-to-init
* Remove deprecated should_profile argument
* WASM __init__ call and variable names
* Mute warnings about printing evm account IDs
LGTM thinks we're logging potentially sensitive data when we create a symbolic account and print the user ID. I can't imagine a context where we would ever care about this alert in general, so I'm going to disable it.
* Fix mixed attribute/function names
* Another missing __init__ call
* Remove single-op form of _bitwise_instruction
It's never used
* Use built-in ops instead of lambda
* Missing import
* Some unreachable code
Still missing some in evm.py
* Blacken
* Tag examples as examples
* NotImplemented -> NotImplementedError
* Fix unnecessary `pass`
* Revert "Remove single-op form of _bitwise_instruction"
This reverts commit 1b7a4110f4.
* Mute overzealous call argument error
Co-authored-by: Brad Larsen <[email protected]>
142 lines
3.5 KiB
Python
142 lines
3.5 KiB
Python
import subprocess
|
|
|
|
count = 0
|
|
|
|
prompt = ""
|
|
subproc = None
|
|
_arch = None
|
|
|
|
|
|
def drain():
|
|
str_buffer = ""
|
|
while not str_buffer.endswith(prompt):
|
|
c = subproc.stdout.read(1)
|
|
str_buffer += c
|
|
return str_buffer[: -len(prompt)]
|
|
|
|
|
|
def start(arch, argv, port=1234, _prompt="(gdb) "):
|
|
global prompt, subproc
|
|
prompt = _prompt
|
|
gdb = "gdb-multiarch"
|
|
try:
|
|
subproc = subprocess.Popen(
|
|
[gdb, argv[0]], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT
|
|
)
|
|
except OSError:
|
|
msg = f"'{gdb}' binary not found in PATH (needed for tracing)"
|
|
raise RuntimeError(msg)
|
|
|
|
drain()
|
|
# correspond(f'set architecture {arch}\n')
|
|
correspond(f"file {argv[0]}\n")
|
|
correspond(f"target remote :{port}\n")
|
|
correspond("set pagination off\n")
|
|
|
|
|
|
def correspond(text):
|
|
"""Communicate with the child process without closing stdin."""
|
|
subproc.stdin.write(text)
|
|
subproc.stdin.flush()
|
|
return drain()
|
|
|
|
|
|
def getInstruction():
|
|
return correspond("x/i $pc\n").split("\n")[0]
|
|
|
|
|
|
def getR(reg):
|
|
reg = "$" + reg
|
|
if "XMM" in reg:
|
|
reg = reg + ".uint128"
|
|
val = correspond(f"p {reg.lower()}\n").split("=")[-1].split("\n")[0]
|
|
if "0x" in val:
|
|
return int(val.split("0x")[-1], 16)
|
|
else:
|
|
return int(val)
|
|
if "FLAG" in reg:
|
|
reg = "(unsigned) " + reg
|
|
if reg in [f"$R{i}B" for i in range(16)]:
|
|
reg = reg[:-1] + "&0xff"
|
|
if reg in [f"$R{i}W" for i in range(16)]:
|
|
reg = reg[:-1] + "&0xffff"
|
|
val = correspond(f"p /x {reg.lower()}\n")
|
|
val = val.split("0x")[-1]
|
|
return int(val.split("\n")[0], 16)
|
|
|
|
|
|
def getCanonicalRegisters():
|
|
reg_output = correspond("info reg\n")
|
|
registers = {}
|
|
for line in reg_output.split("\n"):
|
|
line = line.strip()
|
|
if not line:
|
|
continue
|
|
name, hex_val = line.split()[:2]
|
|
if name != "cpsr":
|
|
registers[name] = int(hex_val, 0)
|
|
else:
|
|
# We just want the NZCV flags
|
|
registers[name] = int(hex_val, 0) & 0xF0000000
|
|
return registers
|
|
|
|
|
|
def setR(reg, value):
|
|
correspond(f"set ${reg.lower()} = {int(value)}\n")
|
|
|
|
|
|
def stepi():
|
|
# print subproc.correspond("x/i $pc\n")
|
|
correspond("stepi\n")
|
|
|
|
|
|
def getM(m):
|
|
try:
|
|
return int(correspond(f"x/xg {m}\n").strip().split("\t")[-1], 0)
|
|
except Exception as e:
|
|
raise e
|
|
|
|
|
|
def getPid():
|
|
return int(correspond("info proc\n").split("\n")[0].split(" ")[-1])
|
|
|
|
|
|
def getStack():
|
|
p = correspond("info proc\n").split("\n")[0].split(" ")[-1]
|
|
with open(f"/proc/{p}/maps") as f:
|
|
maps = f.read().split("\n")
|
|
i, o = [int(x, 16) for x in maps[-3].split(" ")[0].split("-")]
|
|
|
|
|
|
def setByte(addr, val):
|
|
cmdstr = f"set {{char}}{addr} = {ord(val)}"
|
|
correspond(cmdstr + "\n")
|
|
|
|
|
|
def getByte(m):
|
|
arch = get_arch()
|
|
mask = {"i386": 0xFFFFFFFF, "armv7": 0xFFFFFFFF, "amd64": 0xFFFFFFFFFFFFFFFF}[arch]
|
|
return int(correspond(f"x/1bx {m & mask}\n").split("\t")[-1].split("\n")[0][2:], 16)
|
|
|
|
|
|
def get_entry():
|
|
a = correspond("info target\n")
|
|
return int(a[a.find("Entry point:") :].split("\n")[0].split(" ")[-1][2:], 16)
|
|
|
|
|
|
def get_arch():
|
|
global _arch
|
|
if _arch is not None:
|
|
return _arch
|
|
infotarget = correspond("info target\n")
|
|
if "elf32-i386" in infotarget:
|
|
_arch = "i386"
|
|
elif "elf64-x86-64" in infotarget:
|
|
_arch = "amd64"
|
|
elif "elf32-littlearm" in infotarget:
|
|
_arch = "armv7"
|
|
else:
|
|
print(infotarget)
|
|
raise NotImplementedError
|
|
return _arch
|