smallworld-re 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (166) hide show
  1. smallworld/__init__.py +35 -0
  2. smallworld/analyses/__init__.py +14 -0
  3. smallworld/analyses/analysis.py +88 -0
  4. smallworld/analyses/code_coverage.py +31 -0
  5. smallworld/analyses/colorizer.py +682 -0
  6. smallworld/analyses/colorizer_summary.py +100 -0
  7. smallworld/analyses/field_detection/__init__.py +14 -0
  8. smallworld/analyses/field_detection/field_analysis.py +536 -0
  9. smallworld/analyses/field_detection/guards.py +26 -0
  10. smallworld/analyses/field_detection/hints.py +133 -0
  11. smallworld/analyses/field_detection/malloc.py +211 -0
  12. smallworld/analyses/forced_exec/__init__.py +3 -0
  13. smallworld/analyses/forced_exec/forced_exec.py +87 -0
  14. smallworld/analyses/underlays/__init__.py +4 -0
  15. smallworld/analyses/underlays/basic.py +13 -0
  16. smallworld/analyses/underlays/underlay.py +31 -0
  17. smallworld/analyses/unstable/__init__.py +4 -0
  18. smallworld/analyses/unstable/angr/__init__.py +0 -0
  19. smallworld/analyses/unstable/angr/base.py +12 -0
  20. smallworld/analyses/unstable/angr/divergence.py +274 -0
  21. smallworld/analyses/unstable/angr/model.py +383 -0
  22. smallworld/analyses/unstable/angr/nwbt.py +63 -0
  23. smallworld/analyses/unstable/angr/typedefs.py +170 -0
  24. smallworld/analyses/unstable/angr/utils.py +25 -0
  25. smallworld/analyses/unstable/angr/visitor.py +315 -0
  26. smallworld/analyses/unstable/angr_nwbt.py +106 -0
  27. smallworld/analyses/unstable/code_coverage.py +54 -0
  28. smallworld/analyses/unstable/code_reachable.py +44 -0
  29. smallworld/analyses/unstable/control_flow_tracer.py +71 -0
  30. smallworld/analyses/unstable/pointer_finder.py +90 -0
  31. smallworld/arch/__init__.py +0 -0
  32. smallworld/arch/aarch64_arch.py +286 -0
  33. smallworld/arch/amd64_arch.py +86 -0
  34. smallworld/arch/i386_arch.py +44 -0
  35. smallworld/emulators/__init__.py +14 -0
  36. smallworld/emulators/angr/__init__.py +7 -0
  37. smallworld/emulators/angr/angr.py +1652 -0
  38. smallworld/emulators/angr/default.py +15 -0
  39. smallworld/emulators/angr/exceptions.py +7 -0
  40. smallworld/emulators/angr/exploration/__init__.py +9 -0
  41. smallworld/emulators/angr/exploration/bounds.py +27 -0
  42. smallworld/emulators/angr/exploration/default.py +17 -0
  43. smallworld/emulators/angr/exploration/terminate.py +22 -0
  44. smallworld/emulators/angr/factory.py +55 -0
  45. smallworld/emulators/angr/machdefs/__init__.py +35 -0
  46. smallworld/emulators/angr/machdefs/aarch64.py +292 -0
  47. smallworld/emulators/angr/machdefs/amd64.py +192 -0
  48. smallworld/emulators/angr/machdefs/arm.py +387 -0
  49. smallworld/emulators/angr/machdefs/i386.py +221 -0
  50. smallworld/emulators/angr/machdefs/machdef.py +138 -0
  51. smallworld/emulators/angr/machdefs/mips.py +184 -0
  52. smallworld/emulators/angr/machdefs/mips64.py +189 -0
  53. smallworld/emulators/angr/machdefs/ppc.py +101 -0
  54. smallworld/emulators/angr/machdefs/riscv.py +261 -0
  55. smallworld/emulators/angr/machdefs/xtensa.py +255 -0
  56. smallworld/emulators/angr/memory/__init__.py +7 -0
  57. smallworld/emulators/angr/memory/default.py +10 -0
  58. smallworld/emulators/angr/memory/fixups.py +43 -0
  59. smallworld/emulators/angr/memory/memtrack.py +105 -0
  60. smallworld/emulators/angr/scratch.py +43 -0
  61. smallworld/emulators/angr/simos.py +53 -0
  62. smallworld/emulators/angr/utils.py +70 -0
  63. smallworld/emulators/emulator.py +1013 -0
  64. smallworld/emulators/hookable.py +252 -0
  65. smallworld/emulators/panda/__init__.py +5 -0
  66. smallworld/emulators/panda/machdefs/__init__.py +28 -0
  67. smallworld/emulators/panda/machdefs/aarch64.py +93 -0
  68. smallworld/emulators/panda/machdefs/amd64.py +71 -0
  69. smallworld/emulators/panda/machdefs/arm.py +89 -0
  70. smallworld/emulators/panda/machdefs/i386.py +36 -0
  71. smallworld/emulators/panda/machdefs/machdef.py +86 -0
  72. smallworld/emulators/panda/machdefs/mips.py +94 -0
  73. smallworld/emulators/panda/machdefs/mips64.py +91 -0
  74. smallworld/emulators/panda/machdefs/ppc.py +79 -0
  75. smallworld/emulators/panda/panda.py +575 -0
  76. smallworld/emulators/unicorn/__init__.py +13 -0
  77. smallworld/emulators/unicorn/machdefs/__init__.py +28 -0
  78. smallworld/emulators/unicorn/machdefs/aarch64.py +310 -0
  79. smallworld/emulators/unicorn/machdefs/amd64.py +326 -0
  80. smallworld/emulators/unicorn/machdefs/arm.py +321 -0
  81. smallworld/emulators/unicorn/machdefs/i386.py +137 -0
  82. smallworld/emulators/unicorn/machdefs/machdef.py +117 -0
  83. smallworld/emulators/unicorn/machdefs/mips.py +202 -0
  84. smallworld/emulators/unicorn/unicorn.py +684 -0
  85. smallworld/exceptions/__init__.py +5 -0
  86. smallworld/exceptions/exceptions.py +85 -0
  87. smallworld/exceptions/unstable/__init__.py +1 -0
  88. smallworld/exceptions/unstable/exceptions.py +25 -0
  89. smallworld/extern/__init__.py +4 -0
  90. smallworld/extern/ctypes.py +94 -0
  91. smallworld/extern/unstable/__init__.py +1 -0
  92. smallworld/extern/unstable/ghidra.py +129 -0
  93. smallworld/helpers.py +107 -0
  94. smallworld/hinting/__init__.py +8 -0
  95. smallworld/hinting/hinting.py +214 -0
  96. smallworld/hinting/hints.py +427 -0
  97. smallworld/hinting/unstable/__init__.py +2 -0
  98. smallworld/hinting/utils.py +19 -0
  99. smallworld/instructions/__init__.py +18 -0
  100. smallworld/instructions/aarch64.py +20 -0
  101. smallworld/instructions/arm.py +18 -0
  102. smallworld/instructions/bsid.py +67 -0
  103. smallworld/instructions/instructions.py +258 -0
  104. smallworld/instructions/mips.py +21 -0
  105. smallworld/instructions/x86.py +100 -0
  106. smallworld/logging.py +90 -0
  107. smallworld/platforms.py +95 -0
  108. smallworld/py.typed +0 -0
  109. smallworld/state/__init__.py +6 -0
  110. smallworld/state/cpus/__init__.py +32 -0
  111. smallworld/state/cpus/aarch64.py +563 -0
  112. smallworld/state/cpus/amd64.py +676 -0
  113. smallworld/state/cpus/arm.py +630 -0
  114. smallworld/state/cpus/cpu.py +71 -0
  115. smallworld/state/cpus/i386.py +239 -0
  116. smallworld/state/cpus/mips.py +374 -0
  117. smallworld/state/cpus/mips64.py +372 -0
  118. smallworld/state/cpus/powerpc.py +229 -0
  119. smallworld/state/cpus/riscv.py +357 -0
  120. smallworld/state/cpus/xtensa.py +80 -0
  121. smallworld/state/memory/__init__.py +7 -0
  122. smallworld/state/memory/code.py +70 -0
  123. smallworld/state/memory/elf/__init__.py +3 -0
  124. smallworld/state/memory/elf/elf.py +564 -0
  125. smallworld/state/memory/elf/rela/__init__.py +32 -0
  126. smallworld/state/memory/elf/rela/aarch64.py +27 -0
  127. smallworld/state/memory/elf/rela/amd64.py +32 -0
  128. smallworld/state/memory/elf/rela/arm.py +51 -0
  129. smallworld/state/memory/elf/rela/i386.py +32 -0
  130. smallworld/state/memory/elf/rela/mips.py +45 -0
  131. smallworld/state/memory/elf/rela/ppc.py +45 -0
  132. smallworld/state/memory/elf/rela/rela.py +63 -0
  133. smallworld/state/memory/elf/rela/riscv64.py +27 -0
  134. smallworld/state/memory/elf/rela/xtensa.py +15 -0
  135. smallworld/state/memory/elf/structs.py +55 -0
  136. smallworld/state/memory/heap.py +85 -0
  137. smallworld/state/memory/memory.py +181 -0
  138. smallworld/state/memory/stack/__init__.py +31 -0
  139. smallworld/state/memory/stack/aarch64.py +22 -0
  140. smallworld/state/memory/stack/amd64.py +42 -0
  141. smallworld/state/memory/stack/arm.py +66 -0
  142. smallworld/state/memory/stack/i386.py +22 -0
  143. smallworld/state/memory/stack/mips.py +34 -0
  144. smallworld/state/memory/stack/mips64.py +34 -0
  145. smallworld/state/memory/stack/ppc.py +34 -0
  146. smallworld/state/memory/stack/riscv.py +22 -0
  147. smallworld/state/memory/stack/stack.py +127 -0
  148. smallworld/state/memory/stack/xtensa.py +34 -0
  149. smallworld/state/models/__init__.py +6 -0
  150. smallworld/state/models/mmio.py +186 -0
  151. smallworld/state/models/model.py +163 -0
  152. smallworld/state/models/posix.py +455 -0
  153. smallworld/state/models/x86/__init__.py +2 -0
  154. smallworld/state/models/x86/microsoftcdecl.py +35 -0
  155. smallworld/state/models/x86/systemv.py +240 -0
  156. smallworld/state/state.py +962 -0
  157. smallworld/state/unstable/__init__.py +0 -0
  158. smallworld/state/unstable/elf.py +393 -0
  159. smallworld/state/x86_registers.py +30 -0
  160. smallworld/utils.py +935 -0
  161. smallworld_re-1.0.0.dist-info/LICENSE.txt +21 -0
  162. smallworld_re-1.0.0.dist-info/METADATA +189 -0
  163. smallworld_re-1.0.0.dist-info/RECORD +166 -0
  164. smallworld_re-1.0.0.dist-info/WHEEL +5 -0
  165. smallworld_re-1.0.0.dist-info/entry_points.txt +2 -0
  166. smallworld_re-1.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,252 @@
