diff --git a/bindings/dotnet/Unicorn/Unicorn.fs b/bindings/dotnet/Unicorn/Unicorn.fs
index 7e4e34bd..79108c1d 100644
--- a/bindings/dotnet/Unicorn/Unicorn.fs
+++ b/bindings/dotnet/Unicorn/Unicorn.fs
@@ -73,29 +73,44 @@ and Unicorn(arch: Int32, mode: Int32) =
let err = NativeUnicornEngine.uc_open(uint32 arch, uint32 mode, _eng)
checkResult(err, "Unable to open the Unicorn Engine")
+ member private this.CheckResult(errorCode: Int32) =
+ // return the exception instead of raising it in order to have a more meaningful stack trace
+ if errorCode <> Common.UC_ERR_OK then
+ let errorMessage = this.StrError(errorCode)
+ Some <| UnicornEngineException(errorCode, errorMessage)
+ else None
+
member this.MemMap(address: UInt64, size: UIntPtr, perm: Int32) =
- NativeUnicornEngine.mem_map(_eng.[0], address, size, uint32 perm)
+ match NativeUnicornEngine.mem_map(_eng.[0], address, size, uint32 perm) |> this.CheckResult with
+ | Some e -> raise e | None -> ()
- member this.MemWrite(address: UInt64, buffer: Byte array) =
- NativeUnicornEngine.mem_write(_eng.[0], address, buffer, new UIntPtr(uint32 buffer.Length))
+ member this.MemWrite(address: UInt64, value: Byte array) =
+ match NativeUnicornEngine.mem_write(_eng.[0], address, value, new UIntPtr(uint32 value.Length)) |> this.CheckResult with
+ | Some e -> raise e | None -> ()
- member this.MemRead(address: UInt64, value: Byte array) =
- NativeUnicornEngine.mem_read(_eng.[0], address, value, new UIntPtr(uint32 value.Length))
+ member this.MemRead(address: UInt64, memValue: Byte array) =
+ match NativeUnicornEngine.mem_read(_eng.[0], address, memValue, new UIntPtr(uint32 memValue.Length)) |> this.CheckResult with
+ | Some e -> raise e | None -> ()
member this.RegWrite(regId: Int32, value: Byte array) =
- NativeUnicornEngine.reg_write(_eng.[0], regId, value)
+ match NativeUnicornEngine.reg_write(_eng.[0], regId, value) |> this.CheckResult with
+ | Some e -> raise e | None -> ()
member this.RegRead(regId: Int32, regValue: Byte array) =
- NativeUnicornEngine.reg_read(_eng.[0], regId, regValue)
+ match NativeUnicornEngine.reg_read(_eng.[0], regId, regValue) |> this.CheckResult with
+ | Some e -> raise e | None -> ()
member this.EmuStart(beginAddr: UInt64, untilAddr: UInt64, timeout: UInt64, count: UIntPtr) =
- NativeUnicornEngine.emu_start(_eng.[0], beginAddr, untilAddr, timeout, count)
+ match NativeUnicornEngine.emu_start(_eng.[0], beginAddr, untilAddr, timeout, count) |> this.CheckResult with
+ | Some e -> raise e | None -> ()
member this.EmuStop() =
- NativeUnicornEngine.emu_stop(_eng.[0])
+ match NativeUnicornEngine.emu_stop(_eng.[0]) |> this.CheckResult with
+ | Some e -> raise e | None -> ()
member this.Close() =
- NativeUnicornEngine.close(_eng.[0])
+ match NativeUnicornEngine.close(_eng.[0]) |> this.CheckResult with
+ | Some e -> raise e | None -> ()
member this.ArchSupported(arch: Int32) =
NativeUnicornEngine.arch_supported(arch)
@@ -117,7 +132,8 @@ and Unicorn(arch: Int32, mode: Int32) =
let funcPointer = Marshal.GetFunctionPointerForDelegate(new CodeHookInternal(trampoline))
let hh = new UIntPtr(Marshal.AllocHGlobal(IntPtr.Size).ToPointer())
- (NativeUnicornEngine.hook_add_arg0_arg1(_eng.[0], hh, Common.UC_HOOK_CODE, new UIntPtr(funcPointer.ToPointer()), id, beginAdd, endAddr), hh)
+ match NativeUnicornEngine.hook_add_arg0_arg1(_eng.[0], hh, Common.UC_HOOK_CODE, new UIntPtr(funcPointer.ToPointer()), id, beginAdd, endAddr) |> this.CheckResult with
+ | Some e -> raise e | None -> ()
member this.HookDel(callback: CodeHook) =
hookDel _codeHooks callback
@@ -132,7 +148,8 @@ and Unicorn(arch: Int32, mode: Int32) =
let funcPointer = Marshal.GetFunctionPointerForDelegate(new BlockHookInternal(trampoline))
let hh = new UIntPtr(Marshal.AllocHGlobal(IntPtr.Size).ToPointer())
- (NativeUnicornEngine.hook_add_arg0_arg1(_eng.[0], hh, Common.UC_HOOK_BLOCK, new UIntPtr(funcPointer.ToPointer()), id, beginAdd, endAddr), hh)
+ match NativeUnicornEngine.hook_add_arg0_arg1(_eng.[0], hh, Common.UC_HOOK_BLOCK, new UIntPtr(funcPointer.ToPointer()), id, beginAdd, endAddr) |> this.CheckResult with
+ | Some e -> raise e | None -> ()
member this.HookDel(callback: BlockHook) =
hookDel _blockHooks callback
@@ -147,7 +164,8 @@ and Unicorn(arch: Int32, mode: Int32) =
let funcPointer = Marshal.GetFunctionPointerForDelegate(new InterruptHookInternal(trampoline))
let hh = new UIntPtr(Marshal.AllocHGlobal(IntPtr.Size).ToPointer())
- (NativeUnicornEngine.hook_add_noarg(_eng.[0], hh, Common.UC_HOOK_INTR, new UIntPtr(funcPointer.ToPointer()), id), hh)
+ match NativeUnicornEngine.hook_add_noarg(_eng.[0], hh, Common.UC_HOOK_INTR, new UIntPtr(funcPointer.ToPointer()), id) |> this.CheckResult with
+ | Some e -> raise e | None -> ()
member this.HookDel(callback: InterruptHook) =
hookDel _interruptHooks callback
@@ -162,7 +180,8 @@ and Unicorn(arch: Int32, mode: Int32) =
let funcPointer = Marshal.GetFunctionPointerForDelegate(new MemReadHookInternal(trampoline))
let hh = new UIntPtr(Marshal.AllocHGlobal(IntPtr.Size).ToPointer())
- (NativeUnicornEngine.hook_add_arg0_arg1(_eng.[0], hh, Common.UC_HOOK_MEM_READ, new UIntPtr(funcPointer.ToPointer()), id, beginAdd, endAddr), hh)
+ match NativeUnicornEngine.hook_add_arg0_arg1(_eng.[0], hh, Common.UC_HOOK_MEM_READ, new UIntPtr(funcPointer.ToPointer()), id, beginAdd, endAddr) |> this.CheckResult with
+ | Some e -> raise e | None -> ()
member this.HookDel(callback: MemReadHook) =
hookDel _memReadHooks callback
@@ -177,7 +196,8 @@ and Unicorn(arch: Int32, mode: Int32) =
let funcPointer = Marshal.GetFunctionPointerForDelegate(new MemWriteHookInternal(trampoline))
let hh = new UIntPtr(Marshal.AllocHGlobal(IntPtr.Size).ToPointer())
- (NativeUnicornEngine.hook_add_arg0_arg1(_eng.[0], hh, Common.UC_HOOK_MEM_WRITE, new UIntPtr(funcPointer.ToPointer()), id, beginAdd, endAddr), hh)
+ match NativeUnicornEngine.hook_add_arg0_arg1(_eng.[0], hh, Common.UC_HOOK_MEM_WRITE, new UIntPtr(funcPointer.ToPointer()), id, beginAdd, endAddr) |> this.CheckResult with
+ | Some e -> raise e | None -> ()
member this.HookDel(callback: MemWriteHook) =
hookDel _memWriteHooks callback
@@ -193,7 +213,8 @@ and Unicorn(arch: Int32, mode: Int32) =
let funcPointer = Marshal.GetFunctionPointerForDelegate(new EventMemHookInternal(trampoline))
let hh = new UIntPtr(Marshal.AllocHGlobal(IntPtr.Size).ToPointer())
- (NativeUnicornEngine.hook_add_noarg(_eng.[0], hh, check, new UIntPtr(funcPointer.ToPointer()), id), hh)
+ match NativeUnicornEngine.hook_add_noarg(_eng.[0], hh, check, new UIntPtr(funcPointer.ToPointer()), id) |> this.CheckResult with
+ | Some e -> raise e | None -> ()
// test all the events types agains the input eventType
[
@@ -221,7 +242,8 @@ and Unicorn(arch: Int32, mode: Int32) =
let funcPointer = Marshal.GetFunctionPointerForDelegate(new InHookInternal(trampoline))
let hh = new UIntPtr(Marshal.AllocHGlobal(IntPtr.Size).ToPointer())
- (NativeUnicornEngine.hook_add_arg0(_eng.[0], hh, Common.UC_HOOK_INSN, new UIntPtr(funcPointer.ToPointer()), id, new IntPtr(X86.UC_X86_INS_IN)), hh)
+ match NativeUnicornEngine.hook_add_arg0(_eng.[0], hh, Common.UC_HOOK_INSN, new UIntPtr(funcPointer.ToPointer()), id, new IntPtr(X86.UC_X86_INS_IN)) |> this.CheckResult with
+ | Some e -> raise e | None -> ()
member this.AddOutHook(callback: OutHook, userData: Object) =
let trampoline(u: IntPtr) (port: Int32) (size: Int32) (value: Int32) (user: IntPtr) =
@@ -233,7 +255,8 @@ and Unicorn(arch: Int32, mode: Int32) =
let funcPointer = Marshal.GetFunctionPointerForDelegate(new OutHookInternal(trampoline))
let hh = new UIntPtr(Marshal.AllocHGlobal(IntPtr.Size).ToPointer())
- (NativeUnicornEngine.hook_add_arg0(_eng.[0], hh, Common.UC_HOOK_INSN, new UIntPtr(funcPointer.ToPointer()), id, new IntPtr(X86.UC_X86_INS_OUT)), hh)
+ match NativeUnicornEngine.hook_add_arg0(_eng.[0], hh, Common.UC_HOOK_INSN, new UIntPtr(funcPointer.ToPointer()), id, new IntPtr(X86.UC_X86_INS_OUT)) |> this.CheckResult with
+ | Some e -> raise e | None -> ()
member this.AddSyscallHook(callback: SyscallHook, userData: Object) =
let trampoline(u: IntPtr) (user: IntPtr) =
@@ -245,7 +268,8 @@ and Unicorn(arch: Int32, mode: Int32) =
let funcPointer = Marshal.GetFunctionPointerForDelegate(new SyscallHookInternal(trampoline))
let hh = new UIntPtr(Marshal.AllocHGlobal(IntPtr.Size).ToPointer())
- (NativeUnicornEngine.hook_add_arg0(_eng.[0], hh, Common.UC_HOOK_INSN, new UIntPtr(funcPointer.ToPointer()), id, new IntPtr(X86.UC_X86_INS_SYSCALL)), hh)
+ match NativeUnicornEngine.hook_add_arg0(_eng.[0], hh, Common.UC_HOOK_INSN, new UIntPtr(funcPointer.ToPointer()), id, new IntPtr(X86.UC_X86_INS_SYSCALL)) |> this.CheckResult with
+ | Some e -> raise e | None -> ()
member this.Version() =
let (major, minor) = (new UIntPtr(), new UIntPtr())
diff --git a/bindings/dotnet/Unicorn/Unicorn.fsproj b/bindings/dotnet/Unicorn/Unicorn.fsproj
index adc80fff..8f6ee136 100644
--- a/bindings/dotnet/Unicorn/Unicorn.fsproj
+++ b/bindings/dotnet/Unicorn/Unicorn.fsproj
@@ -51,9 +51,9 @@
-
+
diff --git a/bindings/dotnet/Unicorn/UnicornEngineException.fs b/bindings/dotnet/Unicorn/UnicornEngineException.fs
new file mode 100644
index 00000000..7b1cd845
--- /dev/null
+++ b/bindings/dotnet/Unicorn/UnicornEngineException.fs
@@ -0,0 +1,30 @@
+(*
+
+.NET bindings for the UnicornEngine Emulator Engine
+
+Copyright(c) 2015 Antonio Parata
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+version 2 as published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*)
+
+namespace UnicornEngine
+
+open System
+
+type UnicornEngineException(errNo: Int32, msg: String) =
+ inherit ApplicationException(msg)
+
+ member this.ErrorNo = errNo
+
diff --git a/bindings/dotnet/UnicornTests/ShellcodeTest.cs b/bindings/dotnet/UnicornTests/ShellcodeTest.cs
index bba47f29..e254fb4a 100644
--- a/bindings/dotnet/UnicornTests/ShellcodeTest.cs
+++ b/bindings/dotnet/UnicornTests/ShellcodeTest.cs
@@ -1,4 +1,25 @@
-using System;
+/*
+
+.NET bindings for the UnicornEngine Emulator Engine
+
+Copyright(c) 2015 Antonio Parata
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+version 2 as published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
@@ -49,33 +70,40 @@ namespace UnicornTests
public static void RunTest(Byte[] code, UInt64 address)
{
- var u = new Unicorn(Common.UC_ARCH_X86, Common.UC_MODE_32);
- Console.WriteLine("Unicorn version: {0}", u.Version());
+ try
+ {
+ var u = new Unicorn(Common.UC_ARCH_X86, Common.UC_MODE_32);
+ Console.WriteLine("Unicorn version: {0}", u.Version());
- // map 2MB of memory for this emulation
- Utils.CheckError(u.MemMap(address, new UIntPtr(2 * 1024 * 1024), Common.UC_PROT_ALL));
+ // map 2MB of memory for this emulation
+ u.MemMap(address, new UIntPtr(2 * 1024 * 1024), Common.UC_PROT_ALL);
- // write machine code to be emulated to memory
- Utils.CheckError(u.MemWrite(address, code));
+ // write machine code to be emulated to memory
+ u.MemWrite(address, code);
- // initialize machine registers
- Utils.CheckError(u.RegWrite(X86.UC_X86_REG_ESP, Utils.Int64ToBytes(address + 0x200000)));
+ // initialize machine registers
+ u.RegWrite(X86.UC_X86_REG_ESP, Utils.Int64ToBytes(address + 0x200000));
- // tracing all instructions by having @begin > @end
- Utils.CheckError(u.AddCodeHook(CodeHookCallback, null, 1, 0).Item1);
+ // tracing all instructions by having @begin > @end
+ u.AddCodeHook(CodeHookCallback, null, 1, 0);
- // handle interrupt ourself
- Utils.CheckError(u.AddInterruptHook(InterruptHookCallback, null).Item1);
+ // handle interrupt ourself
+ u.AddInterruptHook(InterruptHookCallback, null);
- // handle SYSCALL
- Utils.CheckError(u.AddSyscallHook(SyscallHookCallback, null).Item1);
+ // handle SYSCALL
+ u.AddSyscallHook(SyscallHookCallback, null);
- Console.WriteLine(">>> Start tracing linux code");
+ Console.WriteLine(">>> Start tracing linux code");
- // emulate machine code in infinite time
- u.EmuStart(address, address + (UInt64)code.Length, 0u, new UIntPtr(0));
+ // emulate machine code in infinite time
+ u.EmuStart(address, address + (UInt64)code.Length, 0u, new UIntPtr(0));
- Console.WriteLine(">>> Emulation Done!");
+ Console.WriteLine(">>> Emulation Done!");
+ }
+ catch (UnicornEngineException ex)
+ {
+ Console.Error.WriteLine("Emulation FAILED! " + ex.Message);
+ }
}
private static void CodeHookCallback(Unicorn u, UInt64 addr, Int32 size, Object userData)
@@ -83,11 +111,11 @@ namespace UnicornTests
Console.Write("Tracing >>> 0x{0} ", addr.ToString("X"));
var eipBuffer = new Byte[4];
- Utils.CheckError(u.RegRead(X86.UC_X86_REG_EIP, eipBuffer));
+ u.RegRead(X86.UC_X86_REG_EIP, eipBuffer);
var effectiveSize = Math.Min(16, size);
var tmp = new Byte[effectiveSize];
- Utils.CheckError(u.MemRead(addr, tmp));
+ u.MemRead(addr, tmp);
foreach (var t in tmp)
{
@@ -100,7 +128,7 @@ namespace UnicornTests
private static void SyscallHookCallback(Unicorn u, Object userData)
{
var eaxBuffer = new Byte[4];
- Utils.CheckError(u.RegRead(X86.UC_X86_REG_EAX, eaxBuffer));
+ u.RegRead(X86.UC_X86_REG_EAX, eaxBuffer);
var eax = Utils.ToInt(eaxBuffer);
Console.WriteLine("Syscall >>> EAX = 0x{0}", eax.ToString("X"));
@@ -119,8 +147,8 @@ namespace UnicornTests
var eaxBuffer = new Byte[4];
var eipBuffer = new Byte[4];
- Utils.CheckError(u.RegRead(X86.UC_X86_REG_EAX, eaxBuffer));
- Utils.CheckError(u.RegRead(X86.UC_X86_REG_EIP, eipBuffer));
+ u.RegRead(X86.UC_X86_REG_EAX, eaxBuffer);
+ u.RegRead(X86.UC_X86_REG_EIP, eipBuffer);
var eax = Utils.ToInt(eaxBuffer);
var eip = Utils.ToInt(eipBuffer);
@@ -142,8 +170,8 @@ namespace UnicornTests
// EDX = buffer size
var edxBuffer = new Byte[4];
- Utils.CheckError(u.RegRead(X86.UC_X86_REG_ECX, ecxBuffer));
- Utils.CheckError(u.RegRead(X86.UC_X86_REG_EDX, edxBuffer));
+ u.RegRead(X86.UC_X86_REG_ECX, ecxBuffer);
+ u.RegRead(X86.UC_X86_REG_EDX, edxBuffer);
var ecx = Utils.ToInt(ecxBuffer);
var edx = Utils.ToInt(edxBuffer);
@@ -151,7 +179,7 @@ namespace UnicornTests
// read the buffer in
var size = Math.Min(256, edx);
var buffer = new Byte[size];
- Utils.CheckError(u.MemRead(ecx, buffer));
+ u.MemRead(ecx, buffer);
var content = Encoding.Default.GetString(buffer);
Console.WriteLine(
diff --git a/bindings/dotnet/UnicornTests/Utils.cs b/bindings/dotnet/UnicornTests/Utils.cs
index 882e8ded..557a9a34 100644
--- a/bindings/dotnet/UnicornTests/Utils.cs
+++ b/bindings/dotnet/UnicornTests/Utils.cs
@@ -1,4 +1,25 @@
-using System;
+/*
+
+.NET bindings for the UnicornEngine Emulator Engine
+
+Copyright(c) 2015 Antonio Parata
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+version 2 as published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -20,14 +41,6 @@ namespace UnicornTests
return res;
}
- public static void CheckError(Int32 err)
- {
- if (err != Common.UC_ERR_OK)
- {
- throw new ApplicationException("Operation failed, error: " + err);
- }
- }
-
public static Byte[] Int64ToBytes(UInt64 intVal)
{
var res = new Byte[8];