Solution refactoring and bug fixing

This commit is contained in:
enkomio
2016-01-04 16:59:05 +01:00
parent 272fb8524f
commit 2c54f1a969
16 changed files with 338 additions and 175 deletions

View File

@@ -22,7 +22,7 @@ type IBinding =
abstract MemUnmap : UIntPtr * UInt64 * UIntPtr -> Int32
abstract MemProtect : UIntPtr * UInt64 * UIntPtr * UInt32 -> Int32
abstract HookAddNoarg : UIntPtr * UIntPtr * Int32 * UIntPtr * IntPtr -> Int32
abstract HookAddArg0 : UIntPtr * UIntPtr * Int32 * UIntPtr * IntPtr * IntPtr -> Int32
abstract HookAddArg0 : UIntPtr * UIntPtr * Int32 * UIntPtr * IntPtr * Int32 -> Int32
abstract HookAddArg0Arg1 : UIntPtr * UIntPtr * Int32 * UIntPtr * IntPtr * UInt64 * UInt64 -> Int32
end

View File

@@ -63,7 +63,7 @@ module NativeBinding =
extern Int32 uc_hook_add_noarg(UIntPtr eng, UIntPtr hh, Int32 callbackType, UIntPtr callback, IntPtr userData)
[<DllImport("unicorn", CallingConvention = CallingConvention.Cdecl, EntryPoint = "uc_hook_add")>]
extern Int32 uc_hook_add_arg0(UIntPtr eng, UIntPtr hh, Int32 callbackType, UIntPtr callback, IntPtr userData, IntPtr arg0)
extern Int32 uc_hook_add_arg0(UIntPtr eng, UIntPtr hh, Int32 callbackType, UIntPtr callback, IntPtr userData, Int32 arg0)
[<DllImport("unicorn", CallingConvention = CallingConvention.Cdecl, EntryPoint = "uc_hook_add")>]
extern Int32 uc_hook_add_arg0_arg1(UIntPtr eng, UIntPtr hh, Int32 callbackType, UIntPtr callback, IntPtr userData, UInt64 arg0, UInt64 arg1)

View File

@@ -7,7 +7,7 @@ open System
[<AutoOpen>]
module Arm =
// ARM registers
// ARM registers
let UC_ARM_REG_INVALID = 0
let UC_ARM_REG_APSR = 1
@@ -122,7 +122,7 @@ module Arm =
let UC_ARM_REG_S31 = 110
let UC_ARM_REG_ENDING = 111
// alias registers
// alias registers
let UC_ARM_REG_R13 = 12
let UC_ARM_REG_R14 = 10
let UC_ARM_REG_R15 = 11

View File

@@ -7,7 +7,7 @@ open System
[<AutoOpen>]
module Arm64 =
// ARM64 registers
// ARM64 registers
let UC_ARM64_REG_INVALID = 0
let UC_ARM64_REG_X29 = 1
@@ -270,11 +270,11 @@ module Arm64 =
let UC_ARM64_REG_V30 = 258
let UC_ARM64_REG_V31 = 259
// pseudo registers
// pseudo registers
let UC_ARM64_REG_PC = 260
let UC_ARM64_REG_ENDING = 261
// alias registers
// alias registers
let UC_ARM64_REG_IP1 = 215
let UC_ARM64_REG_IP0 = 216
let UC_ARM64_REG_FP = 1

View File

@@ -7,7 +7,7 @@ open System
[<AutoOpen>]
module M68k =
// M68K registers
// M68K registers
let UC_M68K_REG_INVALID = 0
let UC_M68K_REG_A0 = 1

View File

