# DumbEmu
A lightweight, performant PE emulator built on Unicorn Engine for Windows executable analysis and function testing.
## Features
### Core Capabilities
- **Architecture Support**: Automatic detection and support for x86 (32-bit) and x64 (64-bit) PE files
- **PE Loading**: Complete PE parsing with proper section mapping and permissions
- **Windows Environment**: TEB/PEB structure initialization for Windows-aware execution
- **IAT Stubbing**: Import Address Table hooking with customizable function stubs
### Memory Management
- **Smart Allocation**: Page-aligned memory allocator with tracking
- **Protection Control**: Fine-grained memory permission management  
- **String Operations**: Native support for ASCII and UTF-16 strings
- **Struct Operations**: Pack/unpack structured data with format strings
### Execution Control
- **Function Calling**: Proper x86/x64 calling convention implementation
- **Raw Execution**: Direct code execution without function overhead
- **Breakpoints**: Set breakpoints to pause execution at specific addresses
- **Instruction Limits**: Prevent infinite loops with instruction count limits
- **Execution Tracing**: Record executed addresses and instruction counts
### Advanced Features
- **Code Hooks**: Install callbacks at specific addresses
- **Register Access**: Full access to all x86/x64 registers including segments
- **Stack Management**: Automatic stack setup with push/pop operations
- **Verbose Logging**: Optional detailed logging for debugging
## Installation
### From PyPI
```bash
pip install dumbemu
```
### From Source
```bash
# Clone the repository
git clone https://github.com/Diefunction/dumbemu
cd dumbemu
# Install in editable mode (recommended for development)
pip install -e .
# Or install directly
pip install .
```
### Requirements
- Python >= 3.8
- unicorn >= 2.0.0
- lief >= 0.13.0
These dependencies will be automatically installed when you install dumbemu.
## Quick Start
### Basic Function Call
```python
from dumbemu import DumbEmu
# Load PE file (architecture auto-detected)
emu = DumbEmu("target.exe")
# Call function at 0x401000 with three arguments
result = emu.call(0x401000, None, 10, 20, 30)
print(f"Result: 0x{result:08X}")
```
### Memory Operations
```python
# Allocate memory
addr = emu.malloc(0x1000)  # Allocate 4KB
# Write data
emu.write(addr, b"Hello, World!")
# Read data
data = emu.read(addr, 13)
# String operations
emu.string.ascii(addr, "Test String")
text = emu.string.cstring(addr)
# Struct operations
emu.struct.write(addr, "IHH", 0xDEADBEEF, 0x1337, 0x42)
values = emu.struct.read(addr, "IHH")
```
### IAT Stubbing
```python
from dumbemu.win.iat import Proto
# Define a stub for GetProcAddress
def get_proc_stub(iat, uc, args):
    # args = (hModule, lpProcName)
    proc_name_ptr = args[1]
    proc_name = iat.strings.cstring(proc_name_ptr)
    print(f"GetProcAddress called for: {proc_name}")
    return 0x12345678  # Return fake address
# Register the stub
emu.stub("kernel32.dll", "GetProcAddress", 
         Proto("GetProcAddress", emu.ctx.conv, [4, 4]),
         get_proc_stub)
# Now any calls to GetProcAddress will use our stub
```
### Execution Hooks
```python
# Define a hook callback
def on_function_entry(uc, address):
    print(f"Entering function at 0x{address:08X}")
    # Read registers
    eax = emu.regs.read('eax')
    print(f"  EAX = 0x{eax:08X}")
# Install hook
emu.hook(0x401000, on_function_entry)
# Execute - hook will be called
emu.call(0x401000)
```
### Execution Tracing
```python
# Enable tracing
emu.tracer.start()
# Execute code
emu.call(0x401000)
# Get execution trace
executed_addrs = emu.tracer.stop()
print(f"Executed {len(executed_addrs)} unique addresses")
# Get history of all traces
history = emu.tracer.history()
```
### Advanced Execution Control
```python
# Execute with instruction limit (prevent infinite loops)
result = emu.call(0x401000, max_insns=10000)
# Execute with breakpoint
result = emu.call(0x401000, breakpoint=0x401050)
# Raw execution (no function call setup)
emu.execute(0x401000, count=100)  # Execute 100 instructions
```
## API Reference
### DumbEmu Class
```python
DumbEmu(path: str, verbose: bool = False)
```
#### Core Methods
- `call(addr, breakpoint=None, *args, max_insns=1000000) -> int`
  - Call function with arguments
  - Returns function return value
  
