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,163 @@
1
+ import abc
2
+ import code
3
+ import logging
4
+ import pdb
5
+ import typing
6
+
7
+ from ... import emulators, exceptions, platforms, utils
8
+ from .. import state
9
+
10
+ logger = logging.getLogger(__name__)
11
+
12
+
13
+ class Hook(state.Stateful):
14
+ """Hook a particular instruction with a function.
15
+
16
+ Runs the function provided when the emulator reaches (but has not
17
+ yet executed) the instruction at a particular address.
18
+
19
+ Arguments:
20
+ address: The address of the instruction.
21
+ function: The function to run.
22
+ """
23
+
24
+ def __init__(
25
+ self, address: int, function: typing.Callable[[emulators.Emulator], None]
26
+ ):
27
+ self._address = address
28
+ self._function = function
29
+
30
+ def extract(self, emulator: emulators.Emulator) -> None:
31
+ # Hooks have no state to extract;
32
+ # Just as we assume the memory layout is the same,
33
+ # we have to assume the hook layout is the same.
34
+ pass
35
+
36
+ def apply(self, emulator: emulators.Emulator) -> None:
37
+ if not isinstance(emulator, emulators.InstructionHookable):
38
+ raise exceptions.ConfigurationError("Emulator cannot hook instructions")
39
+ emulator.hook_instruction(self._address, self._function)
40
+
41
+
42
+ class Breakpoint(Hook):
43
+
44
+ """An interactive breakpoint.
45
+
46
+ Stops execution at the specified address and opens an interactive
47
+ shell, as specified in the self.interact method.
48
+
49
+ Arguments:
50
+ address: The address of the breakpoint.
51
+
52
+ """
53
+
54
+ def __init__(self, address: int):
55
+ super().__init__(address=address, function=self.interact)
56
+
57
+ @staticmethod
58
+ @abc.abstractmethod
59
+ def interact(emulator: emulators.Emulator) -> None:
60
+ pass
61
+
62
+
63
+ class PDBBreakpoint(Breakpoint):
64
+ """A PDB interactive breakpoint."""
65
+
66
+ @staticmethod
67
+ def interact(emulator: emulators.Emulator) -> None:
68
+ pdb.set_trace()
69
+
70
+
71
+ class PythonShellBreakpoint(Breakpoint):
72
+ """A Python shell interactive breakpoint."""
73
+
74
+ @staticmethod
75
+ def interact(emulator: emulators.Emulator) -> None:
76
+ code.interact(local={"emulator": emulator})
77
+
78
+
79
+ class Model(Hook):
80
+ """A runtime function model implemented in Python.
81
+
82
+ If execution reaches the given address, call the function assigned
83
+ to self.model, instead of any code at that address in the
84
+ emulator, and return. This is most often used to model an external
85
+ function, e.g., libc `fread`. It is the responsibility of the
86
+ model to read arguments and generate reasonable return values.
87
+
88
+ Arguments:
89
+ address: The address to model.
90
+
91
+ """
92
+
93
+ def __init__(self, address: int):
94
+ super().__init__(address=address, function=self.model)
95
+
96
+ @property
97
+ @abc.abstractmethod
98
+ def name(self) -> str:
99
+ """A name for this model, e.g., fread or ioctl."""
100
+ return ""
101
+
102
+ @property
103
+ @abc.abstractmethod
104
+ def platform(self) -> platforms.Platform:
105
+ """The platform for which this model is defined."""
106
+ pass
107
+
108
+ @property
109
+ @abc.abstractmethod
110
+ def abi(self) -> platforms.ABI:
111
+ """The ABI according to which this model works."""
112
+ pass
113
+
114
+ @classmethod
115
+ def lookup(
116
+ cls, name: str, platform: platforms.Platform, abi: platforms.ABI, address: int
117
+ ):
118
+ """Instantiate a model by name, platform, and ABI.
119
+
120
+ Arguments:
121
+ name: The name of the model.
122
+ platform: The platform for which this model is defined.
123
+ abi: The ABI according to which this model works.
124
+ address: The instruction address which the model will hook.
125
+
126
+ Returns:
127
+ The fully instantiated model.
128
+ """
129
+ try:
130
+ return utils.find_subclass(
131
+ cls,
132
+ lambda x: x.name == name and x.platform == platform and x.abi == abi,
133
+ address,
134
+ )
135
+ except ValueError:
136
+ raise ValueError(f"no model for '{name}' on {platform} with ABI '{abi}'")
137
+
138
+ def apply(self, emulator: emulators.Emulator) -> None:
139
+ logger.debug(f"Hooking Model {self} {self._address:x}")
140
+ emulator.map_memory(self._address, 16)
141
+ if not isinstance(emulator, emulators.FunctionHookable):
142
+ raise exceptions.ConfigurationError("Emulator cannot hook functions")
143
+ emulator.hook_function(self._address, self._function)
144
+
145
+ @abc.abstractmethod
146
+ def model(self, emulator: emulators.Emulator) -> None:
147
+ """This is the implementation of the model for the named function.
148
+
149
+ Note that implementation will have to make use of knowledge of
150
+ the ABI to obtain arguments and return results, as well as
151
+ modeling the semantics of the modeled functions appropriately.
152
+
153
+ """
154
+ pass
155
+
156
+
157
+ __all__ = [
158
+ "Hook",
159
+ "Breakpoint",
160
+ "PDBBreakpoint",
161
+ "PythonShellBreakpoint",
162
+ "Model",
163
+ ]
@@ -0,0 +1,455 @@
1
+ import abc
2
+ import logging
3
+ import random
4
+
5
+ from ... import emulators
6
+ from .model import Model
7
+
8
+ logger = logging.getLogger(__name__)
9
+
10
+ ######################################################
11
+ # This stuff is private. Dont' add it to __all__ #
12
+ ######################################################
13
+
14
+
15
+ MAX_STRLEN = 0x10000
16
+
17
+
18
+ # obtain addr of emulator heap memory of this size
19
+ # NB: this will map new pages into emulator as needed
20
+ def _emu_alloc(emulator: emulators.Emulator, size: int) -> int:
21
+ address = 0x10000
22
+ memory_map = emulator.get_memory_map()
23
+ if len(memory_map) > 0:
24
+ address = memory_map[-1][1]
25
+ emulator.map_memory(address, size)
26
+ return address
27
+
28
+
29
+ def _emu_calloc(emulator: emulators.Emulator, size: int) -> int:
30
+ addr = _emu_alloc(emulator, size)
31
+ emulator.write_memory(addr, b"\0" * size)
32
+ return addr
33
+
34
+
35
+ def _emu_strlen_n(emulator: emulators.Emulator, addr: int, n: int) -> int:
36
+ sl = 0
37
+ while sl <= n:
38
+ b_opt = emulator.read_memory(addr + sl, 1)
39
+ if b_opt is not None:
40
+ b = b_opt[0]
41
+ if b == 0:
42
+ break
43
+ sl += 1
44
+ else:
45
+ assert b_opt is not None
46
+ return sl
47
+
48
+
49
+ def _emu_strlen(emulator: emulators.Emulator, addr: int) -> int:
50
+ return _emu_strlen_n(emulator, addr, MAX_STRLEN)
51
+
52
+
53
+ def _emu_memcpy(emulator: emulators.Emulator, dst: int, src: int, n: int) -> None:
54
+ src_bytes = emulator.read_memory(src, n)
55
+ emulator.write_memory(dst, src_bytes)
56
+
57
+
58
+ def _emu_strncpy(
59
+ emulator: emulators.Emulator, dst: int, src: int, n: int, is_strncpy: bool
60
+ ) -> None:
61
+ if n == 0:
62
+ return
63
+ if emulator.read_memory(src, 1) is None:
64
+ logger.debug("MEM not available in strncpy read @ {src:x}")
65
+ elif emulator.read_memory(dst, 1) is None:
66
+ logger.debug("MEM not available in strncpy write @ {dst:x}")
67
+ else:
68
+ # at least a byte is available at both src and dst
69
+ # find length of src (not to exceed l)
70
+ l2 = _emu_strlen_n(emulator, src, n)
71
+ l3 = min(n, l2)
72
+ if l3 > 0:
73
+ # read the src string and copy to dst
74
+ src_bytes = emulator.read_memory(src, l3)
75
+ emulator.write_memory(dst, src_bytes)
76
+ if is_strncpy and l3 < n:
77
+ # if src string is less than n bytes then, according to man page
78
+ # strncpy copies 0s to get to n bytes
79
+ emulator.write_memory(dst + l3, b"\0" * (n - l3))
80
+
81
+
82
+ def _emu_strncat(emulator: emulators.Emulator, dst: int, src: int, n: int) -> None:
83
+ if n == 0:
84
+ return
85
+ if emulator.read_memory(src, 1) is None:
86
+ logger.debug("MEM not available in strncpy read @ {src:x}")
87
+ elif emulator.read_memory(dst, 1) is None:
88
+ logger.debug("MEM not available in strncpy write @ {dst:x}")
89
+ else:
90
+ # at least a byte is available at both src and dst
91
+ ld = _emu_strlen_n(emulator, dst, MAX_STRLEN)
92
+ ls = _emu_strlen_n(emulator, src, MAX_STRLEN)
93
+ lsn = min(ls, n)
94
+ b_opt = emulator.read_memory(src, lsn)
95
+ if b_opt is not None:
96
+ src_bytes = b_opt + b"\0"
97
+ emulator.write_memory(dst + ld, src_bytes)
98
+ else:
99
+ assert b_opt is not None
100
+
101
+
102
+ ######################################################
103
+ # End private stuff #
104
+ ######################################################
105
+
106
+
107
+ class PosixModel(Model):
108
+ # Base class for POSIX models.
109
+ #
110
+ # Most POSIX ABIS use a register-based calling convention.
111
+ # Rather than tailor each model for each ABI, this base class
112
+ # lets us play madlibs with the argument and return registers.
113
+ #
114
+ # TODO: i386 and mips32 also have stack-passed arguments.
115
+
116
+ @property
117
+ @abc.abstractmethod
118
+ def argument1(self) -> str:
119
+ return ""
120
+
121
+ @property
122
+ @abc.abstractmethod
123
+ def argument2(self) -> str:
124
+ return ""
125
+
126
+ @property
127
+ @abc.abstractmethod
128
+ def argument3(self) -> str:
129
+ return ""
130
+
131
+ @property
132
+ @abc.abstractmethod
133
+ def argument4(self) -> str:
134
+ return ""
135
+
136
+ @property
137
+ @abc.abstractmethod
138
+ def argument5(self) -> str:
139
+ return ""
140
+
141
+ @property
142
+ @abc.abstractmethod
143
+ def argument6(self) -> str:
144
+ return ""
145
+
146
+ @property
147
+ @abc.abstractmethod
148
+ def return_val(self) -> str:
149
+ return ""
150
+
151
+
152
+ class BasenameModel(PosixModel):
153
+ name = "basename"
154
+
155
+ def model(self, emulator: emulators.Emulator) -> None:
156
+ # char *basename(char "path)
157
+ # returns final component (after last '/') of filename
158
+ # if path ends with '/' return a ptr to an empty string
159
+ path = emulator.read_register(self.argument1)
160
+ sl = _emu_strlen_n(emulator, path, MAX_STRLEN)
161
+ bn = None
162
+ while True:
163
+ b_opt = emulator.read_memory(path + sl, 1)
164
+ if b_opt is not None:
165
+ b = b_opt[0]
166
+ if chr(b) == "/":
167
+ bn = path + sl + 1
168
+ break
169
+ if sl == 0:
170
+ bn = path
171
+ break
172
+ sl = sl - 1
173
+ else:
174
+ assert b_opt is not None
175
+ assert not (bn is None)
176
+ emulator.write_register(self.return_val, bn)
177
+
178
+
179
+ class CallocModel(PosixModel):
180
+ name = "calloc"
181
+
182
+ def model(self, emulator: emulators.Emulator) -> None:
183
+ # void *calloc(size_t count, size_t size);
184
+ count = emulator.read_register(self.argument1)
185
+ size = emulator.read_register(self.argument2)
186
+ num_bytes = count * size
187
+ addr = _emu_calloc(emulator, num_bytes)
188
+ emulator.write_register(self.return_val, addr)
189
+
190
+
191
+ class ReturnsNothingModel(PosixModel):
192
+ def model(self, emulator: emulators.Emulator) -> None:
193
+ # so just do nothing
194
+ pass
195
+
196
+
197
+ class Returns0Model(PosixModel):
198
+ def model(self, emulator: emulators.Emulator) -> None:
199
+ # just return 0
200
+ emulator.write_register(self.return_val, 0)
201
+
202
+
203
+ class DaemonModel(Returns0Model):
204
+ name = "daemon"
205
+
206
+
207
+ class FlockModel(Returns0Model):
208
+ name = "flock"
209
+
210
+
211
+ class Getopt_longModel(PosixModel):
212
+ name = "getopt_long"
213
+
214
+ def model(self, emulator: emulators.Emulator) -> None:
215
+ # int getopt_long(int argc, char * const *argv, const char *optstring, const struct option *longopts, int *longindex);
216
+ # return -1 if no more args
217
+ emulator.write_register(self.return_val, -1)
218
+
219
+
220
+ class GetpagesizeModel(PosixModel):
221
+ name = "getpagesize"
222
+
223
+ def model(self, emulator: emulators.Emulator) -> None:
224
+ # int getpagesize(void);
225
+ emulator.write_register(self.return_val, 0x1000)
226
+
227
+
228
+ class GetppidModel(Returns0Model):
229
+ name = "getppid"
230
+
231
+
232
+ class GetsModel(PosixModel):
233
+ name = "gets"
234
+
235
+ def model(self, emulator: emulators.Emulator) -> None:
236
+ # char *gets(char *str);
237
+ s = emulator.read_register(self.argument1)
238
+ value = input()
239
+ emulator.write_memory(s, value.encode("utf-8"))
240
+ emulator.write_register(self.return_val, s)
241
+
242
+
243
+ class MallocModel(CallocModel):
244
+ name = "malloc"
245
+
246
+
247
+ class MemcpyModel(PosixModel):
248
+ name = "memcpy"
249
+
250
+ def model(self, emulator: emulators.Emulator) -> None:
251
+ # void *memcpy(void *restrict dst, const void *restrict src, size_t n);
252
+ dst = emulator.read_register(self.argument1)
253
+ src = emulator.read_register(self.argument2)
254
+ n = emulator.read_register(self.argument3)
255
+ _emu_memcpy(emulator, dst, src, n)
256
+ emulator.write_register(self.return_val, dst)
257
+
258
+
259
+ class OpenModel(PosixModel):
260
+ name = "open"
261
+
262
+ def model(self, emulator: emulators.Emulator) -> None:
263
+ # int open64(const char *pathname, int oflag,...);
264
+ # just return a fd that's not stdin/stdout/stderr
265
+ emulator.write_register(self.return_val, 3)
266
+
267
+
268
+ class Open64Model(OpenModel):
269
+ name = "open64"
270
+
271
+
272
+ class PutsModel(PosixModel):
273
+ name = "puts"
274
+
275
+ def model(self, emulator: emulators.Emulator) -> None:
276
+ # int fputs(const char *restrict s, FILE *restrict stream);
277
+ addr = emulator.read_register_content(self.argument1)
278
+ sl = _emu_strlen(emulator, addr)
279
+ b_opt = emulator.read_memory(addr, sl)
280
+ if b_opt is not None:
281
+ logger.debug(f"puts stream={self.argument2:x} s=[{b_opt!r}]")
282
+ emulator.write_register(self.return_val, 0)
283
+
284
+
285
+ class PthreadCondInitModel(Returns0Model):
286
+ name = "pthread_cond_init"
287
+
288
+
289
+ class PthreadCondSignalModel(Returns0Model):
290
+ name = "pthread_cond_signal_model"
291
+
292
+
293
+ class PthreadCondWaitModel(Returns0Model):
294
+ name = "pthread_cond_wait"
295
+
296
+
297
+ class PthreadCreateModel(Returns0Model):
298
+ name = "pthread_create"
299
+
300
+
301
+ class PthreadMutexInitModel(Returns0Model):
302
+ name = "pthread_mutex_init"
303
+
304
+
305
+ class PthreadMutexLockModel(Returns0Model):
306
+ name = "ptherad_mutex_lock"
307
+
308
+
309
+ class PthreadMutexUnlockModel(Returns0Model):
310
+ name = "pthread_mutex_unlock"
311
+
312
+
313
+ class PtraceModel(Returns0Model):
314
+ name = "ptrace"
315
+
316
+
317
+ class RandModel(PosixModel):
318
+ name = "rand"
319
+
320
+ def model(self, emulator: emulators.Emulator) -> None:
321
+ # int rand(void);
322
+ emulator.write_register(self.return_val, random.randint(0, 0x7FFFFFFF))
323
+
324
+
325
+ class RandomModel(PosixModel):
326
+ name = "random"
327
+
328
+ def model(self, emulator: emulators.Emulator) -> None:
329
+ # long random(void);
330
+ emulator.write_register(self.return_val, random.randint(0, 0xFFFFFFFF))
331
+
332
+
333
+ class SleepModel(Returns0Model):
334
+ name = "sleep"
335
+
336
+
337
+ class SrandModel(ReturnsNothingModel):
338
+ name = "srand"
339
+
340
+
341
+ class SrandomModel(ReturnsNothingModel):
342
+ name = "srandom"
343
+
344
+
345
+ class StrcatModel(PosixModel):
346
+ name = "strcat"
347
+
348
+ def model(self, emulator: emulators.Emulator) -> None:
349
+ # char *strcat(char *restrict s1, const char *restrict s2);
350
+ dst = emulator.read_register(self.argument1)
351
+ src = emulator.read_register(self.argument2)
352
+ _emu_strncat(emulator, dst, src, MAX_STRLEN)
353
+
354
+
355
+ class StrncatModel(PosixModel):
356
+ name = "strncat"
357
+
358
+ def model(self, emulator: emulators.Emulator) -> None:
359
+ # char *strncat(char *restrict s1, const char *restrict s2, size_t n);
360
+ dst = emulator.read_register(self.argument1)
361
+ src = emulator.read_register(self.argument2)
362
+ msl = emulator.read_register(self.argument3)
363
+ _emu_strncat(emulator, dst, src, msl)
364
+
365
+
366
+ class StrcpyModel(PosixModel):
367
+ name = "strcpy"
368
+
369
+ def model(self, emulator: emulators.Emulator) -> None:
370
+ # char *strcpy(char * dst, const char * src);
371
+ dst = emulator.read_register(self.argument1)
372
+ src = emulator.read_register(self.argument2)
373
+ _emu_strncpy(emulator, dst, src, MAX_STRLEN, is_strncpy=False)
374
+
375
+
376
+ class StrncpyModel(PosixModel):
377
+ name = "strncpy"
378
+
379
+ def model(self, emulator: emulators.Emulator) -> None:
380
+ # char *strncpy(char * dst, const char * src, size_t len);
381
+ dst = emulator.read_register(self.argument1)
382
+ src = emulator.read_register(self.argument2)
383
+ sl = emulator.read_register(self.argument3)
384
+ _emu_strncpy(emulator, dst, src, sl, is_strncpy=True)
385
+
386
+
387
+ class StrdupModel(PosixModel):
388
+ name = "strdup"
389
+
390
+ def model(self, emulator: emulators.Emulator) -> None:
391
+ # char *strdup(const char *s1);
392
+ src = emulator.read_register(self.argument1)
393
+ sl = _emu_strlen_n(emulator, src, MAX_STRLEN)
394
+ dst = _emu_calloc(emulator, sl)
395
+ _emu_memcpy(emulator, dst, src, sl)
396
+ emulator.write_register(self.return_val, dst)
397
+
398
+
399
+ class StrlenModel(PosixModel):
400
+ name = "strlen"
401
+
402
+ def model(self, emulator: emulators.Emulator) -> None:
403
+ # size_t strlen(const char *s)
404
+ ptr = emulator.read_register(self.argument1)
405
+ emulator.write_register(
406
+ self.return_val, _emu_strlen_n(emulator, ptr, MAX_STRLEN)
407
+ )
408
+
409
+
410
+ class StrnlenModel(PosixModel):
411
+ name = "strnlen"
412
+
413
+ def model(self, emulator: emulators.Emulator) -> None:
414
+ # size_t strnlen(const char *s, size_t maxlen);
415
+ ptr = emulator.read_register(self.argument1)
416
+ n = emulator.read_register(self.argument2)
417
+ emulator.write_register(self.return_val, _emu_strlen_n(emulator, ptr, n))
418
+
419
+
420
+ class SysconfModel(PosixModel):
421
+ name = "sysconf"
422
+
423
+ def model(self, emulator: emulators.Emulator) -> None:
424
+ # long sysconf(int name);
425
+ arg1 = emulator.read_register(self.argument1)
426
+ if arg1 == 0x54:
427
+ # this is the one case we know about so far
428
+ # it's asking for the number of cores
429
+ emulator.write_register(self.return_val, 1)
430
+
431
+
432
+ class TimeModel(PosixModel):
433
+ name = "time"
434
+
435
+ def model(self, emulator: emulators.Emulator) -> None:
436
+ # time_t time(time_t *tloc);
437
+ # just return something
438
+ emulator.write_register(self.return_val, 0x1234)
439
+
440
+
441
+ class UnlinkModel(Returns0Model):
442
+ name = "unlink"
443
+
444
+
445
+ class WriteModel(PosixModel):
446
+ name = "write"
447
+
448
+ def model(self, emulator: emulators.Emulator) -> None:
449
+ # ssize_t write(int fildes, const void *buf, size_t nbyte);
450
+ addr = emulator.read_register_content(self.argument2)
451
+ size = emulator.read_register_content(self.argument3)
452
+ b_opt = emulator.read_memory(addr, size)
453
+ if b_opt is not None:
454
+ logger.debug(f"write fd={self.argument1} buf=[{b_opt!r}]")
455
+ emulator.write_register(self.return_val, 0)
@@ -0,0 +1,2 @@
1
+ from .microsoftcdecl import __all__ as __mscdecl__ # noqa: F401
2
+ from .systemv import __all__ as __sysv__ # noqa: F401
@@ -0,0 +1,35 @@
1
+ import typing
2
+
3
+ from .... import platforms
4
+ from ..model import Model
5
+ from ..posix import GetsModel
6
+
7
+
8
+ class AMD64Win32Model(Model):
9
+ platform = platforms.Platform(
10
+ platforms.Architecture.X86_64, platforms.Byteorder.LITTLE
11
+ )
12
+ abi = platforms.ABI.CDECL
13
+
14
+ # NOTE: according to Wikipedia, win32 only allows 4 register-passed arguments.
15
+ argument1 = "rcx"
16
+ argument2 = "rdx"
17
+ argument3 = "r8"
18
+ argument4 = "r9"
19
+
20
+ @property
21
+ def argument5(self) -> str:
22
+ raise ValueError("win32 has no argument 5 register")
23
+
24
+ @property
25
+ def argument6(self) -> str:
26
+ raise ValueError("win32 has no argument 6 register")
27
+
28
+ return_val = "rax"
29
+
30
+
31
+ class AMD64MicrosoftGetsModel(AMD64Win32Model, GetsModel):
32
+ pass
33
+
34
+
35
+ __all__: typing.List[str] = []