@@ -7,11 +7,11 @@ open System
[<AutoOpen>]
module Mips =
// MIPS registers
// MIPS registers
let UC_MIPS_REG_INVALID = 0
// General purpose registers
// General purpose registers
let UC_MIPS_REG_PC = 1
let UC_MIPS_REG_0 = 2
let UC_MIPS_REG_1 = 3
@@ -46,7 +46,7 @@ module Mips =
let UC_MIPS_REG_30 = 32
let UC_MIPS_REG_31 = 33
// DSP registers
// DSP registers
let UC_MIPS_REG_DSPCCOND = 34
let UC_MIPS_REG_DSPCARRY = 35
let UC_MIPS_REG_DSPEFI = 36
@@ -59,13 +59,13 @@ module Mips =
let UC_MIPS_REG_DSPPOS = 43
let UC_MIPS_REG_DSPSCOUNT = 44
// ACC registers
// ACC registers
let UC_MIPS_REG_AC0 = 45
let UC_MIPS_REG_AC1 = 46
let UC_MIPS_REG_AC2 = 47
let UC_MIPS_REG_AC3 = 48
// COP registers
// COP registers
let UC_MIPS_REG_CC0 = 49
let UC_MIPS_REG_CC1 = 50
let UC_MIPS_REG_CC2 = 51
@@ -75,7 +75,7 @@ module Mips =
let UC_MIPS_REG_CC6 = 55
let UC_MIPS_REG_CC7 = 56
// FPU registers
// FPU registers
let UC_MIPS_REG_F0 = 57
let UC_MIPS_REG_F1 = 58
let UC_MIPS_REG_F2 = 59
@@ -117,7 +117,7 @@ module Mips =
let UC_MIPS_REG_FCC6 = 95
let UC_MIPS_REG_FCC7 = 96
// AFPR128
// AFPR128
let UC_MIPS_REG_W0 = 97
let UC_MIPS_REG_W1 = 98
let UC_MIPS_REG_W2 = 99

View File

@@ -7,7 +7,7 @@ open System
[<AutoOpen>]
module Sparc =
// SPARC registers
// SPARC registers
let UC_SPARC_REG_INVALID = 0
let UC_SPARC_REG_F0 = 1

View File

@@ -7,7 +7,7 @@ open System
[<AutoOpen>]
module X86 =
// X86 registers
// X86 registers
let UC_X86_REG_INVALID = 0
let UC_X86_REG_AH = 1
@@ -253,7 +253,7 @@ module X86 =
let UC_X86_REG_R15W = 241
let UC_X86_REG_ENDING = 242
// X86 instructions
// X86 instructions
let UC_X86_INS_INVALID = 0
let UC_X86_INS_AAA = 1
@@ -378,7 +378,7 @@ module X86 =
let UC_X86_INS_CVTPS2DQ = 120
let UC_X86_INS_CVTPS2PD = 121
let UC_X86_INS_CVTSD2SI = 122
(*let UC_X86_INS_CVTSD2SS = 123
let UC_X86_INS_CVTSD2SS = 123
let UC_X86_INS_CVTSI2SD = 124
let UC_X86_INS_CVTSI2SS = 125
let UC_X86_INS_CVTSS2SD = 126
@@ -472,9 +472,9 @@ module X86 =
let UC_X86_INS_HSUBPS = 214
let UC_X86_INS_IDIV = 215
let UC_X86_INS_FILD = 216
let UC_X86_INS_IMUL = 217*)
let UC_X86_INS_IMUL = 217
let UC_X86_INS_IN = 218
(*let UC_X86_INS_INC = 219
let UC_X86_INS_INC = 219
let UC_X86_INS_INSB = 220
let UC_X86_INS_INSERTPS = 221
let UC_X86_INS_INSERTQ = 222
@@ -754,9 +754,9 @@ module X86 =
let UC_X86_INS_MWAIT = 496
let UC_X86_INS_NEG = 497
let UC_X86_INS_NOP = 498
let UC_X86_INS_NOT = 499*)
let UC_X86_INS_NOT = 499
let UC_X86_INS_OUT = 500
(*let UC_X86_INS_OUTSB = 501
let UC_X86_INS_OUTSB = 501
let UC_X86_INS_OUTSD = 502
let UC_X86_INS_OUTSW = 503
let UC_X86_INS_PACKUSDW = 504
@@ -953,9 +953,9 @@ module X86 =
let UC_X86_INS_FSUB = 695
let UC_X86_INS_FISUB = 696
let UC_X86_INS_FSUBP = 697
let UC_X86_INS_SWAPGS = 698*)
let UC_X86_INS_SWAPGS = 698
let UC_X86_INS_SYSCALL = 699
(*let UC_X86_INS_SYSENTER = 700
let UC_X86_INS_SYSENTER = 700
let UC_X86_INS_SYSEXIT = 701
let UC_X86_INS_SYSRET = 702
let UC_X86_INS_T1MSKC = 703
@@ -1594,4 +1594,4 @@ module X86 =
let UC_X86_INS_FDISI8087_NOP = 1336
let UC_X86_INS_FENI8087_NOP = 1337
let UC_X86_INS_ENDING = 1338
*)

