Skip to content

Commit 965e041

Browse files
docs: Add initial README.md file
docs: Add README with project overview, usage examples, and Windows emulation note docs: Update README with Unicorn link and project scope clarification docs: Update README with more practical and comprehensive usage examples docs: Update readme with improved code examples and explanations feat: Add Windows emulation examples for TEB, PEB, and Unicode string handling docs: Update readme with Windows emulation examples and PE loading
1 parent fea5f3f commit 965e041

File tree

1 file changed

+91
-0
lines changed

1 file changed

+91
-0
lines changed

readme.md

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
# ucutils - Unicorn Emulator Utilities
2+
3+
ucutils provides helper utilities and abstractions for working with the [Unicorn CPU emulator](https://www.unicorn-engine.org/).
4+
It simplifies memory management, register access, and architecture-specific operations while supporting both x86 and x64 architectures.
5+
The library also includes Windows-specific utilities for emulating Windows structures and behaviors.
6+
7+
For more comprehensive Windows emulation including API hooking and system call emulation, consider using the [Speakeasy](https://github.com/mandiant/speakeasy) project.
8+
ucutils focuses on providing low-level CPU emulation utilities rather than full system emulation.
9+
10+
Create the extended emulator instance:
11+
```py
12+
emu = ucutils.emu.Emulator(unicorn.UC_ARCH_X86, unicorn.UC_MODE_64)
13+
```
14+
15+
Map and access memory (typical Unicorn API):
16+
```py
17+
emu.mem_map(0x0, 0x1000)
18+
code = b"\x48\xC7\xC0\x01\x00\x00\x00" # mov rax, 0x1
19+
emu.mem_write(0x0, code)
20+
emu.emu_start(0x0, len(code))
21+
````
22+
23+
Easily access registers:
24+
```py
25+
assert emu.rax == 0x1
26+
```
27+
28+
And, easily allocate and access memory:
29+
```py
30+
addr = emu.mem.alloc(0x1000)
31+
emu.mem_write(addr, b"AAAA")
32+
assert emu.mem[addr:addr+4] == b"AAAA"
33+
```
34+
35+
Stack operations:
36+
```py
37+
emu.push(0xAA)
38+
assert emu.pop() == 0xAA
39+
```
40+
41+
Emulation stepping:
42+
```python
43+
emu.mem_map(0x0, 0x1000)
44+
code = b"\x48\xC7\xC0\x01\x00\x00\x00\x48\xC7\xC3\x02\x00\x00\x00" # mov rax,0x1; mov rbx,0x2
45+
emu.mem_write(0x0, code)
46+
emu.stepi() # Execute first instruction
47+
assert emu.pc == 0x7
48+
assert emu.rax == 0x1
49+
```
50+
51+
Checkpointing:
52+
```python
53+
assert emu.rax == 0x0
54+
assert emu.rbx == 0x0
55+
56+
with ucutils.checkpoint.checkpoint(emu):
57+
emu.rax = 0x1
58+
emu.rbx = 0x2
59+
60+
emu.stepi()
61+
62+
# changes will be reverted after the block,
63+
# including memory contents and registry context.
64+
65+
assert emu.rax == 0x0
66+
assert emu.rbx == 0x0
67+
```
68+
69+
Install TEB and PEB for Windows process emulation (useful for shellcode):
70+
```python
71+
# Thread Environment Block (TEB)
72+
teb_addr = ucutils.plat.win64.map_teb(emu)
73+
74+
# Process Environment Block (PEB)
75+
peb_addr = ucutils.plat.win64.map_peb(emu)
76+
77+
ucutils.arch.x64.set_fs(emu, teb_addr)
78+
```
79+
80+
Load a PE file:
81+
```python
82+
pe = pefile.PE(data=b"MZ...")
83+
ucutils.plat.win.load_dll(emu, {"filename": "payload.dll", "pe": pe})
84+
85+
# exports are added to emu.symbols
86+
assert "payload.dll!ServiceMain" in emu.symbols
87+
88+
# LDR_ENTRY is registered in emulated memory,
89+
# which is useful for (shellcode) payloads that manually resolve imports.
90+
```
91+

0 commit comments

Comments
 (0)