smallworld-re 1.0.3__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.
- smallworld/analyses/__init__.py +8 -0
- smallworld/analyses/analysis.py +8 -67
- smallworld/analyses/code_coverage.py +1 -2
- smallworld/analyses/colorizer.py +301 -534
- smallworld/analyses/colorizer_def_use.py +217 -0
- smallworld/analyses/colorizer_summary.py +173 -83
- smallworld/analyses/field_detection/field_analysis.py +7 -8
- smallworld/analyses/field_detection/hints.py +1 -1
- smallworld/analyses/field_detection/malloc.py +2 -2
- smallworld/analyses/trace_execution.py +160 -0
- smallworld/analyses/trace_execution_types.py +42 -0
- smallworld/analyses/unstable/angr/divergence.py +1 -2
- smallworld/analyses/unstable/angr/model.py +5 -6
- smallworld/analyses/unstable/angr_nwbt.py +3 -4
- smallworld/analyses/unstable/code_coverage.py +2 -3
- smallworld/analyses/unstable/code_reachable.py +2 -3
- smallworld/analyses/unstable/control_flow_tracer.py +2 -3
- smallworld/analyses/unstable/pointer_finder.py +2 -3
- smallworld/analyses/unstable/utils/tui.py +71 -0
- smallworld/emulators/__init__.py +3 -1
- smallworld/emulators/angr/angr.py +30 -9
- smallworld/emulators/angr/machdefs/__init__.py +2 -0
- smallworld/emulators/angr/machdefs/aarch64.py +1 -1
- smallworld/emulators/angr/machdefs/amd64.py +0 -4
- smallworld/emulators/angr/machdefs/arm.py +0 -2
- smallworld/emulators/angr/machdefs/i386.py +0 -2
- smallworld/emulators/angr/machdefs/loongarch.py +340 -0
- smallworld/emulators/angr/machdefs/machdef.py +1 -8
- smallworld/emulators/angr/machdefs/mips.py +0 -2
- smallworld/emulators/angr/machdefs/mips64.py +0 -2
- smallworld/emulators/angr/machdefs/ppc.py +1 -2
- smallworld/emulators/angr/machdefs/riscv.py +8 -10
- smallworld/emulators/angr/machdefs/xtensa.py +7 -4
- smallworld/emulators/emulator.py +22 -0
- smallworld/emulators/ghidra/__init__.py +37 -0
- smallworld/emulators/ghidra/ghidra.py +513 -0
- smallworld/emulators/ghidra/machdefs/__init__.py +31 -0
- smallworld/emulators/ghidra/machdefs/aarch64.py +289 -0
- smallworld/emulators/ghidra/machdefs/amd64.py +185 -0
- smallworld/emulators/ghidra/machdefs/arm.py +370 -0
- smallworld/emulators/ghidra/machdefs/i386.py +109 -0
- smallworld/emulators/ghidra/machdefs/loongarch.py +162 -0
- smallworld/emulators/ghidra/machdefs/machdef.py +81 -0
- smallworld/emulators/ghidra/machdefs/mips.py +163 -0
- smallworld/emulators/ghidra/machdefs/mips64.py +186 -0
- smallworld/emulators/ghidra/machdefs/ppc.py +98 -0
- smallworld/emulators/ghidra/machdefs/riscv.py +208 -0
- smallworld/emulators/ghidra/machdefs/xtensa.py +21 -0
- smallworld/emulators/ghidra/typing.py +28 -0
- smallworld/emulators/hookable.py +18 -4
- smallworld/emulators/panda/machdefs/__init__.py +2 -2
- smallworld/emulators/panda/machdefs/aarch64.py +186 -11
- smallworld/emulators/panda/machdefs/amd64.py +103 -11
- smallworld/emulators/panda/machdefs/arm.py +216 -20
- smallworld/emulators/panda/machdefs/i386.py +30 -7
- smallworld/emulators/panda/machdefs/machdef.py +9 -16
- smallworld/emulators/panda/machdefs/mips.py +49 -5
- smallworld/emulators/panda/machdefs/mips64.py +57 -5
- smallworld/emulators/panda/machdefs/ppc.py +38 -13
- smallworld/emulators/panda/panda.py +146 -44
- smallworld/emulators/unicorn/__init__.py +2 -0
- smallworld/emulators/unicorn/machdefs/aarch64.py +253 -264
- smallworld/emulators/unicorn/machdefs/amd64.py +254 -259
- smallworld/emulators/unicorn/machdefs/arm.py +200 -212
- smallworld/emulators/unicorn/machdefs/i386.py +84 -90
- smallworld/emulators/unicorn/machdefs/machdef.py +2 -23
- smallworld/emulators/unicorn/machdefs/mips.py +127 -135
- smallworld/emulators/unicorn/unicorn.py +52 -13
- smallworld/helpers.py +4 -19
- smallworld/hinting/hinting.py +22 -192
- smallworld/hinting/hints.py +50 -18
- smallworld/instructions/bsid.py +8 -8
- smallworld/logging.py +4 -2
- smallworld/platforms/__init__.py +12 -0
- smallworld/platforms/defs/__init__.py +36 -0
- smallworld/platforms/defs/aarch64.py +450 -0
- smallworld/platforms/defs/amd64.py +463 -0
- smallworld/platforms/defs/arm.py +519 -0
- smallworld/platforms/defs/i386.py +258 -0
- smallworld/platforms/defs/loongarch.py +270 -0
- smallworld/platforms/defs/mips.py +321 -0
- smallworld/platforms/defs/mips64.py +313 -0
- smallworld/platforms/defs/platformdef.py +97 -0
- smallworld/platforms/defs/powerpc.py +259 -0
- smallworld/platforms/defs/riscv.py +257 -0
- smallworld/platforms/defs/xtensa.py +96 -0
- smallworld/{platforms.py → platforms/platforms.py} +3 -0
- smallworld/state/cpus/__init__.py +2 -0
- smallworld/state/cpus/aarch64.py +0 -9
- smallworld/state/cpus/amd64.py +6 -28
- smallworld/state/cpus/arm.py +0 -11
- smallworld/state/cpus/cpu.py +0 -11
- smallworld/state/cpus/i386.py +0 -7
- smallworld/state/cpus/loongarch.py +299 -0
- smallworld/state/cpus/mips.py +4 -47
- smallworld/state/cpus/mips64.py +18 -58
- smallworld/state/cpus/powerpc.py +2 -9
- smallworld/state/cpus/riscv.py +1 -11
- smallworld/state/cpus/xtensa.py +0 -5
- smallworld/state/memory/code.py +38 -2
- smallworld/state/memory/elf/__init__.py +5 -1
- smallworld/state/memory/elf/coredump/__init__.py +3 -0
- smallworld/state/memory/elf/coredump/coredump.py +46 -0
- smallworld/state/memory/elf/coredump/prstatus/__init__.py +27 -0
- smallworld/state/memory/elf/coredump/prstatus/aarch64.py +46 -0
- smallworld/state/memory/elf/coredump/prstatus/amd64.py +40 -0
- smallworld/state/memory/elf/coredump/prstatus/arm.py +53 -0
- smallworld/state/memory/elf/coredump/prstatus/i386.py +30 -0
- smallworld/state/memory/elf/coredump/prstatus/mips.py +55 -0
- smallworld/state/memory/elf/coredump/prstatus/mips64.py +57 -0
- smallworld/state/memory/elf/coredump/prstatus/ppc.py +82 -0
- smallworld/state/memory/elf/coredump/prstatus/prstatus.py +129 -0
- smallworld/state/memory/elf/elf.py +211 -57
- smallworld/state/memory/elf/register_state.py +36 -0
- smallworld/state/memory/elf/rela/__init__.py +2 -0
- smallworld/state/memory/elf/rela/aarch64.py +3 -1
- smallworld/state/memory/elf/rela/amd64.py +4 -2
- smallworld/state/memory/elf/rela/arm.py +4 -2
- smallworld/state/memory/elf/rela/i386.py +4 -2
- smallworld/state/memory/elf/rela/loongarch.py +32 -0
- smallworld/state/memory/elf/rela/mips.py +39 -18
- smallworld/state/memory/elf/rela/ppc.py +31 -14
- smallworld/state/memory/elf/structs.py +3 -0
- smallworld/state/memory/heap.py +2 -2
- smallworld/state/memory/memory.py +18 -0
- smallworld/state/memory/pe/__init__.py +3 -0
- smallworld/state/memory/pe/pe.py +361 -0
- smallworld/state/memory/pe/structs.py +60 -0
- smallworld/state/memory/stack/__init__.py +2 -0
- smallworld/state/memory/stack/loongarch.py +26 -0
- smallworld/state/models/__init__.py +29 -2
- smallworld/state/models/aarch64/__init__.py +1 -0
- smallworld/state/models/aarch64/systemv/__init__.py +6 -0
- smallworld/state/models/aarch64/systemv/c99/__init__.py +12 -0
- smallworld/state/models/aarch64/systemv/c99/signal.py +16 -0
- smallworld/state/models/aarch64/systemv/c99/stdio.py +265 -0
- smallworld/state/models/aarch64/systemv/c99/stdlib.py +169 -0
- smallworld/state/models/aarch64/systemv/c99/string.py +139 -0
- smallworld/state/models/aarch64/systemv/c99/time.py +61 -0
- smallworld/state/models/aarch64/systemv/posix/__init__.py +6 -0
- smallworld/state/models/aarch64/systemv/posix/libgen.py +16 -0
- smallworld/state/models/aarch64/systemv/posix/signal.py +157 -0
- smallworld/state/models/aarch64/systemv/systemv.py +80 -0
- smallworld/state/models/amd64/__init__.py +1 -0
- smallworld/state/models/amd64/systemv/__init__.py +6 -0
- smallworld/state/models/amd64/systemv/c99/__init__.py +12 -0
- smallworld/state/models/amd64/systemv/c99/signal.py +16 -0
- smallworld/state/models/amd64/systemv/c99/stdio.py +265 -0
- smallworld/state/models/amd64/systemv/c99/stdlib.py +169 -0
- smallworld/state/models/amd64/systemv/c99/string.py +139 -0
- smallworld/state/models/amd64/systemv/c99/time.py +61 -0
- smallworld/state/models/amd64/systemv/posix/__init__.py +6 -0
- smallworld/state/models/amd64/systemv/posix/libgen.py +16 -0
- smallworld/state/models/amd64/systemv/posix/signal.py +157 -0
- smallworld/state/models/amd64/systemv/systemv.py +78 -0
- smallworld/state/models/armel/__init__.py +1 -0
- smallworld/state/models/armel/systemv/__init__.py +6 -0
- smallworld/state/models/armel/systemv/c99/__init__.py +12 -0
- smallworld/state/models/armel/systemv/c99/signal.py +16 -0
- smallworld/state/models/armel/systemv/c99/stdio.py +265 -0
- smallworld/state/models/armel/systemv/c99/stdlib.py +169 -0
- smallworld/state/models/armel/systemv/c99/string.py +139 -0
- smallworld/state/models/armel/systemv/c99/time.py +61 -0
- smallworld/state/models/armel/systemv/posix/__init__.py +6 -0
- smallworld/state/models/armel/systemv/posix/libgen.py +16 -0
- smallworld/state/models/armel/systemv/posix/signal.py +157 -0
- smallworld/state/models/armel/systemv/systemv.py +82 -0
- smallworld/state/models/armhf/__init__.py +1 -0
- smallworld/state/models/armhf/systemv/__init__.py +6 -0
- smallworld/state/models/armhf/systemv/c99/__init__.py +12 -0
- smallworld/state/models/armhf/systemv/c99/signal.py +16 -0
- smallworld/state/models/armhf/systemv/c99/stdio.py +265 -0
- smallworld/state/models/armhf/systemv/c99/stdlib.py +169 -0
- smallworld/state/models/armhf/systemv/c99/string.py +139 -0
- smallworld/state/models/armhf/systemv/c99/time.py +61 -0
- smallworld/state/models/armhf/systemv/posix/__init__.py +6 -0
- smallworld/state/models/armhf/systemv/posix/libgen.py +16 -0
- smallworld/state/models/armhf/systemv/posix/signal.py +157 -0
- smallworld/state/models/armhf/systemv/systemv.py +77 -0
- smallworld/state/models/c99/__init__.py +12 -0
- smallworld/state/models/c99/fmt_print.py +915 -0
- smallworld/state/models/c99/fmt_scan.py +864 -0
- smallworld/state/models/c99/math.py +362 -0
- smallworld/state/models/c99/signal.py +71 -0
- smallworld/state/models/c99/stdio.py +1305 -0
- smallworld/state/models/c99/stdlib.py +595 -0
- smallworld/state/models/c99/string.py +674 -0
- smallworld/state/models/c99/time.py +340 -0
- smallworld/state/models/c99/utils.py +89 -0
- smallworld/state/models/cstd.py +759 -0
- smallworld/state/models/errno.py +581 -0
- smallworld/state/models/filedesc.py +515 -0
- smallworld/state/models/i386/__init__.py +1 -0
- smallworld/state/models/i386/systemv/__init__.py +6 -0
- smallworld/state/models/i386/systemv/c99/__init__.py +12 -0
- smallworld/state/models/i386/systemv/c99/signal.py +16 -0
- smallworld/state/models/i386/systemv/c99/stdio.py +265 -0
- smallworld/state/models/i386/systemv/c99/stdlib.py +169 -0
- smallworld/state/models/i386/systemv/c99/string.py +139 -0
- smallworld/state/models/i386/systemv/c99/time.py +61 -0
- smallworld/state/models/i386/systemv/posix/__init__.py +6 -0
- smallworld/state/models/i386/systemv/posix/libgen.py +16 -0
- smallworld/state/models/i386/systemv/posix/signal.py +157 -0
- smallworld/state/models/i386/systemv/systemv.py +71 -0
- smallworld/state/models/loongarch64/__init__.py +1 -0
- smallworld/state/models/loongarch64/systemv/__init__.py +6 -0
- smallworld/state/models/loongarch64/systemv/c99/__init__.py +12 -0
- smallworld/state/models/loongarch64/systemv/c99/signal.py +16 -0
- smallworld/state/models/loongarch64/systemv/c99/stdio.py +265 -0
- smallworld/state/models/loongarch64/systemv/c99/stdlib.py +169 -0
- smallworld/state/models/loongarch64/systemv/c99/string.py +139 -0
- smallworld/state/models/loongarch64/systemv/c99/time.py +61 -0
- smallworld/state/models/loongarch64/systemv/posix/__init__.py +6 -0
- smallworld/state/models/loongarch64/systemv/posix/libgen.py +16 -0
- smallworld/state/models/loongarch64/systemv/posix/signal.py +157 -0
- smallworld/state/models/loongarch64/systemv/systemv.py +83 -0
- smallworld/state/models/mips/__init__.py +1 -0
- smallworld/state/models/mips/systemv/__init__.py +6 -0
- smallworld/state/models/mips/systemv/c99/__init__.py +12 -0
- smallworld/state/models/mips/systemv/c99/signal.py +16 -0
- smallworld/state/models/mips/systemv/c99/stdio.py +265 -0
- smallworld/state/models/mips/systemv/c99/stdlib.py +169 -0
- smallworld/state/models/mips/systemv/c99/string.py +139 -0
- smallworld/state/models/mips/systemv/c99/time.py +61 -0
- smallworld/state/models/mips/systemv/posix/__init__.py +6 -0
- smallworld/state/models/mips/systemv/posix/libgen.py +16 -0
- smallworld/state/models/mips/systemv/posix/signal.py +157 -0
- smallworld/state/models/mips/systemv/systemv.py +78 -0
- smallworld/state/models/mips64/__init__.py +1 -0
- smallworld/state/models/mips64/systemv/__init__.py +6 -0
- smallworld/state/models/mips64/systemv/c99/__init__.py +12 -0
- smallworld/state/models/mips64/systemv/c99/signal.py +16 -0
- smallworld/state/models/mips64/systemv/c99/stdio.py +265 -0
- smallworld/state/models/mips64/systemv/c99/stdlib.py +169 -0
- smallworld/state/models/mips64/systemv/c99/string.py +139 -0
- smallworld/state/models/mips64/systemv/c99/time.py +61 -0
- smallworld/state/models/mips64/systemv/posix/__init__.py +6 -0
- smallworld/state/models/mips64/systemv/posix/libgen.py +16 -0
- smallworld/state/models/mips64/systemv/posix/signal.py +157 -0
- smallworld/state/models/mips64/systemv/systemv.py +98 -0
- smallworld/state/models/mips64el/__init__.py +1 -0
- smallworld/state/models/mips64el/systemv/__init__.py +6 -0
- smallworld/state/models/mips64el/systemv/c99/__init__.py +12 -0
- smallworld/state/models/mips64el/systemv/c99/signal.py +16 -0
- smallworld/state/models/mips64el/systemv/c99/stdio.py +265 -0
- smallworld/state/models/mips64el/systemv/c99/stdlib.py +169 -0
- smallworld/state/models/mips64el/systemv/c99/string.py +139 -0
- smallworld/state/models/mips64el/systemv/c99/time.py +61 -0
- smallworld/state/models/mips64el/systemv/posix/__init__.py +6 -0
- smallworld/state/models/mips64el/systemv/posix/libgen.py +16 -0
- smallworld/state/models/mips64el/systemv/posix/signal.py +157 -0
- smallworld/state/models/mips64el/systemv/systemv.py +96 -0
- smallworld/state/models/mipsel/__init__.py +1 -0
- smallworld/state/models/mipsel/systemv/__init__.py +6 -0
- smallworld/state/models/mipsel/systemv/c99/__init__.py +12 -0
- smallworld/state/models/mipsel/systemv/c99/signal.py +16 -0
- smallworld/state/models/mipsel/systemv/c99/stdio.py +265 -0
- smallworld/state/models/mipsel/systemv/c99/stdlib.py +169 -0
- smallworld/state/models/mipsel/systemv/c99/string.py +139 -0
- smallworld/state/models/mipsel/systemv/c99/time.py +61 -0
- smallworld/state/models/mipsel/systemv/posix/__init__.py +6 -0
- smallworld/state/models/mipsel/systemv/posix/libgen.py +16 -0
- smallworld/state/models/mipsel/systemv/posix/signal.py +157 -0
- smallworld/state/models/mipsel/systemv/systemv.py +78 -0
- smallworld/state/models/model.py +27 -2
- smallworld/state/models/posix/__init__.py +6 -0
- smallworld/state/models/posix/libgen.py +123 -0
- smallworld/state/models/posix/signal.py +690 -0
- smallworld/state/models/powerpc/__init__.py +1 -0
- smallworld/state/models/powerpc/systemv/__init__.py +6 -0
- smallworld/state/models/powerpc/systemv/c99/__init__.py +12 -0
- smallworld/state/models/powerpc/systemv/c99/signal.py +16 -0
- smallworld/state/models/powerpc/systemv/c99/stdio.py +265 -0
- smallworld/state/models/powerpc/systemv/c99/stdlib.py +169 -0
- smallworld/state/models/powerpc/systemv/c99/string.py +139 -0
- smallworld/state/models/powerpc/systemv/c99/time.py +61 -0
- smallworld/state/models/powerpc/systemv/posix/__init__.py +6 -0
- smallworld/state/models/powerpc/systemv/posix/libgen.py +16 -0
- smallworld/state/models/powerpc/systemv/posix/signal.py +157 -0
- smallworld/state/models/powerpc/systemv/systemv.py +93 -0
- smallworld/state/models/riscv64/__init__.py +1 -0
- smallworld/state/models/riscv64/systemv/__init__.py +6 -0
- smallworld/state/models/riscv64/systemv/c99/__init__.py +12 -0
- smallworld/state/models/riscv64/systemv/c99/signal.py +16 -0
- smallworld/state/models/riscv64/systemv/c99/stdio.py +265 -0
- smallworld/state/models/riscv64/systemv/c99/stdlib.py +169 -0
- smallworld/state/models/riscv64/systemv/c99/string.py +139 -0
- smallworld/state/models/riscv64/systemv/c99/time.py +61 -0
- smallworld/state/models/riscv64/systemv/posix/__init__.py +6 -0
- smallworld/state/models/riscv64/systemv/posix/libgen.py +16 -0
- smallworld/state/models/riscv64/systemv/posix/signal.py +157 -0
- smallworld/state/models/riscv64/systemv/systemv.py +85 -0
- smallworld/state/state.py +65 -24
- smallworld/state/unstable/elf.py +16 -31
- smallworld/utils.py +6 -1
- {smallworld_re-1.0.3.dist-info → smallworld_re-2.0.0.dist-info}/METADATA +74 -42
- smallworld_re-2.0.0.dist-info/RECORD +374 -0
- {smallworld_re-1.0.3.dist-info → smallworld_re-2.0.0.dist-info}/WHEEL +1 -1
- smallworld/state/models/x86/__init__.py +0 -2
- smallworld/state/models/x86/microsoftcdecl.py +0 -35
- smallworld/state/models/x86/systemv.py +0 -240
- smallworld_re-1.0.3.dist-info/RECORD +0 -166
- /smallworld/state/models/{posix.py → _posix.py} +0 -0
- {smallworld_re-1.0.3.dist-info → smallworld_re-2.0.0.dist-info}/entry_points.txt +0 -0
- {smallworld_re-1.0.3.dist-info → smallworld_re-2.0.0.dist-info}/licenses/LICENSE.txt +0 -0
- {smallworld_re-1.0.3.dist-info → smallworld_re-2.0.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,361 @@
|
|
1
|
+
import typing
|
2
|
+
|
3
|
+
import lief
|
4
|
+
|
5
|
+
from ....exceptions import ConfigurationError
|
6
|
+
from ....platforms import Architecture, Byteorder, Platform, PlatformDef
|
7
|
+
from ....utils import RangeCollection
|
8
|
+
from ...state import BytesValue
|
9
|
+
from ..code import Executable
|
10
|
+
from .structs import PEExport, PEImport
|
11
|
+
|
12
|
+
# PE32+ machine types
|
13
|
+
# There are a lot more of these, but I can only test on amd64 and i386
|
14
|
+
IMAGE_FILE_MACHINE_AMD64 = 0x8664
|
15
|
+
IMAGE_FILE_MACHINE_I386 = 0x14C
|
16
|
+
|
17
|
+
# Section flags
|
18
|
+
# Currently, the only one we care about is "code".
|
19
|
+
# Not sure how the others interact with file loading.
|
20
|
+
IMAGE_SCN_CNT_CODE = 0x20
|
21
|
+
|
22
|
+
# Relocation types
|
23
|
+
# All of these adjust based on the difference between
|
24
|
+
# the requested and actual load addresses
|
25
|
+
IMAGE_REL_BASED_ABSOLUTE = 0x0 # No-op
|
26
|
+
IMAGE_REL_BASED_HIGHLOW = 0x3 # Add 32-bit difference to a 32-bit value
|
27
|
+
IMAGE_REL_BASED_DIR64 = 0xA # Add 64-bit difference to a 64-bit value
|
28
|
+
|
29
|
+
|
30
|
+
class PEExecutable(Executable):
|
31
|
+
"""Executable loaded from a PE32+
|
32
|
+
|
33
|
+
This loads a single PE32+ file into a SmallWorld memory object.
|
34
|
+
It performs no relocation or initialization,
|
35
|
+
just maps the file into memory as the kernel intended.
|
36
|
+
|
37
|
+
Arguments:
|
38
|
+
file: File-like object containing the image
|
39
|
+
platform: Optional platform; used for header verification
|
40
|
+
ignore_platform: Do not try to ID or verify platform from headers
|
41
|
+
user_base: Optional user-specified base address
|
42
|
+
page_size: System page size
|
43
|
+
"""
|
44
|
+
|
45
|
+
def __init__(
|
46
|
+
self,
|
47
|
+
file: typing.BinaryIO,
|
48
|
+
platform: typing.Optional[Platform] = None,
|
49
|
+
ignore_platform: bool = False,
|
50
|
+
user_base: typing.Optional[int] = None,
|
51
|
+
page_size: int = 0x1000,
|
52
|
+
):
|
53
|
+
# Initialize with null address and size;
|
54
|
+
# we will update these later
|
55
|
+
super().__init__(0, 0)
|
56
|
+
|
57
|
+
self.platform = platform
|
58
|
+
self.platdef: typing.Optional[PlatformDef] = None
|
59
|
+
self.bounds: RangeCollection = RangeCollection()
|
60
|
+
|
61
|
+
self._page_size = page_size
|
62
|
+
self._user_base = user_base
|
63
|
+
self._file_base = 0
|
64
|
+
|
65
|
+
self._exports: typing.List[PEExport] = list()
|
66
|
+
self._exports_by_name: typing.Dict[typing.Tuple[str, str], PEExport] = dict()
|
67
|
+
self._exports_by_ordinal: typing.Dict[typing.Tuple[str, int], PEExport] = dict()
|
68
|
+
|
69
|
+
self._imports: typing.List[PEImport] = list()
|
70
|
+
self._imports_by_name: typing.Dict[typing.Tuple[str, str], PEImport] = dict()
|
71
|
+
self._imports_by_ordinal: typing.Dict[typing.Tuple[str, int], PEImport] = dict()
|
72
|
+
|
73
|
+
# Read the entire image out of the file
|
74
|
+
image = file.read()
|
75
|
+
|
76
|
+
# Use lief to check if this is a PE
|
77
|
+
# NOTE: For some reason, this takes list(int), not bytes
|
78
|
+
if not lief.is_pe(list(image)):
|
79
|
+
raise ConfigurationError("Image is not a PE")
|
80
|
+
|
81
|
+
# Use lief to parse the PE
|
82
|
+
# NOTE: For some reason, this takes list(int), not bytes
|
83
|
+
# NOTE: lief objects aren't deep-copyable.
|
84
|
+
# I'd love to keep `pe` around for later use, but I can't.
|
85
|
+
pe = lief.PE.parse(list(image))
|
86
|
+
if pe is None:
|
87
|
+
raise ConfigurationError("Failed parsing PE image")
|
88
|
+
|
89
|
+
# Check machine compatibility
|
90
|
+
if not ignore_platform:
|
91
|
+
hdr_platform = self._platform_for_chdr(pe)
|
92
|
+
if self.platform is not None:
|
93
|
+
if self.platform != hdr_platform:
|
94
|
+
raise ConfigurationError(
|
95
|
+
"Platform mismatch: "
|
96
|
+
f"specified {self.platform}, but got {hdr_platform} from header"
|
97
|
+
)
|
98
|
+
else:
|
99
|
+
self.platform = hdr_platform
|
100
|
+
self.platdef = PlatformDef.for_platform(hdr_platform)
|
101
|
+
|
102
|
+
# Determine the file base address
|
103
|
+
self._file_base = pe.imagebase
|
104
|
+
self._determine_base()
|
105
|
+
|
106
|
+
for section in pe.sections:
|
107
|
+
# TODO: How do PE32+ files distinguish loadable segments?
|
108
|
+
# mingw objdump has some notion of allocated segments,
|
109
|
+
# but it doesn't map to anything in any of the flags.
|
110
|
+
self._map_section(section, image)
|
111
|
+
|
112
|
+
# Fix up the memory image to account for changes in the base address
|
113
|
+
self._apply_base_relocations(pe)
|
114
|
+
|
115
|
+
# Compute the final total capacity
|
116
|
+
for offset, value in self.items():
|
117
|
+
self.size = max(self.size, offset + value.get_size())
|
118
|
+
|
119
|
+
# Extract exports
|
120
|
+
self._extract_exports(pe)
|
121
|
+
|
122
|
+
# Extract imports
|
123
|
+
self._extract_imports(pe)
|
124
|
+
|
125
|
+
def _platform_for_chdr(self, pe):
|
126
|
+
if pe.header.machine.value == IMAGE_FILE_MACHINE_AMD64:
|
127
|
+
return Platform(Architecture.X86_64, Byteorder.LITTLE)
|
128
|
+
elif pe.header.machine.value == IMAGE_FILE_MACHINE_I386:
|
129
|
+
return Platform(Architecture.X86_32, Byteorder.LITTLE)
|
130
|
+
else:
|
131
|
+
raise ConfigurationError(f"Unsupported machine type {pe.header.machine}")
|
132
|
+
|
133
|
+
def _determine_base(self):
|
134
|
+
if self._user_base is None:
|
135
|
+
# No user base requested
|
136
|
+
if self._file_base == 0:
|
137
|
+
# No file base defined (unusal for PE32+)
|
138
|
+
# Need the user to provide one
|
139
|
+
raise ConfigurationError(
|
140
|
+
"No base address provided, and none defined in PE file"
|
141
|
+
)
|
142
|
+
else:
|
143
|
+
self.address = self._file_base
|
144
|
+
else:
|
145
|
+
# PE files are always position-independent;
|
146
|
+
# we'll just have to fix things up later.
|
147
|
+
self.address = self._user_base
|
148
|
+
|
149
|
+
def _rebase_file(self, val: int):
|
150
|
+
# Rebase an offset from file-relative to image-relative
|
151
|
+
res = val + self.address
|
152
|
+
return res
|
153
|
+
|
154
|
+
def _page_align(self, val: int, up: bool = True):
|
155
|
+
if up:
|
156
|
+
val += self._page_size - 1
|
157
|
+
return (val // self._page_size) * self._page_size
|
158
|
+
|
159
|
+
def _map_section(self, sect, image):
|
160
|
+
# NOTE: Unlike ELFs, The physical address of PE sections is not page-aligned.
|
161
|
+
sect_start = sect.offset
|
162
|
+
sect_end = sect.offset + sect.size
|
163
|
+
sect_addr = self._page_align(self._rebase_file(sect.virtual_address), up=False)
|
164
|
+
sect_size = self._page_align(sect.virtual_size)
|
165
|
+
|
166
|
+
sect_data = image[sect_start:sect_end]
|
167
|
+
if len(sect_data) < sect_size:
|
168
|
+
# Section is shorter than what's available in the file;
|
169
|
+
# THis will get zero-padded.
|
170
|
+
pad_size = sect_size - len(sect_data)
|
171
|
+
sect_data += b"\0" * pad_size
|
172
|
+
if len(sect_data) != sect_size:
|
173
|
+
raise ConfigurationError(
|
174
|
+
f"Expected segment of size {sect_size}, but got {len(sect_data)}"
|
175
|
+
)
|
176
|
+
|
177
|
+
if 0 != (sect.characteristics & IMAGE_SCN_CNT_CODE):
|
178
|
+
# This is a code segment; add it to program bounds
|
179
|
+
self.bounds.add_range((sect_addr, sect_addr + sect_size))
|
180
|
+
|
181
|
+
sect_value = BytesValue(sect_data, None)
|
182
|
+
self[sect_addr - self.address] = sect_value
|
183
|
+
|
184
|
+
def _apply_base_relocations(self, pe):
|
185
|
+
# PE32+ files always allow the loader to override
|
186
|
+
# the program's base address.
|
187
|
+
#
|
188
|
+
# The relocation section marks places where
|
189
|
+
# an absolute offset needs fixing
|
190
|
+
# if the loader decides to override
|
191
|
+
if self.address == self._file_base:
|
192
|
+
# This file was not relocated. Nothing to do.
|
193
|
+
return
|
194
|
+
|
195
|
+
if self.platform.byteorder == Byteorder.LITTLE:
|
196
|
+
byteorder = "little"
|
197
|
+
elif self.platform.byteorder == Byteorder.BIG:
|
198
|
+
byteorder = "big"
|
199
|
+
else:
|
200
|
+
raise ConfigurationError(
|
201
|
+
f"Can't encode byteorder {self.platform.byteorder}"
|
202
|
+
)
|
203
|
+
|
204
|
+
for base_reloc in pe.relocations:
|
205
|
+
for entry in base_reloc.entries:
|
206
|
+
if entry.type.value == IMAGE_REL_BASED_ABSOLUTE:
|
207
|
+
# Entry is a no-op; continue
|
208
|
+
continue
|
209
|
+
for off, val in self.items():
|
210
|
+
if entry.address >= off and entry.address <= val.get_size():
|
211
|
+
# Find the section containing this address
|
212
|
+
contents = bytearray(val.get_content())
|
213
|
+
fix_off = entry.address - off
|
214
|
+
|
215
|
+
if entry.type.value == IMAGE_REL_BASED_HIGHLOW:
|
216
|
+
# 4-byte repair
|
217
|
+
tofix = int.from_bytes(
|
218
|
+
contents[fix_off : fix_off + 4], byteorder
|
219
|
+
)
|
220
|
+
tofix += self.address - self._file_base
|
221
|
+
contents[fix_off : fix_off + 4] = tofix.to_bytes(
|
222
|
+
4, byteorder
|
223
|
+
)
|
224
|
+
|
225
|
+
elif entry.type.value == IMAGE_REL_BASED_DIR64:
|
226
|
+
# 8-byte repair
|
227
|
+
tofix = int.from_bytes(
|
228
|
+
contents[fix_off : fix_off + 8], byteorder
|
229
|
+
)
|
230
|
+
tofix += self.address - self._file_base
|
231
|
+
contents[fix_off : fix_off + 8] = tofix.to_bytes(
|
232
|
+
8, byteorder
|
233
|
+
)
|
234
|
+
|
235
|
+
else:
|
236
|
+
raise ConfigurationError(
|
237
|
+
"Unhandled relocation type {entry.type}"
|
238
|
+
)
|
239
|
+
# Reset the data
|
240
|
+
val.set_content(bytes(contents))
|
241
|
+
break
|
242
|
+
|
243
|
+
def _extract_exports(self, pe) -> None:
|
244
|
+
if not pe.has_exports:
|
245
|
+
return
|
246
|
+
|
247
|
+
d = pe.get_export()
|
248
|
+
for e in d.entries:
|
249
|
+
if e.is_forwarded:
|
250
|
+
raise NotImplementedError(
|
251
|
+
"{d.name}.{e.name} is forwarded to {e.forward_information}"
|
252
|
+
)
|
253
|
+
else:
|
254
|
+
exp = PEExport(
|
255
|
+
dll=d.name,
|
256
|
+
name=e.name,
|
257
|
+
ordinal=e.ordinal,
|
258
|
+
forwarder=None,
|
259
|
+
value=e.value + self.address,
|
260
|
+
)
|
261
|
+
self._exports.append(exp)
|
262
|
+
self._exports_by_name[(d.name, e.name)] = exp
|
263
|
+
self._exports_by_ordinal[(d.name, e.ordinal)] = exp
|
264
|
+
|
265
|
+
def _extract_imports(self, pe) -> None:
|
266
|
+
if not pe.has_imports:
|
267
|
+
return
|
268
|
+
|
269
|
+
# Iterate over the import directories
|
270
|
+
# These group imports by the DLL that provides them
|
271
|
+
for d in pe.imports:
|
272
|
+
for e in d.entries:
|
273
|
+
imp = PEImport(
|
274
|
+
dll=d.name,
|
275
|
+
name=e.name if not e.is_ordinal else None,
|
276
|
+
ordinal=e.ordinal if e.is_ordinal else None,
|
277
|
+
iat_address=e.iat_address + self.address,
|
278
|
+
forwarder=None,
|
279
|
+
value=None,
|
280
|
+
)
|
281
|
+
if e.name == "puts":
|
282
|
+
print(f"puts IAT at {e.iat_address:x} or {e.iat_value:x}")
|
283
|
+
self._imports.append(imp)
|
284
|
+
if e.is_ordinal:
|
285
|
+
self._imports_by_ordinal[(d.name, e.ordinal)] = imp
|
286
|
+
else:
|
287
|
+
self._imports_by_name[(d.name, e.name)] = imp
|
288
|
+
|
289
|
+
def update_import(
|
290
|
+
self, dll: str, hint: typing.Union[str, int, PEImport], value: int
|
291
|
+
) -> None:
|
292
|
+
"""Update an imported symbol in this PE file
|
293
|
+
|
294
|
+
Arguments:
|
295
|
+
dll: Name of the DLL where the import is defined
|
296
|
+
hint: Symbol name or ordinal
|
297
|
+
value: New value of the symbol
|
298
|
+
"""
|
299
|
+
# No platform specified
|
300
|
+
if self.platform is None or self.platdef is None:
|
301
|
+
raise ConfigurationError("No platform specified; can't update imports")
|
302
|
+
|
303
|
+
if isinstance(hint, str):
|
304
|
+
# Look up by name
|
305
|
+
if (dll, hint) not in self._imports_by_name:
|
306
|
+
raise ConfigurationError(
|
307
|
+
f"No import for {dll}.{hint}. Try by ordinal?"
|
308
|
+
)
|
309
|
+
imp = self._imports_by_name[(dll, hint)]
|
310
|
+
elif isinstance(hint, int):
|
311
|
+
# Look up by ordinal
|
312
|
+
if (dll, hint) not in self._imports_by_ordinal:
|
313
|
+
raise ConfigurationError(f"No import for {dll}.#{hint}. Try by name?")
|
314
|
+
imp = self._imports_by_ordinal[(dll, hint)]
|
315
|
+
elif isinstance(hint, PEImport):
|
316
|
+
imp = hint
|
317
|
+
else:
|
318
|
+
raise TypeError(f"Unexpected hint {hint} of type {type(hint)}")
|
319
|
+
|
320
|
+
# Save the new value to the import
|
321
|
+
# This marks it as initialized
|
322
|
+
imp.value = value
|
323
|
+
|
324
|
+
# Convert value to bytes
|
325
|
+
if self.platform.byteorder == Byteorder.LITTLE:
|
326
|
+
value_bytes = value.to_bytes(self.platdef.address_size, "little")
|
327
|
+
elif self.platform.byteorder == Byteorder.BIG:
|
328
|
+
value_bytes = value.to_bytes(self.platdef.address_size, "big")
|
329
|
+
else:
|
330
|
+
raise ConfigurationError(
|
331
|
+
f"Can't encode int for byteorder {self.platform.byteorder}"
|
332
|
+
)
|
333
|
+
|
334
|
+
# Rewrite IAT slot
|
335
|
+
# NOTE: PE files can have overlapping segments; check all of them.
|
336
|
+
for off, seg in self.items():
|
337
|
+
start = off + self.address
|
338
|
+
stop = start + seg.get_size()
|
339
|
+
if imp.iat_address >= start and imp.iat_address < stop:
|
340
|
+
start = imp.iat_address - start
|
341
|
+
end = start + len(value_bytes)
|
342
|
+
contents = seg.get_content()
|
343
|
+
contents = contents[0:start] + value_bytes + contents[end:]
|
344
|
+
seg.set_content(contents)
|
345
|
+
|
346
|
+
def link_pe(self, dll: "PEExecutable"):
|
347
|
+
for imp in self._imports:
|
348
|
+
if imp.value is not None:
|
349
|
+
continue
|
350
|
+
|
351
|
+
if imp.name is not None and (imp.dll, imp.name) in dll._exports_by_name:
|
352
|
+
exp = dll._exports_by_name[(imp.dll, imp.name)]
|
353
|
+
elif (
|
354
|
+
imp.ordinal is not None
|
355
|
+
and (imp.dll, imp.ordinal) in dll._exports_by_ordinal
|
356
|
+
):
|
357
|
+
exp = dll._exports_by_ordinal[(imp.dll, imp.ordinal)]
|
358
|
+
else:
|
359
|
+
continue
|
360
|
+
|
361
|
+
self.update_import(imp.dll, imp, exp.value)
|
@@ -0,0 +1,60 @@
|
|
1
|
+
import typing
|
2
|
+
from dataclasses import dataclass
|
3
|
+
|
4
|
+
|
5
|
+
@dataclass(frozen=False)
|
6
|
+
class PEExport:
|
7
|
+
"""PE export struct
|
8
|
+
|
9
|
+
Lief parses this data, but I can't keep the objects around.
|
10
|
+
|
11
|
+
An export defines a symbol that can be imported by other images.
|
12
|
+
See 'PEImport' for more on that process.
|
13
|
+
|
14
|
+
This is a mashup of a number of PE32+ structs
|
15
|
+
(export definitions are actually somewhat complicated
|
16
|
+
compared to import definitions).
|
17
|
+
|
18
|
+
Exports can be referenced by name or by ordinal - a numeric key
|
19
|
+
specific to the DLL.
|
20
|
+
|
21
|
+
Exports can provide an actual address, or a "forwarder".
|
22
|
+
This is the name of another export in another DLL that
|
23
|
+
will provide the actual value of the symbol... or possibly forward again.
|
24
|
+
"""
|
25
|
+
|
26
|
+
dll: str
|
27
|
+
ordinal: int
|
28
|
+
name: str
|
29
|
+
forwarder: typing.Optional[str]
|
30
|
+
value: int
|
31
|
+
|
32
|
+
|
33
|
+
@dataclass(frozen=False)
|
34
|
+
class PEImport:
|
35
|
+
"""PE import struct
|
36
|
+
|
37
|
+
Lief parses this data, but I can't keep the objects around.
|
38
|
+
|
39
|
+
An import defines that a specific exported symbol
|
40
|
+
is required from a specific DLL file.
|
41
|
+
|
42
|
+
They are closer to a relocation entry than a symbol;
|
43
|
+
each import defines the export required, and where
|
44
|
+
to write the exported value. There is exactly one
|
45
|
+
relocation mechanism, making this a lot easier to parse than ELF.
|
46
|
+
|
47
|
+
This class actually mashes up two PE32+ structures:
|
48
|
+
an Import Directory Entry, which defines a DLL that the file needs,
|
49
|
+
and an Import Lookup Entry, which defines a specific export it needs.
|
50
|
+
|
51
|
+
Lookup requires two keys, either the DLL name and export name,
|
52
|
+
or the DLL and export ordinal - a numeric key specified wihtin the DLL.
|
53
|
+
"""
|
54
|
+
|
55
|
+
dll: str # Name of the DLL
|
56
|
+
name: typing.Optional[str] # String name of the export
|
57
|
+
ordinal: typing.Optional[int] # Ordinal of the export
|
58
|
+
iat_address: int # Address of the IAT slot for this import
|
59
|
+
forwarder: typing.Optional[str] # Forwarder export, if provided
|
60
|
+
value: typing.Optional[int] # Value imported
|
@@ -2,6 +2,7 @@ from .aarch64 import AArch64Stack
|
|
2
2
|
from .amd64 import AMD64Stack
|
3
3
|
from .arm import ARMv5tStack, ARMv6mStack, ARMv7aStack, ARMv7mStack, ARMv7rStack
|
4
4
|
from .i386 import X86Stack
|
5
|
+
from .loongarch import LoongArch64Stack
|
5
6
|
from .mips import MIPSBEStack, MIPSELStack
|
6
7
|
from .mips64 import MIPS64BEStack, MIPS64ELStack
|
7
8
|
from .ppc import PowerPC32Stack, PowerPC64Stack
|
@@ -19,6 +20,7 @@ __all__ = __stack__ + [
|
|
19
20
|
"ARMv7rStack",
|
20
21
|
"ARMv7aStack",
|
21
22
|
"X86Stack",
|
23
|
+
"LoongArch64Stack",
|
22
24
|
"MIPSBEStack",
|
23
25
|
"MIPSELStack",
|
24
26
|
"MIPS64BEStack",
|
@@ -0,0 +1,26 @@
|
|
1
|
+
import typing
|
2
|
+
|
3
|
+
from .... import platforms
|
4
|
+
from . import stack
|
5
|
+
|
6
|
+
|
7
|
+
class LoongArchStack(stack.DescendingStack):
|
8
|
+
"""A stack for a LoongArch CPU"""
|
9
|
+
|
10
|
+
def get_pointer(self) -> int:
|
11
|
+
return (self.address + self.size) - self.get_used()
|
12
|
+
|
13
|
+
def get_alignment(self) -> int:
|
14
|
+
return 4
|
15
|
+
|
16
|
+
@classmethod
|
17
|
+
def initialize_stack(cls, argv: typing.List[bytes], *args, **kwargs):
|
18
|
+
raise NotImplementedError("Stack initialization not implemented for MIPS64")
|
19
|
+
|
20
|
+
|
21
|
+
class LoongArch64Stack(LoongArchStack):
|
22
|
+
"""A stack for a LoongArch 64-bit CPU"""
|
23
|
+
|
24
|
+
platform = platforms.Platform(
|
25
|
+
platforms.Architecture.LOONGARCH64, platforms.Byteorder.LITTLE
|
26
|
+
)
|
@@ -1,6 +1,33 @@
|
|
1
|
-
from . import
|
1
|
+
from . import (
|
2
|
+
aarch64,
|
3
|
+
amd64,
|
4
|
+
armel,
|
5
|
+
armhf,
|
6
|
+
i386,
|
7
|
+
loongarch64,
|
8
|
+
mips,
|
9
|
+
mips64,
|
10
|
+
mips64el,
|
11
|
+
mipsel,
|
12
|
+
powerpc,
|
13
|
+
riscv64,
|
14
|
+
)
|
2
15
|
from .mmio import MemoryMappedModel
|
3
16
|
from .model import * # noqa: F401, F403
|
4
17
|
from .model import __all__ as __model__
|
5
18
|
|
6
|
-
__all__ = __model__ + [
|
19
|
+
__all__ = __model__ + [
|
20
|
+
"MemoryMappedModel",
|
21
|
+
"aarch64",
|
22
|
+
"amd64",
|
23
|
+
"armel",
|
24
|
+
"armhf",
|
25
|
+
"i386",
|
26
|
+
"loongarch64",
|
27
|
+
"mips",
|
28
|
+
"mipsel",
|
29
|
+
"mips64",
|
30
|
+
"mips64el",
|
31
|
+
"powerpc",
|
32
|
+
"riscv64",
|
33
|
+
]
|
@@ -0,0 +1 @@
|
|
1
|
+
from .systemv import __all__ as __sysv__ # noqa: F401
|
@@ -0,0 +1,12 @@
|
|
1
|
+
from .signal import * # noqa F401,F403
|
2
|
+
from .signal import __all__ as __signal__
|
3
|
+
from .stdio import * # noqa F401,F403
|
4
|
+
from .stdio import __all__ as __stdio__
|
5
|
+
from .stdlib import * # noqa F401,F403
|
6
|
+
from .stdlib import __all__ as __stdlib__
|
7
|
+
from .string import * # noqa F401,F403
|
8
|
+
from .string import __all__ as __string__
|
9
|
+
from .time import * # noqa F401,F403
|
10
|
+
from .time import __all__ as __time__
|
11
|
+
|
12
|
+
__all__ = __signal__ + __stdlib__ + __string__ + __stdio__ + __time__
|
@@ -0,0 +1,16 @@
|
|
1
|
+
from ....c99.signal import Raise, Signal
|
2
|
+
from ..systemv import AArch64SysVModel
|
3
|
+
|
4
|
+
|
5
|
+
class AArch64SysVRaise(Raise, AArch64SysVModel):
|
6
|
+
pass
|
7
|
+
|
8
|
+
|
9
|
+
class AArch64SysVSignal(Signal, AArch64SysVModel):
|
10
|
+
pass
|
11
|
+
|
12
|
+
|
13
|
+
__all__ = [
|
14
|
+
"AArch64SysVRaise",
|
15
|
+
"AArch64SysVSignal",
|
16
|
+
]
|