1
+ import typing
2
+
3
+ from .emulator import (
4
+ Emulator,
5
+ FunctionHookable,
6
+ InstructionHookable,
7
+ InterruptHookable,
8
+ MemoryReadHookable,
9
+ MemoryWriteHookable,
10
+ )
11
+
12
+
13
+ def range_intersect(r1, r2):
14
+ return range(max(r1.start, r2.start), min(r1.stop, r2.stop)) or None
15
+
16
+
17
+ def range_to_hex_str(r):
18
+ return f"[{r.start:x}..{r.stop:x}]"
19
+
20
+
21
+ class QInstructionHookable(InstructionHookable):
22
+ """Implementation of instruction hook data structure mgmt to be used by qemu-based emulators."""
23
+
24
+ def __init__(self: typing.Any) -> None:
25
+ super().__init__()
26
+ self.instruction_hooks: typing.Dict[int, typing.Callable[[Emulator], None]] = {}
27
+ self.all_instructions_hook: typing.Optional[
28
+ typing.Callable[[Emulator], None]
29
+ ] = None
30
+
31
+ def hook_instructions(self, function: typing.Callable[[Emulator], None]) -> None:
32
+ self.all_instructions_hook = function
33
+
34
+ def unhook_instructions(self):
35
+ self.all_instructions_hook = None
36
+
37
+ def hook_instruction(
38
+ self, address: int, function: typing.Callable[[Emulator], None]
39
+ ) -> None:
40
+ if address in self.instruction_hooks:
41
+ raise ValueError(
42
+ f"can't hook instruction at {address:x} since already hooked"
43
+ )
44
+ self.instruction_hooks[address] = function
45
+
46
+ def unhook_instruction(self, address: int) -> None:
47
+ if address not in self.instruction_hooks:
48
+ raise ValueError(
49
+ f"can't unhook instruction at {address:x} since its not already hooked"
50
+ )
51
+ self.instruction_hooks.pop(address, None)
52
+
53
+ def is_instruction_hooked(
54
+ self, address: int
55
+ ) -> typing.Optional[typing.Callable[[Emulator], None]]:
56
+ if address in self.instruction_hooks:
57
+ return self.instruction_hooks[address]
58
+ else:
59
+ return None
60
+
61
+
62
+ class QFunctionHookable(FunctionHookable):
63
+ """Implementation of function hook data structure mgmt to be used by qemu-based emulators."""
64
+
65
+ def __init__(self: typing.Any) -> None:
66
+ super().__init__()
67
+ self.function_hooks: typing.Dict[int, typing.Callable[[Emulator], None]] = {}
68
+
69
+ def hook_function(
70
+ self, address: int, function: typing.Callable[[Emulator], None]
71
+ ) -> None:
72
+ if address in self.function_hooks:
73
+ raise ValueError(f"can't hook function at {address:x} since already hooked")
74
+ self.function_hooks[address] = function
75
+
76
+ def unhook_function(self, address: int) -> None:
77
+ if address not in self.function_hooks:
78
+ raise ValueError(
79
+ f"can't unhook function at {address:x} since its not already hooked"
80
+ )
81
+ self.function_hooks.pop(address, None)
82
+
83
+ def is_function_hooked(
84
+ self, address: int
85
+ ) -> typing.Optional[typing.Callable[[Emulator], None]]:
86
+ if address in self.function_hooks:
87
+ return self.function_hooks[address]
88
+ else:
89
+ return None
90
+
91
+
92
+ class QMemoryReadHookable(MemoryReadHookable):
93
+ """Implementation of memory read hook data structure mgmt to be used by qemu-based emulators."""
94
+
95
+ def __init__(self: typing.Any) -> None:
96
+ super().__init__()
97
+ self.memory_read_hooks: typing.Dict[
98
+ range, typing.Callable[[Emulator, int, int, bytes], typing.Optional[bytes]]
99
+ ] = {}
100
+ self.all_reads_hook: typing.Optional[
101
+ typing.Callable[[Emulator, int, int, bytes], typing.Optional[bytes]]
102
+ ] = None
103
+
104
+ def hook_memory_reads(
105
+ self,
106
+ function: typing.Callable[[Emulator, int, int, bytes], typing.Optional[bytes]],
107
+ ) -> None:
108
+ self.all_reads_hook = function
109
+
110
+ def unhook_memory_reads(self):
111
+ self.all_reads_hook = None
112
+
113
+ def hook_memory_read(
114
+ self,
115
+ start: int,
116
+ end: int,
117
+ function: typing.Callable[[Emulator, int, int, bytes], typing.Optional[bytes]],
118
+ ) -> None:
119
+ new_range = range(start, end)
120
+ for r in self.memory_read_hooks:
121
+ if range_intersect(r, new_range):
122
+ raise ValueError(
123
+ f"can't hook memory read range {range_to_hex_str(new_range)} since that overlaps already hooked range {range_to_hex_str(r)}"
124
+ )
125
+ self.memory_read_hooks[new_range] = function
126
+
127
+ def unhook_memory_read(self, start: int, end: int) -> None:
128
+ unh_r = range(start, end)
129
+ for r in self.memory_read_hooks:
130
+ if unh_r == r:
131
+ self.memory_read_hooks.pop(r, None)
132
+ return
133
+ raise ValueError(
134
+ f"can't unhook memory read range {range_to_hex_str(unh_r)} since its not already hooked"
135
+ )
136
+
137
+ # def unhook_memory_read(address: int) -> None:
138
+ # if address not in self.memory_read_hooks:
139
+ # raise ValueError(
140
+ # f"can't unhook memory read range {range_to_hex_str(address)} since its not already hooked"
141
+ # )
142
+ # self.memory_read_hooks.pop(address, None)
143
+
144
+ def is_memory_read_hooked(
145
+ self, address: int
146
+ ) -> typing.Optional[
147
+ typing.Callable[[Emulator, int, int, bytes], typing.Optional[bytes]]
148
+ ]:
149
+ for rng in self.memory_read_hooks:
150
+ if address in rng:
151
+ return self.memory_read_hooks[rng]
152
+ return None
153
+
154
+
155
+ class QMemoryWriteHookable(MemoryWriteHookable):
156
+ """Implementation of memory write hook data structure mgmt to be used by qemu-based emulators."""
157
+
158
+ def __init__(self: typing.Any) -> None:
159
+ super().__init__()
160
+ self.memory_write_hooks: typing.Dict[
161
+ range, typing.Callable[[Emulator, int, int, bytes], None]
162
+ ] = {}
163
+ self.all_writes_hook: typing.Optional[
164
+ typing.Callable[[Emulator, int, int, bytes], None]
165
+ ] = None
166
+
167
+ def hook_memory_writes(
168
+ self, function: typing.Callable[[Emulator, int, int, bytes], None]
169
+ ) -> None:
170
+ self.all_writes_hook = function
171
+
172
+ def unhook_memory_writes(self):
173
+ self.all_writes_hook = None
174
+
175
+ def hook_memory_write(
176
+ self,
177
+ start: int,
178
+ end: int,
179
+ function: typing.Callable[[Emulator, int, int, bytes], None],
180
+ ) -> None:
181
+ new_range = range(start, end)
182
+ for r in self.memory_write_hooks:
183
+ if range_intersect(r, new_range):
184
+ raise ValueError(
185
+ f"can't hook memory write range {range_to_hex_str(new_range)} since that overlaps already hooked range {range_to_hex_str(r)}"
186
+ )
187
+ self.memory_write_hooks[new_range] = function
188
+
189
+ def unhook_memory_write(self, start: int, end: int) -> None:
190
+ unh_r = range(start, end)
191
+ for r in self.memory_write_hooks:
192
+ if unh_r == r:
193
+ self.memory_write_hooks.pop(r, None)
194
+ return
195
+ raise ValueError(
196
+ f"can't unhook memory write range {range_to_hex_str(unh_r)} since its not already hooked"
197
+ )
198
+
199
+ # def unhook_memory_write(self, address: int) -> None:
200
+ # if address not in self.memory_write_hooks:
201
+ # raise ValueError(
202
+ # f"can't unhook memory write range {range_to_hex_str(address)} since its not already hooked"
203
+ # )
204
+ # self.memory_write_hooks.pop(address, None)
205
+ def is_memory_write_hooked(
206
+ self, address: int
207
+ ) -> typing.Optional[typing.Callable[[Emulator, int, int, bytes], None]]:
208
+ for rng in self.memory_write_hooks:
209
+ if address in rng:
210
+ return self.memory_write_hooks[rng]
211
+ return None
212
+
213
+
214
+ class QInterruptHookable(InterruptHookable):
215
+ """Implementation of interrupt hook data structure mgmt to be used by qemu-based emulators."""
216
+
217
+ def __init__(self: typing.Any) -> None:
218
+ super().__init__()
219
+ self.all_interrupts_hook: typing.Optional[
220
+ typing.Callable[[Emulator, int], None]
221
+ ] = None
222
+ self.interrupt_hooks: typing.Dict[int, typing.Callable[[Emulator], None]] = {}
223
+
224
+ def hook_interrupts(self, function: typing.Callable[[Emulator, int], None]) -> None:
225
+ self.all_interrupts_hook = function
226
+
227
+ def unhook_interrupts(self):
228
+ self.all_interrupts_hook = None
229
+
230
+ def hook_interrupt(
231
+ self, intno: int, function: typing.Callable[[Emulator], None]
232
+ ) -> None:
233
+ if intno in self.interrupt_hooks:
234
+ raise ValueError(
235
+ f"can't hook interrupt number {intno} since its already hooked"
236
+ )
237
+ self.interrupt_hooks[intno] = function
238
+
239
+ def unhook_interrupt(self, intno: int) -> None:
240
+ if intno not in self.interrupt_hooks:
241
+ raise ValueError(
242
+ f"asked to unhook interrupt {intno} which was not previously hooked"
243
+ )
244
+ self.interrupt_hooks.pop(intno, None)
245
+
246
+ def is_interrupt_hooked(
247
+ self, intno: int
248
+ ) -> typing.Optional[typing.Callable[[Emulator], None]]:
249
+ if intno in self.interrupt_hooks:
250
+ return self.interrupt_hooks[intno]
251
+ else:
252
+ return None
@@ -0,0 +1,5 @@
1
+ from .panda import PandaEmulator
2
+
3
+ __all__ = [
4
+ "PandaEmulator",
5
+ ]
@@ -0,0 +1,28 @@
1
+ from .aarch64 import AArch64MachineDef
2
+ from .amd64 import AMD64MachineDef
3
+ from .arm import ( # ARMv6MMachineDef,; ARMv6MThumbMachineDef,
4
+ ARMv5TMachineDef,
5
+ ARMv7MMachineDef,
6
+ )
7
+ from .i386 import i386MachineDef
8
+ from .machdef import PandaMachineDef
9
+ from .mips import MIPSBEMachineDef, MIPSELMachineDef
10
+ from .mips64 import MIPS64BEMachineDef # , MIPS64ELMachineDef
11
+ from .ppc import PowerPC32MachineDef # , PowerPC64MachineDef
12
+
13
+ __all__ = [
14
+ "AArch64MachineDef",
15
+ "AMD64MachineDef",
16
+ "PandaMachineDef",
17
+ "ARMv5TMachineDef",
18
+ # "ARMv6MMachineDef",
19
+ # "ARMv6MThumbMachineDef",
20
+ "ARMv7MMachineDef",
21
+ "i386MachineDef",
22
+ "MIPSBEMachineDef",
23
+ "MIPSELMachineDef",
24
+ "MIPS64BEMachineDef",
25
+ # "MIPS64ELMachineDef",
26
+ "PowerPC32MachineDef",
27
+ # "PowerPC64MachineDef",
28
+ ]
@@ -0,0 +1,93 @@
1
+ import capstone
2
+
3
+ from ....platforms import Architecture, Byteorder
4
+ from .machdef import PandaMachineDef
5
+
6
+
7
+ class AArch64MachineDef(PandaMachineDef):
8
+ arch = Architecture.AARCH64
9
+ byteorder = Byteorder.LITTLE
10
+
11
+ cs_arch = capstone.CS_ARCH_ARM64
12
+ cs_mode = capstone.CS_MODE_ARM | capstone.CS_MODE_LITTLE_ENDIAN
13
+
14
+ panda_arch = "aarch64"
15
+
16
+ # I'm going to define all the ones we are making possible as of now
17
+ # I need to submit a PR to change to X86 32 bit and to includ eflags
18
+ def __init__(self):
19
+ self._registers = {
20
+ "x0": "x0",
21
+ "w0": "x0",
22
+ "x1": "x1",
23
+ "w1": "x1",
24
+ "x2": "x2",
25
+ "w2": "x2",
26
+ "x3": "x3",
27
+ "w3": "x3",
28
+ "x4": "x4",
29
+ "w4": "x4",
30
+ "x5": "x5",
31
+ "w5": "x5",
32
+ "x6": "x6",
33
+ "w6": "x6",
34
+ "x7": "x7",
35
+ "w7": "x7",
36
+ "x8": "xr",
37
+ "w8": "xr",
38
+ "xr": "xr",
39
+ "x9": "x9",
40
+ "w9": "x9",
41
+ "x10": "x10",
42
+ "w10": "x10",
43
+ "x11": "x11",
44
+ "w11": "x11",
45
+ "x12": "x12",
46
+ "w12": "x12",
47
+ "x13": "x13",
48
+ "w13": "x13",
49
+ "x14": "x14",
50
+ "w14": "x14",
51
+ "x15": "x15",
52
+ "w15": "x15",
53
+ "x16": "ip0",
54
+ "w16": "ip0",
55
+ "ip0": "ip0",
56
+ "x17": "ip1",
57
+ "w17": "ip1",
58
+ "ip1": "ip1",
59
+ "x18": "pr",
60
+ "w18": "pr",
61
+ "pr": "pr",
62
+ "x19": "x19",
63
+ "w19": "x19",
64
+ "x20": "x20",
65
+ "w20": "x20",
66
+ "x21": "x21",
67
+ "w21": "x21",
68
+ "x22": "x22",
69
+ "w22": "x22",
70
+ "x23": "x23",
71
+ "w23": "x23",
72
+ "x24": "x24",
73
+ "w24": "x24",
74
+ "x25": "x25",
75
+ "w25": "x25",
76
+ "x26": "x26",
77
+ "w26": "x26",
78
+ "x27": "x27",
79
+ "w27": "x27",
80
+ "x28": "x28",
81
+ "w28": "x28",
82
+ "x29": "fp",
83
+ "w29": "fp",
84
+ "fp": "fp",
85
+ "x30": "lr",
86
+ "w30": "lr",
87
+ "lr": "lr",
88
+ "pc": "pc",
89
+ "sp": "sp",
90
+ "wsp": "sp",
91
+ }
92
+
93
+ self._registers = {i: j for i, j in self._registers.items()}
@@ -0,0 +1,71 @@
1
+ import capstone
2
+
3
+ from ....platforms import Architecture, Byteorder
4
+ from .machdef import PandaMachineDef
5
+
6
+
7
+ class AMD64MachineDef(PandaMachineDef):
8
+ arch = Architecture.X86_64
9
+ byteorder = Byteorder.LITTLE
10
+
11
+ panda_arch = "x86_64"
12
+
13
+ cs_arch = capstone.CS_ARCH_X86
14
+ cs_mode = capstone.CS_MODE_64
15
+
16
+ # I'm going to define all the ones we are making possible as of now
17
+ # I need to submit a PR to change to X86 32 bit and to includ eflags
18
+ _registers_64 = {
19
+ "rax",
20
+ "rbx",
21
+ "rcx",
22
+ "rdx",
23
+ "rsi",
24
+ "rdi",
25
+ "rsp",
26
+ "rbp",
27
+ "rip",
28
+ "r8",
29
+ "r9",
30
+ "r10",
31
+ "r11",
32
+ "r12",
33
+ "r13",
34
+ "r14",
35
+ "r15",
36
+ }
37
+ _registers_general = {"eax", "ebx", "ecx", "edx", "esi", "edi", "esp", "ebp", "eip"}
38
+ _registers_short = {"ax", "bx", "cx", "dx", "si", "di", "sp", "bp"}
39
+ _registers_byte = {"al", "bl", "cl", "dl", "ah", "bh", "ch", "dh"}
40
+ _registers_seg = {"es", "cs", "ss", "ds", "fs", "gs"}
41
+ _registers_control = {"cr0", "cr1", "cr2", "cr3", "cr4"}
42
+ _registers_mmr = {"gdtr": "gdt", "idtr": "idt", "tr": "tr", "ldtr": "ldt"}
43
+ _registers_xmm = {
44
+ "xmm0",
45
+ "xmm1",
46
+ "xmm2",
47
+ "xmm3",
48
+ "xmm4",
49
+ "xmm5",
50
+ "xmm6",
51
+ "xmm7",
52
+ "xmm8",
53
+ "xmm9",
54
+ "xmm10",
55
+ "xmm11",
56
+ "xmm12",
57
+ "xmm13",
58
+ "xmm14",
59
+ "xmm15",
60
+ }
61
+ _register_pc = {"pc": "rip"}
62
+
63
+ _registers = {}
64
+ _registers = _registers | {i: i for i in _registers_64}
65
+ _registers = _registers | {i: i for i in _registers_general}
66
+ _registers = _registers | {i: i for i in _registers_byte}
67
+ _registers = _registers | {i: i for i in _registers_seg}
68
+ _registers = _registers | {i: i for i in _registers_control}
69
+ _registers = _registers | {i: j for i, j in _registers_mmr.items()}
70
+ _registers = _registers | {i: i for i in _registers_xmm}
71
+ _registers = _registers | {i: j for i, j in _register_pc.items()}
@@ -0,0 +1,89 @@
1
+ import capstone
2
+
3
+ from ....platforms import Architecture, Byteorder
4
+ from .machdef import PandaMachineDef
5
+
6
+
7
+ class ARMMachineDef(PandaMachineDef):
8
+ cs_arch = capstone.CS_ARCH_ARM
9
+ cs_mode = capstone.CS_MODE_ARM | capstone.CS_MODE_LITTLE_ENDIAN
10
+
11
+ panda_arch = "arm"
12
+
13
+ # I'm going to define all the ones we are making possible as of now
14
+ # I need to submit a PR to change to X86 32 bit and to includ eflags
15
+ def __init__(self):
16
+ self._registers = {
17
+ "r0",
18
+ "r1",
19
+ "r2",
20
+ "r3",
21
+ "r4",
22
+ "r5",
23
+ "r6",
24
+ "r7",
25
+ "r8",
26
+ "r9",
27
+ "r10",
28
+ "r11",
29
+ "r12",
30
+ "sp",
31
+ "lr",
32
+ "ip",
33
+ }
34
+
35
+ self._registers = {i: i for i in self._registers}
36
+ self._registers = self._registers | {"pc": "ip"}
37
+
38
+
39
+ class ARMMachineMixinM:
40
+ """Mixin for ARM M-series machine models"""
41
+
42
+ def __init__(self):
43
+ super().__init__()
44
+ self._registers_m = {
45
+ # NOTE: None of the expected privileged registers exist
46
+ # "psr",
47
+ # "primask",
48
+ # "basepri",
49
+ # "faultmask",
50
+ # "control",
51
+ # "msp",
52
+ # "psp",
53
+ }
54
+ self._registers = self._registers | {i: i for i in self._registers_m}
55
+
56
+
57
+ class ARMMachineMixinA:
58
+ """Mixin for ARM A-series machine models"""
59
+
60
+ def __init__(self):
61
+ super().__init__()
62
+ # TODO: QEMU doesn't quite support what I expect.
63
+ # I expected to see cpsr and spsr.
64
+ # I either got the CPU model wrong, or something else is weird.
65
+ self._registers_a = {
66
+ "psr",
67
+ }
68
+ self._registers = self._registers | {i: i for i in self._registers_a}
69
+
70
+
71
+ class ARMv5TMachineDef(ARMMachineDef):
72
+ arch = Architecture.ARM_V5T
73
+ byteorder = Byteorder.LITTLE
74
+ cpu = "pxa255"
75
+
76
+
77
+ # TODO: Something's very weird with Panda's Arm 7 models.
78
+ # cortex-a9 should be an A-series, but it looks more like an M-series.
79
+ # cortex-m4 looks like an M-series, but aborts; I suspect we're missing configuration.
80
+ class ARMv7AMachineDef(ARMMachineMixinA, ARMMachineDef):
81
+ arch = Architecture.ARM_V7A
82
+ byteorder = Byteorder.LITTLE
83
+ cpu = "cortex-a9"
84
+
85
+
86
+ class ARMv7MMachineDef(ARMMachineMixinM, ARMMachineDef):
87
+ arch = Architecture.ARM_V7M
88
+ byteorder = Byteorder.LITTLE
89
+ cpu = "cortex-m4"
@@ -0,0 +1,36 @@
1
+ import capstone
2
+
3
+ from ....platforms import Architecture, Byteorder
4
+ from .machdef import PandaMachineDef
5
+
6
+
7
+ class i386MachineDef(PandaMachineDef):
8
+ arch = Architecture.X86_32
9
+ byteorder = Byteorder.LITTLE
10
+
11
+ panda_arch = "i386"
12
+
13
+ cs_arch = capstone.CS_ARCH_X86
14
+ cs_mode = capstone.CS_MODE_32
15
+
16
+ # I'm going to define all the ones we are making possible as of now
17
+ # I need to submit a PR to change to X86 32 bit and to includ eflags
18
+ _registers_general = {"eax", "ebx", "ecx", "edx", "esi", "edi", "esp", "ebp", "eip"}
19
+ _registers_short = {"ax", "bx", "cx", "dx", "si", "di", "sp", "bp"}
20
+ _registers_byte = {"al", "bl", "cl", "dl", "ah", "bh", "ch", "dh"}
21
+ _registers_seg = {"es", "cs", "ss", "ds", "fs", "gs"}
22
+ _registers_control = {"cr0", "cr1", "cr2", "cr3", "cr4"}
23
+ _registers_mmr = {"gdtr": "gdt", "idtr": "idt", "tr": "tr", "ldtr": "ldt"}
24
+ _register_pc = {"pc": "eip"}
25
+
26
+ _registers = {}
27
+ _registers = _registers | {i: i for i in _registers_general}
28
+ _registers = _registers | {i: i for i in _registers_byte}
29
+ _registers = _registers | {i: i for i in _registers_seg}
30
+ _registers = _registers | {i: i for i in _registers_control}
31
+ _registers = _registers | {i: j for i, j in _registers_mmr.items()}
32
+ _registers = _registers | {i: j for i, j in _register_pc.items()}
33
+ # _registers = (
34
+ # _registers_general | _registers_byte | _registers_seg | _registers_control
35
+ # )
36
+ # _registers = {**_registers_general, **_register_short, **_registers_seg, **_registers_control}
@@ -0,0 +1,86 @@
1
+ import abc
2
+ import typing
3
+
4
+ from .... import platforms, utils
5
+
6
+
7
+ class PandaMachineDef(metaclass=abc.ABCMeta):
8
+ """Container class for Unicorn architecture-specific definitions"""
9
+
10
+ @property
11
+ @abc.abstractmethod
12
+ def arch(self) -> platforms.Architecture:
13
+ """The architecture ID"""
14
+ raise NotImplementedError("This is an abstract method.")
15
+
16
+ @property
17
+ @abc.abstractmethod
18
+ def byteorder(self) -> platforms.Byteorder:
19
+ """The byte order"""
20
+ raise NotImplementedError("This is an abstract method.")
21
+
22
+ @property
23
+ @abc.abstractmethod
24
+ def panda_arch(self) -> str:
25
+ """The panda architecture to use"""
26
+ raise NotImplementedError("This is an abstract method.")
27
+
28
+ @property
29
+ @abc.abstractmethod
30
+ def cs_arch(self) -> int:
31
+ """The capstone architecture to use"""
32
+ raise NotImplementedError("This is an abstract method.")
33
+
34
+ @property
35
+ @abc.abstractmethod
36
+ def cs_mode(self) -> int:
37
+ """The capstone mode to use"""
38
+ raise NotImplementedError("This is an abstract method.")
39
+
40
+ _registers: typing.Dict[str, str] = {}
41
+
42
+ def panda_reg(self, name: str) -> str:
43
+ if name in self._registers:
44
+ return self._registers[name]
45
+ else:
46
+ raise ValueError(
47
+ f"Unknown register for {self.arch}:{self.byteorder}: {name}"
48
+ )
49
+
50
+ def check_panda_reg(self, name: str) -> bool:
51
+ """Convert a register name to panda cpu field, index, mask
52
+
53
+ This must cover all names defined in the CPU state model
54
+ for this arch/mode/byteorder, or return 0,
55
+ which always indicates an invalid register
56
+ """
57
+ if name in self._registers:
58
+ return True
59
+ else:
60
+ return False
61
+
62
+ @classmethod
63
+ def for_platform(cls, platform: platforms.Platform):
64
+ """Find the appropriate MachineDef for your architecture
65
+
66
+ Arguments:
67
+ arch: The architecture ID you want
68
+ mode: The mode ID you want
69
+ byteorder: The byteorderness you want
70
+
71
+ Returns:
72
+ An instance of the appropriate MachineDef
73
+
74
+ Raises:
75
+ ValueError: If no MachineDef subclass matches your request
76
+ """
77
+ try:
78
+ return utils.find_subclass(
79
+ cls,
80
+ lambda x: x.arch == platform.architecture
81
+ and x.byteorder == platform.byteorder,
82
+ )
83
+ except:
84
+ raise ValueError(
85
+ f"No machine model for {platform.architecture}:{platform.byteorder}"
86
+ )