├── .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 |
--------------------------------------------------------------------------------