├── .gitignore ├── .vscode ├── launch.json └── tasks.json ├── LICENSE ├── README.md ├── Unicorn.Net.sln ├── samples ├── Unicorn.Net.Samples.Arm │ ├── Program.cs │ └── Unicorn.Net.Samples.Arm.csproj ├── Unicorn.Net.Samples.Mips │ ├── Program.cs │ └── Unicorn.Net.Samples.Mips.csproj ├── Unicorn.Net.Samples.Shellcode │ ├── Program.cs │ └── Unicorn.Net.Samples.Shellcode.csproj └── Unicorn.Net.Samples.X86 │ ├── Program.cs │ └── Unicorn.Net.Samples.X86.csproj ├── scripts ├── gen_ins_fields.py └── gen_reg_properties.py └── src ├── Unicorn.Net.ConsoleTests ├── Program.cs └── Unicorn.Net.ConsoleTests.csproj └── Unicorn.Net ├── Arm ├── ArmEmulator.cs ├── ArmMode.cs └── ArmRegisters.cs ├── Bindings.cs ├── BlockHooksContainer.cs ├── CodeHooksContainer.cs ├── Context.cs ├── Emulator.cs ├── GlobalSuppressions.cs ├── HookContainer.cs ├── HookHandle.cs ├── Hooks.cs ├── IBindings.cs ├── Instruction.cs ├── InstructionHookContainer.cs ├── Internal ├── uc_arch.cs ├── uc_err.cs ├── uc_hook_type.cs ├── uc_mem_region.cs ├── uc_mem_type.cs ├── uc_mode.cs ├── uc_query_type.cs └── unicorn.cs ├── InterruptHookContainer.cs ├── Memory.cs ├── MemoryHookContainer.cs ├── MemoryPermissions.cs ├── MemoryRegion.cs ├── Mips ├── MipsEmulator.cs ├── MipsMode.cs └── MipsRegisters.cs ├── Registers.cs ├── Unicorn.Net.csproj ├── UnicornArch.cs ├── UnicornError.cs ├── UnicornException.cs ├── UnicornHookType.cs ├── UnicornMode.cs ├── UnicornQueryType.cs ├── UnicornVersion.cs └── X86 ├── X86Emulator.cs ├── X86Instructions.cs ├── X86Mode.cs └── X86Registers.cs /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries 2 | bin/ 3 | obj/ 4 | 5 | # Visual Studio 6 | .vs/ 7 | Debug/ 8 | Release/ 9 | *.VC.db 10 | *.VC.opendb 11 | *.user 12 | 13 | # Scripts output/input files. 14 | scripts/*.cs 15 | scripts/*.reg 16 | scripts/*.ins 17 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Unicorn.Net.ConsoleTests", 6 | "type": "coreclr", 7 | "request": "launch", 8 | "preLaunchTask": "build Unicorn.Net.ConsoleTests", 9 | "program": "${workspaceFolder}/src/Unicorn.Net.ConsoleTests/bin/Debug/netcoreapp2.0/Unicorn.Net.ConsoleTests.dll", 10 | "args": [], 11 | "cwd": "${workspaceFolder}/src/Unicorn.Net.ConsoleTests", 12 | "stopAtEntry": false, 13 | "console": "internalConsole", 14 | "internalConsoleOptions": "openOnSessionStart" 15 | }, 16 | { 17 | "name": "Unicorn.Net.Samples.Mips", 18 | "type": "coreclr", 19 | "request": "launch", 20 | "preLaunchTask": "build Unicorn.Net.Samples.Mips", 21 | "program": "${workspaceRoot}/samples/Unicorn.Net.Samples.Mips/bin/Debug/netcoreapp2.0/Unicorn.Net.Samples.Mips.dll", 22 | "args": [], 23 | "cwd": "${workspaceRoot}/samples/Unicorn.Net.Samples.Mips", 24 | "stopAtEntry": false, 25 | "console": "internalConsole", 26 | "internalConsoleOptions": "openOnSessionStart" 27 | } 28 | ] 29 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "label": "build Unicorn.Net", 6 | "command": "dotnet", 7 | "type": "process", 8 | "args": [ 9 | "build", 10 | "-f", 11 | "netstandard2.0", 12 | "${workspaceFolder}/src/Unicorn.Net/Unicorn.Net.csproj" 13 | ], 14 | "problemMatcher": "$msCompile" 15 | }, 16 | { 17 | "label": "build Unicorn.Net.ConsoleTests", 18 | "command": "dotnet", 19 | "type": "process", 20 | "args": [ 21 | "build", 22 | "-f", 23 | "netcoreapp2.0", 24 | "${workspaceFolder}/src/Unicorn.Net.ConsoleTests/Unicorn.Net.ConsoleTests.csproj" 25 | ], 26 | "problemMatcher": "$msCompile" 27 | }, 28 | { 29 | "label": "build Unicorn.Net.Samples.Mips", 30 | "command": "dotnet", 31 | "type": "process", 32 | "args": [ 33 | "build", 34 | "-f", 35 | "netcoreapp2.0", 36 | "${workspaceFolder}/samples/Unicorn.Net.Samples.Mips/Unicorn.Net.Samples.Mips.csproj" 37 | ], 38 | "problemMatcher": "$msCompile" 39 | }, 40 | { 41 | "label": "build all", 42 | "command": "dotnet", 43 | "type": "process", 44 | "args": [ 45 | "build", 46 | "${workspaceFolder}" 47 | ], 48 | "problemMatcher": "$msCompile" 49 | } 50 | ] 51 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 FICTURE7 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 7 | of the Software, and to permit persons to whom the Software is furnished to do 8 | so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Unicorn.Net 2 | Slightly fancier *WIP* .NET binding/wrapper for the [Unicorn engine](https://github.com/unicorn-engine/unicorn). 3 | 4 | #### NOTE 5 | The API is very prone to changes at the moment. 6 | 7 | ### Examples 8 | 9 | Here is an example of how to use it. This is also the same example as the official documentation available [here](http://www.unicorn-engine.org/docs/tutorial.html) but in C# and using Unicorn.Net. 10 | ```csharp 11 | using (var emulator = new X86Emulator(X86Mode.b32)) 12 | { 13 | ulong addr = 0x1000000; 14 | byte[] x86code = 15 | { 16 | 0x41, // INC ECX 17 | 0x4a // DEC EDX 18 | }; 19 | 20 | var ecx = 0x1234; 21 | var edx = 0x7890; 22 | 23 | // Map 2mb of memory. 24 | emulator.Memory.Map(addr, 2 * 1024 * 1024, MemoryPermissions.All); 25 | 26 | emulator.Registers.ECX = ecx; 27 | emulator.Registers.EDX = edx; 28 | 29 | emulator.Memory.Write(addr, x86code, x86code.Length); 30 | 31 | emulator.Start(addr, addr + (ulong)x86code.Length); 32 | 33 | Console.WriteLine(emulator.Registers.ECX); 34 | Console.WriteLine(emulator.Registers.EDX); 35 | } 36 | ``` 37 | 38 | #### Registers 39 | Reading and writing to registers. 40 | ##### NOTE 41 | Currently there is no way to write to registers using register IDs, but this may change. 42 | ```csharp 43 | // Assume emulator is an instance of the X86Emulator type. 44 | 45 | // Reading from registers. 46 | var val = emulator.Registers.ECX; 47 | // Writing to registers. 48 | emulator.Registers.ECX = 0x10; 49 | ``` 50 | 51 | #### Memory 52 | Mapping, unmapping, reading, writing and changing memory permissions. 53 | ```csharp 54 | var addr = 0x100000; 55 | // Getting memory regions. 56 | var regions = emulator.Memory.Regions; 57 | // Getting memory page size. 58 | var pageSize = emulator.Memory.PageSize; 59 | 60 | // Mapping memory. 61 | emulator.Memory.Map(addr, 2 * 1024, 2 * 1024, MemoryPermissions.All); 62 | // Unmapping memory. 63 | emulator.Memory.Unmap(addr + (4 * 1024), 4 * 1024); 64 | // Changing memory permissions. 65 | emulator.Memory.Protect(addr + (4 * 1024), 4 * 1024, MemoryPermissions.Read); 66 | 67 | // Code to write to memory. 68 | var code = new byte[] 69 | { 70 | 0x41, // INC ECX 71 | 0x4a // DEC EDX 72 | } 73 | 74 | // Buffer thats going to be the storage for data read from memory. 75 | var buffer = new byte[2]; 76 | 77 | // Writing to memory. 78 | emulator.Memory.Write(code, 0, code.Length); 79 | // Reading to memory. 80 | emulator.Memory.Read(buffer, 0, buffer.Length); 81 | ``` 82 | 83 | #### Hooking 84 | Currently hooking is still under the works and may change. 85 | ```csharp 86 | // Adding a memory read hook. 87 | emulator.Hooks.Memory.Add(MemoryHookType.Read, (emu, type, address, size, val, userData) => { 88 | Console.WriteLine(" stuff was read from memory."); 89 | }, addr, addr + (ulong)code.Length, null); 90 | ``` 91 | 92 | #### Contexts 93 | Capturing and restoring contexts. 94 | ```csharp 95 | // emulator.Context will create a new Context object 96 | // which you will to dispose afterwards. Hence the `using` statement. 97 | 98 | // Capturing the context. 99 | using (var ctx = emulator.Context) 100 | { 101 | ... 102 | 103 | // To restore the context simply do this. 104 | emulator.Context = ctx; 105 | } 106 | ``` 107 | 108 | #### Raw Bindings 109 | Unicorn.Net also provide some raw bindings through the `Bindings` class. 110 | ```csharp 111 | var bindings = new Bindings(); 112 | bindings.Open(...); 113 | bindings.MemMap(...); 114 | ... 115 | ``` 116 | 117 | 118 | ### TODO 119 | List of stuff thats needs to be implemented or that has been implemented. 120 | - [x] Emulator 121 | - [x] uc_emu_start 122 | - [x] uc_emu_stop 123 | - [x] uc_query 124 | - [x] Context 125 | - [x] uc_context_alloc 126 | - [x] uc_context_save 127 | - [x] uc_context_restore 128 | - [x] Registers 129 | - [x] uc_reg_read 130 | - [x] uc_reg_write 131 | - [x] Memory 132 | - [x] uc_mem_write 133 | - [x] uc_mem_read 134 | - [x] uc_mem_protect 135 | - [x] uc_mem_regions 136 | - [x] uc_mem_map 137 | - [x] uc_mem_unmap 138 | - [ ] Hooking 139 | - [ ] uc_hook_add 140 | - [ ] uc_hook_del 141 | - [ ] Arches 142 | - [x] x86 143 | - [ ] arm 144 | - [ ] arm64 145 | - [ ] m68k 146 | - [ ] mips 147 | - [ ] sparc 148 | 149 | - [ ] Actual bindings 150 | 151 | ### Licensing 152 | Unicorn.Net is licensed under the permissive [MIT License](/LICENSE). 153 | -------------------------------------------------------------------------------- /Unicorn.Net.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 12.00 2 | # Visual Studio Version 16 3 | VisualStudioVersion = 16.0.29102.190 4 | MinimumVisualStudioVersion = 15.0.26124.0 5 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{0F6974D1-E9BD-41B6-A37A-100790E3B57A}" 6 | EndProject 7 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Unicorn.Net", "src\Unicorn.Net\Unicorn.Net.csproj", "{8F778952-21E3-4576-9522-8B636B8F7E5F}" 8 | EndProject 9 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Unicorn.Net.ConsoleTests", "src\Unicorn.Net.ConsoleTests\Unicorn.Net.ConsoleTests.csproj", "{7720430A-8615-437A-B488-C7D6964BB40C}" 10 | EndProject 11 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{67355AB9-E588-45AB-8B21-F200C03DA4D2}" 12 | EndProject 13 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Unicorn.Net.Samples.Arm", "samples\Unicorn.Net.Samples.Arm\Unicorn.Net.Samples.Arm.csproj", "{F10A53EB-41AB-461C-9D18-E2C3CF47FEBE}" 14 | EndProject 15 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Unicorn.Net.Samples.Mips", "samples\Unicorn.Net.Samples.Mips\Unicorn.Net.Samples.Mips.csproj", "{DBC23BBB-0028-4F5E-BAE2-F2FC3C708B59}" 16 | EndProject 17 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Unicorn.Net.Samples.Shellcode", "samples\Unicorn.Net.Samples.Shellcode\Unicorn.Net.Samples.Shellcode.csproj", "{7366613D-0132-42DF-BC16-899259FCA10B}" 18 | EndProject 19 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Unicorn.Net.Samples.X86", "samples\Unicorn.Net.Samples.X86\Unicorn.Net.Samples.X86.csproj", "{2B3D5780-B146-49D6-B855-4088897DF742}" 20 | EndProject 21 | Global 22 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 23 | Debug|Any CPU = Debug|Any CPU 24 | Debug|x64 = Debug|x64 25 | Debug|x86 = Debug|x86 26 | Release|Any CPU = Release|Any CPU 27 | Release|x64 = Release|x64 28 | Release|x86 = Release|x86 29 | EndGlobalSection 30 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 31 | {8F778952-21E3-4576-9522-8B636B8F7E5F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 32 | {8F778952-21E3-4576-9522-8B636B8F7E5F}.Debug|Any CPU.Build.0 = Debug|Any CPU 33 | {8F778952-21E3-4576-9522-8B636B8F7E5F}.Debug|x64.ActiveCfg = Debug|Any CPU 34 | {8F778952-21E3-4576-9522-8B636B8F7E5F}.Debug|x64.Build.0 = Debug|Any CPU 35 | {8F778952-21E3-4576-9522-8B636B8F7E5F}.Debug|x86.ActiveCfg = Debug|Any CPU 36 | {8F778952-21E3-4576-9522-8B636B8F7E5F}.Debug|x86.Build.0 = Debug|Any CPU 37 | {8F778952-21E3-4576-9522-8B636B8F7E5F}.Release|Any CPU.ActiveCfg = Release|Any CPU 38 | {8F778952-21E3-4576-9522-8B636B8F7E5F}.Release|Any CPU.Build.0 = Release|Any CPU 39 | {8F778952-21E3-4576-9522-8B636B8F7E5F}.Release|x64.ActiveCfg = Release|Any CPU 40 | {8F778952-21E3-4576-9522-8B636B8F7E5F}.Release|x64.Build.0 = Release|Any CPU 41 | {8F778952-21E3-4576-9522-8B636B8F7E5F}.Release|x86.ActiveCfg = Release|Any CPU 42 | {8F778952-21E3-4576-9522-8B636B8F7E5F}.Release|x86.Build.0 = Release|Any CPU 43 | {7720430A-8615-437A-B488-C7D6964BB40C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 44 | {7720430A-8615-437A-B488-C7D6964BB40C}.Debug|Any CPU.Build.0 = Debug|Any CPU 45 | {7720430A-8615-437A-B488-C7D6964BB40C}.Debug|x64.ActiveCfg = Debug|Any CPU 46 | {7720430A-8615-437A-B488-C7D6964BB40C}.Debug|x64.Build.0 = Debug|Any CPU 47 | {7720430A-8615-437A-B488-C7D6964BB40C}.Debug|x86.ActiveCfg = Debug|Any CPU 48 | {7720430A-8615-437A-B488-C7D6964BB40C}.Debug|x86.Build.0 = Debug|Any CPU 49 | {7720430A-8615-437A-B488-C7D6964BB40C}.Release|Any CPU.ActiveCfg = Release|Any CPU 50 | {7720430A-8615-437A-B488-C7D6964BB40C}.Release|Any CPU.Build.0 = Release|Any CPU 51 | {7720430A-8615-437A-B488-C7D6964BB40C}.Release|x64.ActiveCfg = Release|Any CPU 52 | {7720430A-8615-437A-B488-C7D6964BB40C}.Release|x64.Build.0 = Release|Any CPU 53 | {7720430A-8615-437A-B488-C7D6964BB40C}.Release|x86.ActiveCfg = Release|Any CPU 54 | {7720430A-8615-437A-B488-C7D6964BB40C}.Release|x86.Build.0 = Release|Any CPU 55 | {F10A53EB-41AB-461C-9D18-E2C3CF47FEBE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 56 | {F10A53EB-41AB-461C-9D18-E2C3CF47FEBE}.Debug|Any CPU.Build.0 = Debug|Any CPU 57 | {F10A53EB-41AB-461C-9D18-E2C3CF47FEBE}.Debug|x64.ActiveCfg = Debug|Any CPU 58 | {F10A53EB-41AB-461C-9D18-E2C3CF47FEBE}.Debug|x64.Build.0 = Debug|Any CPU 59 | {F10A53EB-41AB-461C-9D18-E2C3CF47FEBE}.Debug|x86.ActiveCfg = Debug|Any CPU 60 | {F10A53EB-41AB-461C-9D18-E2C3CF47FEBE}.Debug|x86.Build.0 = Debug|Any CPU 61 | {F10A53EB-41AB-461C-9D18-E2C3CF47FEBE}.Release|Any CPU.ActiveCfg = Release|Any CPU 62 | {F10A53EB-41AB-461C-9D18-E2C3CF47FEBE}.Release|Any CPU.Build.0 = Release|Any CPU 63 | {F10A53EB-41AB-461C-9D18-E2C3CF47FEBE}.Release|x64.ActiveCfg = Release|Any CPU 64 | {F10A53EB-41AB-461C-9D18-E2C3CF47FEBE}.Release|x64.Build.0 = Release|Any CPU 65 | {F10A53EB-41AB-461C-9D18-E2C3CF47FEBE}.Release|x86.ActiveCfg = Release|Any CPU 66 | {F10A53EB-41AB-461C-9D18-E2C3CF47FEBE}.Release|x86.Build.0 = Release|Any CPU 67 | {DBC23BBB-0028-4F5E-BAE2-F2FC3C708B59}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 68 | {DBC23BBB-0028-4F5E-BAE2-F2FC3C708B59}.Debug|Any CPU.Build.0 = Debug|Any CPU 69 | {DBC23BBB-0028-4F5E-BAE2-F2FC3C708B59}.Debug|x64.ActiveCfg = Debug|Any CPU 70 | {DBC23BBB-0028-4F5E-BAE2-F2FC3C708B59}.Debug|x64.Build.0 = Debug|Any CPU 71 | {DBC23BBB-0028-4F5E-BAE2-F2FC3C708B59}.Debug|x86.ActiveCfg = Debug|Any CPU 72 | {DBC23BBB-0028-4F5E-BAE2-F2FC3C708B59}.Debug|x86.Build.0 = Debug|Any CPU 73 | {DBC23BBB-0028-4F5E-BAE2-F2FC3C708B59}.Release|Any CPU.ActiveCfg = Release|Any CPU 74 | {DBC23BBB-0028-4F5E-BAE2-F2FC3C708B59}.Release|Any CPU.Build.0 = Release|Any CPU 75 | {DBC23BBB-0028-4F5E-BAE2-F2FC3C708B59}.Release|x64.ActiveCfg = Release|Any CPU 76 | {DBC23BBB-0028-4F5E-BAE2-F2FC3C708B59}.Release|x64.Build.0 = Release|Any CPU 77 | {DBC23BBB-0028-4F5E-BAE2-F2FC3C708B59}.Release|x86.ActiveCfg = Release|Any CPU 78 | {DBC23BBB-0028-4F5E-BAE2-F2FC3C708B59}.Release|x86.Build.0 = Release|Any CPU 79 | {7366613D-0132-42DF-BC16-899259FCA10B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 80 | {7366613D-0132-42DF-BC16-899259FCA10B}.Debug|Any CPU.Build.0 = Debug|Any CPU 81 | {7366613D-0132-42DF-BC16-899259FCA10B}.Debug|x64.ActiveCfg = Debug|Any CPU 82 | {7366613D-0132-42DF-BC16-899259FCA10B}.Debug|x64.Build.0 = Debug|Any CPU 83 | {7366613D-0132-42DF-BC16-899259FCA10B}.Debug|x86.ActiveCfg = Debug|Any CPU 84 | {7366613D-0132-42DF-BC16-899259FCA10B}.Debug|x86.Build.0 = Debug|Any CPU 85 | {7366613D-0132-42DF-BC16-899259FCA10B}.Release|Any CPU.ActiveCfg = Release|Any CPU 86 | {7366613D-0132-42DF-BC16-899259FCA10B}.Release|Any CPU.Build.0 = Release|Any CPU 87 | {7366613D-0132-42DF-BC16-899259FCA10B}.Release|x64.ActiveCfg = Release|Any CPU 88 | {7366613D-0132-42DF-BC16-899259FCA10B}.Release|x64.Build.0 = Release|Any CPU 89 | {7366613D-0132-42DF-BC16-899259FCA10B}.Release|x86.ActiveCfg = Release|Any CPU 90 | {7366613D-0132-42DF-BC16-899259FCA10B}.Release|x86.Build.0 = Release|Any CPU 91 | {2B3D5780-B146-49D6-B855-4088897DF742}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 92 | {2B3D5780-B146-49D6-B855-4088897DF742}.Debug|Any CPU.Build.0 = Debug|Any CPU 93 | {2B3D5780-B146-49D6-B855-4088897DF742}.Debug|x64.ActiveCfg = Debug|Any CPU 94 | {2B3D5780-B146-49D6-B855-4088897DF742}.Debug|x64.Build.0 = Debug|Any CPU 95 | {2B3D5780-B146-49D6-B855-4088897DF742}.Debug|x86.ActiveCfg = Debug|Any CPU 96 | {2B3D5780-B146-49D6-B855-4088897DF742}.Debug|x86.Build.0 = Debug|Any CPU 97 | {2B3D5780-B146-49D6-B855-4088897DF742}.Release|Any CPU.ActiveCfg = Release|Any CPU 98 | {2B3D5780-B146-49D6-B855-4088897DF742}.Release|Any CPU.Build.0 = Release|Any CPU 99 | {2B3D5780-B146-49D6-B855-4088897DF742}.Release|x64.ActiveCfg = Release|Any CPU 100 | {2B3D5780-B146-49D6-B855-4088897DF742}.Release|x64.Build.0 = Release|Any CPU 101 | {2B3D5780-B146-49D6-B855-4088897DF742}.Release|x86.ActiveCfg = Release|Any CPU 102 | {2B3D5780-B146-49D6-B855-4088897DF742}.Release|x86.Build.0 = Release|Any CPU 103 | EndGlobalSection 104 | GlobalSection(SolutionProperties) = preSolution 105 | HideSolutionNode = FALSE 106 | EndGlobalSection 107 | GlobalSection(NestedProjects) = preSolution 108 | {8F778952-21E3-4576-9522-8B636B8F7E5F} = {0F6974D1-E9BD-41B6-A37A-100790E3B57A} 109 | {7720430A-8615-437A-B488-C7D6964BB40C} = {0F6974D1-E9BD-41B6-A37A-100790E3B57A} 110 | {F10A53EB-41AB-461C-9D18-E2C3CF47FEBE} = {67355AB9-E588-45AB-8B21-F200C03DA4D2} 111 | {DBC23BBB-0028-4F5E-BAE2-F2FC3C708B59} = {67355AB9-E588-45AB-8B21-F200C03DA4D2} 112 | {7366613D-0132-42DF-BC16-899259FCA10B} = {67355AB9-E588-45AB-8B21-F200C03DA4D2} 113 | {2B3D5780-B146-49D6-B855-4088897DF742} = {67355AB9-E588-45AB-8B21-F200C03DA4D2} 114 | EndGlobalSection 115 | GlobalSection(ExtensibilityGlobals) = postSolution 116 | SolutionGuid = {8843C534-A879-477F-A705-B7A42D7DEC57} 117 | EndGlobalSection 118 | EndGlobal 119 | -------------------------------------------------------------------------------- /samples/Unicorn.Net.Samples.Arm/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Unicorn.Arm; 3 | 4 | namespace Unicorn.Net.Samples.Arm 5 | { 6 | // Similar to sample_arm.c 7 | public class Program 8 | { 9 | public static void HookBlock(Emulator emu, ulong address, int size, object userToken) 10 | { 11 | Console.WriteLine($">>> Tracing basic block at 0x{address.ToString("x2")}, block size = 0x{size.ToString("x2")}"); 12 | } 13 | 14 | public static void HookCode(Emulator emu, ulong address, int size, object userToken) 15 | { 16 | Console.WriteLine($">>> Tracing instruction at 0x{address.ToString("x2")}, instruction size = 0x{size.ToString("x2")}"); 17 | } 18 | 19 | // test_arm 20 | public static void TestArm() 21 | { 22 | Console.WriteLine("Emulate ARM code"); 23 | 24 | using (var emulator = new ArmEmulator(ArmMode.Arm)) 25 | { 26 | ulong addr = 0x10000; 27 | 28 | // mov r0, #0x37; sub r1, r2, r3 29 | byte[] armcode = 30 | { 31 | 0x37, 0x00, 0xa0, 0xe3, 0x03, 0x10, 0x42, 0xe0 32 | }; 33 | 34 | // Map 2mb of memory. 35 | emulator.Memory.Map(addr, 2 * 1024 * 1024, MemoryPermissions.All); 36 | emulator.Memory.Write(addr, armcode, armcode.Length); 37 | 38 | emulator.Registers.R0 = 0x1234; 39 | emulator.Registers.R2 = 0x6789; 40 | emulator.Registers.R3 = 0x3333; 41 | 42 | emulator.Hooks.Block.Add(HookBlock, null); 43 | emulator.Hooks.Code.Add(HookCode, addr, addr, null); 44 | 45 | emulator.Start(addr, addr + (ulong)armcode.Length); 46 | 47 | Console.WriteLine(">>> Emulation done. Below is the CPU context"); 48 | Console.WriteLine($">>> R0 = 0x{emulator.Registers.R0.ToString("x2")}"); 49 | Console.WriteLine($">>> R1 = 0x{emulator.Registers.R1.ToString("x2")}"); 50 | } 51 | } 52 | 53 | // test_thumb 54 | public static void TestThumb() 55 | { 56 | Console.WriteLine("Emulate THUMB code"); 57 | 58 | using (var emulator = new ArmEmulator(ArmMode.Thumb)) 59 | { 60 | ulong addr = 0x10000; 61 | 62 | // sub sp, #0xc 63 | byte[] armcode = 64 | { 65 | 0x83, 0xb0 66 | }; 67 | 68 | // Map 2mb of memory. 69 | emulator.Memory.Map(addr, 2 * 1024 * 1024, MemoryPermissions.All); 70 | emulator.Memory.Write(addr, armcode, armcode.Length); 71 | 72 | emulator.Registers.SP = 0x1234; 73 | 74 | emulator.Hooks.Block.Add(HookBlock, null); 75 | emulator.Hooks.Code.Add(HookCode, addr, addr, null); 76 | 77 | emulator.Start(addr | 1, addr + (ulong)armcode.Length); 78 | 79 | Console.WriteLine(">>> Emulation done. Below is the CPU context"); 80 | Console.WriteLine($">>> SP = 0x{emulator.Registers.SP.ToString("x2")}"); 81 | } 82 | } 83 | 84 | public static void Main(string[] args) 85 | { 86 | TestArm(); 87 | 88 | Console.WriteLine("=========================="); 89 | 90 | TestThumb(); 91 | 92 | Console.ReadLine(); 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /samples/Unicorn.Net.Samples.Arm/Unicorn.Net.Samples.Arm.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | netcoreapp1.1;netcoreapp2.0;net45 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /samples/Unicorn.Net.Samples.Mips/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Unicorn.Mips; 3 | 4 | namespace Unicorn.Net.Samples.Mips 5 | { 6 | // Similar to 7 | // samples/sample_mips.c 8 | 9 | public static class Program 10 | { 11 | // test_mips_eb 12 | public static void TestMipsEb() 13 | { 14 | Console.WriteLine("Emulate MIPS code (big-endian)"); 15 | 16 | using (var emulator = new MipsEmulator(MipsMode.b32 | MipsMode.BigEndian)) 17 | { 18 | ulong addr = 0x10000; 19 | byte[] mipscode = 20 | { 21 | 0x34, 0x21, 0x34, 0x56 22 | }; 23 | 24 | emulator.Memory.Map(addr, 2 * 1024 * 1024, MemoryPermissions.All); 25 | emulator.Memory.Write(addr, mipscode, mipscode.Length); 26 | 27 | emulator.Registers.AT = 0x6789; 28 | // or 29 | // emulator.Registers._1 = 0x6789 30 | 31 | emulator.Hooks.Block.Add(BlockHook, null); 32 | emulator.Hooks.Code.Add(CodeHook, addr, addr, null); 33 | emulator.Start(addr, addr + (ulong)mipscode.Length); 34 | 35 | Console.WriteLine(">>> Emulation done. Below is the CPU context"); 36 | Console.WriteLine($">>> R1 = 0x{emulator.Registers.AT.ToString("x2")}"); 37 | } 38 | } 39 | 40 | // test_mips_el 41 | public static void TestMipsEl() 42 | { 43 | Console.WriteLine("==========================="); 44 | Console.WriteLine("Emulate MIPS code (little-endian)"); 45 | 46 | using (var emulator = new MipsEmulator(MipsMode.b32 | MipsMode.LittleEndian)) 47 | { 48 | ulong addr = 0x10000; 49 | byte[] mipscode = 50 | { 51 | 0x56, 0x34, 0x21, 0x34 52 | }; 53 | 54 | emulator.Memory.Map(addr, 2 * 1024 * 1024, MemoryPermissions.All); 55 | emulator.Memory.Write(addr, mipscode, mipscode.Length); 56 | 57 | emulator.Registers.AT = 0x6789; 58 | // or 59 | // emulator.Registers._1 = 0x6789 60 | 61 | emulator.Hooks.Block.Add(BlockHook, null); 62 | emulator.Hooks.Code.Add(CodeHook, addr, addr, null); 63 | emulator.Start(addr, addr + (ulong)mipscode.Length); 64 | 65 | Console.WriteLine(">>> Emulation done. Below is the CPU context"); 66 | Console.WriteLine($">>> R1 = 0x{emulator.Registers.AT.ToString("x2")}"); 67 | } 68 | } 69 | 70 | public static void Main(string[] args) 71 | { 72 | TestMipsEb(); 73 | TestMipsEl(); 74 | } 75 | 76 | private static void BlockHook(Emulator emulator, ulong address, int size, object userToken) 77 | { 78 | Console.WriteLine($">>> Tracing basic block at 0x{address.ToString("x2")}, block size = 0x{size.ToString("x2")}"); 79 | } 80 | 81 | private static void CodeHook(Emulator emulator, ulong address, int size, object userToken) 82 | { 83 | Console.WriteLine($">>> Tracing instruction at 0x{address.ToString("x2")}, instruction size = 0x{size.ToString("x2")}"); 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /samples/Unicorn.Net.Samples.Mips/Unicorn.Net.Samples.Mips.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | netcoreapp1.1;netcoreapp2.0;net45 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /samples/Unicorn.Net.Samples.Shellcode/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using Unicorn.X86; 4 | 5 | namespace Unicorn.Net.Samples.Shellcode 6 | { 7 | // Similar to 8 | // samples/sample_shellcode.c 9 | 10 | public class Program 11 | { 12 | // test_i386 13 | public static void Test() 14 | { 15 | ulong addr = 0x1000000; 16 | ulong esp = addr + 0x200000; 17 | byte[] code = 18 | { 19 | 0xeb, 0x1c, 0x5a, 0x89, 0xd6, 0x8b, 0x02, 0x66, 0x3d, 20 | 0xca, 0x7d, 0x75, 0x06, 0x66, 0x05, 0x03, 0x03, 0x89, 21 | 0x02, 0xfe, 0xc2, 0x3d, 0x41, 0x41, 0x41, 0x41, 0x75, 22 | 0xe9, 0xff, 0xe6, 0xe8, 0xdf, 0xff, 0xff, 0xff, 0x31, 23 | 0xd2, 0x6a, 0x0b, 0x58, 0x99, 0x52, 0x68, 0x2f, 0x2f, 24 | 0x73, 0x68, 0x68, 0x2f, 0x62, 0x69, 0x6e, 0x89, 0xe3, 25 | 0x52, 0x53, 0x89, 0xe1, 0xca, 0x7d, 0x41, 0x41, 0x41, 26 | 0x41, 0x41, 0x41, 0x41, 0x41 27 | }; 28 | 29 | Console.WriteLine("Emulate i386 code"); 30 | 31 | using (var emulator = new X86Emulator(X86Mode.b32)) 32 | { 33 | emulator.Memory.Map(addr, 2 * 1024 * 1024, MemoryPermissions.All); 34 | emulator.Memory.Write(addr, code, code.Length); 35 | 36 | emulator.Registers.ESP = (long)esp; 37 | 38 | emulator.Hooks.Code.Add(HookCode, null); 39 | emulator.Hooks.Interrupt.Add(HookInterrupt, null); 40 | 41 | Console.WriteLine(); 42 | Console.WriteLine(">>> Start tracing this Linux code"); 43 | 44 | emulator.Start(addr, addr + (ulong)code.Length); 45 | 46 | Console.WriteLine(); 47 | Console.WriteLine(">>> Emulation done."); 48 | } 49 | } 50 | 51 | // hook_intr 52 | private static void HookInterrupt(Emulator emulator, int into, object userData) 53 | { 54 | var registers = ((X86Emulator)emulator).Registers; 55 | var buffer = new byte[256]; 56 | 57 | if (into != 0x80) 58 | return; 59 | 60 | var eax = registers.EAX; 61 | var eip = registers.EIP; 62 | switch (eax) 63 | { 64 | default: 65 | Console.WriteLine($">>> 0x{eip.ToString("x2")}: interrupt 0x{into.ToString("x2")}, EAX = 0x{eax.ToString("x2")}"); 66 | break; 67 | 68 | case 1: // sys_exit 69 | Console.WriteLine($">>> 0x{eip.ToString("x2")}: interrupt 0x{into.ToString("x2")}, SYS_EXIT. quit!"); 70 | Console.WriteLine(); 71 | emulator.Stop(); 72 | break; 73 | 74 | case 4: 75 | var ecx = registers.ECX; 76 | var edx = registers.EDX; 77 | 78 | var count = buffer.Length < edx ? buffer.Length : (int)edx; 79 | emulator.Memory.Read((ulong)ecx, buffer, count); 80 | 81 | // >>> 0x%x: interrupt 0x%x, SYS_WRITE. buffer = 0x%x, size = %u, content = '%s'\n 82 | // r_eip, intno, r_ecx, r_edx, buffer 83 | Console.WriteLine($">>> 0x{eip.ToString("x2")}: interrupts 0x{into.ToString("x2")}, SYS_WRITE. buffer = 0x{ecx.ToString("x2")}, size = {edx.ToString("x2")}, content = {Encoding.UTF8.GetString(buffer)}"); 84 | break; 85 | } 86 | } 87 | 88 | // hook_code 89 | private static void HookCode(Emulator emulator, ulong address, int size, object userData) 90 | { 91 | Console.WriteLine($"Tracing instruction at 0x{address.ToString("x2")}, instruction size = 0x{size.ToString("x2")}"); 92 | 93 | var tmp = new byte[16]; 94 | var eip = ((X86Emulator)emulator).Registers.EIP; 95 | var count = tmp.Length < size ? tmp.Length : size; // MIN 96 | 97 | Console.Write($"*** EIP = {eip.ToString("x2")} ***: "); 98 | 99 | emulator.Memory.Read(address, tmp, count); 100 | for (int i = 0; i < count; i++) 101 | Console.Write(tmp[i].ToString("x2") + " "); 102 | Console.WriteLine(); 103 | } 104 | 105 | public static void Main(string[] args) 106 | { 107 | Test(); 108 | 109 | Console.ReadLine(); 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /samples/Unicorn.Net.Samples.Shellcode/Unicorn.Net.Samples.Shellcode.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | netcoreapp1.1;netcoreapp2.0;net45 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /samples/Unicorn.Net.Samples.X86/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using Unicorn.X86; 4 | 5 | namespace Unicorn.Net.Samples.X86 6 | { 7 | // Similar to 8 | // samples/sample_x86.c 9 | 10 | public class Program 11 | { 12 | // test_i386_invalid_mem_read 13 | public static void TestInvalidMemoryRead() 14 | { 15 | var addr = 0x1000000UL; 16 | var code = new byte[] 17 | { 18 | 0x8B, 0x0D, 0xAA, 0xAA, 0xAA, 0xAA, // MOV ecx [0xaaaaaaaa] 19 | 0x41, // INC ecx 20 | 0x4A // DEC edx 21 | }; 22 | 23 | Console.WriteLine("==================================="); 24 | Console.WriteLine("Emulate i386 code that read from invalid memory."); 25 | 26 | using (var emulator = new X86Emulator(X86Mode.b32)) 27 | { 28 | // Map 2MB of memory. 29 | emulator.Memory.Map(addr, 2 * 1024 * 1024, MemoryPermissions.All); 30 | // Write machine code to be emulated. 31 | emulator.Memory.Write(addr, code, code.Length); 32 | 33 | // Initialize registers. 34 | emulator.Registers.ECX = 0x1234; 35 | emulator.Registers.EDX = 0x7890; 36 | 37 | // Trace all basic blocks. 38 | emulator.Hooks.Block.Add(BlockHook, null); 39 | // Trace all instructions. 40 | emulator.Hooks.Code.Add(CodeHook, null); 41 | 42 | try 43 | { 44 | // Start emulating the machine written machine code. 45 | emulator.Start(addr, addr + (ulong)code.Length); 46 | } 47 | catch (UnicornException ex) 48 | { 49 | Debug.Assert(ex.ErrorCode == UnicornError.ReadUnmapped, "Unexpected error code in caught UnicornException."); 50 | Console.WriteLine($"Failed to start emulator instance. -> {ex.Message}."); 51 | } 52 | 53 | Console.WriteLine(">>> Emulation done. Below is the CPU context"); 54 | Console.WriteLine($">>> ECX = 0x{emulator.Registers.ECX.ToString("x2")}"); 55 | Console.WriteLine($">>> EDX = 0x{emulator.Registers.EDX.ToString("x2")}"); 56 | } 57 | } 58 | 59 | // test_i386_invalid_mem_write 60 | public static void TestInvalidMemoryWrite() 61 | { 62 | var addr = 0x1000000UL; 63 | var code = new byte[] 64 | { 65 | 0x89, 0x0D, 0xAA, 0xAA, 0xAA, 0xAA, // MOV [0xaaaaaaaa] ecx 66 | 0x41, // INC ecx 67 | 0x4A // DEC edx 68 | }; 69 | 70 | Console.WriteLine("==================================="); 71 | Console.WriteLine("Emulate i386 code that write to invalid memory."); 72 | 73 | using (var emulator = new X86Emulator(X86Mode.b32)) 74 | { 75 | // Map 2MB of memory. 76 | emulator.Memory.Map(addr, 2 * 1024 * 1024, MemoryPermissions.All); 77 | // Write machine code to be emulated. 78 | emulator.Memory.Write(addr, code, code.Length); 79 | 80 | // Initialize registers. 81 | emulator.Registers.ECX = 0x1234; 82 | emulator.Registers.EDX = 0x7890; 83 | 84 | emulator.Hooks.Code.Add(CodeHook, null); 85 | emulator.Hooks.Memory.Add(MemoryEventHookType.UnmappedRead | MemoryEventHookType.UnmappedWrite, InvalidMemoryHook, null); 86 | 87 | // Start emulating the machine written machine code. 88 | emulator.Start(addr, addr + (ulong)code.Length); 89 | 90 | Console.WriteLine(">>> Emulation done. Below is the CPU context"); 91 | Console.WriteLine($">>> ECX = 0x{emulator.Registers.ECX.ToString("x2")}"); 92 | Console.WriteLine($">>> EDX = 0x{emulator.Registers.EDX.ToString("x2")}"); 93 | 94 | // Read from memory. 95 | var buffer = new byte[4]; 96 | var tmp = 0; 97 | 98 | emulator.Memory.Read(0xAAAAAAAA, buffer, buffer.Length); 99 | tmp = BitConverter.ToInt32(buffer, 0); 100 | 101 | Console.WriteLine($">>> Read 4 bytes from [0x{0xAAAAAAAA.ToString("x2")}] = 0x{tmp.ToString("x2")}"); 102 | 103 | try 104 | { 105 | emulator.Memory.Read(0xFFFFFFAA, buffer, buffer.Length); 106 | tmp = BitConverter.ToInt32(buffer, 0); 107 | Console.WriteLine($">>> Read 4 bytes from [0x{0xFFFFFFAA.ToString("x2")}] = 0x{tmp.ToString("x2")}"); 108 | } 109 | catch 110 | { 111 | Console.WriteLine($">>> Failed to read 4 bytes from [0x{0xFFFFFFAA.ToString("x2")}]"); 112 | } 113 | } 114 | } 115 | 116 | // test_i386_context_save 117 | public static void TestContextSave() 118 | { 119 | var addr = 0x1000000UL; 120 | var code = new byte[] 121 | { 122 | 0x40, // INC eax 123 | }; 124 | 125 | Console.WriteLine("==================================="); 126 | Console.WriteLine("Save/restore CPU context in opaque blob."); 127 | 128 | using (var emulator = new X86Emulator(X86Mode.b32)) 129 | { 130 | // Map 8KB of memory for emulation. 131 | emulator.Memory.Map(addr, 8 * 1024, MemoryPermissions.All); 132 | // Write machine code to emulate. 133 | emulator.Memory.Write(addr, code, code.Length); 134 | 135 | // Initialize registers. 136 | emulator.Registers.EAX = 1; 137 | 138 | // Emulate written machine code. 139 | emulator.Start(addr, addr + (ulong)code.Length); 140 | 141 | Console.WriteLine(">>> Emulation done. Below is the CPU context"); 142 | Console.WriteLine($">>> EAX = 0x{emulator.Registers.EAX.ToString("x2")}"); 143 | 144 | Console.WriteLine(">>> Saving CPU context"); 145 | 146 | using (var context = emulator.Context) 147 | { 148 | Console.WriteLine(">>> Running emulation for the second time"); 149 | 150 | // Emulate machine code again. 151 | emulator.Start(addr, addr + (ulong)code.Length); 152 | 153 | Console.WriteLine(">>> Emulation done. Below is the CPU context"); 154 | Console.WriteLine($">>> EAX = 0x{emulator.Registers.EAX.ToString("x2")}"); 155 | 156 | emulator.Context = context; 157 | } 158 | 159 | Console.WriteLine(">>> CPU context restored. Below is the CPU context"); 160 | Console.WriteLine($">>> EAX = 0x{emulator.Registers.EAX.ToString("x2")}"); 161 | } 162 | } 163 | 164 | // test_i386_inout 165 | public static void TestInOut() 166 | { 167 | var addr = 0x1000000UL; 168 | var code = new byte[] 169 | { 170 | 0x41, // INC ecx 171 | 0xE4, 0x3F, // IN AL 0x3F 172 | 0x4A, // DEC edx 173 | 0xE6, 0x46, // OUT 0x46 AL 174 | 0x43 // INC ebx 175 | }; 176 | 177 | Console.WriteLine("==================================="); 178 | Console.WriteLine("Emulate i386 code with IN/OUT instructions."); 179 | 180 | using (var emulator = new X86Emulator(X86Mode.b32)) 181 | { 182 | // Map 2MB of memory. 183 | emulator.Memory.Map(addr, 2 * 1024 * 1024, MemoryPermissions.All); 184 | // Write machine code to be emulated. 185 | emulator.Memory.Write(addr, code, code.Length); 186 | 187 | // Initialize registers. 188 | emulator.Registers.ECX = 0x1234; 189 | emulator.Registers.EDX = 0x7890; 190 | 191 | // Trace all basic blocks. 192 | emulator.Hooks.Block.Add(BlockHook, null); 193 | // Trace all instructions. 194 | emulator.Hooks.Code.Add(CodeHook, null); 195 | // Hook X86 IN instructions. 196 | emulator.Hooks.Instruction.Add(HookIn, X86Instructions.IN, null); 197 | // Hook X86 OUT instructions. 198 | emulator.Hooks.Instruction.Add(HookOut, X86Instructions.OUT, null); 199 | 200 | // Start emulating the machine written machine code. 201 | emulator.Start(addr, addr + (ulong)code.Length); 202 | 203 | Console.WriteLine(">>> Emulation done. Below is the CPU context"); 204 | Console.WriteLine($">>> ECX = 0x{emulator.Registers.ECX.ToString("x2")}"); 205 | Console.WriteLine($">>> EDX = 0x{emulator.Registers.EDX.ToString("x2")}"); 206 | } 207 | } 208 | 209 | // test_i386_loop 210 | public static void TestLoop() 211 | { 212 | var addr = 0x1000000UL; 213 | var code = new byte[] 214 | { 215 | 0x41, // INC ecx 216 | 0x4A, // DEC edx 217 | 0xEB, // JMP self-loop 218 | 0xFE 219 | }; 220 | 221 | Console.WriteLine("==================================="); 222 | Console.WriteLine("Emulate i386 code that emulates forever."); 223 | 224 | using (var emulator = new X86Emulator(X86Mode.b32)) 225 | { 226 | // Map 2MB of memory. 227 | emulator.Memory.Map(addr, 2 * 1024 * 1024, MemoryPermissions.All); 228 | // Write machine code to be emulated. 229 | emulator.Memory.Write(addr, code, code.Length); 230 | 231 | // Initialize registers. 232 | emulator.Registers.ECX = 0x1234; 233 | emulator.Registers.EDX = 0x7890; 234 | 235 | // Emulate code for 2 seconds, so we can exit the code since it loops forever. 236 | emulator.Start(addr, addr + (ulong)code.Length, TimeSpan.FromSeconds(2), 0); 237 | 238 | Console.WriteLine(">>> Emulation done. Below is the CPU context"); 239 | Console.WriteLine($">>> ECX = 0x{emulator.Registers.ECX.ToString("x2")}"); 240 | Console.WriteLine($">>> EDX = 0x{emulator.Registers.EDX.ToString("x2")}"); 241 | } 242 | } 243 | 244 | // hook_code 245 | public static void CodeHook(Emulator emulator, ulong address, int size, object userData) 246 | { 247 | var eflags = ((X86Emulator)emulator).Registers.EFLAGS; 248 | 249 | Console.WriteLine($">>> Tracing instruction at 0x{address.ToString("x2")}, instruction size = 0x{size.ToString("x2")}."); 250 | Console.WriteLine($">>> --- EFLAGS is {eflags.ToString("x2")}"); 251 | } 252 | 253 | // hook_block 254 | private static void BlockHook(Emulator emulator, ulong address, int size, object userData) 255 | { 256 | Console.WriteLine($">>> Tracing basic block at 0x{address.ToString("x2")}, block size = 0x{size.ToString("x2")}"); 257 | } 258 | 259 | // hook_out 260 | private static void HookOut(Emulator emulator, int port, int size, int value, object userData) 261 | { 262 | var registers = ((X86Emulator)emulator).Registers; 263 | var eip = registers.EIP; 264 | var tmp = 0L; 265 | 266 | Console.WriteLine($">>> --- Writing to port 0x{port.ToString("x2")}, size: {size}, value: 0x{value.ToString("x2")}, address: 0x{eip.ToString("x2")}"); 267 | 268 | switch (size) 269 | { 270 | case 1: 271 | tmp = registers.AL; 272 | break; 273 | case 2: 274 | tmp = registers.AX; 275 | break; 276 | case 4: 277 | tmp = registers.EAX; 278 | break; 279 | default: 280 | return; 281 | } 282 | 283 | Console.WriteLine($">>> --- Register value = 0x{tmp.ToString("x2")}"); 284 | } 285 | 286 | // hook_in 287 | private static int HookIn(Emulator emulator, int port, int size, object userData) 288 | { 289 | var eip = ((X86Emulator)emulator).Registers.EIP; 290 | Console.WriteLine($">>> --- Reading from port 0x{port.ToString("x2")}, size: {size}, address: 0x{eip.ToString("x2")}"); 291 | 292 | switch (size) 293 | { 294 | case 1: 295 | return 0xF1; 296 | case 2: 297 | return 0xF2; 298 | case 4: 299 | return 0xF4; 300 | default: 301 | return 0; 302 | } 303 | } 304 | 305 | // hook_mem_invalid 306 | private static bool InvalidMemoryHook(Emulator emulator, MemoryType type, ulong address, int size, ulong value, object userData) 307 | { 308 | switch (type) 309 | { 310 | case MemoryType.WriteUnmapped: 311 | Console.WriteLine($">>> Missing memory is being WRITE at 0x{address.ToString("x2")}, data size = {size}, data value = 0x{value.ToString("x2")}"); 312 | 313 | // Map missing memory & return true to tell unicorn we want to continue execution. 314 | emulator.Memory.Map(0xAAAA0000, 2 * 1024 * 1024, MemoryPermissions.All); 315 | return true; 316 | 317 | default: 318 | return false; 319 | } 320 | } 321 | 322 | public static void Main(string[] args) 323 | { 324 | TestInvalidMemoryRead(); 325 | TestInvalidMemoryWrite(); 326 | TestInOut(); 327 | TestContextSave(); 328 | TestLoop(); 329 | 330 | Console.ReadLine(); 331 | } 332 | } 333 | } 334 | -------------------------------------------------------------------------------- /samples/Unicorn.Net.Samples.X86/Unicorn.Net.Samples.X86.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | netcoreapp1.1;netcoreapp2.0;net45 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /scripts/gen_ins_fields.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | def main(args): 4 | if len(args) < 2: 5 | print("Must specify file defining instructions in command line argument.", file=sys.stderr) 6 | exit(1) 7 | 8 | ins_file = open(args[1], 'r') 9 | inses = ins_file.read().split(',') 10 | ins_file.close() 11 | 12 | insid = 1 13 | final_code = "" 14 | for ins in inses: 15 | ins = ins.strip() 16 | 17 | name = ins[ins.rindex('_') + 1:] 18 | code = "/// \n/// Represents the {0} instruction.\n/// \n".format(name) 19 | code += "public static readonly Instruction {0} = new Instruction({1});\n\n".format(name, insid) 20 | 21 | insid += 1 22 | final_code += code 23 | 24 | code_file = open(args[1] + '.cs', 'w') 25 | code_file.write(final_code); 26 | 27 | if __name__ == "__main__": 28 | main(sys.argv) -------------------------------------------------------------------------------- /scripts/gen_reg_properties.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import os 3 | 4 | from enum import Enum 5 | 6 | class Register(object): 7 | def __init__(self, name, id): 8 | self.__name = name 9 | self.__id = id 10 | 11 | @property 12 | def name(self): 13 | return self.__name 14 | 15 | @property 16 | def id(self): 17 | return self.__id 18 | 19 | @id.setter 20 | def id(self, id): 21 | self.__id = id 22 | 23 | def __str__(self): 24 | return "reg({0}:{1})".format(self.name, self.id) 25 | 26 | class TokenType(Enum): 27 | EOF = 0 28 | IDENT = 1 29 | INTEGER = 2 30 | EQUAL = 3 31 | COMMA = 4 32 | 33 | class Token(object): 34 | def __init__(self, value, type): 35 | self.__value = value 36 | self.__type = type 37 | 38 | @property 39 | def value(self): 40 | return self.__value 41 | 42 | @property 43 | def type(self): 44 | return self.__type 45 | 46 | def __str__(self): 47 | return "tok({0}:'{1}')".format(self.__type, self.__value) 48 | 49 | class Lexer(object): 50 | def __init__(self, src): 51 | self.__cur = None 52 | self.__src = src 53 | self.__pos = 0 54 | 55 | # Set the __cur character we're processing. 56 | self.__advance() 57 | 58 | def __skip_whitespace(self): 59 | while self.__cur.isspace(): 60 | self.__advance() 61 | 62 | def __advance(self): 63 | if (self.__pos > len(self.__src) - 1): 64 | self.__cur = None 65 | else: 66 | self.__cur = self.__src[self.__pos] 67 | self.__pos += 1 68 | 69 | def next(self): 70 | # Figure out if we're lexing a comment. 71 | in_comment = True 72 | # Continueously skip comment lines and whitespaces. 73 | while in_comment: 74 | # EOF 75 | if self.__cur == None: 76 | return Token(None, TokenType.EOF) 77 | 78 | # Skip whitespace. 79 | self.__skip_whitespace() 80 | 81 | # Skip comments. 82 | # NOTE: Not checking for the second '/', because not really necessary. 83 | if self.__cur == '/': 84 | in_comment = True 85 | 86 | # Skip current line, assuming it started with '//' 87 | while self.__cur != '\n': 88 | self.__advance() 89 | else: 90 | in_comment = False 91 | 92 | # Scan equal operator. 93 | if self.__cur == '=': 94 | self.__advance() 95 | return Token('=', TokenType.EQUAL) 96 | 97 | # Scan seperator. 98 | if self.__cur == ',': 99 | self.__advance() 100 | return Token(',', TokenType.COMMA) 101 | 102 | # Scan identifiers. 103 | if self.__cur.isalpha() or self.__cur == '_': 104 | ident = '' 105 | while self.__cur.isalpha() or self.__cur == '_' or self.__cur.isdigit(): 106 | ident += self.__cur 107 | self.__advance() 108 | 109 | return Token(ident, TokenType.IDENT) 110 | 111 | # Scan integers. 112 | if self.__cur.isdigit(): 113 | integer = '' 114 | while self.__cur.isdigit(): 115 | integer += self.__cur 116 | self.__advance() 117 | 118 | return Token(integer, TokenType.INTEGER) 119 | 120 | raise Exception("Unexpected character: '{0}' index: {1}".format(str(self.__cur), str(self.__pos))) 121 | 122 | class Parser(object): 123 | def __init__(self, lexer): 124 | self.__lexer = lexer 125 | self.__cur = self.__lexer.next() 126 | 127 | def __eat(self, type): 128 | if self.__cur.type != type: 129 | raise Exception("Unexpected token: {0}", str(self.__cur)) 130 | self.__cur = self.__lexer.next() 131 | 132 | def parse(self): 133 | # Return None when we've reached EOF. 134 | if self.__cur.type == TokenType.EOF: 135 | return None 136 | 137 | ident = self.__cur.value 138 | self.__eat(TokenType.IDENT) 139 | 140 | if self.__cur.type == TokenType.COMMA: 141 | # => reg, 142 | self.__eat(TokenType.COMMA) 143 | return Register(ident, None) 144 | 145 | elif self.__cur.type == TokenType.EQUAL: 146 | self.__eat(TokenType.EQUAL) 147 | if self.__cur.type == TokenType.INTEGER: 148 | # => reg = INTEGER, 149 | integer = self.__cur.value 150 | self.__eat(TokenType.INTEGER) 151 | self.__eat(TokenType.COMMA) 152 | return Register(ident, int(integer)) 153 | 154 | elif self.__cur.type == TokenType.IDENT: 155 | # => reg = reg2, 156 | ident2 = self.__cur.value 157 | self.__eat(TokenType.IDENT) 158 | self.__eat(TokenType.COMMA) 159 | return Register(ident, ident2) 160 | 161 | raise Exception() 162 | 163 | def main(args): 164 | if len(args) < 2: 165 | print("error: no input file specified", file=sys.stderr) 166 | return 1 167 | 168 | src_filename = args[1] 169 | with open(src_filename, "r") as f: 170 | src = f.read() 171 | 172 | register_id = 1 173 | registers = {} 174 | 175 | lexer = Lexer(src) 176 | parser = Parser(lexer) 177 | 178 | # Parse registers and put them in a ditionary 179 | # mapping register names to register instances. 180 | register = parser.parse() 181 | while register != None: 182 | if register != None: 183 | registers[register.name] = register 184 | register = parser.parse() 185 | 186 | # Resolves the register IDs. 187 | for register_name, register in registers.items(): 188 | if register.id == None: 189 | register.id = register_id 190 | register_id += 1 191 | elif type(register.id) is str: 192 | # NOTE: Does not support 'nested' references. 193 | register.id = registers[register.id].id 194 | elif type(register.id) is int: 195 | register_id = register.id + 1 196 | 197 | # Where the code generation begins. 198 | PREFIX = '_REG_' 199 | PREFIX_LEN = len(PREFIX) 200 | code = '// Generated by ' + os.path.basename(__file__) + '.\r\n' 201 | 202 | # Iterating over the registers again, cause why not. 203 | for register_name, register in registers.items(): 204 | name = register_name[register_name.index(PREFIX) + PREFIX_LEN:] 205 | id = register.id 206 | if name[0].isdigit(): 207 | name = '_' + name 208 | 209 | # Skip enum value used to indicating ending of register enum. 210 | if name == 'ENDING': 211 | continue 212 | 213 | code += "/// \n/// Gets or sets the value of {0} register.\n/// \n".format(name) 214 | code += "public long {0} \n{{\n".format(name) 215 | code += " get {{ return Read({0}); }}\n".format(id) 216 | code += " set {{ Write({0}, value); }}".format(id) 217 | code += "\n}\n\n" 218 | 219 | # Write to disk. 220 | out_filename = src_filename + ".cs" 221 | with open(out_filename, "w") as f: 222 | f.write(code) 223 | return 0 224 | 225 | if __name__ == '__main__': 226 | main(sys.argv) 227 | -------------------------------------------------------------------------------- /src/Unicorn.Net.ConsoleTests/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Unicorn.Arm; 3 | using Unicorn.Mips; 4 | 5 | namespace Unicorn.ConsoleTests 6 | { 7 | public class Program 8 | { 9 | public static void Main(string[] args) 10 | { 11 | Console.WriteLine("Unicorn version - " + UnicornVersion.Current); 12 | 13 | using (var emulator = new MipsEmulator(MipsMode.b32 | MipsMode.BigEndian)) 14 | { 15 | ulong addr = 0x10000; 16 | byte[] mipscode = 17 | { 18 | 0x34, 0x21, 0x34, 0x56 19 | }; 20 | 21 | emulator.Memory.Map(addr, 2 * 1024 * 1024, MemoryPermissions.All); 22 | emulator.Memory.Write(addr, mipscode, mipscode.Length); 23 | 24 | emulator.Registers._1 = 0x6789; 25 | 26 | emulator.Hooks.Code.Add(CodeHook, null); 27 | emulator.Start(addr, addr + (ulong)mipscode.Length); 28 | 29 | Console.WriteLine("{0}", emulator.Registers._1); 30 | } 31 | 32 | using (var emulator = new ArmEmulator(ArmMode.Arm)) 33 | { 34 | ulong addr = 0x10000; 35 | 36 | // mov r0, #0x37; sub r1, r2, r3 37 | byte[] armcode = 38 | { 39 | 0x37, 0x00, 0xa0, 0xe3, 0x03, 0x10, 0x42, 0xe0 40 | }; 41 | 42 | // Map 2mb of memory. 43 | emulator.Memory.Map(addr, 2 * 1024 * 1024, MemoryPermissions.All); 44 | emulator.Memory.Write(addr, armcode, armcode.Length); 45 | 46 | emulator.Registers.R0 = 0x1234; 47 | emulator.Registers.R2 = 0x6789; 48 | emulator.Registers.R3 = 0x3333; 49 | 50 | emulator.Hooks.Block.Add((emu, address, size, userToken) => 51 | { 52 | Console.WriteLine($">>> Tracing basic block at 0x{address.ToString("x2")}, block size = 0x{size.ToString("x2")}"); 53 | }, null); 54 | 55 | emulator.Hooks.Code.Add((emu, address, size, userToken) => 56 | { 57 | Console.WriteLine($">>> Tracing instruction at 0x{address.ToString("x2")}, instruction size = 0x{size.ToString("x2")}"); 58 | }, null); 59 | 60 | emulator.Start(addr, addr + (ulong)armcode.Length); 61 | 62 | Console.WriteLine(">>> Emulation done. Below is the CPU context"); 63 | Console.WriteLine($">>> R0 = 0x{emulator.Registers.R0.ToString("x2")}"); 64 | Console.WriteLine($">>> R1 = 0x{emulator.Registers.R1.ToString("x2")}"); 65 | } 66 | 67 | /* 68 | using (var emulator = new X86Emulator(X86Mode.b32)) 69 | { 70 | ulong addr = 0x1000000; 71 | byte[] x86code = 72 | { 73 | 0x41, // INC ECX 74 | 0x4a // DEC EDX 75 | }; 76 | 77 | var ecx = 0x1234; 78 | var edx = 0x7890; 79 | 80 | // Map 2mb of memory. 81 | emulator.Memory.Map(addr, 2 * 1024 * 1024, MemoryPermissions.All); 82 | 83 | var handle = emulator.Hooks.Code.Add(CodeHook, null); 84 | 85 | // Capture context. 86 | Console.WriteLine("-> Capturing context..."); 87 | using (var context = emulator.Context) 88 | { 89 | emulator.Registers.ECX = ecx; 90 | emulator.Registers.EDX = edx; 91 | 92 | emulator.Memory.Write(addr, x86code, x86code.Length); 93 | 94 | emulator.Start(addr, addr + (ulong)x86code.Length); 95 | 96 | Console.WriteLine($"ECX = {emulator.Registers.ECX}"); 97 | Console.WriteLine($"EDX = {emulator.Registers.EDX}"); 98 | 99 | 100 | Console.WriteLine("-> Restoring context..."); 101 | 102 | // Restore captured context. 103 | emulator.Context = context; 104 | } 105 | 106 | Console.WriteLine($"ECX = {emulator.Registers.ECX}"); 107 | Console.WriteLine($"EDX = {emulator.Registers.EDX}"); 108 | } 109 | */ 110 | 111 | Console.ReadLine(); 112 | } 113 | 114 | private static void CodeHook(Emulator emulator, ulong address, int size, object userData) 115 | { 116 | var casted = (MipsEmulator)emulator; 117 | var eflags = casted.Registers._1; 118 | 119 | Console.WriteLine($"-> Tracing instruction at 0x{address.ToString("x2")} of size 0x{size.ToString("x2")}."); 120 | Console.WriteLine($"-> EFLAGS = {eflags.ToString("x2")}"); 121 | } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/Unicorn.Net.ConsoleTests/Unicorn.Net.ConsoleTests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | netcoreapp1.1;netcoreapp2.0;net45 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/Unicorn.Net/Arm/ArmEmulator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Unicorn.Arm 4 | { 5 | /// 6 | /// Represents an ARM architecture . 7 | /// 8 | public class ArmEmulator : Emulator 9 | { 10 | private readonly ArmRegisters _registers; 11 | 12 | /// 13 | /// Initializes a new instance of the class with the specified 14 | /// to use. 15 | /// 16 | /// Mode to use. 17 | public ArmEmulator(ArmMode mode) : base(UnicornArch.ARM, (UnicornMode)mode) 18 | { 19 | _registers = new ArmRegisters(this); 20 | } 21 | 22 | /// 23 | /// Gets the of the instance. 24 | /// 25 | /// instance is disposed. 26 | public new ArmRegisters Registers 27 | { 28 | get 29 | { 30 | ThrowIfDisposed(); 31 | return _registers; 32 | } 33 | } 34 | 35 | /// 36 | /// Gets the of the . 37 | /// 38 | /// instance is disposed. 39 | public new ArmMode Mode 40 | { 41 | get 42 | { 43 | ThrowIfDisposed(); 44 | return (ArmMode)_mode; 45 | } 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/Unicorn.Net/Arm/ArmMode.cs: -------------------------------------------------------------------------------- 1 | namespace Unicorn.Arm 2 | { 3 | /// 4 | /// Defines the modes of an . 5 | /// 6 | public enum ArmMode 7 | { 8 | /// 9 | /// ARM mode. 10 | /// 11 | Arm = UnicornMode.ARM, 12 | 13 | /// 14 | /// Thumb mode. 15 | /// 16 | Thumb = UnicornMode.ARMThumb, 17 | 18 | /// 19 | /// Cortext-M series mode. 20 | /// 21 | MClass = UnicornMode.ARMMClass, 22 | 23 | /// 24 | /// ARMv8 A32 encoding mode. 25 | /// 26 | V8 = UnicornMode.ARMv8 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Unicorn.Net/Arm/ArmRegisters.cs: -------------------------------------------------------------------------------- 1 | namespace Unicorn.Arm 2 | { 3 | /// 4 | /// Represents the registers of an . 5 | /// 6 | public class ArmRegisters : Registers 7 | { 8 | internal ArmRegisters(Emulator emulator) : base(emulator) 9 | { 10 | // Space 11 | } 12 | 13 | // Generated by /scripts/gen_reg_properties.py. 14 | 15 | /// 16 | /// Gets or sets the value of APSR register. 17 | /// 18 | public long APSR 19 | { 20 | get { return Read(1); } 21 | set { Write(1, value); } 22 | } 23 | 24 | /// 25 | /// Gets or sets the value of APSR_NZCV register. 26 | /// 27 | public long APSR_NZCV 28 | { 29 | get { return Read(2); } 30 | set { Write(2, value); } 31 | } 32 | 33 | /// 34 | /// Gets or sets the value of CPSR register. 35 | /// 36 | public long CPSR 37 | { 38 | get { return Read(3); } 39 | set { Write(3, value); } 40 | } 41 | 42 | /// 43 | /// Gets or sets the value of FPEXC register. 44 | /// 45 | public long FPEXC 46 | { 47 | get { return Read(4); } 48 | set { Write(4, value); } 49 | } 50 | 51 | /// 52 | /// Gets or sets the value of FPINST register. 53 | /// 54 | public long FPINST 55 | { 56 | get { return Read(5); } 57 | set { Write(5, value); } 58 | } 59 | 60 | /// 61 | /// Gets or sets the value of FPSCR register. 62 | /// 63 | public long FPSCR 64 | { 65 | get { return Read(6); } 66 | set { Write(6, value); } 67 | } 68 | 69 | /// 70 | /// Gets or sets the value of FPSCR_NZCV register. 71 | /// 72 | public long FPSCR_NZCV 73 | { 74 | get { return Read(7); } 75 | set { Write(7, value); } 76 | } 77 | 78 | /// 79 | /// Gets or sets the value of FPSID register. 80 | /// 81 | public long FPSID 82 | { 83 | get { return Read(8); } 84 | set { Write(8, value); } 85 | } 86 | 87 | /// 88 | /// Gets or sets the value of ITSTATE register. 89 | /// 90 | public long ITSTATE 91 | { 92 | get { return Read(9); } 93 | set { Write(9, value); } 94 | } 95 | 96 | /// 97 | /// Gets or sets the value of LR register. 98 | /// 99 | public long LR 100 | { 101 | get { return Read(10); } 102 | set { Write(10, value); } 103 | } 104 | 105 | /// 106 | /// Gets or sets the value of PC register. 107 | /// 108 | public long PC 109 | { 110 | get { return Read(11); } 111 | set { Write(11, value); } 112 | } 113 | 114 | /// 115 | /// Gets or sets the value of SP register. 116 | /// 117 | public long SP 118 | { 119 | get { return Read(12); } 120 | set { Write(12, value); } 121 | } 122 | 123 | /// 124 | /// Gets or sets the value of SPSR register. 125 | /// 126 | public long SPSR 127 | { 128 | get { return Read(13); } 129 | set { Write(13, value); } 130 | } 131 | 132 | /// 133 | /// Gets or sets the value of D0 register. 134 | /// 135 | public long D0 136 | { 137 | get { return Read(14); } 138 | set { Write(14, value); } 139 | } 140 | 141 | /// 142 | /// Gets or sets the value of D1 register. 143 | /// 144 | public long D1 145 | { 146 | get { return Read(15); } 147 | set { Write(15, value); } 148 | } 149 | 150 | /// 151 | /// Gets or sets the value of D2 register. 152 | /// 153 | public long D2 154 | { 155 | get { return Read(16); } 156 | set { Write(16, value); } 157 | } 158 | 159 | /// 160 | /// Gets or sets the value of D3 register. 161 | /// 162 | public long D3 163 | { 164 | get { return Read(17); } 165 | set { Write(17, value); } 166 | } 167 | 168 | /// 169 | /// Gets or sets the value of D4 register. 170 | /// 171 | public long D4 172 | { 173 | get { return Read(18); } 174 | set { Write(18, value); } 175 | } 176 | 177 | /// 178 | /// Gets or sets the value of D5 register. 179 | /// 180 | public long D5 181 | { 182 | get { return Read(19); } 183 | set { Write(19, value); } 184 | } 185 | 186 | /// 187 | /// Gets or sets the value of D6 register. 188 | /// 189 | public long D6 190 | { 191 | get { return Read(20); } 192 | set { Write(20, value); } 193 | } 194 | 195 | /// 196 | /// Gets or sets the value of D7 register. 197 | /// 198 | public long D7 199 | { 200 | get { return Read(21); } 201 | set { Write(21, value); } 202 | } 203 | 204 | /// 205 | /// Gets or sets the value of D8 register. 206 | /// 207 | public long D8 208 | { 209 | get { return Read(22); } 210 | set { Write(22, value); } 211 | } 212 | 213 | /// 214 | /// Gets or sets the value of D9 register. 215 | /// 216 | public long D9 217 | { 218 | get { return Read(23); } 219 | set { Write(23, value); } 220 | } 221 | 222 | /// 223 | /// Gets or sets the value of D10 register. 224 | /// 225 | public long D10 226 | { 227 | get { return Read(24); } 228 | set { Write(24, value); } 229 | } 230 | 231 | /// 232 | /// Gets or sets the value of D11 register. 233 | /// 234 | public long D11 235 | { 236 | get { return Read(25); } 237 | set { Write(25, value); } 238 | } 239 | 240 | /// 241 | /// Gets or sets the value of D12 register. 242 | /// 243 | public long D12 244 | { 245 | get { return Read(26); } 246 | set { Write(26, value); } 247 | } 248 | 249 | /// 250 | /// Gets or sets the value of D13 register. 251 | /// 252 | public long D13 253 | { 254 | get { return Read(27); } 255 | set { Write(27, value); } 256 | } 257 | 258 | /// 259 | /// Gets or sets the value of D14 register. 260 | /// 261 | public long D14 262 | { 263 | get { return Read(28); } 264 | set { Write(28, value); } 265 | } 266 | 267 | /// 268 | /// Gets or sets the value of D15 register. 269 | /// 270 | public long D15 271 | { 272 | get { return Read(29); } 273 | set { Write(29, value); } 274 | } 275 | 276 | /// 277 | /// Gets or sets the value of D16 register. 278 | /// 279 | public long D16 280 | { 281 | get { return Read(30); } 282 | set { Write(30, value); } 283 | } 284 | 285 | /// 286 | /// Gets or sets the value of D17 register. 287 | /// 288 | public long D17 289 | { 290 | get { return Read(31); } 291 | set { Write(31, value); } 292 | } 293 | 294 | /// 295 | /// Gets or sets the value of D18 register. 296 | /// 297 | public long D18 298 | { 299 | get { return Read(32); } 300 | set { Write(32, value); } 301 | } 302 | 303 | /// 304 | /// Gets or sets the value of D19 register. 305 | /// 306 | public long D19 307 | { 308 | get { return Read(33); } 309 | set { Write(33, value); } 310 | } 311 | 312 | /// 313 | /// Gets or sets the value of D20 register. 314 | /// 315 | public long D20 316 | { 317 | get { return Read(34); } 318 | set { Write(34, value); } 319 | } 320 | 321 | /// 322 | /// Gets or sets the value of D21 register. 323 | /// 324 | public long D21 325 | { 326 | get { return Read(35); } 327 | set { Write(35, value); } 328 | } 329 | 330 | /// 331 | /// Gets or sets the value of D22 register. 332 | /// 333 | public long D22 334 | { 335 | get { return Read(36); } 336 | set { Write(36, value); } 337 | } 338 | 339 | /// 340 | /// Gets or sets the value of D23 register. 341 | /// 342 | public long D23 343 | { 344 | get { return Read(37); } 345 | set { Write(37, value); } 346 | } 347 | 348 | /// 349 | /// Gets or sets the value of D24 register. 350 | /// 351 | public long D24 352 | { 353 | get { return Read(38); } 354 | set { Write(38, value); } 355 | } 356 | 357 | /// 358 | /// Gets or sets the value of D25 register. 359 | /// 360 | public long D25 361 | { 362 | get { return Read(39); } 363 | set { Write(39, value); } 364 | } 365 | 366 | /// 367 | /// Gets or sets the value of D26 register. 368 | /// 369 | public long D26 370 | { 371 | get { return Read(40); } 372 | set { Write(40, value); } 373 | } 374 | 375 | /// 376 | /// Gets or sets the value of D27 register. 377 | /// 378 | public long D27 379 | { 380 | get { return Read(41); } 381 | set { Write(41, value); } 382 | } 383 | 384 | /// 385 | /// Gets or sets the value of D28 register. 386 | /// 387 | public long D28 388 | { 389 | get { return Read(42); } 390 | set { Write(42, value); } 391 | } 392 | 393 | /// 394 | /// Gets or sets the value of D29 register. 395 | /// 396 | public long D29 397 | { 398 | get { return Read(43); } 399 | set { Write(43, value); } 400 | } 401 | 402 | /// 403 | /// Gets or sets the value of D30 register. 404 | /// 405 | public long D30 406 | { 407 | get { return Read(44); } 408 | set { Write(44, value); } 409 | } 410 | 411 | /// 412 | /// Gets or sets the value of D31 register. 413 | /// 414 | public long D31 415 | { 416 | get { return Read(45); } 417 | set { Write(45, value); } 418 | } 419 | 420 | /// 421 | /// Gets or sets the value of FPINST2 register. 422 | /// 423 | public long FPINST2 424 | { 425 | get { return Read(46); } 426 | set { Write(46, value); } 427 | } 428 | 429 | /// 430 | /// Gets or sets the value of MVFR0 register. 431 | /// 432 | public long MVFR0 433 | { 434 | get { return Read(47); } 435 | set { Write(47, value); } 436 | } 437 | 438 | /// 439 | /// Gets or sets the value of MVFR1 register. 440 | /// 441 | public long MVFR1 442 | { 443 | get { return Read(48); } 444 | set { Write(48, value); } 445 | } 446 | 447 | /// 448 | /// Gets or sets the value of MVFR2 register. 449 | /// 450 | public long MVFR2 451 | { 452 | get { return Read(49); } 453 | set { Write(49, value); } 454 | } 455 | 456 | /// 457 | /// Gets or sets the value of Q0 register. 458 | /// 459 | public long Q0 460 | { 461 | get { return Read(50); } 462 | set { Write(50, value); } 463 | } 464 | 465 | /// 466 | /// Gets or sets the value of Q1 register. 467 | /// 468 | public long Q1 469 | { 470 | get { return Read(51); } 471 | set { Write(51, value); } 472 | } 473 | 474 | /// 475 | /// Gets or sets the value of Q2 register. 476 | /// 477 | public long Q2 478 | { 479 | get { return Read(52); } 480 | set { Write(52, value); } 481 | } 482 | 483 | /// 484 | /// Gets or sets the value of Q3 register. 485 | /// 486 | public long Q3 487 | { 488 | get { return Read(53); } 489 | set { Write(53, value); } 490 | } 491 | 492 | /// 493 | /// Gets or sets the value of Q4 register. 494 | /// 495 | public long Q4 496 | { 497 | get { return Read(54); } 498 | set { Write(54, value); } 499 | } 500 | 501 | /// 502 | /// Gets or sets the value of Q5 register. 503 | /// 504 | public long Q5 505 | { 506 | get { return Read(55); } 507 | set { Write(55, value); } 508 | } 509 | 510 | /// 511 | /// Gets or sets the value of Q6 register. 512 | /// 513 | public long Q6 514 | { 515 | get { return Read(56); } 516 | set { Write(56, value); } 517 | } 518 | 519 | /// 520 | /// Gets or sets the value of Q7 register. 521 | /// 522 | public long Q7 523 | { 524 | get { return Read(57); } 525 | set { Write(57, value); } 526 | } 527 | 528 | /// 529 | /// Gets or sets the value of Q8 register. 530 | /// 531 | public long Q8 532 | { 533 | get { return Read(58); } 534 | set { Write(58, value); } 535 | } 536 | 537 | /// 538 | /// Gets or sets the value of Q9 register. 539 | /// 540 | public long Q9 541 | { 542 | get { return Read(59); } 543 | set { Write(59, value); } 544 | } 545 | 546 | /// 547 | /// Gets or sets the value of Q10 register. 548 | /// 549 | public long Q10 550 | { 551 | get { return Read(60); } 552 | set { Write(60, value); } 553 | } 554 | 555 | /// 556 | /// Gets or sets the value of Q11 register. 557 | /// 558 | public long Q11 559 | { 560 | get { return Read(61); } 561 | set { Write(61, value); } 562 | } 563 | 564 | /// 565 | /// Gets or sets the value of Q12 register. 566 | /// 567 | public long Q12 568 | { 569 | get { return Read(62); } 570 | set { Write(62, value); } 571 | } 572 | 573 | /// 574 | /// Gets or sets the value of Q13 register. 575 | /// 576 | public long Q13 577 | { 578 | get { return Read(63); } 579 | set { Write(63, value); } 580 | } 581 | 582 | /// 583 | /// Gets or sets the value of Q14 register. 584 | /// 585 | public long Q14 586 | { 587 | get { return Read(64); } 588 | set { Write(64, value); } 589 | } 590 | 591 | /// 592 | /// Gets or sets the value of Q15 register. 593 | /// 594 | public long Q15 595 | { 596 | get { return Read(65); } 597 | set { Write(65, value); } 598 | } 599 | 600 | /// 601 | /// Gets or sets the value of R0 register. 602 | /// 603 | public long R0 604 | { 605 | get { return Read(66); } 606 | set { Write(66, value); } 607 | } 608 | 609 | /// 610 | /// Gets or sets the value of R1 register. 611 | /// 612 | public long R1 613 | { 614 | get { return Read(67); } 615 | set { Write(67, value); } 616 | } 617 | 618 | /// 619 | /// Gets or sets the value of R2 register. 620 | /// 621 | public long R2 622 | { 623 | get { return Read(68); } 624 | set { Write(68, value); } 625 | } 626 | 627 | /// 628 | /// Gets or sets the value of R3 register. 629 | /// 630 | public long R3 631 | { 632 | get { return Read(69); } 633 | set { Write(69, value); } 634 | } 635 | 636 | /// 637 | /// Gets or sets the value of R4 register. 638 | /// 639 | public long R4 640 | { 641 | get { return Read(70); } 642 | set { Write(70, value); } 643 | } 644 | 645 | /// 646 | /// Gets or sets the value of R5 register. 647 | /// 648 | public long R5 649 | { 650 | get { return Read(71); } 651 | set { Write(71, value); } 652 | } 653 | 654 | /// 655 | /// Gets or sets the value of R6 register. 656 | /// 657 | public long R6 658 | { 659 | get { return Read(72); } 660 | set { Write(72, value); } 661 | } 662 | 663 | /// 664 | /// Gets or sets the value of R7 register. 665 | /// 666 | public long R7 667 | { 668 | get { return Read(73); } 669 | set { Write(73, value); } 670 | } 671 | 672 | /// 673 | /// Gets or sets the value of R8 register. 674 | /// 675 | public long R8 676 | { 677 | get { return Read(74); } 678 | set { Write(74, value); } 679 | } 680 | 681 | /// 682 | /// Gets or sets the value of R9 register. 683 | /// 684 | public long R9 685 | { 686 | get { return Read(75); } 687 | set { Write(75, value); } 688 | } 689 | 690 | /// 691 | /// Gets or sets the value of R10 register. 692 | /// 693 | public long R10 694 | { 695 | get { return Read(76); } 696 | set { Write(76, value); } 697 | } 698 | 699 | /// 700 | /// Gets or sets the value of R11 register. 701 | /// 702 | public long R11 703 | { 704 | get { return Read(77); } 705 | set { Write(77, value); } 706 | } 707 | 708 | /// 709 | /// Gets or sets the value of R12 register. 710 | /// 711 | public long R12 712 | { 713 | get { return Read(78); } 714 | set { Write(78, value); } 715 | } 716 | 717 | /// 718 | /// Gets or sets the value of S0 register. 719 | /// 720 | public long S0 721 | { 722 | get { return Read(79); } 723 | set { Write(79, value); } 724 | } 725 | 726 | /// 727 | /// Gets or sets the value of S1 register. 728 | /// 729 | public long S1 730 | { 731 | get { return Read(80); } 732 | set { Write(80, value); } 733 | } 734 | 735 | /// 736 | /// Gets or sets the value of S2 register. 737 | /// 738 | public long S2 739 | { 740 | get { return Read(81); } 741 | set { Write(81, value); } 742 | } 743 | 744 | /// 745 | /// Gets or sets the value of S3 register. 746 | /// 747 | public long S3 748 | { 749 | get { return Read(82); } 750 | set { Write(82, value); } 751 | } 752 | 753 | /// 754 | /// Gets or sets the value of S4 register. 755 | /// 756 | public long S4 757 | { 758 | get { return Read(83); } 759 | set { Write(83, value); } 760 | } 761 | 762 | /// 763 | /// Gets or sets the value of S5 register. 764 | /// 765 | public long S5 766 | { 767 | get { return Read(84); } 768 | set { Write(84, value); } 769 | } 770 | 771 | /// 772 | /// Gets or sets the value of S6 register. 773 | /// 774 | public long S6 775 | { 776 | get { return Read(85); } 777 | set { Write(85, value); } 778 | } 779 | 780 | /// 781 | /// Gets or sets the value of S7 register. 782 | /// 783 | public long S7 784 | { 785 | get { return Read(86); } 786 | set { Write(86, value); } 787 | } 788 | 789 | /// 790 | /// Gets or sets the value of S8 register. 791 | /// 792 | public long S8 793 | { 794 | get { return Read(87); } 795 | set { Write(87, value); } 796 | } 797 | 798 | /// 799 | /// Gets or sets the value of S9 register. 800 | /// 801 | public long S9 802 | { 803 | get { return Read(88); } 804 | set { Write(88, value); } 805 | } 806 | 807 | /// 808 | /// Gets or sets the value of S10 register. 809 | /// 810 | public long S10 811 | { 812 | get { return Read(89); } 813 | set { Write(89, value); } 814 | } 815 | 816 | /// 817 | /// Gets or sets the value of S11 register. 818 | /// 819 | public long S11 820 | { 821 | get { return Read(90); } 822 | set { Write(90, value); } 823 | } 824 | 825 | /// 826 | /// Gets or sets the value of S12 register. 827 | /// 828 | public long S12 829 | { 830 | get { return Read(91); } 831 | set { Write(91, value); } 832 | } 833 | 834 | /// 835 | /// Gets or sets the value of S13 register. 836 | /// 837 | public long S13 838 | { 839 | get { return Read(92); } 840 | set { Write(92, value); } 841 | } 842 | 843 | /// 844 | /// Gets or sets the value of S14 register. 845 | /// 846 | public long S14 847 | { 848 | get { return Read(93); } 849 | set { Write(93, value); } 850 | } 851 | 852 | /// 853 | /// Gets or sets the value of S15 register. 854 | /// 855 | public long S15 856 | { 857 | get { return Read(94); } 858 | set { Write(94, value); } 859 | } 860 | 861 | /// 862 | /// Gets or sets the value of S16 register. 863 | /// 864 | public long S16 865 | { 866 | get { return Read(95); } 867 | set { Write(95, value); } 868 | } 869 | 870 | /// 871 | /// Gets or sets the value of S17 register. 872 | /// 873 | public long S17 874 | { 875 | get { return Read(96); } 876 | set { Write(96, value); } 877 | } 878 | 879 | /// 880 | /// Gets or sets the value of S18 register. 881 | /// 882 | public long S18 883 | { 884 | get { return Read(97); } 885 | set { Write(97, value); } 886 | } 887 | 888 | /// 889 | /// Gets or sets the value of S19 register. 890 | /// 891 | public long S19 892 | { 893 | get { return Read(98); } 894 | set { Write(98, value); } 895 | } 896 | 897 | /// 898 | /// Gets or sets the value of S20 register. 899 | /// 900 | public long S20 901 | { 902 | get { return Read(99); } 903 | set { Write(99, value); } 904 | } 905 | 906 | /// 907 | /// Gets or sets the value of S21 register. 908 | /// 909 | public long S21 910 | { 911 | get { return Read(100); } 912 | set { Write(100, value); } 913 | } 914 | 915 | /// 916 | /// Gets or sets the value of S22 register. 917 | /// 918 | public long S22 919 | { 920 | get { return Read(101); } 921 | set { Write(101, value); } 922 | } 923 | 924 | /// 925 | /// Gets or sets the value of S23 register. 926 | /// 927 | public long S23 928 | { 929 | get { return Read(102); } 930 | set { Write(102, value); } 931 | } 932 | 933 | /// 934 | /// Gets or sets the value of S24 register. 935 | /// 936 | public long S24 937 | { 938 | get { return Read(103); } 939 | set { Write(103, value); } 940 | } 941 | 942 | /// 943 | /// Gets or sets the value of S25 register. 944 | /// 945 | public long S25 946 | { 947 | get { return Read(104); } 948 | set { Write(104, value); } 949 | } 950 | 951 | /// 952 | /// Gets or sets the value of S26 register. 953 | /// 954 | public long S26 955 | { 956 | get { return Read(105); } 957 | set { Write(105, value); } 958 | } 959 | 960 | /// 961 | /// Gets or sets the value of S27 register. 962 | /// 963 | public long S27 964 | { 965 | get { return Read(106); } 966 | set { Write(106, value); } 967 | } 968 | 969 | /// 970 | /// Gets or sets the value of S28 register. 971 | /// 972 | public long S28 973 | { 974 | get { return Read(107); } 975 | set { Write(107, value); } 976 | } 977 | 978 | /// 979 | /// Gets or sets the value of S29 register. 980 | /// 981 | public long S29 982 | { 983 | get { return Read(108); } 984 | set { Write(108, value); } 985 | } 986 | 987 | /// 988 | /// Gets or sets the value of S30 register. 989 | /// 990 | public long S30 991 | { 992 | get { return Read(109); } 993 | set { Write(109, value); } 994 | } 995 | 996 | /// 997 | /// Gets or sets the value of S31 register. 998 | /// 999 | public long S31 1000 | { 1001 | get { return Read(110); } 1002 | set { Write(110, value); } 1003 | } 1004 | 1005 | /// 1006 | /// Gets or sets the value of C1_C0_2 register. 1007 | /// 1008 | public long C1_C0_2 1009 | { 1010 | get { return Read(111); } 1011 | set { Write(111, value); } 1012 | } 1013 | 1014 | /// 1015 | /// Gets or sets the value of C13_C0_2 register. 1016 | /// 1017 | public long C13_C0_2 1018 | { 1019 | get { return Read(112); } 1020 | set { Write(112, value); } 1021 | } 1022 | 1023 | /// 1024 | /// Gets or sets the value of C13_C0_3 register. 1025 | /// 1026 | public long C13_C0_3 1027 | { 1028 | get { return Read(113); } 1029 | set { Write(113, value); } 1030 | } 1031 | } 1032 | } 1033 | -------------------------------------------------------------------------------- /src/Unicorn.Net/Bindings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using Unicorn.Internal; 4 | 5 | using static Unicorn.Internal.unicorn; 6 | 7 | namespace Unicorn 8 | { 9 | public class Bindings : IBindings 10 | { 11 | public static readonly Bindings Instance = new Bindings(); 12 | 13 | public string StrError(UnicornError err) 14 | => Marshal.PtrToStringAnsi(uc_strerror((uc_err)err)); 15 | 16 | public int Version(ref int major, ref int minor) 17 | => uc_version(ref major, ref minor); 18 | 19 | public void Free(IntPtr ptr) 20 | => ThrowIfError(uc_free(ptr)); 21 | 22 | public void Open(UnicornArch arch, UnicornMode mode, ref IntPtr uc) 23 | => ThrowIfError(uc_open((uc_arch)arch, (uc_mode)mode, ref uc)); 24 | 25 | public void Close(IntPtr uc) 26 | => ThrowIfError(uc_close(uc)); 27 | 28 | public void ContextAlloc(IntPtr uc, ref IntPtr ctx) 29 | => ThrowIfError(uc_context_alloc(uc, ref ctx)); 30 | 31 | public void ContextRestore(IntPtr uc, IntPtr ctx) 32 | => ThrowIfError(uc_context_restore(uc, ctx)); 33 | 34 | public void ContextSave(IntPtr uc, IntPtr ctx) 35 | => ThrowIfError(uc_context_save(uc, ctx)); 36 | 37 | public void EmuStart(IntPtr uc, ulong begin, ulong end, ulong timeout, int count) 38 | => ThrowIfError(uc_emu_start(uc, begin, end, timeout, count)); 39 | 40 | public void EmuStop(IntPtr uc) 41 | => ThrowIfError(uc_emu_stop(uc)); 42 | 43 | public void HookAdd(IntPtr uc, ref IntPtr hh, UnicornHookType type, IntPtr callback, IntPtr userData, ulong address, ulong end) 44 | => ThrowIfError(uc_hook_add(uc, ref hh, (uc_hook_type)type, callback, userData, address, end)); 45 | 46 | public void HookAdd(IntPtr uc, ref IntPtr hh, UnicornHookType type, IntPtr callback, IntPtr userData, ulong address, ulong end, int instruction) 47 | => ThrowIfError(uc_hook_add(uc, ref hh, (uc_hook_type)type, callback, userData, address, end, instruction)); 48 | 49 | public void HookDel(IntPtr uc, IntPtr hh) 50 | => ThrowIfError(uc_hook_del(uc, hh)); 51 | 52 | public void MemMap(IntPtr uc, ulong address, int size, MemoryPermissions perms) 53 | => ThrowIfError(uc_mem_map(uc, address, size, (int)perms)); 54 | 55 | public void MemProtect(IntPtr uc, ulong address, int size, MemoryPermissions perms) 56 | => ThrowIfError(uc_mem_protect(uc, address, size, (int)perms)); 57 | 58 | public void MemRead(IntPtr uc, ulong address, byte[] buffer, int count) 59 | => ThrowIfError(uc_mem_read(uc, address, buffer, count)); 60 | 61 | public void MemRegions(IntPtr uc, ref MemoryRegion[] regions) 62 | { 63 | uint count = 0; 64 | IntPtr regionsPtr = IntPtr.Zero; 65 | 66 | ThrowIfError(uc_mem_regions(uc, ref regionsPtr, ref count)); 67 | 68 | regions = new MemoryRegion[count]; 69 | 70 | if (count > 0 && regionsPtr != IntPtr.Zero) 71 | { 72 | var ptr = regionsPtr; 73 | var size = Marshal.SizeOf(typeof(uc_mem_region)); 74 | for (int i = 0; i < count; i++) 75 | { 76 | var nativeRegion = (uc_mem_region)Marshal.PtrToStructure(ptr, typeof(uc_mem_region)); 77 | regions[i] = new MemoryRegion(nativeRegion.begin, nativeRegion.end, (MemoryPermissions)nativeRegion.perms); 78 | ptr += size; 79 | } 80 | 81 | Free(regionsPtr); 82 | } 83 | } 84 | 85 | public void MemUnmap(IntPtr uc, ulong address, int size) 86 | => ThrowIfError(uc_mem_unmap(uc, address, size)); 87 | 88 | public void MemWrite(IntPtr uc, ulong address, byte[] bytes, int size) 89 | => ThrowIfError(uc_mem_write(uc, address, bytes, size)); 90 | 91 | public void Query(IntPtr uc, UnicornQueryType type, ref int value) 92 | => ThrowIfError(uc_query(uc, (uc_query_type)type, ref value)); 93 | 94 | public void RegRead(IntPtr uc, int regId, ref long value) 95 | => ThrowIfError(uc_reg_read(uc, regId, ref value)); 96 | 97 | public void RegWrite(IntPtr uc, int regId, ref long value) 98 | => ThrowIfError(uc_reg_write(uc, regId, ref value)); 99 | 100 | private static void ThrowIfError(uc_err err) 101 | { 102 | if (err != uc_err.UC_ERR_OK) 103 | throw new UnicornException(err); 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/Unicorn.Net/BlockHooksContainer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Runtime.InteropServices; 4 | using Unicorn.Internal; 5 | 6 | namespace Unicorn 7 | { 8 | /// 9 | /// Callback for tracing basic blocks. 10 | /// 11 | /// which raised the callback. 12 | /// Address where the code is being executed. 13 | /// Size of the block. 14 | /// Object associated with the callback. 15 | public delegate void BlockHookCallback(Emulator emulator, ulong address, int size, object userToken); 16 | 17 | /// 18 | /// Represents hooks for basic block of an . 19 | /// 20 | public class BlockHooksContainer : HookContainer 21 | { 22 | internal BlockHooksContainer(Emulator emulator) : base(emulator) 23 | { 24 | // Space 25 | } 26 | 27 | /// 28 | /// Adds a to the with the specified user token which 29 | /// is called anytime the hook is triggered. 30 | /// 31 | /// 32 | /// to add. 33 | /// Object associated with the callback. 34 | /// A which represents the hook. 35 | /// 36 | /// is null. 37 | /// Unicorn did not return . 38 | /// instance is disposed. 39 | public HookHandle Add(BlockHookCallback callback, object userToken) 40 | { 41 | Emulator.ThrowIfDisposed(); 42 | 43 | if (callback == null) 44 | throw new ArgumentNullException(nameof(callback)); 45 | 46 | return AddInternal(callback, 1, 0, userToken); 47 | } 48 | 49 | /// 50 | /// Adds a to the with the specified user token which 51 | /// is called when the hook is triggered within the specified start address and end address. 52 | /// 53 | /// 54 | /// to add. 55 | /// Start address of where the hook is effective (inclusive). 56 | /// End address of where the hook is effective (inclusive). 57 | /// Object associated with the callback. 58 | /// A which represents the hook. 59 | /// 60 | /// 61 | /// If > , the callback is called anytime the hook triggers. 62 | /// 63 | /// 64 | /// is null. 65 | /// Unicorn did not return . 66 | /// instance is disposed. 67 | public HookHandle Add(BlockHookCallback callback, ulong begin, ulong end, object userToken) 68 | { 69 | Emulator.ThrowIfDisposed(); 70 | 71 | if (callback == null) 72 | throw new ArgumentNullException(nameof(callback)); 73 | 74 | return AddInternal(callback, begin, end, userToken); 75 | } 76 | 77 | private HookHandle AddInternal(BlockHookCallback callback, ulong begin, ulong end, object userToken) 78 | { 79 | var wrapper = new uc_cb_hookcode((uc, addr, size, user_data) => 80 | { 81 | Debug.Assert(uc == Emulator.Handle); 82 | callback(Emulator, addr, size, userToken); 83 | }); 84 | 85 | return Add(UnicornHookType.Block, wrapper, begin, end); 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/Unicorn.Net/CodeHooksContainer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Runtime.InteropServices; 4 | using Unicorn.Internal; 5 | 6 | namespace Unicorn 7 | { 8 | /// 9 | /// Callback for tracing code. 10 | /// 11 | /// which raised the callback. 12 | /// Address where the code is being executed. 13 | /// Size of the block. 14 | /// Object associated with the callback. 15 | public delegate void CodeHookCallback(Emulator emulator, ulong address, int size, object userToken); 16 | 17 | /// 18 | /// Represents hooks for code of an . 19 | /// 20 | public class CodeHooksContainer : HookContainer 21 | { 22 | internal CodeHooksContainer(Emulator emulator) : base(emulator) 23 | { 24 | // Space 25 | } 26 | 27 | /// 28 | /// Adds a to the with the specified user token which 29 | /// is called anytime the hook is triggered. 30 | /// 31 | /// 32 | /// to add. 33 | /// Object associated with the callback. 34 | /// A which represents the hook. 35 | /// 36 | /// is null. 37 | /// Unicorn did not return . 38 | /// instance is disposed. 39 | public HookHandle Add(CodeHookCallback callback, object userToken) 40 | { 41 | Emulator.ThrowIfDisposed(); 42 | 43 | if (callback == null) 44 | throw new ArgumentNullException(nameof(callback)); 45 | 46 | return AddInternal(callback, 1, 0, userToken); 47 | } 48 | 49 | /// 50 | /// Adds a to the with the specified user token which 51 | /// is called when the hook is triggered within the specified start address and end address. 52 | /// 53 | /// 54 | /// to add. 55 | /// Start address of where the hook is effective (inclusive). 56 | /// End address of where the hook is effective (inclusive). 57 | /// Object associated with the callback. 58 | /// A which represents the hook. 59 | /// 60 | /// 61 | /// If > , the callback is called anytime the hook triggers. 62 | /// 63 | /// 64 | /// is null. 65 | /// Unicorn did not return . 66 | /// instance is disposed. 67 | public HookHandle Add(CodeHookCallback callback, ulong begin, ulong end, object userToken) 68 | { 69 | Emulator.ThrowIfDisposed(); 70 | 71 | if (callback == null) 72 | throw new ArgumentNullException(nameof(callback)); 73 | 74 | return AddInternal(callback, begin, end, userToken); 75 | } 76 | 77 | private HookHandle AddInternal(CodeHookCallback callback, ulong begin, ulong end, object userToken) 78 | { 79 | var wrapper = new uc_cb_hookcode((uc, addr, size, user_data) => 80 | { 81 | Debug.Assert(uc == Emulator.Handle); 82 | callback(Emulator, addr, size, userToken); 83 | }); 84 | 85 | return Add(UnicornHookType.Code, wrapper, begin, end); 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/Unicorn.Net/Context.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | 4 | namespace Unicorn 5 | { 6 | /// 7 | /// Represents an context. 8 | /// 9 | public class Context : IDisposable 10 | { 11 | //TODO: Consider making strongly typed Contexts, like X86Context etc... 12 | 13 | internal bool _disposed; 14 | internal readonly UnicornArch _arch; 15 | internal readonly UnicornMode _mode; 16 | internal readonly IntPtr _context; 17 | private readonly Emulator _emulator; 18 | 19 | internal Context(Emulator emulator) 20 | { 21 | Debug.Assert(emulator != null); 22 | 23 | emulator.Bindings.ContextAlloc(emulator.Handle, ref _context); 24 | 25 | _arch = emulator._arch; 26 | _mode = emulator._mode; 27 | _emulator = emulator; 28 | } 29 | 30 | internal void Capture(Emulator emulator) 31 | { 32 | Debug.Assert(emulator != null); 33 | Debug.Assert(emulator._arch == _arch); 34 | Debug.Assert(emulator._mode == _mode); 35 | 36 | emulator.Bindings.ContextSave(emulator.Handle, _context); 37 | } 38 | 39 | internal void Restore(Emulator emulator) 40 | { 41 | Debug.Assert(emulator != null); 42 | Debug.Assert(emulator._arch == _arch); 43 | Debug.Assert(emulator._mode == _mode); 44 | 45 | emulator.Bindings.ContextRestore(emulator.Handle, _context); 46 | } 47 | 48 | /// 49 | /// Finalizes the instance. 50 | /// 51 | ~Context() 52 | { 53 | Dispose(false); 54 | } 55 | 56 | /// 57 | /// Releases all resources used by the current instance of the class. 58 | /// 59 | public void Dispose() 60 | { 61 | Dispose(true); 62 | GC.SuppressFinalize(this); 63 | } 64 | 65 | /// 66 | /// Releases all unmanaged and optionally managed resources used by the current instance of the class. 67 | /// 68 | /// true to dispose managed resources. 69 | protected virtual void Dispose(bool disposing) 70 | { 71 | if (_disposed) 72 | return; 73 | 74 | try { _emulator.Bindings.Free(_context); } 75 | catch (Exception) 76 | { 77 | Debug.WriteLine("Exception thrown during disposal of Context object."); 78 | } 79 | 80 | _disposed = true; 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/Unicorn.Net/Emulator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | 4 | namespace Unicorn 5 | { 6 | /// 7 | /// Represents a unicorn-engine emulator. 8 | /// 9 | public class Emulator : IDisposable 10 | { 11 | private bool _disposed; 12 | private readonly Hooks _hooks; 13 | private readonly Memory _memory; 14 | private readonly Registers _registers; 15 | private readonly IntPtr _handle; 16 | 17 | internal readonly UnicornArch _arch; 18 | internal readonly UnicornMode _mode; 19 | 20 | /// 21 | /// Gets the handle of the . 22 | /// 23 | public IntPtr Handle => _handle; 24 | 25 | /// 26 | /// Gets the of the . 27 | /// 28 | internal IBindings Bindings { get; } 29 | 30 | /// 31 | /// Gets the of the . 32 | /// 33 | /// instance is disposed. 34 | public UnicornMode Mode 35 | { 36 | get 37 | { 38 | ThrowIfDisposed(); 39 | return _mode; 40 | } 41 | } 42 | 43 | /// 44 | /// Gets the of the . 45 | /// 46 | /// instance is disposed. 47 | public UnicornArch Arch 48 | { 49 | get 50 | { 51 | ThrowIfDisposed(); 52 | return _arch; 53 | } 54 | } 55 | 56 | /// 57 | /// Gets the of the . 58 | /// 59 | public Registers Registers 60 | { 61 | get 62 | { 63 | ThrowIfDisposed(); 64 | return _registers; 65 | } 66 | } 67 | 68 | /// 69 | /// Gets the of the . 70 | /// 71 | /// instance is disposed. 72 | public Memory Memory 73 | { 74 | get 75 | { 76 | ThrowIfDisposed(); 77 | return _memory; 78 | } 79 | } 80 | 81 | /// 82 | /// Gets the of the . 83 | /// 84 | /// instance is disposed. 85 | public Hooks Hooks 86 | { 87 | get 88 | { 89 | ThrowIfDisposed(); 90 | return _hooks; 91 | } 92 | } 93 | 94 | /// 95 | /// Gets or sets the of the instance. 96 | /// 97 | /// is null. 98 | /// has a differnt mode or architecture than the . 99 | /// Unicorn did not return . 100 | /// instance is disposed. 101 | public Context Context 102 | { 103 | get 104 | { 105 | ThrowIfDisposed(); 106 | 107 | var context = new Context(this); 108 | context.Capture(this); 109 | return context; 110 | } 111 | set 112 | { 113 | ThrowIfDisposed(); 114 | 115 | if (value == null) 116 | throw new ArgumentNullException(nameof(value)); 117 | if (value._disposed) 118 | throw new ObjectDisposedException(null, "Can not access disposed Context object."); 119 | if (value._arch != _arch || value._mode != _mode) 120 | throw new ArgumentException("value must have same arch and mode as the Emulator instance.", nameof(value)); 121 | 122 | value.Restore(this); 123 | } 124 | } 125 | 126 | /// 127 | /// Initializes a new instance of the class with the specified 128 | /// and . 129 | /// 130 | /// to use. 131 | /// to use. 132 | public Emulator(UnicornArch arch, UnicornMode mode) : this(arch, mode, Unicorn.Bindings.Instance) 133 | { 134 | /* Space */ 135 | } 136 | 137 | /// 138 | /// Initializes a new instance of the class with the specified 139 | /// instance. 140 | /// 141 | internal Emulator(UnicornArch arch, UnicornMode mode, IBindings bindings) 142 | { 143 | _arch = arch; 144 | _mode = mode; 145 | _registers = new Registers(this); 146 | _memory = new Memory(this); 147 | _hooks = new Hooks(this); 148 | 149 | Bindings = bindings; 150 | Bindings.Open(arch, mode, ref _handle); 151 | } 152 | 153 | /// 154 | /// Starts emulation at the specified begin address and end address. 155 | /// 156 | /// Address at which to begin emulation. 157 | /// Address at which to end emulation. 158 | /// Unicorn did not return . 159 | /// instance is disposed. 160 | public void Start(ulong begin, ulong end) 161 | { 162 | ThrowIfDisposed(); 163 | Bindings.EmuStart(Handle, begin, end, 0, 0); 164 | } 165 | 166 | /// 167 | /// Starts emulation at the specified begin address, end address, timeout and number of instructions to execute. 168 | /// 169 | /// Address at which to begin emulation. 170 | /// Address at which to end emulation. 171 | /// Duration to run emulation. 172 | /// Number of instructions to execute. 173 | /// Unicorn did not return . 174 | /// instance is disposed. 175 | public void Start(ulong begin, ulong end, TimeSpan timeout, int count) 176 | { 177 | ThrowIfDisposed(); 178 | var microSeconds = (ulong)Math.Round(timeout.TotalMilliseconds * 1000); 179 | Bindings.EmuStart(Handle, begin, end, microSeconds, count); 180 | } 181 | 182 | /// 183 | /// Stops the emulation. 184 | /// 185 | /// Unicorn did not return . 186 | /// instance is disposed. 187 | public void Stop() 188 | { 189 | ThrowIfDisposed(); 190 | Bindings.EmuStop(Handle); 191 | } 192 | 193 | /// 194 | /// Finalizes the instance. 195 | /// 196 | ~Emulator() 197 | { 198 | Dispose(false); 199 | } 200 | 201 | /// 202 | /// Releases all resources used by the current instance of the class. 203 | /// 204 | public void Dispose() 205 | { 206 | Dispose(true); 207 | GC.SuppressFinalize(this); 208 | } 209 | 210 | /// 211 | /// Releases all unmanaged and optionally managed resources used by the current instance of the class. 212 | /// 213 | /// true to dispose managed resources. 214 | protected virtual void Dispose(bool disposing) 215 | { 216 | if (_disposed) 217 | return; 218 | 219 | try { Bindings.Close(Handle); } 220 | catch { Debug.WriteLine("Bindings.Close() threw an exception."); } 221 | 222 | _disposed = true; 223 | } 224 | 225 | internal void RegRead(int regId, ref long value) 226 | => Bindings.RegRead(Handle, regId, ref value); 227 | 228 | internal void RegWrite(int regId, ref long value) 229 | => Bindings.RegWrite(Handle, regId, ref value); 230 | 231 | internal void ThrowIfDisposed() 232 | { 233 | if (_disposed) 234 | throw new ObjectDisposedException(null, "Can not access disposed Emulator object."); 235 | } 236 | } 237 | } 238 | -------------------------------------------------------------------------------- /src/Unicorn.Net/GlobalSuppressions.cs: -------------------------------------------------------------------------------- 1 |  2 | // This file is used by Code Analysis to maintain SuppressMessage 3 | // attributes that are applied to this project. 4 | // Project-level suppressions either have no target or are given 5 | // a specific target and scoped to a namespace, type, member, etc. 6 | 7 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "")] 8 | 9 | -------------------------------------------------------------------------------- /src/Unicorn.Net/HookContainer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Diagnostics; 5 | using System.Runtime.InteropServices; 6 | 7 | namespace Unicorn 8 | { 9 | /// 10 | /// Base class of hook containers. 11 | /// 12 | public abstract class HookContainer : IEnumerable 13 | { 14 | private readonly Emulator _emulator; 15 | private readonly List _handles; 16 | 17 | internal HookContainer(Emulator emulator) 18 | { 19 | Debug.Assert(emulator != null); 20 | _emulator = emulator; 21 | _handles = new List(); 22 | } 23 | 24 | /// 25 | /// Gets the number of in this . 26 | /// 27 | public int Count => _handles.Count; 28 | 29 | /// 30 | /// Gets the instance which owns this . 31 | /// 32 | protected Emulator Emulator => _emulator; 33 | 34 | /// 35 | /// Gets the list of in this . 36 | /// 37 | protected List Handles => _handles; 38 | 39 | /// 40 | /// Base method to add a hook to . 41 | /// 42 | /// Type of hook. 43 | /// Pointer to callback method. 44 | /// Start address of where the hook is effective (inclusive). 45 | /// End address of where the hook is effective (inclusive). 46 | /// A which represents hook. 47 | protected HookHandle Add(UnicornHookType type, Delegate callback, ulong begin, ulong end) 48 | { 49 | //NOTE: Not calling Emulator.CheckDispose() here because the caller should take responsibility of doing so. 50 | 51 | var hh = IntPtr.Zero; 52 | var callbackPtr = Marshal.GetFunctionPointerForDelegate(callback); 53 | Emulator.Bindings.HookAdd(Emulator.Handle, ref hh, type, callbackPtr, IntPtr.Zero, begin, end); 54 | 55 | var handle = new HookHandle(hh, callback); 56 | _handles.Add(handle); 57 | 58 | return handle; 59 | } 60 | 61 | /// 62 | /// Removes a hook with the specified from the . 63 | /// 64 | /// to the hook to remove. 65 | /// true if was found and removed; otherwise false. 66 | /// 67 | /// Unicorn did not return . 68 | /// instance is disposed. 69 | public bool Remove(HookHandle handle) 70 | { 71 | Emulator.ThrowIfDisposed(); 72 | Emulator.Bindings.HookDel(Emulator.Handle, handle._hh); 73 | return _handles.Remove(handle); 74 | } 75 | 76 | /// 77 | /// Returns an which iterates through the of the . 78 | /// 79 | /// An which iterates through the of the . 80 | public IEnumerator GetEnumerator() => ((IEnumerable)_handles).GetEnumerator(); 81 | 82 | IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)_handles).GetEnumerator(); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/Unicorn.Net/HookHandle.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Unicorn 4 | { 5 | /// 6 | /// Represents a hook handle. 7 | /// 8 | public struct HookHandle 9 | { 10 | internal readonly IntPtr _hh; 11 | private readonly Delegate _hCallback; 12 | 13 | internal HookHandle(IntPtr hh, Delegate d) 14 | { 15 | _hh = hh; 16 | _hCallback = d; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Unicorn.Net/Hooks.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | 4 | namespace Unicorn 5 | { 6 | /// 7 | /// Represents the hooks of an . 8 | /// 9 | public class Hooks 10 | { 11 | // Emulator instance which owns this Hooks object instance. 12 | private readonly Emulator _emulator; 13 | private readonly MemoryHookContainer _memoryHooks; 14 | private readonly CodeHooksContainer _codeHooks; 15 | private readonly BlockHooksContainer _blockHooks; 16 | private readonly InstructionHookContainer _instructionHooks; 17 | private readonly InterruptHookContainer _interruptHooks; 18 | 19 | internal Hooks(Emulator emulator) 20 | { 21 | Debug.Assert(emulator != null); 22 | 23 | _emulator = emulator; 24 | _memoryHooks = new MemoryHookContainer(emulator); 25 | _codeHooks = new CodeHooksContainer(emulator); 26 | _blockHooks = new BlockHooksContainer(emulator); 27 | _instructionHooks = new InstructionHookContainer(emulator); 28 | _interruptHooks = new InterruptHookContainer(emulator); 29 | } 30 | 31 | /// 32 | /// Gets the of the . 33 | /// 34 | /// instance is disposed. 35 | public MemoryHookContainer Memory 36 | { 37 | get 38 | { 39 | _emulator.ThrowIfDisposed(); 40 | 41 | return _memoryHooks; 42 | } 43 | } 44 | 45 | /// 46 | /// Gets the of the . 47 | /// 48 | /// instance is disposed. 49 | public CodeHooksContainer Code 50 | { 51 | get 52 | { 53 | _emulator.ThrowIfDisposed(); 54 | 55 | return _codeHooks; 56 | } 57 | } 58 | 59 | /// 60 | /// Gets the of the . 61 | /// 62 | /// instance is disposed. 63 | public BlockHooksContainer Block 64 | { 65 | get 66 | { 67 | _emulator.ThrowIfDisposed(); 68 | 69 | return _blockHooks; 70 | } 71 | } 72 | 73 | /// 74 | /// Gets the of the . 75 | /// 76 | /// instance is disposed. 77 | public InstructionHookContainer Instruction 78 | { 79 | get 80 | { 81 | _emulator.ThrowIfDisposed(); 82 | 83 | return _instructionHooks; 84 | } 85 | } 86 | 87 | /// 88 | /// Gets the of the . 89 | /// 90 | /// instance is disposed. 91 | public InterruptHookContainer Interrupt 92 | { 93 | get 94 | { 95 | _emulator.ThrowIfDisposed(); 96 | 97 | return _interruptHooks; 98 | } 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/Unicorn.Net/IBindings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Unicorn 4 | { 5 | public interface IBindings 6 | { 7 | string StrError(UnicornError err); 8 | int Version(ref int major, ref int minor); 9 | void Free(IntPtr ptr); 10 | 11 | void Open(UnicornArch arch, UnicornMode mode, ref IntPtr uc); 12 | void Close(IntPtr uc); 13 | 14 | void ContextAlloc(IntPtr uc, ref IntPtr ctx); 15 | void ContextRestore(IntPtr uc, IntPtr ctx); 16 | void ContextSave(IntPtr uc, IntPtr ctx); 17 | 18 | void EmuStart(IntPtr uc, ulong begin, ulong end, ulong timeout, int count); 19 | void EmuStop(IntPtr uc); 20 | 21 | void HookAdd(IntPtr uc, ref IntPtr hh, UnicornHookType type, IntPtr callback, IntPtr userData, ulong address, ulong end); 22 | void HookAdd(IntPtr uc, ref IntPtr hh, UnicornHookType type, IntPtr callback, IntPtr userData, ulong address, ulong end, int instruction); 23 | void HookDel(IntPtr uc, IntPtr hh); 24 | 25 | void MemMap(IntPtr uc, ulong address, int size, MemoryPermissions permissions); 26 | void MemProtect(IntPtr uc, ulong address, int size, MemoryPermissions permissions); 27 | void MemRead(IntPtr uc, ulong address, byte[] buffer, int count); 28 | void MemRegions(IntPtr uc, ref MemoryRegion[] regions); 29 | void MemUnmap(IntPtr uc, ulong address, int size); 30 | void MemWrite(IntPtr uc, ulong address, byte[] buffer, int count); 31 | 32 | void Query(IntPtr uc, UnicornQueryType type, ref int value); 33 | 34 | void RegRead(IntPtr uc, int regId, ref long value); 35 | void RegWrite(IntPtr uc, int regId, ref long value); 36 | } 37 | } -------------------------------------------------------------------------------- /src/Unicorn.Net/Instruction.cs: -------------------------------------------------------------------------------- 1 | namespace Unicorn 2 | { 3 | /// 4 | /// Represents an instruction. 5 | /// 6 | public struct Instruction 7 | { 8 | internal readonly int _id; 9 | internal Instruction(int id) 10 | { 11 | _id = id; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Unicorn.Net/InstructionHookContainer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Runtime.InteropServices; 4 | using Unicorn.Internal; 5 | using Unicorn.X86; 6 | 7 | namespace Unicorn 8 | { 9 | /// 10 | /// Callback for tracing . 11 | /// 12 | /// which raised the callback. 13 | /// Port number. 14 | /// Data size read from . 15 | /// Object associated with the callback. 16 | /// Data read. 17 | public delegate int InstructionInHookCallback(Emulator emulator, int port, int size, object userToken); 18 | 19 | /// 20 | /// Callback for tracing . 21 | /// 22 | /// which raised the callback. 23 | /// Port number. 24 | /// Data size written to . 25 | /// Data to be written to . 26 | /// Object associated with the callback. 27 | public delegate void InstructionOutHookCallback(Emulator emulator, int port, int size, int value, object userToken); 28 | 29 | /// 30 | /// Represents hooks for instructions of an . 31 | /// 32 | public class InstructionHookContainer : HookContainer 33 | { 34 | internal InstructionHookContainer(Emulator emulator) : base(emulator) 35 | { 36 | // Space 37 | } 38 | 39 | /// 40 | /// Adds a to the with the specified and user token which 41 | /// is called anytime the hook is triggered. 42 | /// 43 | /// 44 | /// to add. 45 | /// to hook. 46 | /// Object associated with the callback. 47 | /// A which represents the hook. 48 | /// 49 | /// is null. 50 | /// Unicorn did not return . 51 | /// instance is disposed. 52 | public HookHandle Add(InstructionInHookCallback callback, Instruction instruction, object userToken) 53 | { 54 | Emulator.ThrowIfDisposed(); 55 | 56 | if (callback == null) 57 | throw new ArgumentNullException(nameof(callback)); 58 | 59 | return AddInInternal(callback, instruction, 1, 0, userToken); 60 | } 61 | 62 | /// 63 | /// Adds a to the with the specified and user token which 64 | /// is called when the hook is triggered within the specified start address and end address. 65 | /// 66 | /// 67 | /// to add. 68 | /// to hook. 69 | /// Start address of where the hook is effective (inclusive). 70 | /// End address of where the hook is effective (inclusive). 71 | /// Object associated with the callback. 72 | /// A which represents the hook. 73 | /// 74 | /// is null. 75 | /// Unicorn did not return . 76 | /// instance is disposed. 77 | public HookHandle Add(InstructionInHookCallback callback, Instruction instruction, ulong begin, ulong end, object userToken) 78 | { 79 | Emulator.ThrowIfDisposed(); 80 | 81 | if (callback == null) 82 | throw new ArgumentNullException(nameof(callback)); 83 | 84 | return AddInInternal(callback, instruction, begin, end, userToken); 85 | } 86 | 87 | /// 88 | /// Adds a to the with the specified and user token which 89 | /// is called anytime the hook is triggered. 90 | /// 91 | /// 92 | /// to add. 93 | /// to hook. 94 | /// Object associated with the callback. 95 | /// A which represents the hook. 96 | /// 97 | /// is null. 98 | /// Unicorn did not return . 99 | /// instance is disposed. 100 | public HookHandle Add(InstructionOutHookCallback callback, Instruction instruction, object userToken) 101 | { 102 | Emulator.ThrowIfDisposed(); 103 | 104 | if (callback == null) 105 | throw new ArgumentNullException(nameof(callback)); 106 | 107 | return AddOutInternal(callback, instruction, 1, 0, userToken); 108 | } 109 | 110 | /// 111 | /// Adds a to the with the specified and user token which 112 | /// is called when the hook is triggered within the specified start address and end address. 113 | /// 114 | /// 115 | /// to add. 116 | /// to hook. 117 | /// Start address of where the hook is effective (inclusive). 118 | /// End address of where the hook is effective (inclusive). 119 | /// Object associated with the callback. 120 | /// A which represents the hook. 121 | /// 122 | /// is null. 123 | /// Unicorn did not return . 124 | /// instance is disposed. 125 | public HookHandle Add(InstructionOutHookCallback callback, Instruction instruction, ulong begin, ulong end, object userToken) 126 | { 127 | Emulator.ThrowIfDisposed(); 128 | 129 | if (callback == null) 130 | throw new ArgumentNullException(nameof(callback)); 131 | 132 | return AddOutInternal(callback, instruction, begin, end, userToken); 133 | } 134 | 135 | private HookHandle AddInInternal(InstructionInHookCallback callback, Instruction instruction, ulong begin, ulong end, object userToken) 136 | { 137 | var wrapper = new uc_cb_insn_in((uc, port, size, user_data) => 138 | { 139 | Debug.Assert(uc == Emulator.Handle); 140 | return callback(Emulator, port, size, userToken); 141 | }); 142 | 143 | return AddInternal(wrapper, begin, end, instruction); 144 | } 145 | 146 | private HookHandle AddOutInternal(InstructionOutHookCallback callback, Instruction instruction, ulong begin, ulong end, object userToken) 147 | { 148 | var wrapper = new uc_cb_insn_out((uc, port, size, value, user_data) => 149 | { 150 | Debug.Assert(uc == Emulator.Handle); 151 | callback(Emulator, port, size, value, userToken); 152 | }); 153 | 154 | return AddInternal(wrapper, begin, end, instruction); 155 | } 156 | 157 | private HookHandle AddInternal(Delegate callback, ulong begin, ulong end, Instruction inst) 158 | { 159 | var ptr = IntPtr.Zero; 160 | var callbackPtr = Marshal.GetFunctionPointerForDelegate(callback); 161 | Emulator.Bindings.HookAdd(Emulator.Handle, ref ptr, UnicornHookType.Instructions, callbackPtr, IntPtr.Zero, begin, end, inst._id); 162 | 163 | var handle = new HookHandle(ptr, callback); 164 | Handles.Add(handle); 165 | 166 | return handle; 167 | } 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /src/Unicorn.Net/Internal/uc_arch.cs: -------------------------------------------------------------------------------- 1 | namespace Unicorn.Internal 2 | { 3 | internal enum uc_arch 4 | { 5 | // From unicorn.h 6 | 7 | UC_ARCH_ARM = 1, // ARM architecture (including Thumb, Thumb-2) 8 | UC_ARCH_ARM64, // ARM-64, also called AArch64 9 | UC_ARCH_MIPS, // Mips architecture 10 | UC_ARCH_X86, // X86 architecture (including x86 & x86-64) 11 | UC_ARCH_PPC, // PowerPC architecture (currently unsupported) 12 | UC_ARCH_SPARC, // Sparc architecture 13 | UC_ARCH_M68K, // M68K architecture 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Unicorn.Net/Internal/uc_err.cs: -------------------------------------------------------------------------------- 1 | namespace Unicorn.Internal 2 | { 3 | internal enum uc_err 4 | { 5 | // From unicorn.h 6 | 7 | UC_ERR_OK = 0, // No error: everything was fine 8 | UC_ERR_NOMEM, // Out-Of-Memory error: uc_open(), uc_emulate() 9 | UC_ERR_ARCH, // Unsupported architecture: uc_open() 10 | UC_ERR_HANDLE, // Invalid handle 11 | UC_ERR_MODE, // Invalid/unsupported mode: uc_open() 12 | UC_ERR_VERSION, // Unsupported version (bindings) 13 | UC_ERR_READ_UNMAPPED, // Quit emulation due to READ on unmapped memory: uc_emu_start() 14 | UC_ERR_WRITE_UNMAPPED, // Quit emulation due to WRITE on unmapped memory: uc_emu_start() 15 | UC_ERR_FETCH_UNMAPPED, // Quit emulation due to FETCH on unmapped memory: uc_emu_start() 16 | UC_ERR_HOOK, // Invalid hook type: uc_hook_add() 17 | UC_ERR_INSN_INVALID, // Quit emulation due to invalid instruction: uc_emu_start() 18 | UC_ERR_MAP, // Invalid memory mapping: uc_mem_map() 19 | UC_ERR_WRITE_PROT, // Quit emulation due to UC_MEM_WRITE_PROT violation: uc_emu_start() 20 | UC_ERR_READ_PROT, // Quit emulation due to UC_MEM_READ_PROT violation: uc_emu_start() 21 | UC_ERR_FETCH_PROT, // Quit emulation due to UC_MEM_FETCH_PROT violation: uc_emu_start() 22 | UC_ERR_ARG, // Inavalid argument provided to uc_xxx function (See specific function API) 23 | UC_ERR_READ_UNALIGNED, // Unaligned read 24 | UC_ERR_WRITE_UNALIGNED, // Unaligned write 25 | UC_ERR_FETCH_UNALIGNED, // Unaligned fetch 26 | UC_ERR_HOOK_EXIST, // hook for this event already existed 27 | UC_ERR_RESOURCE, // Insufficient resource: uc_emu_start() 28 | UC_ERR_EXCEPTION, // Unhandled CPU exception 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Unicorn.Net/Internal/uc_hook_type.cs: -------------------------------------------------------------------------------- 1 | namespace Unicorn.Internal 2 | { 3 | internal enum uc_hook_type 4 | { 5 | // From unicorn.h 6 | 7 | // Hook all interrupt/syscall events 8 | UC_HOOK_INTR = 1 << 0, 9 | // Hook a particular instruction - only a very small subset of instructions supported here 10 | UC_HOOK_INSN = 1 << 1, 11 | // Hook a range of code 12 | UC_HOOK_CODE = 1 << 2, 13 | // Hook basic blocks 14 | UC_HOOK_BLOCK = 1 << 3, 15 | // Hook for memory read on unmapped memory 16 | UC_HOOK_MEM_READ_UNMAPPED = 1 << 4, 17 | // Hook for invalid memory write events 18 | UC_HOOK_MEM_WRITE_UNMAPPED = 1 << 5, 19 | // Hook for invalid memory fetch for execution events 20 | UC_HOOK_MEM_FETCH_UNMAPPED = 1 << 6, 21 | // Hook for memory read on read-protected memory 22 | UC_HOOK_MEM_READ_PROT = 1 << 7, 23 | // Hook for memory write on write-protected memory 24 | UC_HOOK_MEM_WRITE_PROT = 1 << 8, 25 | // Hook for memory fetch on non-executable memory 26 | UC_HOOK_MEM_FETCH_PROT = 1 << 9, 27 | // Hook memory read events. 28 | UC_HOOK_MEM_READ = 1 << 10, 29 | // Hook memory write events. 30 | UC_HOOK_MEM_WRITE = 1 << 11, 31 | // Hook memory fetch for execution events 32 | UC_HOOK_MEM_FETCH = 1 << 12, 33 | // Hook memory read events, but only successful access. 34 | // The callback will be triggered after successful read. 35 | UC_HOOK_MEM_READ_AFTER = 1 << 13, 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Unicorn.Net/Internal/uc_mem_region.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | 3 | namespace Unicorn.Internal 4 | { 5 | [StructLayout(LayoutKind.Sequential)] 6 | internal struct uc_mem_region 7 | { 8 | public ulong begin; 9 | public ulong end; 10 | public ulong perms; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Unicorn.Net/Internal/uc_mem_type.cs: -------------------------------------------------------------------------------- 1 | namespace Unicorn.Internal 2 | { 3 | internal enum uc_mem_type 4 | { 5 | // From unicorn.h 6 | 7 | UC_MEM_READ = 16, // Memory is read from 8 | UC_MEM_WRITE, // Memory is written to 9 | UC_MEM_FETCH, // Memory is fetched 10 | UC_MEM_READ_UNMAPPED, // Unmapped memory is read from 11 | UC_MEM_WRITE_UNMAPPED, // Unmapped memory is written to 12 | UC_MEM_FETCH_UNMAPPED, // Unmapped memory is fetched 13 | UC_MEM_WRITE_PROT, // Write to write protected, but mapped, memory 14 | UC_MEM_READ_PROT, // Read from read protected, but mapped, memory 15 | UC_MEM_FETCH_PROT, // Fetch from non-executable, but mapped, memory 16 | UC_MEM_READ_AFTER, // Memory is read from (successful access) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Unicorn.Net/Internal/uc_mode.cs: -------------------------------------------------------------------------------- 1 | namespace Unicorn.Internal 2 | { 3 | internal enum uc_mode 4 | { 5 | // From unicorn.h 6 | 7 | UC_MODE_LITTLE_ENDIAN = 0, // little-endian mode (default mode) 8 | UC_MODE_BIG_ENDIAN = 1 << 30, // big-endian mode 9 | // arm / arm64 10 | UC_MODE_ARM = 0, // ARM mode 11 | UC_MODE_THUMB = 1 << 4, // THUMB mode (including Thumb-2) 12 | UC_MODE_MCLASS = 1 << 5, // ARM's Cortex-M series (currently unsupported) 13 | UC_MODE_V8 = 1 << 6, // ARMv8 A32 encodings for ARM (currently unsupported) 14 | // mips 15 | UC_MODE_MICRO = 1 << 4, // MicroMips mode (currently unsupported) 16 | UC_MODE_MIPS3 = 1 << 5, // Mips III ISA (currently unsupported) 17 | UC_MODE_MIPS32R6 = 1 << 6, // Mips32r6 ISA (currently unsupported) 18 | UC_MODE_MIPS32 = 1 << 2, // Mips32 ISA 19 | UC_MODE_MIPS64 = 1 << 3, // Mips64 ISA 20 | // x86 / x64 21 | UC_MODE_16 = 1 << 1, // 16-bit mode 22 | UC_MODE_32 = 1 << 2, // 32-bit mode 23 | UC_MODE_64 = 1 << 3, // 64-bit mode 24 | // ppc 25 | UC_MODE_PPC32 = 1 << 2, // 32-bit mode (currently unsupported) 26 | UC_MODE_PPC64 = 1 << 3, // 64-bit mode (currently unsupported) 27 | UC_MODE_QPX = 1 << 4, // Quad Processing eXtensions mode (currently unsupported) 28 | // sparc 29 | UC_MODE_SPARC32 = 1 << 2, // 32-bit mode 30 | UC_MODE_SPARC64 = 1 << 3, // 64-bit mode 31 | UC_MODE_V9 = 1 << 4, // SparcV9 mode (currently unsupported) 32 | // m68k 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Unicorn.Net/Internal/uc_query_type.cs: -------------------------------------------------------------------------------- 1 | namespace Unicorn.Internal 2 | { 3 | internal enum uc_query_type 4 | { 5 | // From unicorn.h 6 | 7 | // Dynamically query current hardware mode. 8 | UC_QUERY_MODE = 1, 9 | UC_QUERY_PAGE_SIZE, 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Unicorn.Net/Internal/unicorn.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | namespace Unicorn.Internal 5 | { 6 | /// 7 | /// Provides DLL imports of the unicorn library. 8 | /// 9 | internal static class unicorn 10 | { 11 | public const string UNICORN_LIB = "unicorn"; 12 | 13 | [DllImport(UNICORN_LIB, CallingConvention = CallingConvention.Cdecl)] 14 | public static extern int uc_version(ref int major, ref int minor); 15 | 16 | [DllImport(UNICORN_LIB, CallingConvention = CallingConvention.Cdecl)] 17 | public static extern IntPtr uc_strerror(uc_err err); 18 | 19 | [DllImport(UNICORN_LIB, CallingConvention = CallingConvention.Cdecl)] 20 | public static extern uc_err uc_free(IntPtr mem); 21 | 22 | [DllImport(UNICORN_LIB, CallingConvention = CallingConvention.Cdecl)] 23 | public static extern uc_err uc_query(IntPtr uc, uc_query_type query, ref int result); 24 | 25 | #if !RELEASE 26 | [DllImport(UNICORN_LIB, CallingConvention = CallingConvention.Cdecl)] 27 | public static extern bool uc_arch_supported(int arch); // Not used. 28 | #endif 29 | 30 | [DllImport(UNICORN_LIB, CallingConvention = CallingConvention.Cdecl)] 31 | public static extern uc_err uc_open(uc_arch arch, uc_mode mode, ref IntPtr uc); 32 | 33 | [DllImport(UNICORN_LIB, CallingConvention = CallingConvention.Cdecl)] 34 | public static extern uc_err uc_close(IntPtr uc); 35 | 36 | [DllImport(UNICORN_LIB, CallingConvention = CallingConvention.Cdecl)] 37 | public static extern uc_err uc_reg_read(IntPtr uc, int regid, ref long value); 38 | 39 | [DllImport(UNICORN_LIB, CallingConvention = CallingConvention.Cdecl)] 40 | public static extern uc_err uc_reg_write(IntPtr uc, int regid, ref long value); 41 | 42 | [DllImport(UNICORN_LIB, CallingConvention = CallingConvention.Cdecl)] 43 | public static extern uc_err uc_emu_start(IntPtr uc, ulong begin, ulong end, ulong timeout, int count); 44 | 45 | [DllImport(UNICORN_LIB, CallingConvention = CallingConvention.Cdecl)] 46 | public static extern uc_err uc_emu_stop(IntPtr uc); 47 | 48 | [DllImport(UNICORN_LIB, CallingConvention = CallingConvention.Cdecl)] 49 | public static extern uc_err uc_mem_map(IntPtr uc, ulong address, int size, int perms); 50 | 51 | [DllImport(UNICORN_LIB, CallingConvention = CallingConvention.Cdecl)] 52 | public static extern uc_err uc_mem_unmap(IntPtr uc, ulong address, int size); 53 | 54 | [DllImport(UNICORN_LIB, CallingConvention = CallingConvention.Cdecl)] 55 | public static extern uc_err uc_mem_write(IntPtr uc, ulong address, byte[] bytes, int size); 56 | 57 | [DllImport(UNICORN_LIB, CallingConvention = CallingConvention.Cdecl)] 58 | public static extern uc_err uc_mem_read(IntPtr uc, ulong address, byte[] bytes, int size); 59 | 60 | [DllImport(UNICORN_LIB, CallingConvention = CallingConvention.Cdecl)] 61 | public static extern uc_err uc_mem_protect(IntPtr uc, ulong address, int size, int perms); 62 | 63 | [DllImport(UNICORN_LIB, CallingConvention = CallingConvention.Cdecl)] 64 | public static extern uc_err uc_mem_regions(IntPtr uc, ref IntPtr regions, ref uint count); 65 | 66 | [DllImport(UNICORN_LIB, CallingConvention = CallingConvention.Cdecl)] 67 | public static extern uc_err uc_context_alloc(IntPtr uc, ref IntPtr ctx); 68 | 69 | [DllImport(UNICORN_LIB, CallingConvention = CallingConvention.Cdecl)] 70 | public static extern uc_err uc_context_save(IntPtr uc, IntPtr ctx); 71 | 72 | [DllImport(UNICORN_LIB, CallingConvention = CallingConvention.Cdecl)] 73 | public static extern uc_err uc_context_restore(IntPtr uc, IntPtr ctx); 74 | 75 | [DllImport(UNICORN_LIB, CallingConvention = CallingConvention.Cdecl)] 76 | public static extern uc_err uc_hook_add(IntPtr uc, ref IntPtr hh, uc_hook_type type, IntPtr callback, IntPtr user_data, ulong address, ulong end); 77 | 78 | [DllImport(UNICORN_LIB, CallingConvention = CallingConvention.Cdecl)] 79 | public static extern uc_err uc_hook_add(IntPtr uc, ref IntPtr hh, uc_hook_type type, IntPtr callback, IntPtr user_data, ulong address, ulong end, int instruction); 80 | 81 | [DllImport(UNICORN_LIB, CallingConvention = CallingConvention.Cdecl)] 82 | public static extern uc_err uc_hook_del(IntPtr uc, IntPtr hh); 83 | } 84 | 85 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 86 | internal delegate void uc_cb_hookcode(IntPtr uc, ulong address, int size, IntPtr user_data); 87 | 88 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 89 | internal delegate void uc_cb_hookintr(IntPtr uc, int into, IntPtr user_data); 90 | 91 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 92 | internal delegate int uc_cb_insn_in(IntPtr uc, int port, int size, IntPtr user_data); 93 | 94 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 95 | internal delegate void uc_cb_insn_out(IntPtr uc, int port, int size, int value, IntPtr user_data); 96 | 97 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 98 | internal delegate void uc_cb_hookmem(IntPtr uc, uc_mem_type type, ulong address, int size, ulong value, IntPtr user_data); 99 | 100 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 101 | internal delegate bool uc_cb_eventmem(IntPtr uc, uc_mem_type type, ulong address, int size, ulong value, IntPtr user_data); 102 | } 103 | -------------------------------------------------------------------------------- /src/Unicorn.Net/InterruptHookContainer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Runtime.InteropServices; 4 | using Unicorn.Internal; 5 | 6 | namespace Unicorn 7 | { 8 | /// 9 | /// Callback for tracing interrupts. 10 | /// 11 | /// which raised the callback. 12 | /// Interrupt number. 13 | /// Object associated with the callback. 14 | public delegate void InterruptHookCallback(Emulator emulator, int into, object userToken); 15 | 16 | /// 17 | /// Represents hooks for interrupts of an . 18 | /// 19 | public class InterruptHookContainer : HookContainer 20 | { 21 | internal InterruptHookContainer(Emulator emulator) : base(emulator) 22 | { 23 | // Space 24 | } 25 | 26 | /// 27 | /// Adds a to the with the specified user token which 28 | /// is called anytime the hook is triggered. 29 | /// 30 | /// 31 | /// to add. 32 | /// Object associated with the callback. 33 | /// A which represents the hook. 34 | /// 35 | /// is null. 36 | /// Unicorn did not return . 37 | /// instance is disposed. 38 | public HookHandle Add(InterruptHookCallback callback, object userToken) 39 | { 40 | Emulator.ThrowIfDisposed(); 41 | 42 | if (callback == null) 43 | throw new ArgumentNullException(nameof(callback)); 44 | 45 | return AddInternal(callback, 1, 0, userToken); 46 | } 47 | 48 | /// 49 | /// Adds a to the with the specified user token which 50 | /// is called when the hook is triggered within the specified start address and end address. 51 | /// 52 | /// 53 | /// to add. 54 | /// Start address of where the hook is effective (inclusive). 55 | /// End address of where the hook is effective (inclusive). 56 | /// Object associated with the callback. 57 | /// A which represents the hook. 58 | /// 59 | /// 60 | /// If > , the callback is called anytime the hook triggers. 61 | /// 62 | /// 63 | /// is null. 64 | /// Unicorn did not return . 65 | /// instance is disposed. 66 | public HookHandle Add(InterruptHookCallback callback, ulong begin, ulong end, object userToken) 67 | { 68 | Emulator.ThrowIfDisposed(); 69 | 70 | if (callback == null) 71 | throw new ArgumentNullException(nameof(callback)); 72 | 73 | return AddInternal(callback, begin, end, userToken); 74 | } 75 | 76 | private HookHandle AddInternal(InterruptHookCallback callback, ulong begin, ulong end, object userToken) 77 | { 78 | var wrapper = new uc_cb_hookintr((uc, into, user_data) => 79 | { 80 | Debug.Assert(uc == Emulator.Handle); 81 | callback(Emulator, into, userToken); 82 | }); 83 | 84 | return Add(UnicornHookType.Interrupts, wrapper, begin, end); 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/Unicorn.Net/Memory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | 4 | namespace Unicorn 5 | { 6 | /// 7 | /// Represents the memory of an . 8 | /// 9 | public class Memory 10 | { 11 | // Emulator object instance which owns this Memory object instance. 12 | private readonly Emulator _emulator; 13 | 14 | internal Memory(Emulator emulator) 15 | { 16 | Debug.Assert(emulator != null); 17 | _emulator = emulator; 18 | } 19 | 20 | /// 21 | /// Gets all the mapped for emulation. 22 | /// 23 | /// 24 | /// Unicorn did not return . 25 | /// instance is disposed. 26 | public MemoryRegion[] Regions 27 | { 28 | get 29 | { 30 | MemoryRegion[] regions = null; 31 | _emulator.ThrowIfDisposed(); 32 | _emulator.Bindings.MemRegions(_emulator.Handle, ref regions); 33 | return regions; 34 | } 35 | } 36 | 37 | /// 38 | /// Gets the page size of which is 4KB. 39 | /// 40 | /// 41 | /// Unicorn did not return . 42 | /// instance is disposed. 43 | public int PageSize 44 | { 45 | get 46 | { 47 | int size = 0; 48 | _emulator.ThrowIfDisposed(); 49 | _emulator.Bindings.Query(_emulator.Handle, UnicornQueryType.PageSize, ref size); 50 | return size; 51 | } 52 | } 53 | 54 | /// 55 | /// Maps a memory region for emulation with the specified starting address, size and . 56 | /// 57 | /// Starting address of memory region. 58 | /// Size of memory region. 59 | /// Permissions of memory region. 60 | /// 61 | /// is not aligned with . 62 | /// is not a multiple of . 63 | /// is less than 0. 64 | /// Unicorn did not return . 65 | /// instance is disposed. 66 | public void Map(ulong address, int size, MemoryPermissions permissions) 67 | { 68 | _emulator.ThrowIfDisposed(); 69 | 70 | if ((address & (ulong)PageSize) != 0) 71 | throw new ArgumentException("Address must be aligned with page size.", nameof(address)); 72 | if ((size & PageSize) != 0) 73 | throw new ArgumentException("Size must be a multiple of page size.", nameof(size)); 74 | 75 | if (size < 0) 76 | throw new ArgumentOutOfRangeException(nameof(size), "Size must be non-negative."); 77 | if (permissions > MemoryPermissions.All) 78 | throw new ArgumentException("Permissions is invalid.", nameof(permissions)); 79 | 80 | _emulator.Bindings.MemMap(_emulator.Handle, address, size, permissions); 81 | } 82 | 83 | /// 84 | /// Unmaps a region of memory used for emulation with the specified starting address and size. 85 | /// 86 | /// Starting address of memory region. 87 | /// Size of memory region. 88 | /// 89 | /// is not aligned with . 90 | /// is not a multiple of . 91 | /// is less than 0. 92 | /// Unicorn did not return . 93 | /// instance is disposed. 94 | public void Unmap(ulong address, int size) 95 | { 96 | _emulator.ThrowIfDisposed(); 97 | 98 | if ((address & (ulong)PageSize) != (ulong)PageSize) 99 | throw new ArgumentException("Address must be aligned with page size.", nameof(address)); 100 | if ((size & PageSize) != PageSize) 101 | throw new ArgumentException("Size must be a multiple of page size.", nameof(size)); 102 | 103 | if (size < 0) 104 | throw new ArgumentOutOfRangeException(nameof(size), "Size must be non-negative."); 105 | 106 | _emulator.Bindings.MemUnmap(_emulator.Handle, address, size); 107 | } 108 | 109 | /// 110 | /// Sets permissions for a region of memory with the specified starting address, size and . 111 | /// 112 | /// Starting address of memory region. 113 | /// Size of memory region. 114 | /// Permissions of memory region. 115 | /// 116 | /// is not aligned with . 117 | /// is not a multiple of . 118 | /// is less than 0. 119 | /// Unicorn did not return . 120 | /// instance is disposed. 121 | public void Protect(ulong address, int size, MemoryPermissions permissions) 122 | { 123 | _emulator.ThrowIfDisposed(); 124 | 125 | if ((address & (ulong)PageSize) != (ulong)PageSize) 126 | throw new ArgumentException("Address must be aligned with page size.", nameof(address)); 127 | if ((size & PageSize) != PageSize) 128 | throw new ArgumentException("Size must be a multiple of page size.", nameof(size)); 129 | 130 | if (size < 0) 131 | throw new ArgumentOutOfRangeException(nameof(size), "Size must be non-negative."); 132 | if (permissions > MemoryPermissions.All) 133 | throw new ArgumentException("Permissions is invalid.", nameof(permissions)); 134 | 135 | _emulator.Bindings.MemProtect(_emulator.Handle, address, size, permissions); 136 | } 137 | 138 | /// 139 | /// Writes the specified buffer to the specified memory address. 140 | /// 141 | /// Address to write data. 142 | /// Data to write. 143 | /// Amount of data to write. 144 | /// 145 | /// is null. 146 | /// is less than 0 or greater than the length of . 147 | /// Unicorn did not return . 148 | /// instance is disposed. 149 | public void Write(ulong address, byte[] buffer, int count) 150 | { 151 | _emulator.ThrowIfDisposed(); 152 | 153 | if (buffer == null) 154 | throw new ArgumentNullException(nameof(buffer)); 155 | if (count < 0 || count > buffer.Length) 156 | throw new ArgumentOutOfRangeException(nameof(count), "Count must be non-negative and less or equal to the length of data."); 157 | 158 | _emulator.Bindings.MemWrite(_emulator.Handle, address, buffer, count); 159 | } 160 | 161 | /// 162 | /// Reads data at the specified address to the specified buffer. 163 | /// 164 | /// Address to read. 165 | /// Buffer thats going to contain the read data. 166 | /// Amount of data to read. 167 | /// 168 | /// is null. 169 | /// is less than 0 or greater than the length of . 170 | /// Unicorn did not return . 171 | /// instance is disposed. 172 | public void Read(ulong address, byte[] buffer, int count) 173 | { 174 | _emulator.ThrowIfDisposed(); 175 | 176 | if (buffer == null) 177 | throw new ArgumentNullException(nameof(buffer)); 178 | if (count < 0 || count > buffer.Length) 179 | throw new ArgumentOutOfRangeException(nameof(count), "Count must be non-negative and less or equal to the length of data."); 180 | 181 | _emulator.Bindings.MemRead(_emulator.Handle, address, buffer, count); 182 | } 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /src/Unicorn.Net/MemoryHookContainer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Runtime.InteropServices; 4 | using Unicorn.Internal; 5 | 6 | namespace Unicorn 7 | { 8 | /// 9 | /// Callback for hooking memory. 10 | /// 11 | /// which raised the callback. 12 | /// Type of memory access. 13 | /// Address where code is being executed. 14 | /// Size of data being read or written. 15 | /// Data being written to memory; irrelevant if is . 16 | /// Object associated with the callback. 17 | public delegate void MemoryHookCallback(Emulator emulator, MemoryType type, ulong address, int size, ulong value, object userToken); 18 | 19 | /// 20 | /// Callback for handling invalid memory accesses. 21 | /// 22 | /// which raised the callback. 23 | /// Type of memory access. 24 | /// Address where code is being executed. 25 | /// Size of data being read or written. 26 | /// Data being written to memory; irrelevant if is . 27 | /// Object associated with the callback. 28 | /// Return true to continue execution; otherwise false to stop execution. 29 | public delegate bool MemoryEventHookCallback(Emulator emulator, MemoryType type, ulong address, int size, ulong value, object userToken); 30 | 31 | /// 32 | /// Represents hooks for memory of an . 33 | /// 34 | public class MemoryHookContainer : HookContainer 35 | { 36 | internal MemoryHookContainer(Emulator emulator) : base(emulator) 37 | { 38 | // Space 39 | } 40 | 41 | /// 42 | /// Adds a to the with the specified and user token which 43 | /// is called anytime the hook is triggered. 44 | /// 45 | /// 46 | /// Type of . 47 | /// to add. 48 | /// Object associated with the callback. 49 | /// A which represents the hook. 50 | /// 51 | /// is null. 52 | /// Unicorn did not return . 53 | /// instance is disposed. 54 | public HookHandle Add(MemoryHookType type, MemoryHookCallback callback, object userToken) 55 | { 56 | Emulator.ThrowIfDisposed(); 57 | 58 | if (callback == null) 59 | throw new ArgumentNullException(nameof(callback)); 60 | 61 | return AddInternal(type, callback, 1, 0, userToken); 62 | } 63 | 64 | /// 65 | /// Adds a to the with the specified and user token which 66 | /// is called when the hook is triggered within the specified start address and end address. 67 | /// 68 | /// 69 | /// Type of . 70 | /// to add. 71 | /// Start address of where the hook is effective (inclusive). 72 | /// End address of where the hook is effective (inclusive). 73 | /// Object associated with the callback. 74 | /// A which represents the hook. 75 | /// 76 | /// 77 | /// If > , the callback is called anytime the hook triggers. 78 | /// 79 | /// 80 | /// is null. 81 | /// Unicorn did not return . 82 | /// instance is disposed. 83 | public HookHandle Add(MemoryHookType type, MemoryHookCallback callback, ulong begin, ulong end, object userToken) 84 | { 85 | Emulator.ThrowIfDisposed(); 86 | 87 | if (callback == null) 88 | throw new ArgumentNullException(nameof(callback)); 89 | 90 | return AddInternal(type, callback, begin, end, userToken); 91 | } 92 | 93 | /// 94 | /// Adds a to the with the specified and user token which 95 | /// is called anytime the hook is triggered. 96 | /// 97 | /// 98 | /// Type of . 99 | /// to add. 100 | /// Object associated with the callback. 101 | /// A which represents the hook. 102 | /// 103 | /// is null. 104 | /// Unicorn did not return . 105 | /// instance is disposed. 106 | public HookHandle Add(MemoryEventHookType type, MemoryEventHookCallback callback, object userToken) 107 | { 108 | Emulator.ThrowIfDisposed(); 109 | 110 | if (callback == null) 111 | throw new ArgumentNullException(nameof(callback)); 112 | 113 | return AddEventInternal(type, callback, 1, 0, userToken); 114 | } 115 | 116 | /// 117 | /// Adds a to the with the specified and user token which 118 | /// is called when the hook is triggered within the specified start address and end address. 119 | /// 120 | /// 121 | /// Type of . 122 | /// to add. 123 | /// Start address of where the hook is effective (inclusive). 124 | /// End address of where the hook is effective (inclusive). 125 | /// Object associated with the callback. 126 | /// A which represents the hook. 127 | /// 128 | /// 129 | /// If > , the callback is called anytime the hook triggers. 130 | /// 131 | /// 132 | /// is null. 133 | /// Unicorn did not return . 134 | /// instance is disposed. 135 | public HookHandle Add(MemoryEventHookType type, MemoryEventHookCallback callback, ulong begin, ulong end, object userToken) 136 | { 137 | Emulator.ThrowIfDisposed(); 138 | 139 | if (callback == null) 140 | throw new ArgumentNullException(nameof(callback)); 141 | 142 | return AddEventInternal(type, callback, begin, end, userToken); 143 | } 144 | 145 | private HookHandle AddEventInternal(MemoryEventHookType type, MemoryEventHookCallback callback, ulong begin, ulong end, object userToken) 146 | { 147 | var wrapper = new uc_cb_eventmem((uc, _type, addr, size, value, user_data) => 148 | { 149 | Debug.Assert(uc == Emulator.Handle); 150 | return callback(Emulator, (MemoryType)_type, addr, size, value, userToken); 151 | }); 152 | 153 | return Add((UnicornHookType)type, wrapper, begin, end); 154 | } 155 | 156 | private HookHandle AddInternal(MemoryHookType type, MemoryHookCallback callback, ulong begin, ulong end, object userToken) 157 | { 158 | var wrapper = new uc_cb_hookmem((uc, _type, addr, size, value, user_data) => 159 | { 160 | Debug.Assert(uc == Emulator.Handle); 161 | callback(Emulator, (MemoryType)_type, addr, size, value, userToken); 162 | }); 163 | 164 | return Add((UnicornHookType)type, wrapper, begin, end); 165 | } 166 | } 167 | 168 | /// 169 | /// Types of memory accesses for . 170 | /// 171 | [Flags] 172 | public enum MemoryHookType 173 | { 174 | /// 175 | /// Read memory. 176 | /// 177 | Read = UnicornHookType.MemRead, 178 | 179 | /// 180 | /// Write memory. 181 | /// 182 | Write = UnicornHookType.MemWrite, 183 | 184 | /// 185 | /// Fetch memory. 186 | /// 187 | Fetch = UnicornHookType.MemFetch, 188 | 189 | /// 190 | /// Read memory successful access. 191 | /// 192 | ReadAfter = UnicornHookType.MemReadAfter 193 | } 194 | 195 | /// 196 | /// Types of invalid memory accesses for . 197 | /// 198 | [Flags] 199 | public enum MemoryEventHookType 200 | { 201 | /// 202 | /// Unmapped memory read. 203 | /// 204 | UnmappedRead = UnicornHookType.MemReadUnmapped, 205 | 206 | /// 207 | /// Unmapped memory write. 208 | /// 209 | UnmappedWrite = UnicornHookType.MemWriteUnmapped, 210 | 211 | /// 212 | /// Unmapped memory fetch. 213 | /// 214 | UnmappedFetch = UnicornHookType.MemFetchUnmapped, 215 | 216 | /// 217 | /// Protected memory read. 218 | /// 219 | ProtectedRead = UnicornHookType.MemReadProtected, 220 | 221 | /// 222 | /// Protected memory write. 223 | /// 224 | ProtectedWrite = UnicornHookType.MemWriteProtected, 225 | 226 | /// 227 | /// Protected memory fetch. 228 | /// 229 | ProtectedFetch = UnicornHookType.MemFetchProtected, 230 | } 231 | 232 | /// 233 | /// Types of memory accesses for memory hooks. 234 | /// 235 | public enum MemoryType 236 | { 237 | /// 238 | /// Memory read from. 239 | /// 240 | Read = uc_mem_type.UC_MEM_READ, 241 | /// 242 | /// Memory written to. 243 | /// 244 | Write = uc_mem_type.UC_MEM_WRITE, 245 | /// 246 | /// Memory fetched at. 247 | /// 248 | Fetch = uc_mem_type.UC_MEM_FETCH, 249 | 250 | /// 251 | /// Unmapped memory read from. 252 | /// 253 | ReadUnmapped = uc_mem_type.UC_MEM_READ_UNMAPPED, 254 | /// 255 | /// Unmapped memory written to. 256 | /// 257 | WriteUnmapped = uc_mem_type.UC_MEM_WRITE_UNMAPPED, 258 | /// 259 | /// Unmapped memory fetched at. 260 | /// 261 | FetchUnmapped = uc_mem_type.UC_MEM_FETCH_UNMAPPED, 262 | 263 | /// 264 | /// Write to write protected memory. 265 | /// 266 | WriteProtected = uc_mem_type.UC_MEM_WRITE_PROT, 267 | /// 268 | /// Read to read protected memory. 269 | /// 270 | ReadProtected = uc_mem_type.UC_MEM_READ_PROT, 271 | /// 272 | /// Fetch on non-executable memory. 273 | /// 274 | FetchProtected = uc_mem_type.UC_MEM_FETCH_PROT, 275 | 276 | /// 277 | /// Successful memory read. 278 | /// 279 | ReadAfter = uc_mem_type.UC_MEM_READ_AFTER 280 | } 281 | } 282 | -------------------------------------------------------------------------------- /src/Unicorn.Net/MemoryPermissions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Unicorn 4 | { 5 | /// 6 | /// Defines memory region permissions. 7 | /// 8 | [Flags] 9 | public enum MemoryPermissions 10 | { 11 | /// 12 | /// No permission. 13 | /// 14 | None = 0, 15 | 16 | /// 17 | /// Read permission. 18 | /// 19 | Read = 1, 20 | 21 | /// 22 | /// Write permission. 23 | /// 24 | Write = 2, 25 | 26 | /// 27 | /// Execute permission. 28 | /// 29 | Execute = 4, 30 | 31 | /// 32 | /// All permission. 33 | /// 34 | All = Read | Write | Execute 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Unicorn.Net/MemoryRegion.cs: -------------------------------------------------------------------------------- 1 | namespace Unicorn 2 | { 3 | /// 4 | /// Represents a memory region for emulation. 5 | /// 6 | public struct MemoryRegion 7 | { 8 | private readonly ulong _begin; 9 | private readonly ulong _end; 10 | private readonly MemoryPermissions _perms; 11 | 12 | // Wrap the native uc_mem_region structure. 13 | internal MemoryRegion(ulong begin, ulong end, MemoryPermissions perms) 14 | { 15 | _begin = begin; 16 | _end = end; 17 | _perms = perms; 18 | } 19 | 20 | /// 21 | /// Gets the address at which the starts. 22 | /// 23 | public ulong Begin => _begin; 24 | 25 | /// 26 | /// Gets the address at which the ends. 27 | /// 28 | public ulong End => _end; 29 | 30 | /// 31 | /// Gets the permissions of the . 32 | /// 33 | public MemoryPermissions Permissions => _perms; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Unicorn.Net/Mips/MipsEmulator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Unicorn.Mips 4 | { 5 | /// 6 | /// Represents a MIPS architecture . 7 | /// 8 | public class MipsEmulator : Emulator 9 | { 10 | private readonly MipsRegisters _registers; 11 | 12 | /// 13 | /// Initializes a new instance of the class with the specified 14 | /// to use. 15 | /// 16 | /// Mode to use. 17 | public MipsEmulator(MipsMode mode) : base(UnicornArch.MIPS, (UnicornMode)mode) 18 | { 19 | _registers = new MipsRegisters(this); 20 | } 21 | 22 | /// 23 | /// Gets the of the instance. 24 | /// 25 | /// instance is disposed. 26 | public new MipsRegisters Registers 27 | { 28 | get 29 | { 30 | ThrowIfDisposed(); 31 | return _registers; 32 | } 33 | } 34 | 35 | /// 36 | /// Gets the of the . 37 | /// 38 | /// instance is disposed. 39 | public new MipsMode Mode 40 | { 41 | get 42 | { 43 | ThrowIfDisposed(); 44 | return (MipsMode)_mode; 45 | } 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/Unicorn.Net/Mips/MipsMode.cs: -------------------------------------------------------------------------------- 1 | namespace Unicorn.Mips 2 | { 3 | /// 4 | /// Defines the modes of an . 5 | /// 6 | public enum MipsMode 7 | { 8 | /// 9 | /// Big endian mode. 10 | /// 11 | BigEndian = UnicornMode.BigEndian, 12 | 13 | /// 14 | /// Little endian mode. 15 | /// 16 | LittleEndian = UnicornMode.LittleEndian, 17 | 18 | /// 19 | /// MicroMips mode. 20 | /// 21 | Micro = UnicornMode.MIPSMicro, 22 | 23 | /// 24 | /// MIPS III ISA mode. 25 | /// 26 | III = UnicornMode.MIPS3, 27 | 28 | /// 29 | /// MIPS32R6 ISA mode. 30 | /// 31 | b32R6 = UnicornMode.MIPS32R6, 32 | 33 | /// 34 | /// MIPS32 ISA mode. 35 | /// 36 | b32 = UnicornMode.MIPS32, 37 | 38 | /// 39 | /// MIPS64 ISA mode. 40 | /// 41 | b64 = UnicornMode.MIPS64, 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Unicorn.Net/Registers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | 4 | namespace Unicorn 5 | { 6 | /// 7 | /// Represents the registers of an . 8 | /// 9 | public class Registers 10 | { 11 | // Emulator object instance which owns this Registers object instance. 12 | private readonly Emulator _emulator; 13 | 14 | internal Registers(Emulator emulator) 15 | { 16 | Debug.Assert(emulator != null); 17 | _emulator = emulator; 18 | } 19 | 20 | /// 21 | /// Reads the value of the register with specified register ID. 22 | /// 23 | /// Register ID. 24 | /// Value of register read. 25 | /// Unicorn did not return . 26 | /// instance is disposed. 27 | public long Read(int registerId) 28 | { 29 | long value = 0; 30 | 31 | _emulator.ThrowIfDisposed(); 32 | _emulator.RegRead(registerId, ref value); 33 | return value; 34 | } 35 | 36 | /// 37 | /// Writes the specified value to the register with the specified register ID. 38 | /// 39 | /// Register ID. 40 | /// Value to write to register. 41 | /// Unicorn did not return . 42 | /// instance is disposed. 43 | public void Write(int registerId, long value) 44 | { 45 | _emulator.ThrowIfDisposed(); 46 | _emulator.RegWrite(registerId, ref value); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Unicorn.Net/Unicorn.Net.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard1.1;netstandard2.0 5 | 1.0.0 6 | 7 | True 8 | 9 | .NET binding/wrapper for the Unicorn engine. 10 | Copyright 2018 (c) FICTURE7 11 | FICTURE7 12 | 13 | Unicorn.Net 14 | $(Version) 15 | False 16 | unicorn wrapper binding 17 | 18 | https://github.com/FICTURE7/unicorn-net 19 | $(PackageProjectUrl)/blob/master/LICENSE 20 | 21 | $(PackageProjectUrl).git 22 | git 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/Unicorn.Net/UnicornArch.cs: -------------------------------------------------------------------------------- 1 | using Unicorn.Internal; 2 | 3 | namespace Unicorn 4 | { 5 | /// 6 | /// Types of unicorn-engine CPU architecture. 7 | /// 8 | public enum UnicornArch 9 | { 10 | /// 11 | /// ARM. 12 | /// 13 | ARM = uc_arch.UC_ARCH_ARM, 14 | 15 | /// 16 | /// ARM64. 17 | /// 18 | ARM64 = uc_arch.UC_ARCH_ARM64, 19 | 20 | /// 21 | /// MIPS. 22 | /// 23 | MIPS = uc_arch.UC_ARCH_MIPS, 24 | 25 | /// 26 | /// x86. 27 | /// 28 | X86 = uc_arch.UC_ARCH_X86, 29 | 30 | /// 31 | /// PPC. 32 | /// 33 | PPC = uc_arch.UC_ARCH_PPC, 34 | 35 | /// 36 | /// SPARC. 37 | /// 38 | SPARC = uc_arch.UC_ARCH_SPARC, 39 | 40 | /// 41 | /// M68k. 42 | /// 43 | M68k = uc_arch.UC_ARCH_M68K 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Unicorn.Net/UnicornError.cs: -------------------------------------------------------------------------------- 1 | using Unicorn.Internal; 2 | 3 | namespace Unicorn 4 | { 5 | /// 6 | /// Types of unicorn-engine error. 7 | /// 8 | public enum UnicornError 9 | { 10 | /// 11 | /// No error. 12 | /// 13 | Ok = uc_err.UC_ERR_OK, 14 | /// 15 | /// Out of memory. 16 | /// 17 | NoMem = uc_err.UC_ERR_NOMEM, 18 | /// 19 | /// Unsupported architecture. 20 | /// 21 | Arch = uc_err.UC_ERR_ARCH, 22 | /// 23 | /// Invalid handle. 24 | /// 25 | Handle = uc_err.UC_ERR_HANDLE, 26 | /// 27 | /// Invalid or unsupported mode. 28 | /// 29 | Mode = uc_err.UC_ERR_MODE, 30 | /// 31 | /// Unsupported version. 32 | /// 33 | Version = uc_err.UC_ERR_VERSION, 34 | /// 35 | /// Quit emulation due to read on unmapped memory. 36 | /// 37 | ReadUnmapped = uc_err.UC_ERR_READ_UNMAPPED, 38 | /// 39 | /// Quit emulation due to write on unmapped memory. 40 | /// 41 | WriteUnmapped = uc_err.UC_ERR_WRITE_UNMAPPED, 42 | /// 43 | /// Quit emulation due to fetch on unmapped memory. 44 | /// 45 | FetchUnmapped = uc_err.UC_ERR_FETCH_UNMAPPED, 46 | /// 47 | /// Invalid hook type. 48 | /// 49 | Hook = uc_err.UC_ERR_HOOK, 50 | /// 51 | /// Quit emulation due to invalid instruction. 52 | /// 53 | InstructionInvalid = uc_err.UC_ERR_INSN_INVALID, 54 | /// 55 | /// Invalid memory mapping. 56 | /// 57 | Map = uc_err.UC_ERR_MAP, 58 | /// 59 | /// Quit emulation due to write on write protected memory. 60 | /// 61 | WriteProtected = uc_err.UC_ERR_WRITE_PROT, 62 | /// 63 | /// Quit emulation due to write on read protected memory. 64 | /// 65 | ReadProtected = uc_err.UC_ERR_READ_PROT, 66 | /// 67 | /// Quit emulation due to write on non-executable memory. 68 | /// 69 | FetchProtected = uc_err.UC_ERR_FETCH_PROT, 70 | /// 71 | /// Invalid argument provided. 72 | /// 73 | Argument = uc_err.UC_ERR_ARG, 74 | /// 75 | /// Unaligned read. 76 | /// 77 | ReadUnaligned = uc_err.UC_ERR_READ_UNALIGNED, 78 | /// 79 | /// Unaligned write. 80 | /// 81 | WriteUnaligned = uc_err.UC_ERR_WRITE_UNALIGNED, 82 | /// 83 | /// Unaligned fetch. 84 | /// 85 | FetchUnaligned = uc_err.UC_ERR_FETCH_UNALIGNED, 86 | /// 87 | /// Hook for this event already existed. 88 | /// 89 | HookExist = uc_err.UC_ERR_HOOK_EXIST, 90 | /// 91 | /// Insufficient resource. 92 | /// 93 | Resource = uc_err.UC_ERR_RESOURCE, 94 | /// 95 | /// Unhandled CPU exception. 96 | /// 97 | Exception = uc_err.UC_ERR_EXCEPTION, 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/Unicorn.Net/UnicornException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Unicorn.Internal; 3 | 4 | namespace Unicorn 5 | { 6 | /// 7 | /// Exception thrown when the unicorn-engine does not return UC_ERR_OK. 8 | /// 9 | public class UnicornException : Exception 10 | { 11 | /// 12 | /// Gets the of the . 13 | /// 14 | public UnicornError ErrorCode { get; } 15 | 16 | /// 17 | /// Initializes a new instance of the class with the specified . 18 | /// 19 | /// error code. 20 | public UnicornException(UnicornError error) : base(Bindings.Instance.StrError(error)) 21 | { 22 | ErrorCode = error; 23 | } 24 | 25 | internal UnicornException(uc_err err) : this((UnicornError)err) 26 | { 27 | // Space 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Unicorn.Net/UnicornHookType.cs: -------------------------------------------------------------------------------- 1 | using Unicorn.Internal; 2 | 3 | namespace Unicorn 4 | { 5 | /// 6 | /// Types of unicorn-engine hooks. 7 | /// 8 | public enum UnicornHookType 9 | { 10 | /// 11 | /// Interrupts/Syscalls. 12 | /// 13 | Interrupts = uc_hook_type.UC_HOOK_INTR, 14 | /// 15 | /// Particular instruction. 16 | /// 17 | Instructions = uc_hook_type.UC_HOOK_INSN, 18 | 19 | /// 20 | /// Range of code. 21 | /// 22 | Code = uc_hook_type.UC_HOOK_CODE, 23 | /// 24 | /// Basic block. 25 | /// 26 | Block = uc_hook_type.UC_HOOK_BLOCK, 27 | 28 | /// 29 | /// Memory read on unmapped memory. 30 | /// 31 | MemReadUnmapped = uc_hook_type.UC_HOOK_MEM_READ_UNMAPPED, 32 | /// 33 | /// Memory write on unmapped memory. 34 | /// 35 | MemWriteUnmapped = uc_hook_type.UC_HOOK_MEM_WRITE_UNMAPPED, 36 | /// 37 | /// Memory fetch on unmapped memory. 38 | /// 39 | MemFetchUnmapped = uc_hook_type.UC_HOOK_MEM_FETCH_UNMAPPED, 40 | 41 | /// 42 | /// Memory read on read-protected memory. 43 | /// 44 | MemReadProtected = uc_hook_type.UC_HOOK_MEM_READ_PROT, 45 | /// 46 | /// Memory write on write-protected memory. 47 | /// 48 | MemWriteProtected = uc_hook_type.UC_HOOK_MEM_WRITE_PROT, 49 | /// 50 | /// Memory fetch on non-executable memory. 51 | /// 52 | MemFetchProtected = uc_hook_type.UC_HOOK_MEM_FETCH_PROT, 53 | 54 | /// 55 | /// Memory reads. 56 | /// 57 | MemRead = uc_hook_type.UC_HOOK_MEM_READ, 58 | /// 59 | /// Memory writes. 60 | /// 61 | MemWrite = uc_hook_type.UC_HOOK_MEM_WRITE, 62 | /// 63 | /// Memory fetches. 64 | /// 65 | MemFetch = uc_hook_type.UC_HOOK_MEM_FETCH, 66 | 67 | /// 68 | /// Successful memory reads. 69 | /// 70 | MemReadAfter = uc_hook_type.UC_HOOK_MEM_READ_AFTER, 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/Unicorn.Net/UnicornMode.cs: -------------------------------------------------------------------------------- 1 | using Unicorn.Internal; 2 | 3 | namespace Unicorn 4 | { 5 | /// 6 | /// Types of unicorn-engine modes. 7 | /// 8 | public enum UnicornMode 9 | { 10 | /// 11 | /// Little-endian mode default mode. 12 | /// 13 | LittleEndian = uc_mode.UC_MODE_LITTLE_ENDIAN, 14 | /// 15 | /// Big-endian mode. 16 | /// 17 | BigEndian = uc_mode.UC_MODE_BIG_ENDIAN, 18 | 19 | /// 20 | /// ARM mode. 21 | /// 22 | ARM = uc_mode.UC_MODE_ARM, 23 | /// 24 | /// Thumb mode. 25 | /// 26 | ARMThumb = uc_mode.UC_MODE_THUMB, 27 | /// 28 | /// Cortex-M series. 29 | /// 30 | ARMMClass = uc_mode.UC_MODE_MCLASS, 31 | /// 32 | /// ARMv8 A32 encodings. 33 | /// 34 | ARMv8 = uc_mode.UC_MODE_V8, 35 | 36 | /// 37 | /// MicroMips mode. 38 | /// 39 | MIPSMicro = uc_mode.UC_MODE_MICRO, 40 | /// 41 | /// MIPS III ISA mode. 42 | /// 43 | MIPS3 = uc_mode.UC_MODE_MIPS3, 44 | /// 45 | /// MIPS32R6 ISA mode. 46 | /// 47 | MIPS32R6 = uc_mode.UC_MODE_MIPS32R6, 48 | /// 49 | /// MIPS32 ISA mode. 50 | /// 51 | MIPS32 = uc_mode.UC_MODE_MIPS32, 52 | /// 53 | /// MIPS64 ISA mode. 54 | /// 55 | MIPS64 = uc_mode.UC_MODE_MIPS64, 56 | 57 | /// 58 | /// 16-bit mode. 59 | /// 60 | X86b16 = uc_mode.UC_MODE_16, 61 | /// 62 | /// 32-bit mode. 63 | /// 64 | X86b32 = uc_mode.UC_MODE_32, 65 | /// 66 | /// 64-bit mode. 67 | /// 68 | X86b64 = uc_mode.UC_MODE_64, 69 | 70 | /// 71 | /// 32-bit mode. 72 | /// 73 | PPC32 = uc_mode.UC_MODE_PPC32, 74 | /// 75 | /// 64-bit mode. 76 | /// 77 | PPC64 = uc_mode.UC_MODE_PPC64, 78 | /// 79 | /// Quad processing eXtensions mode. 80 | /// 81 | PPCQPX = uc_mode.UC_MODE_QPX, 82 | 83 | /// 84 | /// 32-bit mode. 85 | /// 86 | SPARC32 = uc_mode.UC_MODE_SPARC32, 87 | /// 88 | /// 64-bit mode. 89 | /// 90 | SPARC64 = uc_mode.UC_MODE_SPARC64, 91 | /// 92 | /// SPARCV9 mode. 93 | /// 94 | SPARCV9 = uc_mode.UC_MODE_V9, 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/Unicorn.Net/UnicornQueryType.cs: -------------------------------------------------------------------------------- 1 | using Unicorn.Internal; 2 | 3 | namespace Unicorn 4 | { 5 | /// 6 | /// Types of unicorn-engine query. 7 | /// 8 | public enum UnicornQueryType 9 | { 10 | /// 11 | /// Queries the mode. 12 | /// 13 | Mode = uc_query_type.UC_QUERY_MODE, 14 | 15 | /// 16 | /// Queries the page size. 17 | /// 18 | PageSize = uc_query_type.UC_QUERY_PAGE_SIZE 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Unicorn.Net/UnicornVersion.cs: -------------------------------------------------------------------------------- 1 | namespace Unicorn 2 | { 3 | /// 4 | /// Represents a unicorn-engine version number. 5 | /// 6 | public struct UnicornVersion 7 | { 8 | static UnicornVersion() 9 | { 10 | var mmajor = 0; 11 | var mminor = 0; 12 | 13 | var nativeVersion = Bindings.Instance.Version(ref mmajor, ref mminor); 14 | var major = nativeVersion >> 0x8; 15 | var minor = nativeVersion & 0xF; 16 | 17 | Current = new UnicornVersion(major, minor); 18 | } 19 | 20 | /// 21 | /// Gets the current of the wrapped unicorn-engine library. 22 | /// 23 | public static UnicornVersion Current { get; private set; } 24 | 25 | private readonly string _toString; 26 | 27 | /// 28 | /// Gets the major version number. 29 | /// 30 | public int Major { get; } 31 | 32 | /// 33 | /// Gets the minor version number. 34 | /// 35 | public int Minor { get; } 36 | 37 | /// 38 | /// Initializes a new instance of the structure with the specified 39 | /// major and minor version number. 40 | /// 41 | /// Major version number. 42 | /// Minor version number. 43 | public UnicornVersion(int major, int minor) 44 | { 45 | Major = major; 46 | Minor = minor; 47 | 48 | _toString = Major + "." + Minor; 49 | } 50 | 51 | /// 52 | /// Returns a string representation of the object. 53 | /// 54 | /// String representation of the object. 55 | public override string ToString() => _toString; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/Unicorn.Net/X86/X86Emulator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Unicorn.X86 4 | { 5 | /// 6 | /// Represents an X86 architecture . 7 | /// 8 | public class X86Emulator : Emulator 9 | { 10 | private readonly X86Registers _registers; 11 | 12 | /// 13 | /// Initializes a new instance of the class with the specified 14 | /// to use. 15 | /// 16 | /// Mode to use. 17 | public X86Emulator(X86Mode mode) : base(UnicornArch.X86, (UnicornMode)mode) 18 | { 19 | _registers = new X86Registers(this); 20 | } 21 | 22 | /// 23 | /// Gets the of the instance. 24 | /// 25 | /// instance is disposed. 26 | public new X86Registers Registers 27 | { 28 | get 29 | { 30 | ThrowIfDisposed(); 31 | return _registers; 32 | } 33 | } 34 | 35 | /// 36 | /// Gets the of the . 37 | /// 38 | /// instance is disposed. 39 | public new X86Mode Mode 40 | { 41 | get 42 | { 43 | ThrowIfDisposed(); 44 | return (X86Mode)_mode; 45 | } 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/Unicorn.Net/X86/X86Mode.cs: -------------------------------------------------------------------------------- 1 | namespace Unicorn.X86 2 | { 3 | /// 4 | /// Defines the modes of an . 5 | /// 6 | public enum X86Mode 7 | { 8 | /// 9 | /// 16-bit mode. 10 | /// 11 | b16 = UnicornMode.X86b16, 12 | 13 | /// 14 | /// 32-bit mode. 15 | /// 16 | b32 = UnicornMode.X86b32, 17 | 18 | /// 19 | /// 64-bit mode. 20 | /// 21 | b64 = UnicornMode.X86b64 22 | } 23 | } 24 | --------------------------------------------------------------------------------