smallworld-re 1.0.0__tar.gz
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_re-1.0.0/LICENSE.txt +21 -0
- smallworld_re-1.0.0/PKG-INFO +189 -0
- smallworld_re-1.0.0/README.md +152 -0
- smallworld_re-1.0.0/setup.cfg +4 -0
- smallworld_re-1.0.0/setup.py +35 -0
- smallworld_re-1.0.0/smallworld/__init__.py +35 -0
- smallworld_re-1.0.0/smallworld/analyses/__init__.py +14 -0
- smallworld_re-1.0.0/smallworld/analyses/analysis.py +88 -0
- smallworld_re-1.0.0/smallworld/analyses/code_coverage.py +31 -0
- smallworld_re-1.0.0/smallworld/analyses/colorizer.py +682 -0
- smallworld_re-1.0.0/smallworld/analyses/colorizer_summary.py +100 -0
- smallworld_re-1.0.0/smallworld/analyses/field_detection/__init__.py +14 -0
- smallworld_re-1.0.0/smallworld/analyses/field_detection/field_analysis.py +536 -0
- smallworld_re-1.0.0/smallworld/analyses/field_detection/guards.py +26 -0
- smallworld_re-1.0.0/smallworld/analyses/field_detection/hints.py +133 -0
- smallworld_re-1.0.0/smallworld/analyses/field_detection/malloc.py +211 -0
- smallworld_re-1.0.0/smallworld/analyses/forced_exec/__init__.py +3 -0
- smallworld_re-1.0.0/smallworld/analyses/forced_exec/forced_exec.py +87 -0
- smallworld_re-1.0.0/smallworld/analyses/underlays/__init__.py +4 -0
- smallworld_re-1.0.0/smallworld/analyses/underlays/basic.py +13 -0
- smallworld_re-1.0.0/smallworld/analyses/underlays/underlay.py +31 -0
- smallworld_re-1.0.0/smallworld/analyses/unstable/__init__.py +4 -0
- smallworld_re-1.0.0/smallworld/analyses/unstable/angr/__init__.py +0 -0
- smallworld_re-1.0.0/smallworld/analyses/unstable/angr/base.py +12 -0
- smallworld_re-1.0.0/smallworld/analyses/unstable/angr/divergence.py +274 -0
- smallworld_re-1.0.0/smallworld/analyses/unstable/angr/model.py +383 -0
- smallworld_re-1.0.0/smallworld/analyses/unstable/angr/nwbt.py +63 -0
- smallworld_re-1.0.0/smallworld/analyses/unstable/angr/typedefs.py +170 -0
- smallworld_re-1.0.0/smallworld/analyses/unstable/angr/utils.py +25 -0
- smallworld_re-1.0.0/smallworld/analyses/unstable/angr/visitor.py +315 -0
- smallworld_re-1.0.0/smallworld/analyses/unstable/angr_nwbt.py +106 -0
- smallworld_re-1.0.0/smallworld/analyses/unstable/code_coverage.py +54 -0
- smallworld_re-1.0.0/smallworld/analyses/unstable/code_reachable.py +44 -0
- smallworld_re-1.0.0/smallworld/analyses/unstable/control_flow_tracer.py +71 -0
- smallworld_re-1.0.0/smallworld/analyses/unstable/pointer_finder.py +90 -0
- smallworld_re-1.0.0/smallworld/arch/__init__.py +0 -0
- smallworld_re-1.0.0/smallworld/arch/aarch64_arch.py +286 -0
- smallworld_re-1.0.0/smallworld/arch/amd64_arch.py +86 -0
- smallworld_re-1.0.0/smallworld/arch/i386_arch.py +44 -0
- smallworld_re-1.0.0/smallworld/emulators/__init__.py +14 -0
- smallworld_re-1.0.0/smallworld/emulators/angr/__init__.py +7 -0
- smallworld_re-1.0.0/smallworld/emulators/angr/angr.py +1652 -0
- smallworld_re-1.0.0/smallworld/emulators/angr/default.py +15 -0
- smallworld_re-1.0.0/smallworld/emulators/angr/exceptions.py +7 -0
- smallworld_re-1.0.0/smallworld/emulators/angr/exploration/__init__.py +9 -0
- smallworld_re-1.0.0/smallworld/emulators/angr/exploration/bounds.py +27 -0
- smallworld_re-1.0.0/smallworld/emulators/angr/exploration/default.py +17 -0
- smallworld_re-1.0.0/smallworld/emulators/angr/exploration/terminate.py +22 -0
- smallworld_re-1.0.0/smallworld/emulators/angr/factory.py +55 -0
- smallworld_re-1.0.0/smallworld/emulators/angr/machdefs/__init__.py +35 -0
- smallworld_re-1.0.0/smallworld/emulators/angr/machdefs/aarch64.py +292 -0
- smallworld_re-1.0.0/smallworld/emulators/angr/machdefs/amd64.py +192 -0
- smallworld_re-1.0.0/smallworld/emulators/angr/machdefs/arm.py +387 -0
- smallworld_re-1.0.0/smallworld/emulators/angr/machdefs/i386.py +221 -0
- smallworld_re-1.0.0/smallworld/emulators/angr/machdefs/machdef.py +138 -0
- smallworld_re-1.0.0/smallworld/emulators/angr/machdefs/mips.py +184 -0
- smallworld_re-1.0.0/smallworld/emulators/angr/machdefs/mips64.py +189 -0
- smallworld_re-1.0.0/smallworld/emulators/angr/machdefs/ppc.py +101 -0
- smallworld_re-1.0.0/smallworld/emulators/angr/machdefs/riscv.py +261 -0
- smallworld_re-1.0.0/smallworld/emulators/angr/machdefs/xtensa.py +255 -0
- smallworld_re-1.0.0/smallworld/emulators/angr/memory/__init__.py +7 -0
- smallworld_re-1.0.0/smallworld/emulators/angr/memory/default.py +10 -0
- smallworld_re-1.0.0/smallworld/emulators/angr/memory/fixups.py +43 -0
- smallworld_re-1.0.0/smallworld/emulators/angr/memory/memtrack.py +105 -0
- smallworld_re-1.0.0/smallworld/emulators/angr/scratch.py +43 -0
- smallworld_re-1.0.0/smallworld/emulators/angr/simos.py +53 -0
- smallworld_re-1.0.0/smallworld/emulators/angr/utils.py +70 -0
- smallworld_re-1.0.0/smallworld/emulators/emulator.py +1013 -0
- smallworld_re-1.0.0/smallworld/emulators/hookable.py +252 -0
- smallworld_re-1.0.0/smallworld/emulators/panda/__init__.py +5 -0
- smallworld_re-1.0.0/smallworld/emulators/panda/machdefs/__init__.py +28 -0
- smallworld_re-1.0.0/smallworld/emulators/panda/machdefs/aarch64.py +93 -0
- smallworld_re-1.0.0/smallworld/emulators/panda/machdefs/amd64.py +71 -0
- smallworld_re-1.0.0/smallworld/emulators/panda/machdefs/arm.py +89 -0
- smallworld_re-1.0.0/smallworld/emulators/panda/machdefs/i386.py +36 -0
- smallworld_re-1.0.0/smallworld/emulators/panda/machdefs/machdef.py +86 -0
- smallworld_re-1.0.0/smallworld/emulators/panda/machdefs/mips.py +94 -0
- smallworld_re-1.0.0/smallworld/emulators/panda/machdefs/mips64.py +91 -0
- smallworld_re-1.0.0/smallworld/emulators/panda/machdefs/ppc.py +79 -0
- smallworld_re-1.0.0/smallworld/emulators/panda/panda.py +575 -0
- smallworld_re-1.0.0/smallworld/emulators/unicorn/__init__.py +13 -0
- smallworld_re-1.0.0/smallworld/emulators/unicorn/machdefs/__init__.py +28 -0
- smallworld_re-1.0.0/smallworld/emulators/unicorn/machdefs/aarch64.py +310 -0
- smallworld_re-1.0.0/smallworld/emulators/unicorn/machdefs/amd64.py +326 -0
- smallworld_re-1.0.0/smallworld/emulators/unicorn/machdefs/arm.py +321 -0
- smallworld_re-1.0.0/smallworld/emulators/unicorn/machdefs/i386.py +137 -0
- smallworld_re-1.0.0/smallworld/emulators/unicorn/machdefs/machdef.py +117 -0
- smallworld_re-1.0.0/smallworld/emulators/unicorn/machdefs/mips.py +202 -0
- smallworld_re-1.0.0/smallworld/emulators/unicorn/unicorn.py +684 -0
- smallworld_re-1.0.0/smallworld/exceptions/__init__.py +5 -0
- smallworld_re-1.0.0/smallworld/exceptions/exceptions.py +85 -0
- smallworld_re-1.0.0/smallworld/exceptions/unstable/__init__.py +1 -0
- smallworld_re-1.0.0/smallworld/exceptions/unstable/exceptions.py +25 -0
- smallworld_re-1.0.0/smallworld/extern/__init__.py +4 -0
- smallworld_re-1.0.0/smallworld/extern/ctypes.py +94 -0
- smallworld_re-1.0.0/smallworld/extern/unstable/__init__.py +1 -0
- smallworld_re-1.0.0/smallworld/extern/unstable/ghidra.py +129 -0
- smallworld_re-1.0.0/smallworld/helpers.py +107 -0
- smallworld_re-1.0.0/smallworld/hinting/__init__.py +8 -0
- smallworld_re-1.0.0/smallworld/hinting/hinting.py +214 -0
- smallworld_re-1.0.0/smallworld/hinting/hints.py +427 -0
- smallworld_re-1.0.0/smallworld/hinting/unstable/__init__.py +2 -0
- smallworld_re-1.0.0/smallworld/hinting/utils.py +19 -0
- smallworld_re-1.0.0/smallworld/instructions/__init__.py +18 -0
- smallworld_re-1.0.0/smallworld/instructions/aarch64.py +20 -0
- smallworld_re-1.0.0/smallworld/instructions/arm.py +18 -0
- smallworld_re-1.0.0/smallworld/instructions/bsid.py +67 -0
- smallworld_re-1.0.0/smallworld/instructions/instructions.py +258 -0
- smallworld_re-1.0.0/smallworld/instructions/mips.py +21 -0
- smallworld_re-1.0.0/smallworld/instructions/x86.py +100 -0
- smallworld_re-1.0.0/smallworld/logging.py +90 -0
- smallworld_re-1.0.0/smallworld/platforms.py +95 -0
- smallworld_re-1.0.0/smallworld/py.typed +0 -0
- smallworld_re-1.0.0/smallworld/state/__init__.py +6 -0
- smallworld_re-1.0.0/smallworld/state/cpus/__init__.py +32 -0
- smallworld_re-1.0.0/smallworld/state/cpus/aarch64.py +563 -0
- smallworld_re-1.0.0/smallworld/state/cpus/amd64.py +676 -0
- smallworld_re-1.0.0/smallworld/state/cpus/arm.py +630 -0
- smallworld_re-1.0.0/smallworld/state/cpus/cpu.py +71 -0
- smallworld_re-1.0.0/smallworld/state/cpus/i386.py +239 -0
- smallworld_re-1.0.0/smallworld/state/cpus/mips.py +374 -0
- smallworld_re-1.0.0/smallworld/state/cpus/mips64.py +372 -0
- smallworld_re-1.0.0/smallworld/state/cpus/powerpc.py +229 -0
- smallworld_re-1.0.0/smallworld/state/cpus/riscv.py +357 -0
- smallworld_re-1.0.0/smallworld/state/cpus/xtensa.py +80 -0
- smallworld_re-1.0.0/smallworld/state/memory/__init__.py +7 -0
- smallworld_re-1.0.0/smallworld/state/memory/code.py +70 -0
- smallworld_re-1.0.0/smallworld/state/memory/elf/__init__.py +3 -0
- smallworld_re-1.0.0/smallworld/state/memory/elf/elf.py +564 -0
- smallworld_re-1.0.0/smallworld/state/memory/elf/rela/__init__.py +32 -0
- smallworld_re-1.0.0/smallworld/state/memory/elf/rela/aarch64.py +27 -0
- smallworld_re-1.0.0/smallworld/state/memory/elf/rela/amd64.py +32 -0
- smallworld_re-1.0.0/smallworld/state/memory/elf/rela/arm.py +51 -0
- smallworld_re-1.0.0/smallworld/state/memory/elf/rela/i386.py +32 -0
- smallworld_re-1.0.0/smallworld/state/memory/elf/rela/mips.py +45 -0
- smallworld_re-1.0.0/smallworld/state/memory/elf/rela/ppc.py +45 -0
- smallworld_re-1.0.0/smallworld/state/memory/elf/rela/rela.py +63 -0
- smallworld_re-1.0.0/smallworld/state/memory/elf/rela/riscv64.py +27 -0
- smallworld_re-1.0.0/smallworld/state/memory/elf/rela/xtensa.py +15 -0
- smallworld_re-1.0.0/smallworld/state/memory/elf/structs.py +55 -0
- smallworld_re-1.0.0/smallworld/state/memory/heap.py +85 -0
- smallworld_re-1.0.0/smallworld/state/memory/memory.py +181 -0
- smallworld_re-1.0.0/smallworld/state/memory/stack/__init__.py +31 -0
- smallworld_re-1.0.0/smallworld/state/memory/stack/aarch64.py +22 -0
- smallworld_re-1.0.0/smallworld/state/memory/stack/amd64.py +42 -0
- smallworld_re-1.0.0/smallworld/state/memory/stack/arm.py +66 -0
- smallworld_re-1.0.0/smallworld/state/memory/stack/i386.py +22 -0
- smallworld_re-1.0.0/smallworld/state/memory/stack/mips.py +34 -0
- smallworld_re-1.0.0/smallworld/state/memory/stack/mips64.py +34 -0
- smallworld_re-1.0.0/smallworld/state/memory/stack/ppc.py +34 -0
- smallworld_re-1.0.0/smallworld/state/memory/stack/riscv.py +22 -0
- smallworld_re-1.0.0/smallworld/state/memory/stack/stack.py +127 -0
- smallworld_re-1.0.0/smallworld/state/memory/stack/xtensa.py +34 -0
- smallworld_re-1.0.0/smallworld/state/models/__init__.py +6 -0
- smallworld_re-1.0.0/smallworld/state/models/mmio.py +186 -0
- smallworld_re-1.0.0/smallworld/state/models/model.py +163 -0
- smallworld_re-1.0.0/smallworld/state/models/posix.py +455 -0
- smallworld_re-1.0.0/smallworld/state/models/x86/__init__.py +2 -0
- smallworld_re-1.0.0/smallworld/state/models/x86/microsoftcdecl.py +35 -0
- smallworld_re-1.0.0/smallworld/state/models/x86/systemv.py +240 -0
- smallworld_re-1.0.0/smallworld/state/state.py +962 -0
- smallworld_re-1.0.0/smallworld/state/unstable/__init__.py +0 -0
- smallworld_re-1.0.0/smallworld/state/unstable/elf.py +393 -0
- smallworld_re-1.0.0/smallworld/state/x86_registers.py +30 -0
- smallworld_re-1.0.0/smallworld/utils.py +935 -0
- smallworld_re-1.0.0/smallworld_re.egg-info/PKG-INFO +189 -0
- smallworld_re-1.0.0/smallworld_re.egg-info/SOURCES.txt +170 -0
- smallworld_re-1.0.0/smallworld_re.egg-info/dependency_links.txt +1 -0
- smallworld_re-1.0.0/smallworld_re.egg-info/entry_points.txt +2 -0
- smallworld_re-1.0.0/smallworld_re.egg-info/not-zip-safe +1 -0
- smallworld_re-1.0.0/smallworld_re.egg-info/requires.txt +16 -0
- smallworld_re-1.0.0/smallworld_re.egg-info/top_level.txt +1 -0
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
© 2023 Massachusetts Institute of Technology
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
7
|
+
the Software without restriction, including without limitation the rights to
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
9
|
+
of the Software, and to permit persons to whom the Software is furnished to do
|
10
|
+
so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
@@ -0,0 +1,189 @@
|
|
1
|
+
Metadata-Version: 2.2
|
2
|
+
Name: smallworld-re
|
3
|
+
Version: 1.0.0
|
4
|
+
Summary: An emulation stack tracking library
|
5
|
+
Home-page: https://github.com/smallworld-re/smallworld
|
6
|
+
Author: MIT Lincoln Laboratory
|
7
|
+
Author-email: smallworld@ll.mit.edu
|
8
|
+
License: MIT
|
9
|
+
Requires-Python: >=3.8
|
10
|
+
Description-Content-Type: text/markdown
|
11
|
+
License-File: LICENSE.txt
|
12
|
+
Requires-Dist: unicorn
|
13
|
+
Requires-Dist: angr
|
14
|
+
Requires-Dist: capstone
|
15
|
+
Requires-Dist: lief
|
16
|
+
Requires-Dist: pyhidra
|
17
|
+
Requires-Dist: pypcode
|
18
|
+
Provides-Extra: development
|
19
|
+
Requires-Dist: black; extra == "development"
|
20
|
+
Requires-Dist: isort; extra == "development"
|
21
|
+
Requires-Dist: flake8; extra == "development"
|
22
|
+
Requires-Dist: mypy; extra == "development"
|
23
|
+
Requires-Dist: pip-tools; extra == "development"
|
24
|
+
Requires-Dist: pre-commit; extra == "development"
|
25
|
+
Requires-Dist: sphinx; extra == "development"
|
26
|
+
Requires-Dist: sphinxcontrib-programoutput; extra == "development"
|
27
|
+
Dynamic: author
|
28
|
+
Dynamic: author-email
|
29
|
+
Dynamic: description
|
30
|
+
Dynamic: description-content-type
|
31
|
+
Dynamic: home-page
|
32
|
+
Dynamic: license
|
33
|
+
Dynamic: provides-extra
|
34
|
+
Dynamic: requires-dist
|
35
|
+
Dynamic: requires-python
|
36
|
+
Dynamic: summary
|
37
|
+
|
38
|
+
# SmallWorld
|
39
|
+
|
40
|
+
[![commit-style-image]][conventional]
|
41
|
+
[![code-style-image]][black]
|
42
|
+
[![license-image]][mit]
|
43
|
+
|
44
|
+
Easier harnessing of code for analysis!
|
45
|
+
|
46
|
+
## Description
|
47
|
+
|
48
|
+
SmallWorld is an environment for streamlined harnessing of binary code for the
|
49
|
+
purpose of dynamic analysis. If you have code that you got from somewhere and
|
50
|
+
you'd like to run it and analyze those runs to understand what that code does
|
51
|
+
or if it has bugs, then you should try SmallWorld!!
|
52
|
+
|
53
|
+
There are two fundamental tenets behind SmallWorld
|
54
|
+
* Harnessing should be easier
|
55
|
+
* Analysis can accelerate harnessing
|
56
|
+
|
57
|
+
The first of these tenets we hope to support with good software APIs. As a very
|
58
|
+
simple example, consider the harnessing script
|
59
|
+
[stack.py](https://github.com/smallworld-re/smallworld/blob/main/tests/square.py),
|
60
|
+
composed using SmallWorld, in which registers are initialized and a stack is
|
61
|
+
arranged for running the code in
|
62
|
+
[stack.s](https://github.com/smallworld-re/smallworld/blob/main/tests/stack.s).
|
63
|
+
For a more sophisticated example of SmallWorld's harnessing facitilites,
|
64
|
+
consider the code snippet
|
65
|
+
[struct.s](https://github.com/smallworld-re/smallworld/blob/main/tests/struct.s),
|
66
|
+
which assumes a stack and input pointers to a linked list with very specific
|
67
|
+
format. The harnessing script in this case is more complicated, including
|
68
|
+
specifying type information for the linked list element structures as well as
|
69
|
+
use of a simple allocator abstraction provided by SmallWorld to instantiate
|
70
|
+
nodes and link them together appropriately:
|
71
|
+
[struct.py](https://github.com/smallworld-re/smallworld/blob/main/tests/struct.py).
|
72
|
+
|
73
|
+
The second tenet we address with purpose-built analyses which leverage a
|
74
|
+
(possibly incomplete) harness script and that use techniques such as [Micro
|
75
|
+
Execution](https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/microx.pdf)
|
76
|
+
and [Symbolic
|
77
|
+
Execution](https://en.wikipedia.org/wiki/Symbolic_execution#:~:text=In%20computer%20science%2C%20symbolic%20execution,of%20a%20program%20to%20execute)
|
78
|
+
to provide hints that can guide improving a harness.
|
79
|
+
|
80
|
+
This harness is the final output of SmallWorld and might be used in fuzzing or
|
81
|
+
dynamic reverse engineering. Note that these are not applications which
|
82
|
+
SmallWorld directly supports yet.
|
83
|
+
|
84
|
+
|
85
|
+
## Installation
|
86
|
+
|
87
|
+
To install SmallWorld from this repo, run:
|
88
|
+
|
89
|
+
```bash
|
90
|
+
pip install .
|
91
|
+
```
|
92
|
+
|
93
|
+
## Usage
|
94
|
+
|
95
|
+
Print basic usage and help:
|
96
|
+
|
97
|
+
```bash
|
98
|
+
smallworld --help
|
99
|
+
```
|
100
|
+
|
101
|
+
## Contributing
|
102
|
+
|
103
|
+
Pull requests and issues more than welcome.
|
104
|
+
|
105
|
+
### Development
|
106
|
+
|
107
|
+
To set up a development environment from this repo, install SmallWorld in
|
108
|
+
editable mode with extras for development and testing. Use the include
|
109
|
+
constraints to install frozen versions and ensure a consistent development
|
110
|
+
environment.
|
111
|
+
|
112
|
+
```bash
|
113
|
+
pip install -e .[development] -c constraints.txt
|
114
|
+
```
|
115
|
+
|
116
|
+
#### Code Style
|
117
|
+
|
118
|
+
Pre-commit hooks are available for automatic code formatting, linting, and type
|
119
|
+
checking via [pre-commit](https://pre-commit.com/). To enable them (after
|
120
|
+
installing development dependencies), run:
|
121
|
+
|
122
|
+
```bash
|
123
|
+
pre-commit install
|
124
|
+
```
|
125
|
+
|
126
|
+
### Documentation
|
127
|
+
|
128
|
+
To build the full SmallWorld documentation, after installing SmallWorld with
|
129
|
+
`development` extras enabled, from the `docs/` directory, run:
|
130
|
+
|
131
|
+
```bash
|
132
|
+
make html
|
133
|
+
```
|
134
|
+
|
135
|
+
Or other [supported Sphinx output formats](https://www.sphinx-doc.org/en/master/usage/builders/index.html).
|
136
|
+
|
137
|
+
### Testing
|
138
|
+
|
139
|
+
#### Prerequisites
|
140
|
+
|
141
|
+
Building the test binaries requires some dependencies which can be installed
|
142
|
+
with:
|
143
|
+
|
144
|
+
```bash
|
145
|
+
apt-get install `cat tests/dependencies/apt.txt`
|
146
|
+
```
|
147
|
+
|
148
|
+
You can then build the tests by running:
|
149
|
+
|
150
|
+
```bash
|
151
|
+
make -C tests
|
152
|
+
```
|
153
|
+
|
154
|
+
#### Running Tests
|
155
|
+
|
156
|
+
Once the test files have been built and SmallWorld has been installed, you can
|
157
|
+
run unit and integration tests:
|
158
|
+
|
159
|
+
```bash
|
160
|
+
python3 tests/unit.py
|
161
|
+
python3 tests/integration.py
|
162
|
+
```
|
163
|
+
|
164
|
+
## Distribution
|
165
|
+
|
166
|
+
DISTRIBUTION STATEMENT A. Approved for public release. Distribution is
|
167
|
+
unlimited.
|
168
|
+
|
169
|
+
This material is based upon work supported by the Under Secretary of Defense
|
170
|
+
for Research and Engineering under Air Force Contract No. FA8702-15-D-0001. Any
|
171
|
+
opinions, findings, conclusions or recommendations expressed in this material
|
172
|
+
are those of the author(s) and do not necessarily reflect the views of the
|
173
|
+
Under Secretary of Defense for Research and Engineering.
|
174
|
+
|
175
|
+
Delivered to the U.S. Government with Unlimited Rights, as defined in DFARS
|
176
|
+
Part 252.227-7013 or 7014 (Feb 2014). Notwithstanding any copyright notice,
|
177
|
+
U.S. Government rights in this work are defined by DFARS 252.227-7013 or DFARS
|
178
|
+
252.227-7014 as detailed above. Use of this work other than as specifically
|
179
|
+
authorized by the U.S. Government may violate any copyrights that exist in this
|
180
|
+
work.
|
181
|
+
|
182
|
+
[MIT License](LICENSE.txt)
|
183
|
+
|
184
|
+
[commit-style-image]: https://img.shields.io/badge/commits-conventional-fe5196.svg
|
185
|
+
[conventional]: https://www.conventionalcommits.org/en/v1.0.0/
|
186
|
+
[code-style-image]: https://img.shields.io/badge/code%20style-black-000000.svg
|
187
|
+
[black]: https://github.com/psf/black
|
188
|
+
[license-image]: https://img.shields.io/badge/license-MIT-green.svg
|
189
|
+
[mit]: ./LICENSE.txt
|
@@ -0,0 +1,152 @@
|
|
1
|
+
# SmallWorld
|
2
|
+
|
3
|
+
[![commit-style-image]][conventional]
|
4
|
+
[![code-style-image]][black]
|
5
|
+
[![license-image]][mit]
|
6
|
+
|
7
|
+
Easier harnessing of code for analysis!
|
8
|
+
|
9
|
+
## Description
|
10
|
+
|
11
|
+
SmallWorld is an environment for streamlined harnessing of binary code for the
|
12
|
+
purpose of dynamic analysis. If you have code that you got from somewhere and
|
13
|
+
you'd like to run it and analyze those runs to understand what that code does
|
14
|
+
or if it has bugs, then you should try SmallWorld!!
|
15
|
+
|
16
|
+
There are two fundamental tenets behind SmallWorld
|
17
|
+
* Harnessing should be easier
|
18
|
+
* Analysis can accelerate harnessing
|
19
|
+
|
20
|
+
The first of these tenets we hope to support with good software APIs. As a very
|
21
|
+
simple example, consider the harnessing script
|
22
|
+
[stack.py](https://github.com/smallworld-re/smallworld/blob/main/tests/square.py),
|
23
|
+
composed using SmallWorld, in which registers are initialized and a stack is
|
24
|
+
arranged for running the code in
|
25
|
+
[stack.s](https://github.com/smallworld-re/smallworld/blob/main/tests/stack.s).
|
26
|
+
For a more sophisticated example of SmallWorld's harnessing facitilites,
|
27
|
+
consider the code snippet
|
28
|
+
[struct.s](https://github.com/smallworld-re/smallworld/blob/main/tests/struct.s),
|
29
|
+
which assumes a stack and input pointers to a linked list with very specific
|
30
|
+
format. The harnessing script in this case is more complicated, including
|
31
|
+
specifying type information for the linked list element structures as well as
|
32
|
+
use of a simple allocator abstraction provided by SmallWorld to instantiate
|
33
|
+
nodes and link them together appropriately:
|
34
|
+
[struct.py](https://github.com/smallworld-re/smallworld/blob/main/tests/struct.py).
|
35
|
+
|
36
|
+
The second tenet we address with purpose-built analyses which leverage a
|
37
|
+
(possibly incomplete) harness script and that use techniques such as [Micro
|
38
|
+
Execution](https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/microx.pdf)
|
39
|
+
and [Symbolic
|
40
|
+
Execution](https://en.wikipedia.org/wiki/Symbolic_execution#:~:text=In%20computer%20science%2C%20symbolic%20execution,of%20a%20program%20to%20execute)
|
41
|
+
to provide hints that can guide improving a harness.
|
42
|
+
|
43
|
+
This harness is the final output of SmallWorld and might be used in fuzzing or
|
44
|
+
dynamic reverse engineering. Note that these are not applications which
|
45
|
+
SmallWorld directly supports yet.
|
46
|
+
|
47
|
+
|
48
|
+
## Installation
|
49
|
+
|
50
|
+
To install SmallWorld from this repo, run:
|
51
|
+
|
52
|
+
```bash
|
53
|
+
pip install .
|
54
|
+
```
|
55
|
+
|
56
|
+
## Usage
|
57
|
+
|
58
|
+
Print basic usage and help:
|
59
|
+
|
60
|
+
```bash
|
61
|
+
smallworld --help
|
62
|
+
```
|
63
|
+
|
64
|
+
## Contributing
|
65
|
+
|
66
|
+
Pull requests and issues more than welcome.
|
67
|
+
|
68
|
+
### Development
|
69
|
+
|
70
|
+
To set up a development environment from this repo, install SmallWorld in
|
71
|
+
editable mode with extras for development and testing. Use the include
|
72
|
+
constraints to install frozen versions and ensure a consistent development
|
73
|
+
environment.
|
74
|
+
|
75
|
+
```bash
|
76
|
+
pip install -e .[development] -c constraints.txt
|
77
|
+
```
|
78
|
+
|
79
|
+
#### Code Style
|
80
|
+
|
81
|
+
Pre-commit hooks are available for automatic code formatting, linting, and type
|
82
|
+
checking via [pre-commit](https://pre-commit.com/). To enable them (after
|
83
|
+
installing development dependencies), run:
|
84
|
+
|
85
|
+
```bash
|
86
|
+
pre-commit install
|
87
|
+
```
|
88
|
+
|
89
|
+
### Documentation
|
90
|
+
|
91
|
+
To build the full SmallWorld documentation, after installing SmallWorld with
|
92
|
+
`development` extras enabled, from the `docs/` directory, run:
|
93
|
+
|
94
|
+
```bash
|
95
|
+
make html
|
96
|
+
```
|
97
|
+
|
98
|
+
Or other [supported Sphinx output formats](https://www.sphinx-doc.org/en/master/usage/builders/index.html).
|
99
|
+
|
100
|
+
### Testing
|
101
|
+
|
102
|
+
#### Prerequisites
|
103
|
+
|
104
|
+
Building the test binaries requires some dependencies which can be installed
|
105
|
+
with:
|
106
|
+
|
107
|
+
```bash
|
108
|
+
apt-get install `cat tests/dependencies/apt.txt`
|
109
|
+
```
|
110
|
+
|
111
|
+
You can then build the tests by running:
|
112
|
+
|
113
|
+
```bash
|
114
|
+
make -C tests
|
115
|
+
```
|
116
|
+
|
117
|
+
#### Running Tests
|
118
|
+
|
119
|
+
Once the test files have been built and SmallWorld has been installed, you can
|
120
|
+
run unit and integration tests:
|
121
|
+
|
122
|
+
```bash
|
123
|
+
python3 tests/unit.py
|
124
|
+
python3 tests/integration.py
|
125
|
+
```
|
126
|
+
|
127
|
+
## Distribution
|
128
|
+
|
129
|
+
DISTRIBUTION STATEMENT A. Approved for public release. Distribution is
|
130
|
+
unlimited.
|
131
|
+
|
132
|
+
This material is based upon work supported by the Under Secretary of Defense
|
133
|
+
for Research and Engineering under Air Force Contract No. FA8702-15-D-0001. Any
|
134
|
+
opinions, findings, conclusions or recommendations expressed in this material
|
135
|
+
are those of the author(s) and do not necessarily reflect the views of the
|
136
|
+
Under Secretary of Defense for Research and Engineering.
|
137
|
+
|
138
|
+
Delivered to the U.S. Government with Unlimited Rights, as defined in DFARS
|
139
|
+
Part 252.227-7013 or 7014 (Feb 2014). Notwithstanding any copyright notice,
|
140
|
+
U.S. Government rights in this work are defined by DFARS 252.227-7013 or DFARS
|
141
|
+
252.227-7014 as detailed above. Use of this work other than as specifically
|
142
|
+
authorized by the U.S. Government may violate any copyrights that exist in this
|
143
|
+
work.
|
144
|
+
|
145
|
+
[MIT License](LICENSE.txt)
|
146
|
+
|
147
|
+
[commit-style-image]: https://img.shields.io/badge/commits-conventional-fe5196.svg
|
148
|
+
[conventional]: https://www.conventionalcommits.org/en/v1.0.0/
|
149
|
+
[code-style-image]: https://img.shields.io/badge/code%20style-black-000000.svg
|
150
|
+
[black]: https://github.com/psf/black
|
151
|
+
[license-image]: https://img.shields.io/badge/license-MIT-green.svg
|
152
|
+
[mit]: ./LICENSE.txt
|
@@ -0,0 +1,35 @@
|
|
1
|
+
from setuptools import find_packages, setup
|
2
|
+
|
3
|
+
with open("README.md", "r", encoding="utf-8") as f:
|
4
|
+
long_description = f.read()
|
5
|
+
|
6
|
+
setup(
|
7
|
+
name="smallworld-re",
|
8
|
+
version="1.0.0",
|
9
|
+
author="MIT Lincoln Laboratory",
|
10
|
+
author_email="smallworld@ll.mit.edu",
|
11
|
+
url="https://github.com/smallworld-re/smallworld",
|
12
|
+
description="An emulation stack tracking library",
|
13
|
+
long_description=long_description,
|
14
|
+
long_description_content_type="text/markdown",
|
15
|
+
license="MIT",
|
16
|
+
license_files=["LICENSE.txt"],
|
17
|
+
packages=find_packages(),
|
18
|
+
python_requires=">=3.8",
|
19
|
+
install_requires=["unicorn", "angr", "capstone", "lief", "pyhidra", "pypcode"],
|
20
|
+
extras_require={
|
21
|
+
"development": [
|
22
|
+
"black",
|
23
|
+
"isort",
|
24
|
+
"flake8",
|
25
|
+
"mypy",
|
26
|
+
"pip-tools",
|
27
|
+
"pre-commit",
|
28
|
+
"sphinx",
|
29
|
+
"sphinxcontrib-programoutput",
|
30
|
+
],
|
31
|
+
},
|
32
|
+
include_package_data=True,
|
33
|
+
zip_safe=False,
|
34
|
+
entry_points={"console_scripts": ["smallworld = smallworld.__main__:main"]},
|
35
|
+
)
|
@@ -0,0 +1,35 @@
|
|
1
|
+
from importlib import metadata as __metadata
|
2
|
+
|
3
|
+
metadata = __metadata.metadata("smallworld")
|
4
|
+
|
5
|
+
__title__ = metadata["name"]
|
6
|
+
__description__ = metadata["Summary"]
|
7
|
+
__author__ = metadata["Author"]
|
8
|
+
__version__ = metadata["version"]
|
9
|
+
|
10
|
+
|
11
|
+
from . import (
|
12
|
+
analyses,
|
13
|
+
emulators,
|
14
|
+
exceptions,
|
15
|
+
extern,
|
16
|
+
hinting,
|
17
|
+
instructions,
|
18
|
+
logging,
|
19
|
+
platforms,
|
20
|
+
state,
|
21
|
+
)
|
22
|
+
from .helpers import * # noqa: F401, F403
|
23
|
+
from .helpers import __all__ as __helpers__
|
24
|
+
|
25
|
+
__all__ = __helpers__ + [
|
26
|
+
"analyses",
|
27
|
+
"emulators",
|
28
|
+
"exceptions",
|
29
|
+
"extern",
|
30
|
+
"hinting",
|
31
|
+
"instructions",
|
32
|
+
"logging",
|
33
|
+
"platforms",
|
34
|
+
"state",
|
35
|
+
]
|
@@ -0,0 +1,14 @@
|
|
1
|
+
from .analysis import * # noqa: F401, F403
|
2
|
+
from .analysis import __all__ as __analysis__
|
3
|
+
from .colorizer import Colorizer
|
4
|
+
from .colorizer_summary import ColorizerSummary
|
5
|
+
from .field_detection import FieldDetectionAnalysis, ForcedFieldDetectionAnalysis
|
6
|
+
from .forced_exec import ForcedExecution
|
7
|
+
|
8
|
+
__all__ = __analysis__ + [
|
9
|
+
"Colorizer",
|
10
|
+
"ColorizerSummary",
|
11
|
+
"FieldDetectionAnalysis",
|
12
|
+
"ForcedFieldDetectionAnalysis",
|
13
|
+
"ForcedExecution",
|
14
|
+
]
|
@@ -0,0 +1,88 @@
|
|
1
|
+
import abc
|
2
|
+
import logging
|
3
|
+
import typing
|
4
|
+
|
5
|
+
from .. import hinting, state, utils
|
6
|
+
|
7
|
+
|
8
|
+
class Analysis(utils.MetadataMixin):
|
9
|
+
"""An analysis that emits some information about some code, possibly to help with harnessing."""
|
10
|
+
|
11
|
+
@abc.abstractmethod
|
12
|
+
def run(self, machine: state.Machine) -> None:
|
13
|
+
"""Run the analysis.
|
14
|
+
|
15
|
+
This function **should not** modify the provided Machine. Instead, it
|
16
|
+
should be coppied before modification.
|
17
|
+
|
18
|
+
Arguments:
|
19
|
+
machine: A machine state object on which this analysis should run.
|
20
|
+
"""
|
21
|
+
|
22
|
+
pass
|
23
|
+
|
24
|
+
|
25
|
+
class Filter(utils.MetadataMixin):
|
26
|
+
"""Analyses that consume and sometimes produce additional hints.
|
27
|
+
|
28
|
+
Filter analyses are analyses that consume some part of the hint
|
29
|
+
stream and possibly emit new higher-level, synthetic hints. These
|
30
|
+
analyses do not inspect machine state directly, they just react to
|
31
|
+
hints from other analyses.
|
32
|
+
|
33
|
+
"""
|
34
|
+
|
35
|
+
def __init__(self):
|
36
|
+
self.listeners = []
|
37
|
+
|
38
|
+
def listen(
|
39
|
+
self,
|
40
|
+
hint: typing.Type[hinting.Hint],
|
41
|
+
method: typing.Callable[[hinting.Hint], None],
|
42
|
+
) -> None:
|
43
|
+
"""Register a listener for a particular hint type on the hint stream.
|
44
|
+
|
45
|
+
Arguments:
|
46
|
+
hint: A hint type that should trigger this listener. Note: All
|
47
|
+
subclasses `hint` will trigger the listener.
|
48
|
+
method: The method to call when the given hint type is observed.
|
49
|
+
"""
|
50
|
+
|
51
|
+
class Handler(logging.Handler):
|
52
|
+
def emit(self, record):
|
53
|
+
method(record.msg)
|
54
|
+
|
55
|
+
handler = Handler()
|
56
|
+
handler.setLevel(logging.DEBUG)
|
57
|
+
handler.addFilter(hinting.HintSubclassFilter(hint))
|
58
|
+
hinting.root.addHandler(handler)
|
59
|
+
|
60
|
+
self.listeners.append(handler)
|
61
|
+
|
62
|
+
@abc.abstractmethod
|
63
|
+
def activate(self) -> None:
|
64
|
+
"""Activate this filter.
|
65
|
+
|
66
|
+
Implementations should make necessary calls to `listen()` here to
|
67
|
+
register hint listener functions. They will be unregistered
|
68
|
+
automatically on destruction or manual call to `deactivate()`.
|
69
|
+
"""
|
70
|
+
|
71
|
+
pass
|
72
|
+
|
73
|
+
def deactivate(self) -> None:
|
74
|
+
"""Deactivate this filter.
|
75
|
+
|
76
|
+
This is done automatically on destruction of this object - you likely
|
77
|
+
shouldn't need to call this manually.
|
78
|
+
"""
|
79
|
+
|
80
|
+
for handler in self.listeners:
|
81
|
+
hinting.root.removeHandler(handler)
|
82
|
+
|
83
|
+
def __del__(self):
|
84
|
+
self.deactivate()
|
85
|
+
# super().__del__()
|
86
|
+
|
87
|
+
|
88
|
+
__all__ = ["Analysis", "Filter"]
|
@@ -0,0 +1,31 @@
|
|
1
|
+
import logging
|
2
|
+
import typing
|
3
|
+
|
4
|
+
from .. import emulators, hinting
|
5
|
+
from . import analysis
|
6
|
+
|
7
|
+
logger = logging.getLogger(__name__)
|
8
|
+
hinter = hinting.get_hinter(__name__)
|
9
|
+
|
10
|
+
|
11
|
+
class CodeCoverage(analysis.Analysis):
|
12
|
+
"""A simple analysis that logs jumps, calls, and returns."""
|
13
|
+
|
14
|
+
name = "code-coverage"
|
15
|
+
description = ""
|
16
|
+
version = "0.0.1"
|
17
|
+
|
18
|
+
def run(self, machine) -> None:
|
19
|
+
emulator = emulators.UnicornEmulator(machine.get_platform())
|
20
|
+
coverage: typing.Dict[int, int] = {}
|
21
|
+
|
22
|
+
for step in machine.step(emulator):
|
23
|
+
cpu = step.get_cpu()
|
24
|
+
pc = cpu.pc.get_content()
|
25
|
+
if pc in coverage:
|
26
|
+
coverage[pc] += 1
|
27
|
+
else:
|
28
|
+
coverage[pc] = 1
|
29
|
+
|
30
|
+
hint = hinting.CoverageHint(message="Coverage for execution", coverage=coverage)
|
31
|
+
hinter.info(hint)
|