|
|
|
|
@@ -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)
|
|
|
|
|
|