smallworld-re 1.0.2__py3-none-any.whl → 2.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 (306) hide show
  1. smallworld/analyses/__init__.py +8 -0
  2. smallworld/analyses/analysis.py +8 -67
  3. smallworld/analyses/code_coverage.py +1 -2
  4. smallworld/analyses/colorizer.py +301 -534
  5. smallworld/analyses/colorizer_def_use.py +217 -0
  6. smallworld/analyses/colorizer_summary.py +173 -83
  7. smallworld/analyses/field_detection/field_analysis.py +7 -8
  8. smallworld/analyses/field_detection/hints.py +1 -1
  9. smallworld/analyses/field_detection/malloc.py +2 -2
  10. smallworld/analyses/trace_execution.py +160 -0
  11. smallworld/analyses/trace_execution_types.py +42 -0
  12. smallworld/analyses/unstable/angr/divergence.py +1 -2
  13. smallworld/analyses/unstable/angr/model.py +5 -6
  14. smallworld/analyses/unstable/angr_nwbt.py +3 -4
  15. smallworld/analyses/unstable/code_coverage.py +2 -3
  16. smallworld/analyses/unstable/code_reachable.py +2 -3
  17. smallworld/analyses/unstable/control_flow_tracer.py +2 -3
  18. smallworld/analyses/unstable/pointer_finder.py +2 -3
  19. smallworld/analyses/unstable/utils/tui.py +71 -0
  20. smallworld/emulators/__init__.py +3 -1
  21. smallworld/emulators/angr/angr.py +30 -9
  22. smallworld/emulators/angr/machdefs/__init__.py +2 -0
  23. smallworld/emulators/angr/machdefs/aarch64.py +1 -1
  24. smallworld/emulators/angr/machdefs/amd64.py +0 -4
  25. smallworld/emulators/angr/machdefs/arm.py +0 -2
  26. smallworld/emulators/angr/machdefs/i386.py +0 -2
  27. smallworld/emulators/angr/machdefs/loongarch.py +340 -0
  28. smallworld/emulators/angr/machdefs/machdef.py +1 -8
  29. smallworld/emulators/angr/machdefs/mips.py +0 -2
  30. smallworld/emulators/angr/machdefs/mips64.py +0 -2
  31. smallworld/emulators/angr/machdefs/ppc.py +1 -2
  32. smallworld/emulators/angr/machdefs/riscv.py +8 -10
  33. smallworld/emulators/angr/machdefs/xtensa.py +7 -4
  34. smallworld/emulators/emulator.py +22 -0
  35. smallworld/emulators/ghidra/__init__.py +37 -0
  36. smallworld/emulators/ghidra/ghidra.py +513 -0
  37. smallworld/emulators/ghidra/machdefs/__init__.py +31 -0
  38. smallworld/emulators/ghidra/machdefs/aarch64.py +289 -0
  39. smallworld/emulators/ghidra/machdefs/amd64.py +185 -0
  40. smallworld/emulators/ghidra/machdefs/arm.py +370 -0
  41. smallworld/emulators/ghidra/machdefs/i386.py +109 -0
  42. smallworld/emulators/ghidra/machdefs/loongarch.py +162 -0
  43. smallworld/emulators/ghidra/machdefs/machdef.py +81 -0
  44. smallworld/emulators/ghidra/machdefs/mips.py +163 -0
  45. smallworld/emulators/ghidra/machdefs/mips64.py +186 -0
  46. smallworld/emulators/ghidra/machdefs/ppc.py +98 -0
  47. smallworld/emulators/ghidra/machdefs/riscv.py +208 -0
  48. smallworld/emulators/ghidra/machdefs/xtensa.py +21 -0
  49. smallworld/emulators/ghidra/typing.py +28 -0
  50. smallworld/emulators/hookable.py +18 -4
  51. smallworld/emulators/panda/machdefs/__init__.py +2 -2
  52. smallworld/emulators/panda/machdefs/aarch64.py +186 -11
  53. smallworld/emulators/panda/machdefs/amd64.py +103 -11
  54. smallworld/emulators/panda/machdefs/arm.py +216 -20
  55. smallworld/emulators/panda/machdefs/i386.py +30 -7
  56. smallworld/emulators/panda/machdefs/machdef.py +9 -16
  57. smallworld/emulators/panda/machdefs/mips.py +49 -5
  58. smallworld/emulators/panda/machdefs/mips64.py +57 -5
  59. smallworld/emulators/panda/machdefs/ppc.py +38 -13
  60. smallworld/emulators/panda/panda.py +146 -44
  61. smallworld/emulators/unicorn/__init__.py +2 -0
  62. smallworld/emulators/unicorn/machdefs/aarch64.py +253 -264
  63. smallworld/emulators/unicorn/machdefs/amd64.py +254 -259
  64. smallworld/emulators/unicorn/machdefs/arm.py +200 -212
  65. smallworld/emulators/unicorn/machdefs/i386.py +84 -90
  66. smallworld/emulators/unicorn/machdefs/machdef.py +2 -23
  67. smallworld/emulators/unicorn/machdefs/mips.py +127 -135
  68. smallworld/emulators/unicorn/unicorn.py +52 -13
  69. smallworld/helpers.py +4 -19
  70. smallworld/hinting/hinting.py +22 -192
  71. smallworld/hinting/hints.py +50 -18
  72. smallworld/instructions/bsid.py +8 -8
  73. smallworld/logging.py +4 -2
  74. smallworld/platforms/__init__.py +12 -0
  75. smallworld/platforms/defs/__init__.py +36 -0
  76. smallworld/platforms/defs/aarch64.py +450 -0
  77. smallworld/platforms/defs/amd64.py +463 -0
  78. smallworld/platforms/defs/arm.py +519 -0
  79. smallworld/platforms/defs/i386.py +258 -0
  80. smallworld/platforms/defs/loongarch.py +270 -0
  81. smallworld/platforms/defs/mips.py +321 -0
  82. smallworld/platforms/defs/mips64.py +313 -0
  83. smallworld/platforms/defs/platformdef.py +97 -0
  84. smallworld/platforms/defs/powerpc.py +259 -0
  85. smallworld/platforms/defs/riscv.py +257 -0
  86. smallworld/platforms/defs/xtensa.py +96 -0
  87. smallworld/{platforms.py → platforms/platforms.py} +3 -0
  88. smallworld/state/cpus/__init__.py +2 -0
  89. smallworld/state/cpus/aarch64.py +0 -9
  90. smallworld/state/cpus/amd64.py +6 -28
  91. smallworld/state/cpus/arm.py +0 -11
  92. smallworld/state/cpus/cpu.py +0 -11
  93. smallworld/state/cpus/i386.py +0 -7
  94. smallworld/state/cpus/loongarch.py +299 -0
  95. smallworld/state/cpus/mips.py +4 -47
  96. smallworld/state/cpus/mips64.py +18 -58
  97. smallworld/state/cpus/powerpc.py +2 -9
  98. smallworld/state/cpus/riscv.py +1 -11
  99. smallworld/state/cpus/xtensa.py +0 -5
  100. smallworld/state/memory/code.py +44 -2
  101. smallworld/state/memory/elf/__init__.py +5 -1
  102. smallworld/state/memory/elf/coredump/__init__.py +3 -0
  103. smallworld/state/memory/elf/coredump/coredump.py +46 -0
  104. smallworld/state/memory/elf/coredump/prstatus/__init__.py +27 -0
  105. smallworld/state/memory/elf/coredump/prstatus/aarch64.py +46 -0
  106. smallworld/state/memory/elf/coredump/prstatus/amd64.py +40 -0
  107. smallworld/state/memory/elf/coredump/prstatus/arm.py +53 -0
  108. smallworld/state/memory/elf/coredump/prstatus/i386.py +30 -0
  109. smallworld/state/memory/elf/coredump/prstatus/mips.py +55 -0
  110. smallworld/state/memory/elf/coredump/prstatus/mips64.py +57 -0
  111. smallworld/state/memory/elf/coredump/prstatus/ppc.py +82 -0
  112. smallworld/state/memory/elf/coredump/prstatus/prstatus.py +129 -0
  113. smallworld/state/memory/elf/elf.py +225 -61
  114. smallworld/state/memory/elf/register_state.py +36 -0
  115. smallworld/state/memory/elf/rela/__init__.py +2 -0
  116. smallworld/state/memory/elf/rela/aarch64.py +3 -1
  117. smallworld/state/memory/elf/rela/amd64.py +4 -2
  118. smallworld/state/memory/elf/rela/arm.py +4 -2
  119. smallworld/state/memory/elf/rela/i386.py +4 -2
  120. smallworld/state/memory/elf/rela/loongarch.py +32 -0
  121. smallworld/state/memory/elf/rela/mips.py +39 -18
  122. smallworld/state/memory/elf/rela/ppc.py +31 -14
  123. smallworld/state/memory/elf/structs.py +3 -0
  124. smallworld/state/memory/heap.py +2 -2
  125. smallworld/state/memory/memory.py +18 -0
  126. smallworld/state/memory/pe/__init__.py +3 -0
  127. smallworld/state/memory/pe/pe.py +361 -0
  128. smallworld/state/memory/pe/structs.py +60 -0
  129. smallworld/state/memory/stack/__init__.py +2 -0
  130. smallworld/state/memory/stack/loongarch.py +26 -0
  131. smallworld/state/models/__init__.py +29 -2
  132. smallworld/state/models/aarch64/__init__.py +1 -0
  133. smallworld/state/models/aarch64/systemv/__init__.py +6 -0
  134. smallworld/state/models/aarch64/systemv/c99/__init__.py +12 -0
  135. smallworld/state/models/aarch64/systemv/c99/signal.py +16 -0
  136. smallworld/state/models/aarch64/systemv/c99/stdio.py +265 -0
  137. smallworld/state/models/aarch64/systemv/c99/stdlib.py +169 -0
  138. smallworld/state/models/aarch64/systemv/c99/string.py +139 -0
  139. smallworld/state/models/aarch64/systemv/c99/time.py +61 -0
  140. smallworld/state/models/aarch64/systemv/posix/__init__.py +6 -0
  141. smallworld/state/models/aarch64/systemv/posix/libgen.py +16 -0
  142. smallworld/state/models/aarch64/systemv/posix/signal.py +157 -0
  143. smallworld/state/models/aarch64/systemv/systemv.py +80 -0
  144. smallworld/state/models/amd64/__init__.py +1 -0
  145. smallworld/state/models/amd64/systemv/__init__.py +6 -0
  146. smallworld/state/models/amd64/systemv/c99/__init__.py +12 -0
  147. smallworld/state/models/amd64/systemv/c99/signal.py +16 -0
  148. smallworld/state/models/amd64/systemv/c99/stdio.py +265 -0
  149. smallworld/state/models/amd64/systemv/c99/stdlib.py +169 -0
  150. smallworld/state/models/amd64/systemv/c99/string.py +139 -0
  151. smallworld/state/models/amd64/systemv/c99/time.py +61 -0
  152. smallworld/state/models/amd64/systemv/posix/__init__.py +6 -0
  153. smallworld/state/models/amd64/systemv/posix/libgen.py +16 -0
  154. smallworld/state/models/amd64/systemv/posix/signal.py +157 -0
  155. smallworld/state/models/amd64/systemv/systemv.py +78 -0
  156. smallworld/state/models/armel/__init__.py +1 -0
  157. smallworld/state/models/armel/systemv/__init__.py +6 -0
  158. smallworld/state/models/armel/systemv/c99/__init__.py +12 -0
  159. smallworld/state/models/armel/systemv/c99/signal.py +16 -0
  160. smallworld/state/models/armel/systemv/c99/stdio.py +265 -0
  161. smallworld/state/models/armel/systemv/c99/stdlib.py +169 -0
  162. smallworld/state/models/armel/systemv/c99/string.py +139 -0
  163. smallworld/state/models/armel/systemv/c99/time.py +61 -0
  164. smallworld/state/models/armel/systemv/posix/__init__.py +6 -0
  165. smallworld/state/models/armel/systemv/posix/libgen.py +16 -0
  166. smallworld/state/models/armel/systemv/posix/signal.py +157 -0
  167. smallworld/state/models/armel/systemv/systemv.py +82 -0
  168. smallworld/state/models/armhf/__init__.py +1 -0
  169. smallworld/state/models/armhf/systemv/__init__.py +6 -0
  170. smallworld/state/models/armhf/systemv/c99/__init__.py +12 -0
  171. smallworld/state/models/armhf/systemv/c99/signal.py +16 -0
  172. smallworld/state/models/armhf/systemv/c99/stdio.py +265 -0
  173. smallworld/state/models/armhf/systemv/c99/stdlib.py +169 -0
  174. smallworld/state/models/armhf/systemv/c99/string.py +139 -0
  175. smallworld/state/models/armhf/systemv/c99/time.py +61 -0
  176. smallworld/state/models/armhf/systemv/posix/__init__.py +6 -0
  177. smallworld/state/models/armhf/systemv/posix/libgen.py +16 -0
  178. smallworld/state/models/armhf/systemv/posix/signal.py +157 -0
  179. smallworld/state/models/armhf/systemv/systemv.py +77 -0
  180. smallworld/state/models/c99/__init__.py +12 -0
  181. smallworld/state/models/c99/fmt_print.py +915 -0
  182. smallworld/state/models/c99/fmt_scan.py +864 -0
  183. smallworld/state/models/c99/math.py +362 -0
  184. smallworld/state/models/c99/signal.py +71 -0
  185. smallworld/state/models/c99/stdio.py +1305 -0
  186. smallworld/state/models/c99/stdlib.py +595 -0
  187. smallworld/state/models/c99/string.py +674 -0
  188. smallworld/state/models/c99/time.py +340 -0
  189. smallworld/state/models/c99/utils.py +89 -0
  190. smallworld/state/models/cstd.py +759 -0
  191. smallworld/state/models/errno.py +581 -0
  192. smallworld/state/models/filedesc.py +515 -0
  193. smallworld/state/models/i386/__init__.py +1 -0
  194. smallworld/state/models/i386/systemv/__init__.py +6 -0
  195. smallworld/state/models/i386/systemv/c99/__init__.py +12 -0
  196. smallworld/state/models/i386/systemv/c99/signal.py +16 -0
  197. smallworld/state/models/i386/systemv/c99/stdio.py +265 -0
  198. smallworld/state/models/i386/systemv/c99/stdlib.py +169 -0
  199. smallworld/state/models/i386/systemv/c99/string.py +139 -0
  200. smallworld/state/models/i386/systemv/c99/time.py +61 -0
  201. smallworld/state/models/i386/systemv/posix/__init__.py +6 -0
  202. smallworld/state/models/i386/systemv/posix/libgen.py +16 -0
  203. smallworld/state/models/i386/systemv/posix/signal.py +157 -0
  204. smallworld/state/models/i386/systemv/systemv.py +71 -0
  205. smallworld/state/models/loongarch64/__init__.py +1 -0
  206. smallworld/state/models/loongarch64/systemv/__init__.py +6 -0
  207. smallworld/state/models/loongarch64/systemv/c99/__init__.py +12 -0
  208. smallworld/state/models/loongarch64/systemv/c99/signal.py +16 -0
  209. smallworld/state/models/loongarch64/systemv/c99/stdio.py +265 -0
  210. smallworld/state/models/loongarch64/systemv/c99/stdlib.py +169 -0
  211. smallworld/state/models/loongarch64/systemv/c99/string.py +139 -0
  212. smallworld/state/models/loongarch64/systemv/c99/time.py +61 -0
  213. smallworld/state/models/loongarch64/systemv/posix/__init__.py +6 -0
  214. smallworld/state/models/loongarch64/systemv/posix/libgen.py +16 -0
  215. smallworld/state/models/loongarch64/systemv/posix/signal.py +157 -0
  216. smallworld/state/models/loongarch64/systemv/systemv.py +83 -0
  217. smallworld/state/models/mips/__init__.py +1 -0
  218. smallworld/state/models/mips/systemv/__init__.py +6 -0
  219. smallworld/state/models/mips/systemv/c99/__init__.py +12 -0
  220. smallworld/state/models/mips/systemv/c99/signal.py +16 -0
  221. smallworld/state/models/mips/systemv/c99/stdio.py +265 -0
  222. smallworld/state/models/mips/systemv/c99/stdlib.py +169 -0
  223. smallworld/state/models/mips/systemv/c99/string.py +139 -0
  224. smallworld/state/models/mips/systemv/c99/time.py +61 -0
  225. smallworld/state/models/mips/systemv/posix/__init__.py +6 -0
  226. smallworld/state/models/mips/systemv/posix/libgen.py +16 -0
  227. smallworld/state/models/mips/systemv/posix/signal.py +157 -0
  228. smallworld/state/models/mips/systemv/systemv.py +78 -0
  229. smallworld/state/models/mips64/__init__.py +1 -0
  230. smallworld/state/models/mips64/systemv/__init__.py +6 -0
  231. smallworld/state/models/mips64/systemv/c99/__init__.py +12 -0
  232. smallworld/state/models/mips64/systemv/c99/signal.py +16 -0
  233. smallworld/state/models/mips64/systemv/c99/stdio.py +265 -0
  234. smallworld/state/models/mips64/systemv/c99/stdlib.py +169 -0
  235. smallworld/state/models/mips64/systemv/c99/string.py +139 -0
  236. smallworld/state/models/mips64/systemv/c99/time.py +61 -0
  237. smallworld/state/models/mips64/systemv/posix/__init__.py +6 -0
  238. smallworld/state/models/mips64/systemv/posix/libgen.py +16 -0
  239. smallworld/state/models/mips64/systemv/posix/signal.py +157 -0
  240. smallworld/state/models/mips64/systemv/systemv.py +98 -0
  241. smallworld/state/models/mips64el/__init__.py +1 -0
  242. smallworld/state/models/mips64el/systemv/__init__.py +6 -0
  243. smallworld/state/models/mips64el/systemv/c99/__init__.py +12 -0
  244. smallworld/state/models/mips64el/systemv/c99/signal.py +16 -0
  245. smallworld/state/models/mips64el/systemv/c99/stdio.py +265 -0
  246. smallworld/state/models/mips64el/systemv/c99/stdlib.py +169 -0
  247. smallworld/state/models/mips64el/systemv/c99/string.py +139 -0
  248. smallworld/state/models/mips64el/systemv/c99/time.py +61 -0
  249. smallworld/state/models/mips64el/systemv/posix/__init__.py +6 -0
  250. smallworld/state/models/mips64el/systemv/posix/libgen.py +16 -0
  251. smallworld/state/models/mips64el/systemv/posix/signal.py +157 -0
  252. smallworld/state/models/mips64el/systemv/systemv.py +96 -0
  253. smallworld/state/models/mipsel/__init__.py +1 -0
  254. smallworld/state/models/mipsel/systemv/__init__.py +6 -0
  255. smallworld/state/models/mipsel/systemv/c99/__init__.py +12 -0
  256. smallworld/state/models/mipsel/systemv/c99/signal.py +16 -0
  257. smallworld/state/models/mipsel/systemv/c99/stdio.py +265 -0
  258. smallworld/state/models/mipsel/systemv/c99/stdlib.py +169 -0
  259. smallworld/state/models/mipsel/systemv/c99/string.py +139 -0
  260. smallworld/state/models/mipsel/systemv/c99/time.py +61 -0
  261. smallworld/state/models/mipsel/systemv/posix/__init__.py +6 -0
  262. smallworld/state/models/mipsel/systemv/posix/libgen.py +16 -0
  263. smallworld/state/models/mipsel/systemv/posix/signal.py +157 -0
  264. smallworld/state/models/mipsel/systemv/systemv.py +78 -0
  265. smallworld/state/models/model.py +27 -2
  266. smallworld/state/models/posix/__init__.py +6 -0
  267. smallworld/state/models/posix/libgen.py +123 -0
  268. smallworld/state/models/posix/signal.py +690 -0
  269. smallworld/state/models/powerpc/__init__.py +1 -0
  270. smallworld/state/models/powerpc/systemv/__init__.py +6 -0
  271. smallworld/state/models/powerpc/systemv/c99/__init__.py +12 -0
  272. smallworld/state/models/powerpc/systemv/c99/signal.py +16 -0
  273. smallworld/state/models/powerpc/systemv/c99/stdio.py +265 -0
  274. smallworld/state/models/powerpc/systemv/c99/stdlib.py +169 -0
  275. smallworld/state/models/powerpc/systemv/c99/string.py +139 -0
  276. smallworld/state/models/powerpc/systemv/c99/time.py +61 -0
  277. smallworld/state/models/powerpc/systemv/posix/__init__.py +6 -0
  278. smallworld/state/models/powerpc/systemv/posix/libgen.py +16 -0
  279. smallworld/state/models/powerpc/systemv/posix/signal.py +157 -0
  280. smallworld/state/models/powerpc/systemv/systemv.py +93 -0
  281. smallworld/state/models/riscv64/__init__.py +1 -0
  282. smallworld/state/models/riscv64/systemv/__init__.py +6 -0
  283. smallworld/state/models/riscv64/systemv/c99/__init__.py +12 -0
  284. smallworld/state/models/riscv64/systemv/c99/signal.py +16 -0
  285. smallworld/state/models/riscv64/systemv/c99/stdio.py +265 -0
  286. smallworld/state/models/riscv64/systemv/c99/stdlib.py +169 -0
  287. smallworld/state/models/riscv64/systemv/c99/string.py +139 -0
  288. smallworld/state/models/riscv64/systemv/c99/time.py +61 -0
  289. smallworld/state/models/riscv64/systemv/posix/__init__.py +6 -0
  290. smallworld/state/models/riscv64/systemv/posix/libgen.py +16 -0
  291. smallworld/state/models/riscv64/systemv/posix/signal.py +157 -0
  292. smallworld/state/models/riscv64/systemv/systemv.py +85 -0
  293. smallworld/state/state.py +65 -24
  294. smallworld/state/unstable/elf.py +16 -31
  295. smallworld/utils.py +6 -1
  296. {smallworld_re-1.0.2.dist-info → smallworld_re-2.0.0.dist-info}/METADATA +76 -43
  297. smallworld_re-2.0.0.dist-info/RECORD +374 -0
  298. {smallworld_re-1.0.2.dist-info → smallworld_re-2.0.0.dist-info}/WHEEL +1 -1
  299. smallworld/state/models/x86/__init__.py +0 -2
  300. smallworld/state/models/x86/microsoftcdecl.py +0 -35
  301. smallworld/state/models/x86/systemv.py +0 -240
  302. smallworld_re-1.0.2.dist-info/RECORD +0 -166
  303. /smallworld/state/models/{posix.py → _posix.py} +0 -0
  304. {smallworld_re-1.0.2.dist-info → smallworld_re-2.0.0.dist-info}/entry_points.txt +0 -0
  305. {smallworld_re-1.0.2.dist-info → smallworld_re-2.0.0.dist-info/licenses}/LICENSE.txt +0 -0
  306. {smallworld_re-1.0.2.dist-info → smallworld_re-2.0.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,513 @@
1
+ import logging
2
+ import typing
3
+
4
+ import claripy
5
+ import jpype
6
+ from ghidra.pcode.emu import PcodeEmulator, PcodeThread
7
+ from ghidra.pcode.exec import PcodeExecutorStatePiece
8
+ from ghidra.program.model.address import AddressRangeImpl
9
+ from ghidra.program.model.pcode import Varnode
10
+
11
+ from ... import exceptions, platforms, utils
12
+ from ..emulator import Emulator
13
+ from .machdefs import GhidraMachineDef
14
+ from .typing import AbstractGhidraEmulator
15
+
16
+ log = logging.getLogger(__name__)
17
+
18
+
19
+ class GhidraEmulator(AbstractGhidraEmulator):
20
+ name = "pcode-emulator"
21
+ description = "Emulator based on pyghidra and pcode"
22
+ version = "0.0.1"
23
+
24
+ # Convert bytes into a JPype byte[]
25
+ # bytes and bytearray are considered variants of String by JPype
26
+ bytes_py_to_java = jpype.JByte[:]
27
+
28
+ @staticmethod
29
+ def bytes_java_to_py(val: jpype.JByte[:]):
30
+ # Convert a JPype byte[] into a bytes object
31
+ bytelist = list(
32
+ map(lambda x: x.numerator if x.numerator >= 0 else 256 + x.numerator, val)
33
+ )
34
+ return bytes(bytelist)
35
+
36
+ def __init__(self, platform: platforms.Platform):
37
+ super().__init__(platform)
38
+ self.platform: platforms.Platform = platform
39
+ self.platdef: platforms.PlatformDef = platforms.PlatformDef.for_platform(
40
+ platform
41
+ )
42
+ self.machdef: GhidraMachineDef = GhidraMachineDef.for_platform(platform)
43
+
44
+ self._emu: PcodeEmulator = PcodeEmulator(self.machdef.language)
45
+ # Set up the context configuration.
46
+ # This includes execution mode information,
47
+ # and isn't automatically propagated to the thread.
48
+ self._thread.overrideContextWithDefault()
49
+
50
+ self._memory_map = utils.RangeCollection()
51
+
52
+ # Instruction hooking callbacks
53
+ self._instructions_hook: typing.Optional[
54
+ typing.Callable[[Emulator], None]
55
+ ] = None
56
+ self._instruction_hooks: typing.Dict[
57
+ int, typing.Callable[[Emulator], None]
58
+ ] = dict()
59
+
60
+ # Function hooking callbacks
61
+ self._function_hooks: typing.Dict[
62
+ int, typing.Callable[[Emulator], None]
63
+ ] = dict()
64
+
65
+ # Memory hooking callbacks
66
+ self._mem_reads_hook: typing.Optional[
67
+ typing.Callable[[Emulator, int, int, bytes], typing.Optional[bytes]]
68
+ ] = None
69
+ self._mem_read_hooks: typing.Dict[
70
+ typing.Tuple[int, int],
71
+ typing.Callable[[Emulator, int, int, bytes], typing.Optional[bytes]],
72
+ ] = dict()
73
+ self._mem_writes_hook: typing.Optional[
74
+ typing.Callable[[Emulator, int, int, bytes], None]
75
+ ] = None
76
+ self._mem_write_hooks: typing.Dict[
77
+ typing.Tuple[int, int], typing.Callable[[Emulator, int, int, bytes], None]
78
+ ] = dict()
79
+
80
+ @property
81
+ def _thread(self) -> PcodeThread:
82
+ return self._emu.getThread("main", True)
83
+
84
+ def read_register_content(self, name: str) -> int:
85
+ # Determine address and size of register
86
+ if name == "pc":
87
+ name = self.platdef.pc_register
88
+ reg = self.machdef.pcode_reg(name)
89
+
90
+ # Get the thread's register state
91
+ state = self._thread.getState()
92
+
93
+ # Get the register value in bytes
94
+ val = state.getVar(reg, PcodeExecutorStatePiece.Reason.INSPECT)
95
+
96
+ if self.platform.byteorder is platforms.Byteorder.LITTLE:
97
+ return int.from_bytes(val, "little")
98
+ elif self.platform.byteorder is platforms.Byteorder.BIG:
99
+ return int.from_bytes(val, "big")
100
+ else:
101
+ raise Exception("Unable to decode byteorder {self.platform.byteorder}")
102
+
103
+ def write_register_content(
104
+ self, name: str, value: typing.Union[None, int, claripy.ast.bv.BV]
105
+ ) -> None:
106
+ # Determine address and size of register
107
+ if name == "pc":
108
+ name = self.platdef.pc_register
109
+ reg = self.machdef.pcode_reg(name)
110
+
111
+ if value is None:
112
+ return
113
+ if not isinstance(value, int):
114
+ raise TypeError("Pcode emulator can't support symbolic values")
115
+
116
+ state = self._thread.getState()
117
+
118
+ if self.platform.byteorder is platforms.Byteorder.BIG:
119
+ val = value.to_bytes(reg.getMinimumByteSize(), "big")
120
+ elif self.platform.byteorder is platforms.Byteorder.LITTLE:
121
+ val = value.to_bytes(reg.getMinimumByteSize(), "little")
122
+ else:
123
+ raise Exception("Unable to encode byteorder {self.platform.byteorder}")
124
+
125
+ state.setVar(reg, self.bytes_py_to_java(val))
126
+
127
+ def read_memory_content(self, address: int, size: int) -> bytes:
128
+ # Get the thread's memory state
129
+ shared = self._emu.getSharedState()
130
+
131
+ if self.platform.byteorder is platforms.Byteorder.BIG:
132
+ addr_bytes = address.to_bytes(self.platdef.address_size, "big")
133
+ elif self.platform.byteorder is platforms.Byteorder.LITTLE:
134
+ addr_bytes = address.to_bytes(self.platdef.address_size, "little")
135
+ else:
136
+ raise Exception("Unable to encode byteorder {self.platform.byteorder}")
137
+
138
+ # Get the data out of the default address space
139
+ # NOTE: Ghidra can support machines with multiple address spaces.
140
+ # SmallWorld does not.
141
+ val = shared.getVar(
142
+ self.machdef.language.getDefaultSpace(),
143
+ self.bytes_py_to_java(addr_bytes),
144
+ size,
145
+ False,
146
+ shared.Reason.INSPECT,
147
+ )
148
+ return self.bytes_java_to_py(val)
149
+
150
+ def map_memory(self, address: int, size: int) -> None:
151
+ region = (address, address + size)
152
+ self._memory_map.add_range(region)
153
+
154
+ def get_memory_map(self) -> typing.List[typing.Tuple[int, int]]:
155
+ return list(self._memory_map.ranges)
156
+
157
+ def write_memory_content(
158
+ self, address: int, content: typing.Union[bytes, claripy.ast.bv.BV]
159
+ ):
160
+ if isinstance(content, claripy.ast.bv.BV):
161
+ raise TypeError("Pcode emulator can't handle symbolic expressions")
162
+
163
+ log.info(f"Writing {hex(len(content))} bytes at {hex(address)}")
164
+
165
+ # Get the thread's memory state
166
+ shared = self._emu.getSharedState()
167
+
168
+ val = self.bytes_py_to_java(content)
169
+ if self.platform.byteorder is platforms.Byteorder.BIG:
170
+ addr_bytes = address.to_bytes(self.platdef.address_size, "big")
171
+ elif self.platform.byteorder is platforms.Byteorder.LITTLE:
172
+ addr_bytes = address.to_bytes(self.platdef.address_size, "little")
173
+ else:
174
+ raise Exception("Unable to encode byteorder {self.platform.byteorder}")
175
+
176
+ # Get the data out of the default address space
177
+ # NOTE: Ghidra can support machines with multiple address spaces.
178
+ # SmallWorld does not.
179
+ shared.setVar(
180
+ self.machdef.language.getDefaultSpace(),
181
+ self.bytes_py_to_java(addr_bytes),
182
+ len(content),
183
+ False,
184
+ val,
185
+ )
186
+
187
+ def hook_instruction(
188
+ self, address: int, function: typing.Callable[[Emulator], None]
189
+ ) -> None:
190
+ self._instruction_hooks[address] = function
191
+
192
+ def unhook_instruction(self, address: int) -> None:
193
+ if address in self._instruction_hooks:
194
+ del self._instruction_hooks[address]
195
+
196
+ def hook_instructions(self, function: typing.Callable[[Emulator], None]) -> None:
197
+ self._instructions_hook = function
198
+
199
+ def unhook_instructions(self) -> None:
200
+ self._instructions_hook = None
201
+
202
+ def _process_function_hook(self, address: int):
203
+ if address not in self._function_hooks:
204
+ # This really should never happen unless someone calls this manually.
205
+ raise exceptions.ConfigurationError(f"No function hook at {hex(address)}")
206
+
207
+ # Run the hook
208
+ self._function_hooks[address](self)
209
+
210
+ # Mimic a platform-specific "return" instruction.
211
+ if self.platform.architecture == platforms.Architecture.X86_32:
212
+ sp = self.read_register("esp")
213
+ if self.platform.byteorder == platforms.Byteorder.LITTLE:
214
+ ret = int.from_bytes(self.read_memory(sp, 4), "little")
215
+ elif self.platform.byteorder == platforms.Byteorder.BIG:
216
+ ret = int.from_bytes(self.read_memory(sp, 4), "big")
217
+ self.write_register("esp", sp + 4)
218
+ elif self.platform.architecture == platforms.Architecture.X86_64:
219
+ # amd64: pop an 8-byte value off the stack
220
+ sp = self.read_register("rsp")
221
+ if self.platform.byteorder == platforms.Byteorder.LITTLE:
222
+ ret = int.from_bytes(self.read_memory(sp, 8), "little")
223
+ elif self.platform.byteorder == platforms.Byteorder.BIG:
224
+ ret = int.from_bytes(self.read_memory(sp, 8), "big")
225
+ self.write_register("rsp", sp + 8)
226
+ elif (
227
+ self.platform.architecture == platforms.Architecture.AARCH64
228
+ or self.platform.architecture == platforms.Architecture.ARM_V5T
229
+ or self.platform.architecture == platforms.Architecture.ARM_V6M
230
+ or self.platform.architecture == platforms.Architecture.ARM_V6M_THUMB
231
+ or self.platform.architecture == platforms.Architecture.ARM_V7A
232
+ or self.platform.architecture == platforms.Architecture.ARM_V7M
233
+ or self.platform.architecture == platforms.Architecture.ARM_V7R
234
+ or self.platform.architecture == platforms.Architecture.POWERPC32
235
+ or self.platform.architecture == platforms.Architecture.POWERPC64
236
+ ):
237
+ # aarch64, arm32, powerpc and powerpc64: branch to register 'lr'
238
+ ret = self.read_register("lr")
239
+ elif (
240
+ self.platform.architecture == platforms.Architecture.LOONGARCH64
241
+ or self.platform.architecture == platforms.Architecture.MIPS32
242
+ or self.platform.architecture == platforms.Architecture.MIPS64
243
+ or self.platform.architecture == platforms.Architecture.RISCV64
244
+ ):
245
+ # mips32, mips64, and riscv64: branch to register 'ra'
246
+ ret = self.read_register("ra")
247
+ elif self.platform.architecture == platforms.Architecture.XTENSA:
248
+ # xtensa: branch to register 'a0'
249
+ ret = self.read_register("a0")
250
+
251
+ self.write_register("pc", ret)
252
+
253
+ def hook_function(
254
+ self, address: int, function: typing.Callable[[Emulator], None]
255
+ ) -> None:
256
+ self._function_hooks[address] = function
257
+
258
+ def unhook_function(self, address: int) -> None:
259
+ if address in self._function_hooks:
260
+ del self._function_hooks[address]
261
+
262
+ def _update_access_breakpoints(self) -> None:
263
+ # Refresh all access breakpoints
264
+ # There's no way to clear a single access breakpoint;
265
+ # you need to clear them all and re-apply.
266
+ return
267
+
268
+ # Wipe out all access breakpoints
269
+ self._emu.clearAccessBreakpoints()
270
+
271
+ addrspace = self.machdef.language.getDefaultSpace()
272
+
273
+ # Add back the global read breakpoint
274
+ if self._mem_reads_hook is not None:
275
+ addr_range = AddressRangeImpl(
276
+ addrspace.getMinAddress(), addrspace.getMaxAddress()
277
+ )
278
+ self._emu.addAccessBreakpoint(addr_range, self._emu.AccessKind.R)
279
+
280
+ # Add back the specific read breakpoints
281
+ for start, end in self._mem_read_hooks:
282
+ start_addr = addrspace.getAddress(start)
283
+ end_addr = addrspace.getAddress(end)
284
+ addr_range = AddressRangeImpl(start_addr, end_addr)
285
+ self._emu.addAccessBreakpoint(addr_range, self._emu.AccessKind.R)
286
+
287
+ # Add back the global write breakpoint
288
+ if self._mem_writes_hook is not None:
289
+ addr_range = AddressRangeImpl(
290
+ addrspace.getMinAddress(), addrspace.getMaxAddress()
291
+ )
292
+ self._emu.addAccessBreakpoint(addr_range, self._emu.AccessKind.W)
293
+
294
+ # Add back the specific write breakpoints
295
+ for start, end in self._mem_write_hooks:
296
+ start_addr = addrspace.getAddress(start)
297
+ end_addr = addrspace.getAddress(end)
298
+ addr_range = AddressRangeImpl(start_addr, end_addr)
299
+ self._emu.addAccessBreakpoint(addr_range, self._emu.AccessKind.W)
300
+
301
+ def _process_read_breakpoint(self, addr_var: Varnode, out_var: Varnode) -> None:
302
+ state = self._thread.getState()
303
+
304
+ # Get the address out of the emulator
305
+ addr_bytes = state.getVar(addr_var, PcodeExecutorStatePiece.Reason.INSPECT)
306
+ if self.platform.byteorder is platforms.Byteorder.BIG:
307
+ addr = int.from_bytes(addr_bytes, "big")
308
+ elif self.platform.byteorder is platforms.Byteorder.LITTLE:
309
+ addr = int.from_bytes(addr_bytes, "little")
310
+
311
+ # Dereference the address to get the original data
312
+ addr_space = self.machdef.language.getDefaultSpace()
313
+ addr_addr = addr_space.getAddress(addr)
314
+ data_var = Varnode(addr_addr, out_var.getSize())
315
+ data = state.getVar(data_var, PcodeExecutorStatePiece.Reason.INSPECT)
316
+
317
+ if self._mem_reads_hook is not None:
318
+ new_data = self._mem_reads_hook(self, addr, len(data), data)
319
+ if new_data is not None:
320
+ data = new_data
321
+
322
+ end_addr = addr + len(data)
323
+
324
+ for (start, end), hook in self._mem_read_hooks.items():
325
+ rng = range(start, end)
326
+ access_rng = range(addr, end_addr)
327
+ if (
328
+ addr in rng
329
+ or end_addr - 1 in rng
330
+ or start in access_rng
331
+ or end - 1 in access_rng
332
+ ):
333
+ new_data = hook(self, addr, len(data), data)
334
+ if new_data is not None:
335
+ data = new_data
336
+
337
+ # Write the data to the output
338
+ #
339
+ # CRITICAL: This must always happen, even if the op wasn't hooked!
340
+ # The main processing loop skips any LOAD opcodes,
341
+ # since their normal execution will clobber any value produced
342
+ # by this handler.
343
+ # Thus, this handler must fully replace the behavior of LOAD.
344
+ state.setVar(out_var, self.bytes_py_to_java(data))
345
+
346
+ def hook_memory_read(
347
+ self,
348
+ start: int,
349
+ end: int,
350
+ function: typing.Callable[[Emulator, int, int, bytes], typing.Optional[bytes]],
351
+ ) -> None:
352
+ self._mem_read_hooks[(start, end)] = function
353
+ self._update_access_breakpoints()
354
+
355
+ def unhook_memory_read(self, start: int, end: int) -> None:
356
+ if (start, end) in self._mem_read_hooks:
357
+ del self._mem_read_hooks[(start, end)]
358
+ self._update_access_breakpoints()
359
+
360
+ def hook_memory_reads(
361
+ self,
362
+ function: typing.Callable[[Emulator, int, int, bytes], typing.Optional[bytes]],
363
+ ) -> None:
364
+ self._mem_reads_hook = function
365
+ self._update_access_breakpoints()
366
+
367
+ def unhook_memory_reads(self) -> None:
368
+ if self._mem_reads_hook is not None:
369
+ self._mem_reads_hook = None
370
+ self._update_access_breakpoints()
371
+
372
+ def _process_write_breakpoint(self, addr_var: Varnode, data_var: Varnode) -> None:
373
+ state = self._thread.getState()
374
+ addr_bytes = state.getVar(addr_var, PcodeExecutorStatePiece.Reason.INSPECT)
375
+ data = state.getVar(data_var, PcodeExecutorStatePiece.Reason.INSPECT)
376
+
377
+ if self.platform.byteorder is platforms.Byteorder.BIG:
378
+ addr = int.from_bytes(addr_bytes, "big")
379
+ elif self.platform.byteorder is platforms.Byteorder.LITTLE:
380
+ addr = int.from_bytes(addr_bytes, "little")
381
+
382
+ if self._mem_writes_hook is not None:
383
+ self._mem_writes_hook(self, addr, len(data), data)
384
+
385
+ end_addr = addr + len(data)
386
+
387
+ for (start, end), hook in self._mem_write_hooks.items():
388
+ rng = range(start, end)
389
+ access_rng = range(addr, end_addr)
390
+ if (
391
+ addr in rng
392
+ or end_addr - 1 in rng
393
+ or start in access_rng
394
+ or end - 1 in access_rng
395
+ ):
396
+ hook(self, addr, len(data), data)
397
+
398
+ def hook_memory_write(
399
+ self,
400
+ start: int,
401
+ end: int,
402
+ function: typing.Callable[[Emulator, int, int, bytes], None],
403
+ ) -> None:
404
+ self._mem_write_hooks[(start, end)] = function
405
+ self._update_access_breakpoints()
406
+
407
+ def unhook_memory_write(self, start: int, end: int) -> None:
408
+ if (start, end) in self._mem_write_hooks:
409
+ del self._mem_write_hooks[(start, end)]
410
+ self._update_access_breakpoints()
411
+
412
+ def hook_memory_writes(
413
+ self,
414
+ function: typing.Callable[[Emulator, int, int, bytes], None],
415
+ ) -> None:
416
+ self._mem_writes_hook = function
417
+ self._update_access_breakpoints()
418
+
419
+ def unhook_memory_writes(self) -> None:
420
+ if self._mem_writes_hook is not None:
421
+ self._mem_writes_hook = None
422
+ self._update_access_breakpoints()
423
+
424
+ def step_instruction(self) -> None:
425
+ if not self.machdef.supports_single_step:
426
+ raise exceptions.ConfigurationError(
427
+ f"PcodeEmulator does not support single-instruction stepping for {self.platform}"
428
+ )
429
+
430
+ # Step!
431
+ pc = self.read_register_content(self.platdef.pc_register)
432
+ pc_addr = self.machdef.language.getDefaultSpace().getAddress(pc)
433
+ self._thread.overrideCounter(pc_addr)
434
+
435
+ # Check for instruction hooks.
436
+ # TODO: Should instruction hooks override the instruction?
437
+ if self._instructions_hook is not None:
438
+ self._instructions_hook(self)
439
+ if pc in self._instruction_hooks:
440
+ self._instruction_hooks[pc](self)
441
+
442
+ # Check for function hooks
443
+ if pc in self._function_hooks:
444
+ # Function hooks bypass normal instruction processing,
445
+ # but I still want bounds/exits to work normally.
446
+ self._process_function_hook(pc)
447
+ else:
448
+ skip = False
449
+ frame = None
450
+ # We need to step individual pcode ops to capture hooks
451
+ # There is an exception-based hooking mechanism,
452
+ # but it's unworkable for SmallWorld's purpose.
453
+ while True:
454
+ if skip:
455
+ # Skip the next op; it was modeled by a hook
456
+ skip = False
457
+ self._thread.skipPcodeOp()
458
+ else:
459
+ # Execute the opcode normally
460
+ self._thread.stepPcodeOp()
461
+
462
+ frame = self._thread.getFrame()
463
+
464
+ if frame is None:
465
+ # No frame; this is the end of the instruction
466
+ break
467
+
468
+ if frame.isFinished():
469
+ # Frame is finished; this is the end of the instruction
470
+ self._thread.finishInstruction()
471
+ break
472
+
473
+ # Inspect the op to see if it's memory-hook relevant
474
+ code = frame.getCode()
475
+ op = code[frame.index()]
476
+ opcode = op.getOpcode()
477
+ if opcode == op.STORE:
478
+ # This is a STORE opcode; could trigger a "write" hook
479
+ _, addr_var, data_var = op.getInputs()
480
+ self._process_write_breakpoint(addr_var, data_var)
481
+ elif opcode == op.LOAD:
482
+ # This is a LOAD opcode; could trigger a "read" hook
483
+ _, addr_var = op.getInputs()
484
+ out_var = op.getOutput()
485
+ self._process_read_breakpoint(addr_var, out_var)
486
+ # Skip the actual LOAD opcode
487
+ # The read breakpoint handler will mimic its behavior;
488
+ # running the op normally will clobber a custom value
489
+ # produced by a hook.
490
+ skip = True
491
+
492
+ # Check exit points and bounds
493
+ pc = self.read_register_content(self.platdef.pc_register)
494
+
495
+ if pc in self._exit_points:
496
+ raise exceptions.EmulationExitpoint()
497
+ if not self._bounds.is_empty() and not self._bounds.contains_value(pc):
498
+ raise exceptions.EmulationBounds()
499
+ if not self._memory_map.is_empty() and not self._memory_map.contains_value(pc):
500
+ raise exceptions.EmulationBounds()
501
+
502
+ def step_block(self) -> None:
503
+ raise NotImplementedError("Not sure how to step by block.")
504
+
505
+ def run(self) -> None:
506
+ try:
507
+ while True:
508
+ self.step_instruction()
509
+ except exceptions.EmulationStop:
510
+ pass
511
+
512
+ def __repr__(self) -> str:
513
+ return "PcodeEmulator"
@@ -0,0 +1,31 @@
1
+ from .aarch64 import AArch64MachineDef
2
+ from .amd64 import AMD64MachineDef
3
+ from .arm import ARMv5TMachineDef, ARMv6MMachineDef, ARMv7AMachineDef, ARMv7MMachineDef
4
+ from .i386 import i386MachineDef
5
+ from .loongarch import LoongArch64MachineDef
6
+ from .machdef import GhidraMachineDef
7
+ from .mips import MIPSBEMachineDef, MIPSELMachineDef
8
+ from .mips64 import MIPS64BEMachineDef, MIPS64ELMachineDef
9
+ from .ppc import PowerPC32MachineDef, PowerPC64MachineDef
10
+ from .riscv import RISCV64MachineDef
11
+ from .xtensa import XTensaMachineDef
12
+
13
+ __all__ = [
14
+ "AArch64MachineDef",
15
+ "AMD64MachineDef",
16
+ "ARMv5TMachineDef",
17
+ "ARMv6MMachineDef",
18
+ "ARMv7MMachineDef",
19
+ "ARMv7AMachineDef",
20
+ "i386MachineDef",
21
+ "LoongArch64MachineDef",
22
+ "MIPS64BEMachineDef",
23
+ "MIPS64ELMachineDef",
24
+ "MIPSBEMachineDef",
25
+ "MIPSELMachineDef",
26
+ "GhidraMachineDef",
27
+ "PowerPC32MachineDef",
28
+ "PowerPC64MachineDef",
29
+ "RISCV64MachineDef",
30
+ "XTensaMachineDef",
31
+ ]