- `execute(addr, until=None, count=None)`
  - Execute raw code without function call setup
  
- `hook(addr, callback)`
  - Install code hook at address
  
- `malloc(size, prot=RW) -> int`
  - Allocate memory region
  
- `free(addr) -> bool`
  - Free allocated memory
#### Memory Access
- `read(addr, size) -> bytes`
  - Read bytes from memory
  
- `write(addr, data)`
  - Write bytes to memory
#### Component Access
- `emu.mem` - Memory manager
- `emu.regs` - Register access
- `emu.stack` - Stack operations
- `emu.struct` - Struct pack/unpack
- `emu.string` - String operations
- `emu.tracer` - Execution tracer
- `emu.iat` - IAT stub manager
### Memory Manager (emu.mem)
- `map(addr, size, prot)` - Map memory region
- `protect(addr, size, prot)` - Change protection
- `pack(addr, value, bits)` - Pack integer to memory
- `unpack(addr, size) -> int` - Unpack integer from memory
### Register Access (emu.regs)
- `read(name) -> int` - Read register value
- `write(name, value)` - Write register value
- Supports all x86/x64 registers: `eax`, `rax`, `r8-r15`, etc.
### String Operations (emu.string)
- `cstring(addr, max_len=4096) -> str` - Read null-terminated ASCII
- `wstring(addr, max_len=4096) -> str` - Read null-terminated UTF-16
- `ascii(addr, text, null=True)` - Write ASCII string
- `wide(addr, text, null=True)` - Write UTF-16 string
### Struct Operations (emu.struct)
- `write(addr, fmt, *values)` - Pack struct to memory
- `read(addr, fmt) -> tuple` - Unpack struct from memory
- `iter(addr, fmt, count) -> iterator` - Iterate structs
- Format strings follow Python's `struct` module
### Stack Operations (emu.stack)
- `push(mem, sp, value) -> int` - Push value, return new SP
- `pop(mem, sp) -> (value, sp)` - Pop value, return value and new SP
- `read(mem, sp, offset) -> int` - Read from stack
- `write(mem, sp, value, offset)` - Write to stack
## Examples
### CTF Challenge Solver
```python
from dumbemu import DumbEmu
# Load the challenge binary
emu = DumbEmu("crackme.exe")
# Set up input buffer
addr = emu.malloc(256)
emu.string.ascii(addr, "FLAG{TEST}")
# Call validation function
valid = emu.call(0x401000, None, addr)
if valid:
    print("[+] Valid flag!")
else:
    print("[-] Invalid flag")
```
### Windows API Stubbing
```python
from dumbemu import DumbEmu
from dumbemu.win.iat import Proto
emu = DumbEmu("malware.exe", verbose = True)
# Stub common Windows APIs
def MessageBoxA(iat, uc, args):
    text_ptr = args[1]
    text = iat.strings.cstring(text_ptr) if text_ptr else ""
    print(f"[MessageBox] {text}")
    return 1  # IDOK
emu.stub("user32.dll", "MessageBoxA",
         Proto("MessageBoxA", emu.ctx.conv, [4, 4, 4, 4]),
         MessageBoxA)
# Run malware function
emu.call(0x401000)
```
## Architecture
DumbEmu is organized into logical components:
```
dumbemu/
├── cpu/          # CPU architecture and registers
│   ├── base.py   # Abstract architecture base
│   ├── x86.py    # x86 32-bit implementation
│   ├── x64.py    # x64 64-bit implementation
│   └── regs.py   # Register access layer
├── mem/          # Memory management
│   ├── memory.py # Core memory operations
│   ├── stack.py  # Stack management
│   ├── alloc.py  # Memory allocator
│   └── hooks.py  # Code hooks
├── data/         # Data operations
│   ├── strings.py # String operations
│   └── structs.py # Struct pack/unpack
├── win/          # Windows environment
│   ├── iat.py    # IAT stubbing
│   └── tebpeb.py # TEB/PEB structures
├── debug/        # Debugging tools
│   └── tracer.py # Execution tracer
├── pe/           # PE file handling
│   └── loader.py # PE parser and loader
└── utils/        # Utilities
    ├── constants.py # Constants and mappings
    └── logger.py    # Logging system
```
## License
This project is licensed under the MIT License - see the LICENSE file for details.
## Acknowledgments
- Built on [Unicorn Engine](https://www.unicorn-engine.org/)
- PE parsing via [LIEF](https://lief-project.github.io/)
            
         
        Raw data
        
            {
    "_id": null,
    "home_page": null,
    "name": "dumbemu",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": null,
    "keywords": "emulator, pe, windows, unicorn, reverse-engineering, ctf",
    "author": "Diefunction",
    "author_email": null,
    "download_url": "https://files.pythonhosted.org/packages/2c/3b/fff45726cd727452102b3d42a22b1f27aab499cd044d941139077805258a/dumbemu-1.0.0.tar.gz",
    "platform": null,
    "description": "# DumbEmu\r\n\r\nA lightweight, performant PE emulator built on Unicorn Engine for Windows executable analysis and function testing.\r\n\r\n## Features\r\n\r\n### Core Capabilities\r\n- **Architecture Support**: Automatic detection and support for x86 (32-bit) and x64 (64-bit) PE files\r\n- **PE Loading**: Complete PE parsing with proper section mapping and permissions\r\n- **Windows Environment**: TEB/PEB structure initialization for Windows-aware execution\r\n- **IAT Stubbing**: Import Address Table hooking with customizable function stubs\r\n\r\n### Memory Management\r\n- **Smart Allocation**: Page-aligned memory allocator with tracking\r\n- **Protection Control**: Fine-grained memory permission management  \r\n- **String Operations**: Native support for ASCII and UTF-16 strings\r\n- **Struct Operations**: Pack/unpack structured data with format strings\r\n\r\n### Execution Control\r\n- **Function Calling**: Proper x86/x64 calling convention implementation\r\n- **Raw Execution**: Direct code execution without function overhead\r\n- **Breakpoints**: Set breakpoints to pause execution at specific addresses\r\n- **Instruction Limits**: Prevent infinite loops with instruction count limits\r\n- **Execution Tracing**: Record executed addresses and instruction counts\r\n\r\n### Advanced Features\r\n- **Code Hooks**: Install callbacks at specific addresses\r\n- **Register Access**: Full access to all x86/x64 registers including segments\r\n- **Stack Management**: Automatic stack setup with push/pop operations\r\n- **Verbose Logging**: Optional detailed logging for debugging\r\n\r\n## Installation\r\n\r\n### From PyPI\r\n\r\n```bash\r\npip install dumbemu\r\n```\r\n\r\n### From Source\r\n\r\n```bash\r\n# Clone the repository\r\ngit clone https://github.com/Diefunction/dumbemu\r\ncd dumbemu\r\n\r\n# Install in editable mode (recommended for development)\r\npip install -e .\r\n\r\n# Or install directly\r\npip install .\r\n```\r\n\r\n### Requirements\r\n\r\n- Python >= 3.8\r\n- unicorn >= 2.0.0\r\n- lief >= 0.13.0\r\n\r\nThese dependencies will be automatically installed when you install dumbemu.\r\n\r\n## Quick Start\r\n\r\n### Basic Function Call\r\n\r\n```python\r\nfrom dumbemu import DumbEmu\r\n\r\n# Load PE file (architecture auto-detected)\r\nemu = DumbEmu(\"target.exe\")\r\n\r\n# Call function at 0x401000 with three arguments\r\nresult = emu.call(0x401000, None, 10, 20, 30)\r\nprint(f\"Result: 0x{result:08X}\")\r\n```\r\n\r\n### Memory Operations\r\n\r\n```python\r\n# Allocate memory\r\naddr = emu.malloc(0x1000)  # Allocate 4KB\r\n\r\n# Write data\r\nemu.write(addr, b\"Hello, World!\")\r\n\r\n# Read data\r\ndata = emu.read(addr, 13)\r\n\r\n# String operations\r\nemu.string.ascii(addr, \"Test String\")\r\ntext = emu.string.cstring(addr)\r\n\r\n# Struct operations\r\nemu.struct.write(addr, \"IHH\", 0xDEADBEEF, 0x1337, 0x42)\r\nvalues = emu.struct.read(addr, \"IHH\")\r\n```\r\n\r\n### IAT Stubbing\r\n\r\n```python\r\nfrom dumbemu.win.iat import Proto\r\n\r\n# Define a stub for GetProcAddress\r\ndef get_proc_stub(iat, uc, args):\r\n    # args = (hModule, lpProcName)\r\n    proc_name_ptr = args[1]\r\n    proc_name = iat.strings.cstring(proc_name_ptr)\r\n    print(f\"GetProcAddress called for: {proc_name}\")\r\n    return 0x12345678  # Return fake address\r\n\r\n# Register the stub\r\nemu.stub(\"kernel32.dll\", \"GetProcAddress\", \r\n         Proto(\"GetProcAddress\", emu.ctx.conv, [4, 4]),\r\n         get_proc_stub)\r\n\r\n# Now any calls to GetProcAddress will use our stub\r\n```\r\n\r\n### Execution Hooks\r\n\r\n```python\r\n# Define a hook callback\r\ndef on_function_entry(uc, address):\r\n    print(f\"Entering function at 0x{address:08X}\")\r\n    # Read registers\r\n    eax = emu.regs.read('eax')\r\n    print(f\"  EAX = 0x{eax:08X}\")\r\n\r\n# Install hook\r\nemu.hook(0x401000, on_function_entry)\r\n\r\n# Execute - hook will be called\r\nemu.call(0x401000)\r\n```\r\n\r\n### Execution Tracing\r\n\r\n```python\r\n# Enable tracing\r\nemu.tracer.start()\r\n\r\n# Execute code\r\nemu.call(0x401000)\r\n\r\n# Get execution trace\r\nexecuted_addrs = emu.tracer.stop()\r\nprint(f\"Executed {len(executed_addrs)} unique addresses\")\r\n\r\n# Get history of all traces\r\nhistory = emu.tracer.history()\r\n```\r\n\r\n### Advanced Execution Control\r\n\r\n```python\r\n# Execute with instruction limit (prevent infinite loops)\r\nresult = emu.call(0x401000, max_insns=10000)\r\n\r\n# Execute with breakpoint\r\nresult = emu.call(0x401000, breakpoint=0x401050)\r\n\r\n# Raw execution (no function call setup)\r\nemu.execute(0x401000, count=100)  # Execute 100 instructions\r\n```\r\n\r\n## API Reference\r\n\r\n### DumbEmu Class\r\n\r\n```python\r\nDumbEmu(path: str, verbose: bool = False)\r\n```\r\n\r\n#### Core Methods\r\n\r\n- `call(addr, breakpoint=None, *args, max_insns=1000000) -> int`\r\n  - Call function with arguments\r\n  - Returns function return value\r\n  \r\n- `execute(addr, until=None, count=None)`\r\n  - Execute raw code without function call setup\r\n  \r\n- `hook(addr, callback)`\r\n  - Install code hook at address\r\n  \r\n- `malloc(size, prot=RW) -> int`\r\n  - Allocate memory region\r\n  \r\n- `free(addr) -> bool`\r\n  - Free allocated memory\r\n\r\n#### Memory Access\r\n\r\n- `read(addr, size) -> bytes`\r\n  - Read bytes from memory\r\n  \r\n- `write(addr, data)`\r\n  - Write bytes to memory\r\n\r\n#### Component Access\r\n\r\n- `emu.mem` - Memory manager\r\n- `emu.regs` - Register access\r\n- `emu.stack` - Stack operations\r\n- `emu.struct` - Struct pack/unpack\r\n- `emu.string` - String operations\r\n- `emu.tracer` - Execution tracer\r\n- `emu.iat` - IAT stub manager\r\n\r\n### Memory Manager (emu.mem)\r\n\r\n- `map(addr, size, prot)` - Map memory region\r\n- `protect(addr, size, prot)` - Change protection\r\n- `pack(addr, value, bits)` - Pack integer to memory\r\n- `unpack(addr, size) -> int` - Unpack integer from memory\r\n\r\n### Register Access (emu.regs)\r\n\r\n- `read(name) -> int` - Read register value\r\n- `write(name, value)` - Write register value\r\n- Supports all x86/x64 registers: `eax`, `rax`, `r8-r15`, etc.\r\n\r\n### String Operations (emu.string)\r\n\r\n- `cstring(addr, max_len=4096) -> str` - Read null-terminated ASCII\r\n- `wstring(addr, max_len=4096) -> str` - Read null-terminated UTF-16\r\n- `ascii(addr, text, null=True)` - Write ASCII string\r\n- `wide(addr, text, null=True)` - Write UTF-16 string\r\n\r\n### Struct Operations (emu.struct)\r\n\r\n- `write(addr, fmt, *values)` - Pack struct to memory\r\n- `read(addr, fmt) -> tuple` - Unpack struct from memory\r\n- `iter(addr, fmt, count) -> iterator` - Iterate structs\r\n- Format strings follow Python's `struct` module\r\n\r\n### Stack Operations (emu.stack)\r\n\r\n- `push(mem, sp, value) -> int` - Push value, return new SP\r\n- `pop(mem, sp) -> (value, sp)` - Pop value, return value and new SP\r\n- `read(mem, sp, offset) -> int` - Read from stack\r\n- `write(mem, sp, value, offset)` - Write to stack\r\n\r\n## Examples\r\n\r\n### CTF Challenge Solver\r\n\r\n```python\r\nfrom dumbemu import DumbEmu\r\n\r\n# Load the challenge binary\r\nemu = DumbEmu(\"crackme.exe\")\r\n\r\n# Set up input buffer\r\naddr = emu.malloc(256)\r\nemu.string.ascii(addr, \"FLAG{TEST}\")\r\n\r\n# Call validation function\r\nvalid = emu.call(0x401000, None, addr)\r\n\r\nif valid:\r\n    print(\"[+] Valid flag!\")\r\nelse:\r\n    print(\"[-] Invalid flag\")\r\n```\r\n\r\n### Windows API Stubbing\r\n\r\n```python\r\nfrom dumbemu import DumbEmu\r\nfrom dumbemu.win.iat import Proto\r\n\r\nemu = DumbEmu(\"malware.exe\", verbose = True)\r\n\r\n# Stub common Windows APIs\r\ndef MessageBoxA(iat, uc, args):\r\n    text_ptr = args[1]\r\n    text = iat.strings.cstring(text_ptr) if text_ptr else \"\"\r\n    print(f\"[MessageBox] {text}\")\r\n    return 1  # IDOK\r\n\r\nemu.stub(\"user32.dll\", \"MessageBoxA\",\r\n         Proto(\"MessageBoxA\", emu.ctx.conv, [4, 4, 4, 4]),\r\n         MessageBoxA)\r\n\r\n# Run malware function\r\nemu.call(0x401000)\r\n```\r\n\r\n## Architecture\r\n\r\nDumbEmu is organized into logical components:\r\n\r\n```\r\ndumbemu/\r\n\u251c\u2500\u2500 cpu/          # CPU architecture and registers\r\n\u2502   \u251c\u2500\u2500 base.py   # Abstract architecture base\r\n\u2502   \u251c\u2500\u2500 x86.py    # x86 32-bit implementation\r\n\u2502   \u251c\u2500\u2500 x64.py    # x64 64-bit implementation\r\n\u2502   \u2514\u2500\u2500 regs.py   # Register access layer\r\n\u251c\u2500\u2500 mem/          # Memory management\r\n\u2502   \u251c\u2500\u2500 memory.py # Core memory operations\r\n\u2502   \u251c\u2500\u2500 stack.py  # Stack management\r\n\u2502   \u251c\u2500\u2500 alloc.py  # Memory allocator\r\n\u2502   \u2514\u2500\u2500 hooks.py  # Code hooks\r\n\u251c\u2500\u2500 data/         # Data operations\r\n\u2502   \u251c\u2500\u2500 strings.py # String operations\r\n\u2502   \u2514\u2500\u2500 structs.py # Struct pack/unpack\r\n\u251c\u2500\u2500 win/          # Windows environment\r\n\u2502   \u251c\u2500\u2500 iat.py    # IAT stubbing\r\n\u2502   \u2514\u2500\u2500 tebpeb.py # TEB/PEB structures\r\n\u251c\u2500\u2500 debug/        # Debugging tools\r\n\u2502   \u2514\u2500\u2500 tracer.py # Execution tracer\r\n\u251c\u2500\u2500 pe/           # PE file handling\r\n\u2502   \u2514\u2500\u2500 loader.py # PE parser and loader\r\n\u2514\u2500\u2500 utils/        # Utilities\r\n    \u251c\u2500\u2500 constants.py # Constants and mappings\r\n    \u2514\u2500\u2500 logger.py    # Logging system\r\n```\r\n\r\n\r\n## License\r\n\r\nThis project is licensed under the MIT License - see the LICENSE file for details.\r\n\r\n## Acknowledgments\r\n\r\n- Built on [Unicorn Engine](https://www.unicorn-engine.org/)\r\n- PE parsing via [LIEF](https://lief-project.github.io/)\r\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "A lightweight, performant PE emulator built on Unicorn Engine for Windows executable analysis",
    "version": "1.0.0",
    "project_urls": {
        "Bug Tracker": "https://github.com/Diefunction/dumbemu/issues",
        "Documentation": "https://github.com/Diefunction/dumbemu#readme",
        "Homepage": "https://github.com/Diefunction/dumbemu"
    },
    "split_keywords": [
        "emulator",
        " pe",
        " windows",
        " unicorn",
        " reverse-engineering",
        " ctf"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "35f8d264df3edc2d032488fffc9fb6d49934eadf7884be1a717b97bba7de4147",
                "md5": "b7da1d0dc585d22ee18efe6dc9fd3164",
                "sha256": "9cb6e7f484a834d091210949fe8c1aeca3a396ac9d8d5fd532c09d0e2782b962"
            },
            "downloads": -1,
            "filename": "dumbemu-1.0.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "b7da1d0dc585d22ee18efe6dc9fd3164",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 27495,
            "upload_time": "2025-10-12T13:58:22",
            "upload_time_iso_8601": "2025-10-12T13:58:22.983922Z",
            "url": "https://files.pythonhosted.org/packages/35/f8/d264df3edc2d032488fffc9fb6d49934eadf7884be1a717b97bba7de4147/dumbemu-1.0.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "2c3bfff45726cd727452102b3d42a22b1f27aab499cd044d941139077805258a",
                "md5": "04cbf6a3596fd858070f2aa036a8f0e5",
                "sha256": "f3058a06301df665e4dbfc323b4e8b8eb15c1b963fad7d495170760eb6222a33"
            },
            "downloads": -1,
            "filename": "dumbemu-1.0.0.tar.gz",
            "has_sig": false,
            "md5_digest": "04cbf6a3596fd858070f2aa036a8f0e5",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 34073,
            "upload_time": "2025-10-12T13:58:24",
            "upload_time_iso_8601": "2025-10-12T13:58:24.099413Z",
            "url": "https://files.pythonhosted.org/packages/2c/3b/fff45726cd727452102b3d42a22b1f27aab499cd044d941139077805258a/dumbemu-1.0.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-10-12 13:58:24",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "Diefunction",
    "github_project": "dumbemu",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "dumbemu"
}