1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
import lldb
from angr.errors import SimConcreteMemoryError, \
SimConcreteRegisterError
from angr_targets.concrete import ConcreteTarget
from angr_targets.memory_map import MemoryMap
class LLDBConcreteTarget(ConcreteTarget):
def __init__(self, executable: str, args: list[str] = []):
# Prepend the executable's path to argv, as is convention
args.insert(0, executable)
self.debugger = lldb.SBDebugger.Create()
self.debugger.SetAsync(False)
self.target = self.debugger.CreateTargetWithFileAndArch(executable,
lldb.LLDB_ARCH_DEFAULT)
self.module = self.target.FindModule(self.target.GetExecutable())
self.interpreter = self.debugger.GetCommandInterpreter()
# Set up objects for process execution
self.error = lldb.SBError()
self.listener = self.debugger.GetListener()
self.process = self.target.Launch(self.listener,
args, None, None,
None, None, None, 0,
True, self.error)
if not self.process.IsValid():
raise RuntimeError(f'[In LLDBConcreteTarget.__init__]: Failed to'
f' launch process.')
def set_breakpoint(self, addr, **kwargs):
command = f'b -a {addr} -s {self.module.GetFileSpec().GetFilename()}'
result = lldb.SBCommandReturnObject()
self.interpreter.HandleCommand(command, result)
def remove_breakpoint(self, addr, **kwargs):
command = f'breakpoint delete {addr}'
result = lldb.SBCommandReturnObject()
self.interpreter.HandleCommand(command, result)
def is_running(self):
return self.process.GetState() == lldb.eStateRunning
def is_exited(self):
"""Not part of the angr interface, but much more useful than
`is_running`.
:return: True if the process has exited. False otherwise.
"""
return self.process.GetState() == lldb.eStateExited
def wait_for_running(self):
while self.process.GetState() != lldb.eStateRunning:
pass
def wait_for_halt(self):
while self.process.GetState() != lldb.eStateStopped:
pass
def run(self):
state = self.process.GetState()
if state == lldb.eStateExited:
raise RuntimeError(f'Tried to resume process execution, but the'
f' process has already exited.')
assert(state == lldb.eStateStopped)
self.process.Continue()
def stop(self):
self.process.Stop()
def exit(self):
self.debugger.Terminate()
print(f'Program exited with status {self.process.GetState()}')
def _get_register(self, regname: str) -> lldb.SBValue:
"""Find a register by name.
:raise SimConcreteRegisterError: If no register with the specified name
can be found.
"""
frame = self.process.GetThreadAtIndex(0).GetFrameAtIndex(0)
reg = frame.FindRegister(regname)
if reg is None:
raise SimConcreteRegisterError(
f'[In LLDBConcreteTarget._get_register]: Register {regname}'
f' not found.')
return reg
def read_register(self, regname: str) -> int:
reg = self._get_register(regname)
val = reg.GetValue()
if val is None:
raise SimConcreteRegisterError(
f'[In LLDBConcreteTarget.read_register]: Register has an'
f' invalid value of {val}.')
return int(val, 16)
def write_register(self, regname: str, value: int):
reg = self._get_register(regname)
error = lldb.SBError()
reg.SetValueFromCString(hex(value), error)
if not error.success:
raise SimConcreteRegisterError(
f'[In LLDBConcreteTarget.write_register]: Unable to set'
f' {regname} to value {hex(value)}!')
def read_memory(self, addr, size):
err = lldb.SBError()
content = self.process.ReadMemory(addr, size, err)
if not err.success:
raise SimConcreteMemoryError(f'Error when reading {size} bytes at'
f' address {hex(addr)}: {err}')
return content
def write_memory(self, addr, value):
err = lldb.SBError()
res = self.process.WriteMemory(addr, value, err)
if not err.success or res != len(value):
raise SimConcreteMemoryError(f'Error when writing to address'
f' {hex(addr)}: {err}')
def get_mappings(self):
mmap = []
region_list = self.process.GetMemoryRegions()
for i in range(region_list.GetSize()):
region = lldb.SBMemoryRegionInfo()
region_list.GetMemoryRegionAtIndex(i, region)
perms = f'{"r" if region.IsReadable() else "-"}' \
f'{"w" if region.IsWritable() else "-"}' \
f'{"x" if region.IsExecutable() else "-"}' \
mmap.append(MemoryMap(region.GetRegionBase(),
region.GetRegionEnd(),
0, # offset?
"<no-name>", # name?
perms))
return mmap
|