Merge pull request #190 from enkomio/master
Implemented error mechanism based on exception raising
This commit is contained in:
commit
88397649be
@ -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())
|
||||
|
@ -51,9 +51,9 @@
|
||||
<Compile Include="Const\Mips.fs" />
|
||||
<Compile Include="Const\Sparc.fs" />
|
||||
<Compile Include="Const\X86.fs" />
|
||||
<Compile Include="Const\UcError.fs" />
|
||||
<Compile Include="Hooks.fs" />
|
||||
<Compile Include="NativeUnicorn.fs" />
|
||||
<Compile Include="UnicornEngineException.fs" />
|
||||
<Compile Include="Unicorn.fs" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
|
30
bindings/dotnet/Unicorn/UnicornEngineException.fs
Normal file
30
bindings/dotnet/Unicorn/UnicornEngineException.fs
Normal file
@ -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
|
||||
|
@ -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(
|
||||
|
@ -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];
|
||||
|
Loading…
Reference in New Issue
Block a user