View File

@@ -0,0 +1,21 @@
namespace UnicornManaged
open System
[<AutoOpen>]
module internal ConvertUtility =
let int64ToBytes(v: Int64) =
let res = Array.zeroCreate<Byte> 8
let mutable uv = uint64 v
for i = 0 to res.Length-1 do
res.[i] <- byte (uv &&& uint64 0xFF)
uv <- uv >>> 8
res
let bytesToInt64(v: Byte array) =
let mutable res = uint64 0
for i = 0 to v.Length-1 do
let tmpV = v.[i] &&& byte 0xFF
res <- res + (uint64 tmpV <<< (i * 8))
int64 res

View File

@@ -20,10 +20,10 @@ type internal MemReadHookInternal = delegate of IntPtr * Int64 * Int32 * IntPtr
type internal MemWriteHookInternal = delegate of IntPtr * Int64 * Int32 * Int64 * IntPtr -> unit
[<UnmanagedFunctionPointer(CallingConvention.Cdecl)>]
type internal EventMemHookInternal = delegate of IntPtr * Int64 * Int32 * Int64 * IntPtr -> unit
type internal EventMemHookInternal = delegate of IntPtr * Int32 * Int64 * Int32 * Int64 * IntPtr-> Boolean
[<UnmanagedFunctionPointer(CallingConvention.Cdecl)>]
type internal InHookInternal = delegate of IntPtr * Int32 * Int32 * IntPtr -> unit
type internal InHookInternal = delegate of IntPtr * Int32 * Int32 * IntPtr -> Int32
[<UnmanagedFunctionPointer(CallingConvention.Cdecl)>]
type internal OutHookInternal = delegate of IntPtr * Int32 * Int32 * Int32 * IntPtr -> unit

View File

