Slightly fancier WIP .NET binding/wrapper for the Unicorn engine.
The API is very prone to changes at the moment.
Here is an example of how to use it. This is also the same example as the official documentation available here but in C# and using Unicorn.Net.
using (var emulator = new X86Emulator(X86Mode.b32))
{
ulong addr = 0x1000000;
byte[] x86code =
{
0x41, // INC ECX
0x4a // DEC EDX
};
var ecx = 0x1234;
var edx = 0x7890;
// Map 2mb of memory.
emulator.Memory.Map(addr, 2 * 1024 * 1024, MemoryPermissions.All);
emulator.Registers.ECX = ecx;
emulator.Registers.EDX = edx;
emulator.Memory.Write(addr, x86code, x86code.Length);
emulator.Start(addr, addr + (ulong)x86code.Length);
Console.WriteLine(emulator.Registers.ECX);
Console.WriteLine(emulator.Registers.EDX);
}
Reading and writing to registers.
Currently there is no way to write to registers using register IDs, but this may change.
// Assume emulator is an instance of the X86Emulator type.
// Reading from registers.
var val = emulator.Registers.ECX;
// Writing to registers.
emulator.Registers.ECX = 0x10;
Mapping, unmapping, reading, writing and changing memory permissions.
var addr = 0x100000;
// Getting memory regions.
var regions = emulator.Memory.Regions;
// Getting memory page size.
var pageSize = emulator.Memory.PageSize;
// Mapping memory.
emulator.Memory.Map(addr, 2 * 1024, 2 * 1024, MemoryPermissions.All);
// Unmapping memory.
emulator.Memory.Unmap(addr + (4 * 1024), 4 * 1024);
// Changing memory permissions.
emulator.Memory.Protect(addr + (4 * 1024), 4 * 1024, MemoryPermissions.Read);
// Code to write to memory.
var code = new byte[]
{
0x41, // INC ECX
0x4a // DEC EDX
}
// Buffer thats going to be the storage for data read from memory.
var buffer = new byte[2];
// Writing to memory.
emulator.Memory.Write(code, 0, code.Length);
// Reading to memory.
emulator.Memory.Read(buffer, 0, buffer.Length);
Currently hooking is still under the works and may change.
// Adding a memory read hook.
emulator.Hooks.Memory.Add(MemoryHookType.Read, (emu, type, address, size, val, userData) => {
Console.WriteLine(" stuff was read from memory.");
}, addr, addr + (ulong)code.Length, null);
Capturing and restoring contexts.
// emulator.Context will create a new Context object
// which you will to dispose afterwards. Hence the `using` statement.
// Capturing the context.
using (var ctx = emulator.Context)
{
...
// To restore the context simply do this.
emulator.Context = ctx;
}
Unicorn.Net also provide some raw bindings through the Bindings
class.
var bindings = new Bindings();
bindings.Open(...);
bindings.MemMap(...);
...
List of stuff thats needs to be implemented or that has been implemented.
-
Emulator
- uc_emu_start
- uc_emu_stop
- uc_query
-
Context
- uc_context_alloc
- uc_context_save
- uc_context_restore
-
Registers
- uc_reg_read
- uc_reg_write
-
Memory
- uc_mem_write
- uc_mem_read
- uc_mem_protect
- uc_mem_regions
- uc_mem_map
- uc_mem_unmap
-
Hooking
- uc_hook_add
- uc_hook_del
-
Arches
- x86
- arm
- arm64
- m68k
- mips
- sparc
-
Actual bindings
Unicorn.Net is licensed under the permissive MIT License.