Merge pull request #1802 from tunz/tunz/hook-del
[dotnet] Use native binding calls whenever possible
This commit is contained in:
@@ -22,17 +22,16 @@ and SyscallHook = delegate of Unicorn * Object -> unit
|
|||||||
and Unicorn(arch: Int32, mode: Int32, binding: IBinding) =
|
and Unicorn(arch: Int32, mode: Int32, binding: IBinding) =
|
||||||
|
|
||||||
// hook callback list
|
// hook callback list
|
||||||
let _codeHooks = new List<(CodeHook * Object)>()
|
let _codeHooks = new List<(CodeHook * (UIntPtr * Object * Object))>()
|
||||||
let _blockHooks = new List<(BlockHook * Object)>()
|
let _blockHooks = new List<(BlockHook * (UIntPtr * Object * Object))>()
|
||||||
let _interruptHooks = new List<(InterruptHook * Object)>()
|
let _interruptHooks = new List<(InterruptHook * (UIntPtr * Object * Object))>()
|
||||||
let _memReadHooks = new List<(MemReadHook * Object)>()
|
let _memReadHooks = new List<(MemReadHook * (UIntPtr * Object * Object))>()
|
||||||
let _memWriteHooks = new List<(MemWriteHook * Object)>()
|
let _memWriteHooks = new List<(MemWriteHook * (UIntPtr * Object * Object))>()
|
||||||
let _memEventHooks = new Dictionary<Int32, List<(EventMemHook * Object)>>()
|
let _memEventHooks = new Dictionary<Int32, List<(EventMemHook * (UIntPtr * Object * Object))>>()
|
||||||
let _inHooks = new List<(InHook * Object)>()
|
let _inHooks = new List<(InHook * (UIntPtr * Object * Object))>()
|
||||||
let _outHooks = new List<(OutHook * Object)>()
|
let _outHooks = new List<(OutHook * (UIntPtr * Object * Object))>()
|
||||||
let _syscallHooks = new List<(SyscallHook * Object)>()
|
let _syscallHooks = new List<(SyscallHook * (UIntPtr * Object * Object))>()
|
||||||
let _disposablePointers = new List<nativeint>()
|
let _disposablePointers = new List<nativeint>()
|
||||||
let _hookInternals = new List<Object>();
|
|
||||||
|
|
||||||
let _eventMemMap =
|
let _eventMemMap =
|
||||||
[
|
[
|
||||||
@@ -46,14 +45,25 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) =
|
|||||||
|
|
||||||
let mutable _eng = [|UIntPtr.Zero|]
|
let mutable _eng = [|UIntPtr.Zero|]
|
||||||
|
|
||||||
let checkResult(errCode: Int32, errMsg: String) =
|
let strError(errorNo: Int32) =
|
||||||
if errCode <> Common.UC_ERR_OK then raise(ApplicationException(String.Format("{0}. Error: {1}", errMsg, errCode)))
|
let errorStringPointer = binding.Strerror(errorNo)
|
||||||
|
Marshal.PtrToStringAnsi(errorStringPointer)
|
||||||
|
|
||||||
let hookDel(callbacks: List<'a * Object>) (callback: 'a)=
|
let checkResult(errorCode: Int32) =
|
||||||
// TODO: invoke the native function in order to not call the trampoline anymore
|
// return the exception instead of raising it in order to have a more meaningful stack trace
|
||||||
callbacks
|
if errorCode <> Common.UC_ERR_OK then
|
||||||
|> Seq.tryFind(fun item -> match item with | (c, _) -> c = callback)
|
let errorMessage = strError(errorCode)
|
||||||
|> (fun k -> if k.IsSome then callbacks.Remove(k.Value) |> ignore)
|
Some <| UnicornEngineException(errorCode, errorMessage)
|
||||||
|
else None
|
||||||
|
|
||||||
|
let hookDel(callbacks: List<'a * (UIntPtr * Object * Object)>) (callback: 'a)=
|
||||||
|
match callbacks |> Seq.tryFind(fun item -> match item with | (c, _) -> c = callback) with
|
||||||
|
| Some(item) ->
|
||||||
|
let (hh, _, _) = snd item
|
||||||
|
match binding.HookDel(_eng.[0], hh) |> checkResult with
|
||||||
|
| Some e -> raise e
|
||||||
|
| None -> callbacks.Remove(item) |> ignore
|
||||||
|
| None -> ()
|
||||||
|
|
||||||
let allocate(size: Int32) =
|
let allocate(size: Int32) =
|
||||||
let mem = Marshal.AllocHGlobal(size)
|
let mem = Marshal.AllocHGlobal(size)
|
||||||
@@ -64,61 +74,55 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) =
|
|||||||
// initialize event list
|
// initialize event list
|
||||||
_eventMemMap
|
_eventMemMap
|
||||||
|> Seq.map(fun kv -> kv.Key)
|
|> Seq.map(fun kv -> kv.Key)
|
||||||
|> Seq.iter (fun eventType -> _memEventHooks.Add(eventType, new List<EventMemHook * Object>()))
|
|> Seq.iter (fun eventType -> _memEventHooks.Add(eventType, new List<EventMemHook * (UIntPtr * Object * Object)>()))
|
||||||
|
|
||||||
// init engine
|
// init engine
|
||||||
_eng <- [|new UIntPtr(allocate(IntPtr.Size))|]
|
_eng <- [|new UIntPtr(allocate(IntPtr.Size))|]
|
||||||
let err = binding.UcOpen(uint32 arch, uint32 mode, _eng)
|
let err = binding.UcOpen(uint32 arch, uint32 mode, _eng)
|
||||||
checkResult(err, "Unable to open the Unicorn Engine")
|
if err <> Common.UC_ERR_OK then
|
||||||
|
raise(ApplicationException(String.Format("Unable to open the Unicorn Engine. Error: {0}", err)))
|
||||||
|
|
||||||
new(arch, mode) = new Unicorn(arch, mode, BindingFactory.getDefault())
|
new(arch, mode) = new Unicorn(arch, mode, BindingFactory.getDefault())
|
||||||
|
|
||||||
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: Int64, size: Int64, perm: Int32) =
|
member this.MemMap(address: Int64, size: Int64, perm: Int32) =
|
||||||
let size = new UIntPtr(uint64 size)
|
let size = new UIntPtr(uint64 size)
|
||||||
match binding.MemMap(_eng.[0], uint64 address, size, uint32 perm) |> this.CheckResult with
|
match binding.MemMap(_eng.[0], uint64 address, size, uint32 perm) |> checkResult with
|
||||||
| Some e -> raise e | None -> ()
|
| Some e -> raise e | None -> ()
|
||||||
|
|
||||||
member this.MemMapPtr(address: Int64, size: Int64, perm: Int32, ptr: IntPtr) =
|
member this.MemMapPtr(address: Int64, size: Int64, perm: Int32, ptr: IntPtr) =
|
||||||
let size = new UIntPtr(uint64 size)
|
let size = new UIntPtr(uint64 size)
|
||||||
let ptr = new UIntPtr(ptr.ToPointer())
|
let ptr = new UIntPtr(ptr.ToPointer())
|
||||||
match binding.MemMapPtr(_eng.[0], uint64 address, size, uint32 perm, ptr) |> this.CheckResult with
|
match binding.MemMapPtr(_eng.[0], uint64 address, size, uint32 perm, ptr) |> checkResult with
|
||||||
| Some e -> raise e | None -> ()
|
| Some e -> raise e | None -> ()
|
||||||
|
|
||||||
member this.MemUnmap(address: Int64, size: Int64) =
|
member this.MemUnmap(address: Int64, size: Int64) =
|
||||||
let size = new UIntPtr(uint64 size)
|
let size = new UIntPtr(uint64 size)
|
||||||
match binding.MemUnmap(_eng.[0], uint64 address, size) |> this.CheckResult with
|
match binding.MemUnmap(_eng.[0], uint64 address, size) |> checkResult with
|
||||||
| Some e -> raise e | None -> ()
|
| Some e -> raise e | None -> ()
|
||||||
|
|
||||||
member this.MemProtect(address: Int64, size: Int64, ?perm: Int32) =
|
member this.MemProtect(address: Int64, size: Int64, ?perm: Int32) =
|
||||||
let size = new UIntPtr(uint64 size)
|
let size = new UIntPtr(uint64 size)
|
||||||
let perm = defaultArg perm Common.UC_PROT_ALL
|
let perm = defaultArg perm Common.UC_PROT_ALL
|
||||||
match binding.MemProtect(_eng.[0], uint64 address, size, uint32 perm) |> this.CheckResult with
|
match binding.MemProtect(_eng.[0], uint64 address, size, uint32 perm) |> checkResult with
|
||||||
| Some e -> raise e | None -> ()
|
| Some e -> raise e | None -> ()
|
||||||
|
|
||||||
member this.MemWrite(address: Int64, value: Byte array) =
|
member this.MemWrite(address: Int64, value: Byte array) =
|
||||||
match binding.MemWrite(_eng.[0], uint64 address, value, new UIntPtr(uint32 value.Length)) |> this.CheckResult with
|
match binding.MemWrite(_eng.[0], uint64 address, value, new UIntPtr(uint32 value.Length)) |> checkResult with
|
||||||
| Some e -> raise e | None -> ()
|
| Some e -> raise e | None -> ()
|
||||||
|
|
||||||
member this.MemRead(address: Int64, memValue: Byte array) =
|
member this.MemRead(address: Int64, memValue: Byte array) =
|
||||||
match binding.MemRead(_eng.[0], uint64 address, memValue, new UIntPtr(uint32 memValue.Length)) |> this.CheckResult with
|
match binding.MemRead(_eng.[0], uint64 address, memValue, new UIntPtr(uint32 memValue.Length)) |> checkResult with
|
||||||
| Some e -> raise e | None -> ()
|
| Some e -> raise e | None -> ()
|
||||||
|
|
||||||
member this.RegWrite(regId: Int32, value: Byte array) =
|
member this.RegWrite(regId: Int32, value: Byte array) =
|
||||||
match binding.RegWrite(_eng.[0], regId, value) |> this.CheckResult with
|
match binding.RegWrite(_eng.[0], regId, value) |> checkResult with
|
||||||
| Some e -> raise e | None -> ()
|
| Some e -> raise e | None -> ()
|
||||||
|
|
||||||
member this.RegWrite(regId: Int32, value: Int64) =
|
member this.RegWrite(regId: Int32, value: Int64) =
|
||||||
this.RegWrite(regId, int64ToBytes value)
|
this.RegWrite(regId, int64ToBytes value)
|
||||||
|
|
||||||
member this.RegRead(regId: Int32, regValue: Byte array) =
|
member this.RegRead(regId: Int32, regValue: Byte array) =
|
||||||
match binding.RegRead(_eng.[0], regId, regValue) |> this.CheckResult with
|
match binding.RegRead(_eng.[0], regId, regValue) |> checkResult with
|
||||||
| Some e -> raise e | None -> ()
|
| Some e -> raise e | None -> ()
|
||||||
|
|
||||||
member this.RegRead(regId: Int32) =
|
member this.RegRead(regId: Int32) =
|
||||||
@@ -127,15 +131,15 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) =
|
|||||||
bytesToInt64 buffer
|
bytesToInt64 buffer
|
||||||
|
|
||||||
member this.EmuStart(beginAddr: Int64, untilAddr: Int64, timeout: Int64, count: Int64) =
|
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
|
match binding.EmuStart(_eng.[0], uint64 beginAddr, uint64 untilAddr, uint64 timeout, uint64 count) |> checkResult with
|
||||||
| Some e -> raise e | None -> ()
|
| Some e -> raise e | None -> ()
|
||||||
|
|
||||||
member this.EmuStop() =
|
member this.EmuStop() =
|
||||||
match binding.EmuStop(_eng.[0]) |> this.CheckResult with
|
match binding.EmuStop(_eng.[0]) |> checkResult with
|
||||||
| Some e -> raise e | None -> ()
|
| Some e -> raise e | None -> ()
|
||||||
|
|
||||||
member this.Close() =
|
member this.Close() =
|
||||||
match binding.Close(_eng.[0]) |> this.CheckResult with
|
match binding.Close(_eng.[0]) |> checkResult with
|
||||||
| Some e -> raise e | None -> ()
|
| Some e -> raise e | None -> ()
|
||||||
|
|
||||||
member this.ArchSupported(arch: Int32) =
|
member this.ArchSupported(arch: Int32) =
|
||||||
@@ -144,24 +148,18 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) =
|
|||||||
member this.ErrNo() =
|
member this.ErrNo() =
|
||||||
binding.Errono(_eng.[0])
|
binding.Errono(_eng.[0])
|
||||||
|
|
||||||
member this.StrError(errorNo: Int32) =
|
|
||||||
let errorStringPointer = binding.Strerror(errorNo)
|
|
||||||
Marshal.PtrToStringAnsi(errorStringPointer)
|
|
||||||
|
|
||||||
member this.AddCodeHook(callback: CodeHook, userData: Object, beginAddr: Int64, endAddr: Int64) =
|
member this.AddCodeHook(callback: CodeHook, userData: Object, beginAddr: Int64, endAddr: Int64) =
|
||||||
let trampoline(u: IntPtr) (addr: Int64) (size: Int32) (user: IntPtr) =
|
let trampoline(u: IntPtr) (addr: Int64) (size: Int32) (user: IntPtr) =
|
||||||
_codeHooks
|
callback.Invoke(this, addr, size, userData)
|
||||||
|> Seq.iter(fun (callback, userData) -> callback.Invoke(this, addr, size, userData))
|
|
||||||
|
|
||||||
if _codeHooks |> Seq.isEmpty then
|
let codeHookInternal = new CodeHookInternal(trampoline)
|
||||||
let codeHookInternal = new CodeHookInternal(trampoline)
|
let funcPointer = Marshal.GetFunctionPointerForDelegate(codeHookInternal)
|
||||||
_hookInternals.Add(codeHookInternal)
|
let hh = new UIntPtr(allocate(IntPtr.Size))
|
||||||
let funcPointer = Marshal.GetFunctionPointerForDelegate(codeHookInternal)
|
match binding.HookAddNoarg(_eng.[0], hh, Common.UC_HOOK_CODE, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 beginAddr, uint64 endAddr) |> checkResult with
|
||||||
let hh = new UIntPtr(allocate(IntPtr.Size))
|
| Some e -> raise e | None -> ()
|
||||||
match binding.HookAddNoarg(_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 -> ()
|
|
||||||
|
|
||||||
_codeHooks.Add(callback, userData)
|
let hh = (unativeint)(Marshal.ReadIntPtr((nativeint)hh))
|
||||||
|
_codeHooks.Add(callback, (hh, userData, codeHookInternal))
|
||||||
|
|
||||||
member this.AddCodeHook(callback: CodeHook, beginAddr: Int64, endAddr: Int64) =
|
member this.AddCodeHook(callback: CodeHook, beginAddr: Int64, endAddr: Int64) =
|
||||||
this.AddCodeHook(callback, null, beginAddr, endAddr)
|
this.AddCodeHook(callback, null, beginAddr, endAddr)
|
||||||
@@ -171,36 +169,32 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) =
|
|||||||
|
|
||||||
member this.AddBlockHook(callback: BlockHook, userData: Object, beginAddr: Int64, endAddr: Int64) =
|
member this.AddBlockHook(callback: BlockHook, userData: Object, beginAddr: Int64, endAddr: Int64) =
|
||||||
let trampoline(u: IntPtr) (addr: Int64) (size: Int32) (user: IntPtr) =
|
let trampoline(u: IntPtr) (addr: Int64) (size: Int32) (user: IntPtr) =
|
||||||
_blockHooks
|
callback.Invoke(this, addr, size, userData)
|
||||||
|> Seq.iter(fun (callback, userData) -> callback.Invoke(this, addr, size, userData))
|
|
||||||
|
|
||||||
if _blockHooks |> Seq.isEmpty then
|
let blockHookInternal = new BlockHookInternal(trampoline)
|
||||||
let blockHookInternal = new BlockHookInternal(trampoline)
|
let funcPointer = Marshal.GetFunctionPointerForDelegate(blockHookInternal)
|
||||||
_hookInternals.Add(blockHookInternal)
|
let hh = new UIntPtr(allocate(IntPtr.Size))
|
||||||
let funcPointer = Marshal.GetFunctionPointerForDelegate(blockHookInternal)
|
match binding.HookAddNoarg(_eng.[0], hh, Common.UC_HOOK_BLOCK, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 beginAddr, uint64 endAddr) |> checkResult with
|
||||||
let hh = new UIntPtr(allocate(IntPtr.Size))
|
| Some e -> raise e | None -> ()
|
||||||
match binding.HookAddNoarg(_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 -> ()
|
|
||||||
|
|
||||||
_blockHooks.Add(callback, userData)
|
let hh = (unativeint)(Marshal.ReadIntPtr((nativeint)hh))
|
||||||
|
_blockHooks.Add(callback, (hh, userData, blockHookInternal))
|
||||||
|
|
||||||
member this.HookDel(callback: BlockHook) =
|
member this.HookDel(callback: BlockHook) =
|
||||||
hookDel _blockHooks callback
|
hookDel _blockHooks callback
|
||||||
|
|
||||||
member this.AddInterruptHook(callback: InterruptHook, userData: Object, hookBegin: UInt64, hookEnd : UInt64) =
|
member this.AddInterruptHook(callback: InterruptHook, userData: Object, hookBegin: UInt64, hookEnd : UInt64) =
|
||||||
let trampoline(u: IntPtr) (intNumber: Int32) (user: IntPtr) =
|
let trampoline(u: IntPtr) (intNumber: Int32) (user: IntPtr) =
|
||||||
_interruptHooks
|
callback.Invoke(this, intNumber, userData)
|
||||||
|> Seq.iter(fun (callback, userData) -> callback.Invoke(this, intNumber, userData))
|
|
||||||
|
|
||||||
if _interruptHooks |> Seq.isEmpty then
|
let interruptHookInternal = new InterruptHookInternal(trampoline)
|
||||||
let interruptHookInternal = new InterruptHookInternal(trampoline)
|
let funcPointer = Marshal.GetFunctionPointerForDelegate(interruptHookInternal)
|
||||||
_hookInternals.Add(interruptHookInternal)
|
let hh = new UIntPtr(allocate(IntPtr.Size))
|
||||||
let funcPointer = Marshal.GetFunctionPointerForDelegate(interruptHookInternal)
|
match binding.HookAddNoarg(_eng.[0], hh, Common.UC_HOOK_INTR, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, hookBegin, hookEnd) |> checkResult with
|
||||||
let hh = new UIntPtr(allocate(IntPtr.Size))
|
| Some e -> raise e | None -> ()
|
||||||
match binding.HookAddNoarg(_eng.[0], hh, Common.UC_HOOK_INTR, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, hookBegin, hookEnd) |> this.CheckResult with
|
|
||||||
| Some e -> raise e | None -> ()
|
|
||||||
|
|
||||||
_interruptHooks.Add(callback, userData)
|
let hh = (unativeint)(Marshal.ReadIntPtr((nativeint)hh))
|
||||||
|
_interruptHooks.Add(callback, (hh, userData, interruptHookInternal))
|
||||||
|
|
||||||
member this.AddInterruptHook(callback: InterruptHook) =
|
member this.AddInterruptHook(callback: InterruptHook) =
|
||||||
this.AddInterruptHook(callback, null, uint64 1, uint64 0)
|
this.AddInterruptHook(callback, null, uint64 1, uint64 0)
|
||||||
@@ -210,129 +204,130 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) =
|
|||||||
|
|
||||||
member this.AddMemReadHook(callback: MemReadHook, userData: Object, beginAddr: Int64, endAddr: Int64) =
|
member this.AddMemReadHook(callback: MemReadHook, userData: Object, beginAddr: Int64, endAddr: Int64) =
|
||||||
let trampoline(u: IntPtr) (_eventType: Int32) (addr: Int64) (size: Int32) (user: IntPtr) =
|
let trampoline(u: IntPtr) (_eventType: Int32) (addr: Int64) (size: Int32) (user: IntPtr) =
|
||||||
_memReadHooks
|
callback.Invoke(this, addr, size, userData)
|
||||||
|> Seq.iter(fun (callback, userData) -> callback.Invoke(this, addr, size, userData))
|
|
||||||
|
|
||||||
if _memReadHooks |> Seq.isEmpty then
|
let memReadHookInternal = new MemReadHookInternal(trampoline)
|
||||||
let memReadHookInternal = new MemReadHookInternal(trampoline)
|
let funcPointer = Marshal.GetFunctionPointerForDelegate(memReadHookInternal)
|
||||||
_hookInternals.Add(memReadHookInternal)
|
let hh = new UIntPtr(allocate(IntPtr.Size))
|
||||||
let funcPointer = Marshal.GetFunctionPointerForDelegate(memReadHookInternal)
|
match binding.HookAddNoarg(_eng.[0], hh, Common.UC_HOOK_MEM_READ, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 beginAddr, uint64 endAddr) |> checkResult with
|
||||||
let hh = new UIntPtr(allocate(IntPtr.Size))
|
| Some e -> raise e | None -> ()
|
||||||
match binding.HookAddNoarg(_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 -> ()
|
|
||||||
|
|
||||||
_memReadHooks.Add(callback, userData)
|
let hh = (unativeint)(Marshal.ReadIntPtr((nativeint)hh))
|
||||||
|
_memReadHooks.Add(callback, (hh, userData, memReadHookInternal))
|
||||||
|
|
||||||
member this.HookDel(callback: MemReadHook) =
|
member this.HookDel(callback: MemReadHook) =
|
||||||
hookDel _memReadHooks callback
|
hookDel _memReadHooks callback
|
||||||
|
|
||||||
member this.AddMemWriteHook(callback: MemWriteHook, userData: Object, beginAddr: Int64, endAddr: Int64) =
|
member this.AddMemWriteHook(callback: MemWriteHook, userData: Object, beginAddr: Int64, endAddr: Int64) =
|
||||||
let trampoline(u: IntPtr) (_eventType: Int32) (addr: Int64) (size: Int32) (value: Int64) (user: IntPtr) =
|
let trampoline(u: IntPtr) (_eventType: Int32) (addr: Int64) (size: Int32) (value: Int64) (user: IntPtr) =
|
||||||
_memWriteHooks
|
callback.Invoke(this, addr, size, value, userData)
|
||||||
|> Seq.iter(fun (callback, userData) -> callback.Invoke(this, addr, size, value, userData))
|
|
||||||
|
|
||||||
if _memWriteHooks |> Seq.isEmpty then
|
let memWriteHookInternal = new MemWriteHookInternal(trampoline)
|
||||||
let memWriteHookInternal = new MemWriteHookInternal(trampoline)
|
let funcPointer = Marshal.GetFunctionPointerForDelegate(memWriteHookInternal)
|
||||||
_hookInternals.Add(memWriteHookInternal)
|
let hh = new UIntPtr(allocate(IntPtr.Size))
|
||||||
let funcPointer = Marshal.GetFunctionPointerForDelegate(memWriteHookInternal)
|
match binding.HookAddNoarg(_eng.[0], hh, Common.UC_HOOK_MEM_WRITE, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 beginAddr, uint64 endAddr) |> checkResult with
|
||||||
let hh = new UIntPtr(allocate(IntPtr.Size))
|
| Some e -> raise e | None -> ()
|
||||||
match binding.HookAddNoarg(_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 -> ()
|
|
||||||
|
|
||||||
_memWriteHooks.Add(callback, userData)
|
let hh = (unativeint)(Marshal.ReadIntPtr((nativeint)hh))
|
||||||
|
_memWriteHooks.Add(callback, (hh, userData, memWriteHookInternal))
|
||||||
|
|
||||||
member this.HookDel(callback: MemWriteHook) =
|
member this.HookDel(callback: MemWriteHook) =
|
||||||
hookDel _memWriteHooks callback
|
hookDel _memWriteHooks callback
|
||||||
|
|
||||||
member this.AddEventMemHook(callback: EventMemHook, eventType: Int32, userData: Object) =
|
member this.AddEventMemHook(callback: EventMemHook, eventType: Int32, userData: Object, beginAddr: Int64, endAddr: Int64) =
|
||||||
let trampoline(u: IntPtr) (eventType: Int32) (addr: Int64) (size: Int32) (value: Int64) (user: IntPtr) =
|
let trampoline(u: IntPtr) (eventType: Int32) (addr: Int64) (size: Int32) (value: Int64) (user: IntPtr) =
|
||||||
_memEventHooks.Keys
|
callback.Invoke(this, eventType, addr, size, value, userData)
|
||||||
|> 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
|
// register the event if not already done
|
||||||
_memEventHooks.Keys
|
_memEventHooks.Keys
|
||||||
|> Seq.filter(fun eventFlag -> (eventType &&& eventFlag) <> 0)
|
|> Seq.filter(fun eventFlag -> (eventType &&& eventFlag) <> 0)
|
||||||
|> Seq.filter(fun eventFlag -> _memEventHooks.[eventFlag] |> Seq.isEmpty)
|
|
||||||
|> Seq.iter(fun eventFlag ->
|
|> Seq.iter(fun eventFlag ->
|
||||||
let memEventHookInternal = new EventMemHookInternal(trampoline)
|
let memEventHookInternal = new EventMemHookInternal(trampoline)
|
||||||
_hookInternals.Add(memEventHookInternal)
|
|
||||||
let funcPointer = Marshal.GetFunctionPointerForDelegate(memEventHookInternal)
|
let funcPointer = Marshal.GetFunctionPointerForDelegate(memEventHookInternal)
|
||||||
let hh = new UIntPtr(allocate(IntPtr.Size))
|
let hh = new UIntPtr(allocate(IntPtr.Size))
|
||||||
match binding.HookAddNoarg(_eng.[0], hh, eventFlag, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 1, uint64 0) |> this.CheckResult with
|
match binding.HookAddNoarg(_eng.[0], hh, eventFlag, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 beginAddr, uint64 endAddr) |> checkResult with
|
||||||
| Some e -> raise e | None -> ()
|
| Some e -> raise e | None -> ()
|
||||||
|
|
||||||
|
let hh = (unativeint)(Marshal.ReadIntPtr((nativeint)hh))
|
||||||
|
_memEventHooks.[eventFlag].Add((callback, (hh, userData, memEventHookInternal)))
|
||||||
)
|
)
|
||||||
|
|
||||||
// register the callbacks
|
member this.AddEventMemHook(callback: EventMemHook, eventType: Int32, userData: Object) =
|
||||||
_memEventHooks.Keys
|
this.AddEventMemHook(callback, eventType, userData, 1, 0)
|
||||||
|> Seq.filter(fun eventFlag -> (eventType &&& eventFlag) <> 0)
|
|
||||||
|> Seq.iter(fun eventFlag -> _memEventHooks.[eventFlag].Add((callback, userData)))
|
|
||||||
|
|
||||||
member this.AddEventMemHook(callback: EventMemHook, eventType: Int32) =
|
member this.AddEventMemHook(callback: EventMemHook, eventType: Int32) =
|
||||||
this.AddEventMemHook(callback, eventType, null)
|
this.AddEventMemHook(callback, eventType, null)
|
||||||
|
|
||||||
member this.HookDel(callback: EventMemHook) =
|
member this.HookDel(callback: EventMemHook) =
|
||||||
let callbacks = (_memEventHooks.Values |> Seq.concat).ToList()
|
_memEventHooks.Keys
|
||||||
hookDel callbacks callback
|
|> Seq.iter(fun eventFlag -> hookDel _memEventHooks.[eventFlag] callback)
|
||||||
|
|
||||||
|
member this.AddInHook(callback: InHook, userData: Object, beginAddr: Int64, endAddr: Int64) =
|
||||||
|
let trampoline(u: IntPtr) (port: Int32) (size: Int32) (user: IntPtr) =
|
||||||
|
callback.Invoke(this, port, size, userData)
|
||||||
|
|
||||||
|
let inHookInternal = new InHookInternal(trampoline)
|
||||||
|
let funcPointer = Marshal.GetFunctionPointerForDelegate(inHookInternal)
|
||||||
|
let hh = new UIntPtr(allocate(IntPtr.Size))
|
||||||
|
match binding.HookAddArg0(_eng.[0], hh, Common.UC_HOOK_INSN, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 beginAddr, uint64 endAddr, X86.UC_X86_INS_IN) |> checkResult with
|
||||||
|
| Some e -> raise e | None -> ()
|
||||||
|
|
||||||
|
let hh = (unativeint)(Marshal.ReadIntPtr((nativeint)hh))
|
||||||
|
_inHooks.Add(callback, (hh, userData, inHookInternal))
|
||||||
|
|
||||||
member this.AddInHook(callback: InHook, userData: Object) =
|
member this.AddInHook(callback: InHook, userData: Object) =
|
||||||
let trampoline(u: IntPtr) (port: Int32) (size: Int32) (user: IntPtr) =
|
this.AddInHook(callback, userData, 1, 0)
|
||||||
_inHooks
|
|
||||||
|> Seq.map(fun (callback, userData) -> callback.Invoke(this, port, size, userData))
|
|
||||||
|> Seq.last
|
|
||||||
|
|
||||||
if _inHooks |> Seq.isEmpty then
|
|
||||||
let inHookInternal = new InHookInternal(trampoline)
|
|
||||||
_hookInternals.Add(inHookInternal)
|
|
||||||
let funcPointer = Marshal.GetFunctionPointerForDelegate(inHookInternal)
|
|
||||||
let hh = new UIntPtr(allocate(IntPtr.Size))
|
|
||||||
match binding.HookAddArg0(_eng.[0], hh, Common.UC_HOOK_INSN, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 1, uint64 0, X86.UC_X86_INS_IN) |> this.CheckResult with
|
|
||||||
| Some e -> raise e | None -> ()
|
|
||||||
|
|
||||||
_inHooks.Add(callback, userData)
|
|
||||||
|
|
||||||
member this.AddInHook(callback: InHook) =
|
member this.AddInHook(callback: InHook) =
|
||||||
this.AddInHook(callback, null)
|
this.AddInHook(callback, null)
|
||||||
|
|
||||||
member this.AddOutHook(callback: OutHook, userData: Object) =
|
member this.HookDel(callback: InHook) =
|
||||||
|
hookDel _inHooks callback
|
||||||
|
|
||||||
|
member this.AddOutHook(callback: OutHook, userData: Object, beginAddr: Int64, endAddr: Int64) =
|
||||||
let trampoline(u: IntPtr) (port: Int32) (size: Int32) (value: Int32) (user: IntPtr) =
|
let trampoline(u: IntPtr) (port: Int32) (size: Int32) (value: Int32) (user: IntPtr) =
|
||||||
_outHooks
|
callback.Invoke(this, port, size, value, userData)
|
||||||
|> Seq.iter(fun (callback, userData) -> callback.Invoke(this, port, size, value, userData))
|
|
||||||
|
|
||||||
if _outHooks |> Seq.isEmpty then
|
let outHookInternal = new OutHookInternal(trampoline)
|
||||||
let outHookInternal = new OutHookInternal(trampoline)
|
let funcPointer = Marshal.GetFunctionPointerForDelegate(outHookInternal)
|
||||||
_hookInternals.Add(outHookInternal)
|
let hh = new UIntPtr(allocate(IntPtr.Size))
|
||||||
let funcPointer = Marshal.GetFunctionPointerForDelegate(outHookInternal)
|
match binding.HookAddArg0(_eng.[0], hh, Common.UC_HOOK_INSN, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 beginAddr, uint64 endAddr, X86.UC_X86_INS_OUT) |> checkResult with
|
||||||
let hh = new UIntPtr(allocate(IntPtr.Size))
|
| Some e -> raise e | None -> ()
|
||||||
match binding.HookAddArg0(_eng.[0], hh, Common.UC_HOOK_INSN, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 1, uint64 0, X86.UC_X86_INS_OUT) |> this.CheckResult with
|
|
||||||
| Some e -> raise e | None -> ()
|
|
||||||
|
|
||||||
_outHooks.Add(callback, userData)
|
let hh = (unativeint)(Marshal.ReadIntPtr((nativeint)hh))
|
||||||
|
_outHooks.Add(callback, (hh, userData, outHookInternal))
|
||||||
|
|
||||||
|
member this.AddOutHook(callback: OutHook, userData: Object) =
|
||||||
|
this.AddOutHook(callback, userData, 1, 0)
|
||||||
|
|
||||||
member this.AddOutHook(callback: OutHook) =
|
member this.AddOutHook(callback: OutHook) =
|
||||||
this.AddOutHook(callback, null)
|
this.AddOutHook(callback, null)
|
||||||
|
|
||||||
member this.AddSyscallHook(callback: SyscallHook, userData: Object) =
|
member this.HookDel(callback: OutHook) =
|
||||||
|
hookDel _outHooks callback
|
||||||
|
|
||||||
|
member this.AddSyscallHook(callback: SyscallHook, userData: Object, beginAddr: Int64, endAddr: Int64) =
|
||||||
let trampoline(u: IntPtr) (user: IntPtr) =
|
let trampoline(u: IntPtr) (user: IntPtr) =
|
||||||
_syscallHooks
|
callback.Invoke(this, userData)
|
||||||
|> Seq.iter(fun (callback, userData) -> callback.Invoke(this, userData))
|
|
||||||
|
|
||||||
if _syscallHooks |> Seq.isEmpty then
|
let syscallHookInternal = new SyscallHookInternal(trampoline)
|
||||||
let syscallHookInternal = new SyscallHookInternal(trampoline)
|
let funcPointer = Marshal.GetFunctionPointerForDelegate(syscallHookInternal)
|
||||||
_hookInternals.Add(syscallHookInternal)
|
let hh = new UIntPtr(allocate(IntPtr.Size))
|
||||||
let funcPointer = Marshal.GetFunctionPointerForDelegate(syscallHookInternal)
|
match binding.HookAddArg0(_eng.[0], hh, Common.UC_HOOK_INSN, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 beginAddr, uint64 endAddr, X86.UC_X86_INS_SYSCALL) |> checkResult with
|
||||||
let hh = new UIntPtr(allocate(IntPtr.Size))
|
| Some e -> raise e | None -> ()
|
||||||
match binding.HookAddArg0(_eng.[0], hh, Common.UC_HOOK_INSN, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 1, uint64 0, X86.UC_X86_INS_SYSCALL) |> this.CheckResult with
|
|
||||||
| Some e -> raise e | None -> ()
|
|
||||||
|
|
||||||
_syscallHooks.Add(callback, userData)
|
let hh = (unativeint)(Marshal.ReadIntPtr((nativeint)hh))
|
||||||
|
_syscallHooks.Add(callback, (hh, userData, syscallHookInternal))
|
||||||
|
|
||||||
|
member this.AddSyscallHook(callback: SyscallHook, userData: Object) =
|
||||||
|
this.AddSyscallHook(callback, userData, 1, 0)
|
||||||
|
|
||||||
member this.AddSyscallHook(callback: SyscallHook) =
|
member this.AddSyscallHook(callback: SyscallHook) =
|
||||||
this.AddSyscallHook(callback, null)
|
this.AddSyscallHook(callback, null)
|
||||||
|
|
||||||
|
member this.HookDel(callback: SyscallHook) =
|
||||||
|
hookDel _syscallHooks callback
|
||||||
|
|
||||||
member this.Version() =
|
member this.Version() =
|
||||||
let (major, minor) = (new UIntPtr(), new UIntPtr())
|
let (major, minor) = (new UIntPtr(), new UIntPtr())
|
||||||
let combined = binding.Version(major, minor)
|
let combined = binding.Version(major, minor)
|
||||||
|
|||||||
Reference in New Issue
Block a user