@@ -4,6 +4,7 @@ open System
open System.Threading
open System.Collections.Generic
open System.Runtime.InteropServices
open System.Linq
open UnicornManaged.Const
open UnicornManaged.Binding
@@ -13,8 +14,8 @@ and BlockHook = delegate of Unicorn * Int64 * Int32 * Object -> unit
and InterruptHook = delegate of Unicorn * Int32 * Object -> unit
and MemReadHook = delegate of Unicorn * Int64 * Int32 * Object -> unit
and MemWriteHook = delegate of Unicorn * Int64 * Int32 * Int64 * Object -> unit
and EventMemHook = delegate of Unicorn * Int64 * Int32 * Int64 * Object -> unit
and InHook = delegate of Unicorn * Int32 * Int32 * Object -> unit
and EventMemHook = delegate of Unicorn * Int32 * Int64 * Int32 * Int64 * Object -> Boolean
and InHook = delegate of Unicorn * Int32 * Int32 * Object -> Int32
and OutHook = delegate of Unicorn * Int32 * Int32 * Int32 * Object -> unit
and SyscallHook = delegate of Unicorn * Object -> unit
@@ -22,30 +23,36 @@ and SyscallHook = delegate of Unicorn * Object -> unit
and Unicorn(arch: Int32, mode: Int32, binding: IBinding) =
// hook callback list
let _codeHooks = new Dictionary<IntPtr, (CodeHook * Object)>()
let _blockHooks = new Dictionary<IntPtr, (BlockHook * Object)>()
let _interruptHooks = new Dictionary<IntPtr, (InterruptHook * Object)>()
let _memReadHooks = new Dictionary<IntPtr, (MemReadHook * Object)>()
let _memWriteHooks = new Dictionary<IntPtr, (MemWriteHook * Object)>()
let _memEventHooks = new Dictionary<IntPtr, (EventMemHook * Object)>()
let _inHooks = new Dictionary<IntPtr, (InHook * Object)>()
let _outHooks = new Dictionary<IntPtr, (OutHook * Object)>()
let _syscallHooks = new Dictionary<IntPtr, (SyscallHook * Object)>()
let _codeHooks = new List<(CodeHook * Object)>()
let _blockHooks = new List<(BlockHook * Object)>()
let _interruptHooks = new List<(InterruptHook * Object)>()
let _memReadHooks = new List<(MemReadHook * Object)>()
let _memWriteHooks = new List<(MemWriteHook * Object)>()
let _memEventHooks = new Dictionary<Int32, List<(EventMemHook * Object)>>()
let _inHooks = new List<(InHook * Object)>()
let _outHooks = new List<(OutHook * Object)>()
let _syscallHooks = new List<(SyscallHook * Object)>()
let _disposablePointers = new List<nativeint>()
let _eventMemMap =
[
(UC_HOOK_MEM_READ_UNMAPPED, UC_MEM_READ_UNMAPPED)
(UC_HOOK_MEM_WRITE_UNMAPPED, UC_MEM_WRITE_UNMAPPED)
(UC_HOOK_MEM_FETCH_UNMAPPED, UC_MEM_FETCH_UNMAPPED)
(UC_HOOK_MEM_READ_PROT, UC_MEM_READ_PROT)
(UC_HOOK_MEM_WRITE_PROT, UC_MEM_WRITE_PROT)
(UC_HOOK_MEM_FETCH_PROT, UC_MEM_FETCH_PROT)
] |> dict
let mutable _eng = [|UIntPtr.Zero|]
let checkResult(errCode: Int32, errMsg: String) =
if errCode <> Common.UC_ERR_OK then raise(ApplicationException(String.Format("{0}. Error: {1}", errMsg, errCode)))
let getId =
let counter = ref 0
fun () -> new IntPtr(Interlocked.Increment(counter))
let hookDel(callbacks: Dictionary<IntPtr, 'a * Object>) (callback: 'a)=
let hookDel(callbacks: List<'a * Object>) (callback: 'a)=
// TODO: invoke the native function in order to not call the trampoline anymore
callbacks.Keys
|> Seq.tryFind(fun k -> match callbacks.[k] with | (c, _) -> c = callback)
callbacks
|> Seq.tryFind(fun item -> match item with | (c, _) -> c = callback)
|> (fun k -> if k.IsSome then callbacks.Remove(k.Value) |> ignore)
let allocate(size: Int32) =
@@ -54,6 +61,12 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) =
mem.ToPointer()
do
// initialize event list
_eventMemMap
|> Seq.map(fun kv -> kv.Key)
|> Seq.iter (fun eventType -> _memEventHooks.Add(eventType, new List<EventMemHook * Object>()))
// init engine
_eng <- [|new UIntPtr(allocate(IntPtr.Size))|]
let err = binding.UcOpen(uint32 arch, uint32 mode, _eng)
checkResult(err, "Unable to open the Unicorn Engine")
@@ -101,10 +114,18 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) =
match binding.RegWrite(_eng.[0], regId, value) |> this.CheckResult with
| Some e -> raise e | None -> ()
member this.RegWrite(regId: Int32, value: Int64) =
this.RegWrite(regId, int64ToBytes value)
member this.RegRead(regId: Int32, regValue: Byte array) =
match binding.RegRead(_eng.[0], regId, regValue) |> this.CheckResult with
| Some e -> raise e | None -> ()
member this.RegRead(regId: Int32) =
let buffer = Array.zeroCreate<Byte> 8
this.RegRead(regId, buffer)
bytesToInt64 buffer
member this.EmuStart(beginAddr: Int64, untilAddr: Int64, timeout: Int64, count: Int64) =
match binding.EmuStart(_eng.[0], uint64 beginAddr, uint64 untilAddr, uint64 timeout, uint64 count) |> this.CheckResult with
| Some e -> raise e | None -> ()
@@ -129,18 +150,18 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) =
member this.AddCodeHook(callback: CodeHook, userData: Object, beginAddr: Int64, endAddr: Int64) =
let trampoline(u: IntPtr) (addr: Int64) (size: Int32) (user: IntPtr) =
let (exist, (callback, userData)) = _codeHooks.TryGetValue(user)
if exist then callback.Invoke(this, addr, size, userData)
_codeHooks
|> Seq.iter(fun (callback, userData) -> callback.Invoke(this, addr, size, userData))
let id = getId()
_codeHooks.Add(id, (callback, userData))
if _codeHooks |> Seq.isEmpty then
let funcPointer = Marshal.GetFunctionPointerForDelegate(new CodeHookInternal(trampoline))
let hh = new UIntPtr(allocate(IntPtr.Size))
match binding.HookAddArg0Arg1(_eng.[0], hh, Common.UC_HOOK_CODE, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 beginAddr, uint64 endAddr) |> this.CheckResult with
| Some e -> raise e | None -> ()
let funcPointer = Marshal.GetFunctionPointerForDelegate(new CodeHookInternal(trampoline))
let hh = new UIntPtr(allocate(IntPtr.Size))
match binding.HookAddArg0Arg1(_eng.[0], hh, Common.UC_HOOK_CODE, new UIntPtr(funcPointer.ToPointer()), id, uint64 beginAddr, uint64 endAddr) |> this.CheckResult with
| Some e -> raise e | None -> ()
_codeHooks.Add(callback, userData)
member this.AddCodeHook(callback: CodeHook, beginAddr: Int64, endAddr: Int64) =
member this.AddCodeHook(callback: CodeHook, beginAddr: Int64, endAddr: Int64) =
this.AddCodeHook(callback, null, beginAddr, endAddr)
member this.HookDel(callback: CodeHook) =
@@ -148,32 +169,32 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) =
member this.AddBlockHook(callback: BlockHook, userData: Object, beginAddr: Int64, endAddr: Int64) =
let trampoline(u: IntPtr) (addr: Int64) (size: Int32) (user: IntPtr) =
let (exist, (callback, userData)) = _blockHooks.TryGetValue(user)
if exist then callback.Invoke(this, addr, size, userData)
_blockHooks
|> Seq.iter(fun (callback, userData) -> callback.Invoke(this, addr, size, userData))
let id = getId()
_blockHooks.Add(id, (callback, userData))
if _blockHooks |> Seq.isEmpty then
let funcPointer = Marshal.GetFunctionPointerForDelegate(new BlockHookInternal(trampoline))
let hh = new UIntPtr(allocate(IntPtr.Size))
match binding.HookAddArg0Arg1(_eng.[0], hh, Common.UC_HOOK_BLOCK, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 beginAddr, uint64 endAddr) |> this.CheckResult with
| Some e -> raise e | None -> ()
let funcPointer = Marshal.GetFunctionPointerForDelegate(new BlockHookInternal(trampoline))
let hh = new UIntPtr(allocate(IntPtr.Size))
match binding.HookAddArg0Arg1(_eng.[0], hh, Common.UC_HOOK_BLOCK, new UIntPtr(funcPointer.ToPointer()), id, uint64 beginAddr, uint64 endAddr) |> this.CheckResult with
| Some e -> raise e | None -> ()
_blockHooks.Add(callback, userData)
member this.HookDel(callback: BlockHook) =
hookDel _blockHooks callback
member this.AddInterruptHook(callback: InterruptHook, userData: Object) =
let trampoline(u: IntPtr) (intNumber: Int32) (user: IntPtr) =
let (exist, (callback, userData)) = _interruptHooks.TryGetValue(user)
if exist then callback.Invoke(this, intNumber, userData)
_interruptHooks
|> Seq.iter(fun (callback, userData) -> callback.Invoke(this, intNumber, userData))
if _interruptHooks |> Seq.isEmpty then
let funcPointer = Marshal.GetFunctionPointerForDelegate(new InterruptHookInternal(trampoline))
let hh = new UIntPtr(allocate(IntPtr.Size))
match binding.HookAddNoarg(_eng.[0], hh, Common.UC_HOOK_INTR, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero) |> this.CheckResult with
| Some e -> raise e | None -> ()
let id = getId()
_interruptHooks.Add(id, (callback, userData))
let funcPointer = Marshal.GetFunctionPointerForDelegate(new InterruptHookInternal(trampoline))
let hh = new UIntPtr(allocate(IntPtr.Size))
match binding.HookAddNoarg(_eng.[0], hh, Common.UC_HOOK_INTR, new UIntPtr(funcPointer.ToPointer()), id) |> this.CheckResult with
| Some e -> raise e | None -> ()
_interruptHooks.Add(callback, userData)
member this.AddInterruptHook(callback: InterruptHook) =
this.AddInterruptHook(callback, null)
@@ -183,104 +204,113 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) =
member this.AddMemReadHook(callback: MemReadHook, userData: Object, beginAddr: Int64, endAddr: Int64) =
let trampoline(u: IntPtr) (addr: Int64) (size: Int32) (user: IntPtr) =
let (exist, (callback, userData)) = _memReadHooks.TryGetValue(user)
if exist then callback.Invoke(this, addr, size, userData)
_memReadHooks
|> Seq.iter(fun (callback, userData) -> callback.Invoke(this, addr, size, userData))
let id = getId()
_memReadHooks.Add(id, (callback, userData))
if _memReadHooks |> Seq.isEmpty then
let funcPointer = Marshal.GetFunctionPointerForDelegate(new MemReadHookInternal(trampoline))
let hh = new UIntPtr(allocate(IntPtr.Size))
match binding.HookAddArg0Arg1(_eng.[0], hh, Common.UC_HOOK_MEM_READ, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 beginAddr, uint64 endAddr) |> this.CheckResult with
| Some e -> raise e | None -> ()
let funcPointer = Marshal.GetFunctionPointerForDelegate(new MemReadHookInternal(trampoline))
let hh = new UIntPtr(allocate(IntPtr.Size))
match binding.HookAddArg0Arg1(_eng.[0], hh, Common.UC_HOOK_MEM_READ, new UIntPtr(funcPointer.ToPointer()), id, uint64 beginAddr, uint64 endAddr) |> this.CheckResult with
| Some e -> raise e | None -> ()
_memReadHooks.Add(callback, userData)
member this.HookDel(callback: MemReadHook) =
hookDel _memReadHooks callback
member this.AddMemWriteHook(callback: MemWriteHook, userData: Object, beginAddr: Int64, endAddr: Int64) =
let trampoline(u: IntPtr) (addr: Int64) (size: Int32) (value: Int64) (user: IntPtr) =
let (exist, (callback, userData)) = _memWriteHooks.TryGetValue(user)
if exist then callback.Invoke(this, addr, size, value, userData)
_memWriteHooks
|> Seq.iter(fun (callback, userData) -> callback.Invoke(this, addr, size, value, userData))
if _memWriteHooks |> Seq.isEmpty then
let funcPointer = Marshal.GetFunctionPointerForDelegate(new MemWriteHookInternal(trampoline))
let hh = new UIntPtr(allocate(IntPtr.Size))
match binding.HookAddArg0Arg1(_eng.[0], hh, Common.UC_HOOK_MEM_WRITE, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 beginAddr, uint64 endAddr) |> this.CheckResult with
| Some e -> raise e | None -> ()
let id = getId()
_memWriteHooks.Add(id, (callback, userData))
let funcPointer = Marshal.GetFunctionPointerForDelegate(new MemWriteHookInternal(trampoline))
let hh = new UIntPtr(allocate(IntPtr.Size))
match binding.HookAddArg0Arg1(_eng.[0], hh, Common.UC_HOOK_MEM_WRITE, new UIntPtr(funcPointer.ToPointer()), id, uint64 beginAddr, uint64 endAddr) |> this.CheckResult with
| Some e -> raise e | None -> ()
_memWriteHooks.Add(callback, userData)
member this.HookDel(callback: MemWriteHook) =
hookDel _memWriteHooks callback
member this.AddEventMemHook(callback: EventMemHook, eventType: Int32, userData: Object) =
let trampoline(u: IntPtr) (addr: Int64) (size: Int32) (value: Int64) (user: IntPtr) =
let (exist, (callback, userData)) = _memEventHooks.TryGetValue(user)
if exist then callback.Invoke(this, addr, size, value, userData)
let registEventMemHook(check: Int32) =
let id = getId()
_memEventHooks.Add(id, (callback, userData))
let trampoline(u: IntPtr) (eventType: Int32) (addr: Int64) (size: Int32) (value: Int64) (user: IntPtr) =
_memEventHooks.Keys
|> Seq.filter(fun eventFlag -> (eventType &&& eventFlag) <> 0)
|> Seq.map(fun eventflag -> _memEventHooks.[eventflag])
|> Seq.concat
|> Seq.map(fun (callback, userData) -> callback.Invoke(this, eventType, addr, size, value, userData))
|> Seq.forall id
// register the event if not already done
_memEventHooks.Keys
|> Seq.filter(fun eventFlag -> (eventType &&& eventFlag) <> 0)
|> Seq.filter(fun eventFlag -> _memEventHooks.[eventFlag] |> Seq.isEmpty)
|> Seq.iter(fun eventFlag ->
let funcPointer = Marshal.GetFunctionPointerForDelegate(new EventMemHookInternal(trampoline))
let hh = new UIntPtr(allocate(IntPtr.Size))
match binding.HookAddNoarg(_eng.[0], hh, check, new UIntPtr(funcPointer.ToPointer()), id) |> this.CheckResult with
let hh = new UIntPtr(allocate(IntPtr.Size))
match binding.HookAddNoarg(_eng.[0], hh, eventFlag, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero) |> this.CheckResult with
| Some e -> raise e | None -> ()
)
// test all the events types agains the input eventType
[
Common.UC_HOOK_MEM_READ_UNMAPPED
Common.UC_HOOK_MEM_WRITE_UNMAPPED
Common.UC_HOOK_MEM_FETCH_UNMAPPED
Common.UC_HOOK_MEM_READ_PROT
Common.UC_HOOK_MEM_WRITE_PROT
Common.UC_HOOK_MEM_FETCH_PROT
]
|> List.filter(fun eventFlag -> eventType &&& eventFlag <> 0)
|> List.map registEventMemHook
|> List.rev |> List.head
// register the callbacks
_memEventHooks.Keys
|> Seq.filter(fun eventFlag -> (eventType &&& eventFlag) <> 0)
|> Seq.iter(fun eventFlag -> _memEventHooks.[eventFlag].Add((callback, userData)))
member this.AddEventMemHook(callback: EventMemHook, eventType: Int32) =
this.AddEventMemHook(callback, eventType, null)
member this.HookDel(callback: EventMemHook) =
hookDel _memEventHooks callback
let callbacks = (_memEventHooks.Values |> Seq.concat).ToList()
hookDel callbacks callback
member this.AddInHook(callback: InHook, userData: Object) =
let trampoline(u: IntPtr) (port: Int32) (size: Int32) (user: IntPtr) =
let (exist, (callback, userData)) = _inHooks.TryGetValue(user)
if exist then callback.Invoke(this, port, size, userData)
_inHooks
|> Seq.map(fun (callback, userData) -> callback.Invoke(this, port, size, userData))
|> Seq.last
if _inHooks |> Seq.isEmpty then
let funcPointer = Marshal.GetFunctionPointerForDelegate(new InHookInternal(trampoline))
let hh = new UIntPtr(allocate(IntPtr.Size))
match binding.HookAddArg0(_eng.[0], hh, Common.UC_HOOK_INSN, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, X86.UC_X86_INS_IN) |> this.CheckResult with
| Some e -> raise e | None -> ()
let id = getId()
_inHooks.Add(id, (callback, userData))
_inHooks.Add(callback, userData)
let funcPointer = Marshal.GetFunctionPointerForDelegate(new InHookInternal(trampoline))
let hh = new UIntPtr(allocate(IntPtr.Size))
match binding.HookAddArg0(_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.AddInHook(callback: InHook) =
this.AddInHook(callback, null)
member this.AddOutHook(callback: OutHook, userData: Object) =
let trampoline(u: IntPtr) (port: Int32) (size: Int32) (value: Int32) (user: IntPtr) =
let (exist, (callback, userData)) = _outHooks.TryGetValue(user)
if exist then callback.Invoke(this, port, size, value, userData)
_outHooks
|> Seq.iter(fun (callback, userData) -> callback.Invoke(this, port, size, value, userData))
if _outHooks |> Seq.isEmpty then
let funcPointer = Marshal.GetFunctionPointerForDelegate(new OutHookInternal(trampoline))
let hh = new UIntPtr(allocate(IntPtr.Size))
match binding.HookAddArg0(_eng.[0], hh, Common.UC_HOOK_INSN, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, X86.UC_X86_INS_OUT) |> this.CheckResult with
| Some e -> raise e | None -> ()
let id = getId()
_outHooks.Add(id, (callback, userData))
_outHooks.Add(callback, userData)
let funcPointer = Marshal.GetFunctionPointerForDelegate(new OutHookInternal(trampoline))
let hh = new UIntPtr(allocate(IntPtr.Size))
match binding.HookAddArg0(_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.AddOutHook(callback: OutHook) =
this.AddOutHook(callback, null)
member this.AddSyscallHook(callback: SyscallHook, userData: Object) =
let trampoline(u: IntPtr) (user: IntPtr) =
let (exist, (callback, userData)) = _syscallHooks.TryGetValue(user)
if exist then callback.Invoke(this, userData)
_syscallHooks
|> Seq.iter(fun (callback, userData) -> callback.Invoke(this, userData))
if _syscallHooks |> Seq.isEmpty then
let funcPointer = Marshal.GetFunctionPointerForDelegate(new SyscallHookInternal(trampoline))
let hh = new UIntPtr(allocate(IntPtr.Size))
match binding.HookAddArg0(_eng.[0], hh, Common.UC_HOOK_INSN, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, X86.UC_X86_INS_SYSCALL) |> this.CheckResult with
| Some e -> raise e | None -> ()
let id = getId()
_syscallHooks.Add(id, (callback, userData))
let funcPointer = Marshal.GetFunctionPointerForDelegate(new SyscallHookInternal(trampoline))
let hh = new UIntPtr(allocate(IntPtr.Size))
match binding.HookAddArg0(_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 -> ()
_syscallHooks.Add(callback, userData)
member this.AddSyscallHook(callback: SyscallHook) =
this.AddSyscallHook(callback, null)

View File

@@ -57,7 +57,8 @@
<Compile Include="Binding\NativeBinding.fs" />
<Compile Include="Binding\BindingFactory.fs" />
<Compile Include="UnicornEngineException.fs" />
<Compile Include="Hooks.fs" />
<Compile Include="InternalHooks.fs" />
<Compile Include="ConvertUtility.fs" />
<Compile Include="Unicorn.fs" />
</ItemGroup>
<PropertyGroup>