Merge pull request #1723 from TSRBerry/update-dotnet

bindings: Refactor and update .NET bindings
This commit is contained in:
2022-10-20 22:01:22 +02:00
committed by GitHub
13 changed files with 245 additions and 489 deletions

View File

@@ -7,15 +7,19 @@ from source.
1. Compile the code 1. Compile the code
[Windows] You need to have at least version 5.0 of .NET installed.
To compile the code open the UnicornSln.sln with Microsoft Visual
Studio 12 or with a newer version and just press Ctrl+Shift+B to build 1. Windows
the solution.
To compile the code open the UnicornSln.sln with Microsoft Visual
You need to have installed at least version 4.5 of the .NET framework. Studio 12 or with a newer version and just press Ctrl+Shift+B to build
the solution.
[Linux]
TODO 2. Linux
To compile the code open a terminal in this directory
and enter the following command to build the solution:
`dotnet build`
2. Usage 2. Usage

View File

@@ -1,41 +0,0 @@
namespace UnicornManaged.AssemblyInfo
open System.Reflection
open System.Runtime.CompilerServices
open System.Runtime.InteropServices
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[<assembly: AssemblyTitle("UnicornManaged")>]
[<assembly: AssemblyDescription("")>]
[<assembly: AssemblyConfiguration("")>]
[<assembly: AssemblyCompany("")>]
[<assembly: AssemblyProduct("UnicornManaged")>]
[<assembly: AssemblyCopyright("Copyright © Antonio Parata 2016")>]
[<assembly: AssemblyTrademark("")>]
[<assembly: AssemblyCulture("")>]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[<assembly: ComVisible(false)>]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[<assembly: Guid("0c21f1c1-2725-4a46-9022-1905f85822a5")>]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [<assembly: AssemblyVersion("1.0.*")>]
[<assembly: AssemblyVersion("1.0.0.0")>]
[<assembly: AssemblyFileVersion("1.0.0.0")>]
do
()

View File

@@ -1,13 +1,11 @@
namespace UnicornManaged.Binding namespace UnicornManaged.Binding
open System
module BindingFactory = module BindingFactory =
let mutable _instance = NativeBinding.instance let mutable _instance = NativeBinding.instance
let setDefaultBinding(binding: IBinding) = let setDefaultBinding(binding: IBinding) =
_instance <- binding _instance <- binding
let getDefault() = let getDefault() =
_instance _instance

View File

@@ -1,7 +1,6 @@
namespace UnicornManaged namespace UnicornManaged
open System open System
open System.Threading
open System.Collections.Generic open System.Collections.Generic
open System.Runtime.InteropServices open System.Runtime.InteropServices
open System.Linq open System.Linq
@@ -20,7 +19,7 @@ and OutHook = delegate of Unicorn * Int32 * Int32 * Int32 * Object -> unit
and SyscallHook = delegate of Unicorn * Object -> unit and SyscallHook = delegate of Unicorn * Object -> unit
// the managed unicorn engine // the managed unicorn engine
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 * Object)>()
@@ -43,24 +42,24 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) =
(UC_HOOK_MEM_WRITE_PROT, UC_MEM_WRITE_PROT) (UC_HOOK_MEM_WRITE_PROT, UC_MEM_WRITE_PROT)
(UC_HOOK_MEM_FETCH_PROT, UC_MEM_FETCH_PROT) (UC_HOOK_MEM_FETCH_PROT, UC_MEM_FETCH_PROT)
] |> dict ] |> dict
let mutable _eng = [|UIntPtr.Zero|] let mutable _eng = [|UIntPtr.Zero|]
let checkResult(errCode: Int32, errMsg: String) = let checkResult(errCode: Int32, errMsg: String) =
if errCode <> Common.UC_ERR_OK then raise(ApplicationException(String.Format("{0}. Error: {1}", errMsg, errCode))) if errCode <> Common.UC_ERR_OK then raise(ApplicationException(String.Format("{0}. Error: {1}", errMsg, errCode)))
let hookDel(callbacks: List<'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 // TODO: invoke the native function in order to not call the trampoline anymore
callbacks callbacks
|> Seq.tryFind(fun item -> match item with | (c, _) -> c = callback) |> Seq.tryFind(fun item -> match item with | (c, _) -> c = callback)
|> (fun k -> if k.IsSome then callbacks.Remove(k.Value) |> ignore) |> (fun k -> if k.IsSome then callbacks.Remove(k.Value) |> ignore)
let allocate(size: Int32) = let allocate(size: Int32) =
let mem = Marshal.AllocHGlobal(size) let mem = Marshal.AllocHGlobal(size)
_disposablePointers.Add(mem) _disposablePointers.Add(mem)
mem.ToPointer() mem.ToPointer()
do do
// initialize event list // initialize event list
_eventMemMap _eventMemMap
|> Seq.map(fun kv -> kv.Key) |> Seq.map(fun kv -> kv.Key)
@@ -72,7 +71,7 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) =
checkResult(err, "Unable to open the Unicorn Engine") checkResult(err, "Unable to open the Unicorn Engine")
new(arch, mode) = new Unicorn(arch, mode, BindingFactory.getDefault()) new(arch, mode) = new Unicorn(arch, mode, BindingFactory.getDefault())
member private this.CheckResult(errorCode: Int32) = member private this.CheckResult(errorCode: Int32) =
// return the exception instead of raising it in order to have a more meaningful stack trace // return the exception instead of raising it in order to have a more meaningful stack trace
if errorCode <> Common.UC_ERR_OK then if errorCode <> Common.UC_ERR_OK then
@@ -82,43 +81,43 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) =
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) |> this.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) |> this.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) |> this.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) |> this.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)) |> this.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)) |> this.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) |> this.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) |> this.CheckResult with
| Some e -> raise e | None -> () | Some e -> raise e | None -> ()
member this.RegRead(regId: Int32) = member this.RegRead(regId: Int32) =
@@ -127,15 +126,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) |> this.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]) |> this.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]) |> this.CheckResult with
| Some e -> raise e | None -> () | Some e -> raise e | None -> ()
member this.ArchSupported(arch: Int32) = member this.ArchSupported(arch: Int32) =
@@ -148,15 +147,15 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) =
let errorStringPointer = binding.Strerror(errorNo) let errorStringPointer = binding.Strerror(errorNo)
Marshal.PtrToStringAnsi(errorStringPointer) 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 _codeHooks
|> Seq.iter(fun (callback, userData) -> callback.Invoke(this, addr, size, userData)) |> Seq.iter(fun (callback, userData) -> callback.Invoke(this, addr, size, userData))
if _codeHooks |> Seq.isEmpty then if _codeHooks |> Seq.isEmpty then
let funcPointer = Marshal.GetFunctionPointerForDelegate(new CodeHookInternal(trampoline)) let funcPointer = Marshal.GetFunctionPointerForDelegate(new CodeHookInternal(trampoline))
let hh = new UIntPtr(allocate(IntPtr.Size)) let hh = new UIntPtr(allocate(IntPtr.Size))
match binding.HookAddNoarg(_eng.[0], hh, Common.UC_HOOK_CODE, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 beginAddr, uint64 endAddr) |> this.CheckResult with 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 -> () | Some e -> raise e | None -> ()
_codeHooks.Add(callback, userData) _codeHooks.Add(callback, userData)
@@ -167,7 +166,7 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) =
member this.HookDel(callback: CodeHook) = member this.HookDel(callback: CodeHook) =
hookDel _codeHooks callback hookDel _codeHooks callback
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 _blockHooks
|> Seq.iter(fun (callback, userData) -> callback.Invoke(this, addr, size, userData)) |> Seq.iter(fun (callback, userData) -> callback.Invoke(this, addr, size, userData))
@@ -175,7 +174,7 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) =
if _blockHooks |> Seq.isEmpty then if _blockHooks |> Seq.isEmpty then
let funcPointer = Marshal.GetFunctionPointerForDelegate(new BlockHookInternal(trampoline)) let funcPointer = Marshal.GetFunctionPointerForDelegate(new BlockHookInternal(trampoline))
let hh = new UIntPtr(allocate(IntPtr.Size)) let hh = new UIntPtr(allocate(IntPtr.Size))
match binding.HookAddNoarg(_eng.[0], hh, Common.UC_HOOK_BLOCK, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 beginAddr, uint64 endAddr) |> this.CheckResult with 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 -> () | Some e -> raise e | None -> ()
_blockHooks.Add(callback, userData) _blockHooks.Add(callback, userData)
@@ -183,15 +182,15 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) =
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 _interruptHooks
|> Seq.iter(fun (callback, userData) -> callback.Invoke(this, intNumber, userData)) |> Seq.iter(fun (callback, userData) -> callback.Invoke(this, intNumber, userData))
if _interruptHooks |> Seq.isEmpty then if _interruptHooks |> Seq.isEmpty then
let funcPointer = Marshal.GetFunctionPointerForDelegate(new InterruptHookInternal(trampoline)) let funcPointer = Marshal.GetFunctionPointerForDelegate(new InterruptHookInternal(trampoline))
let hh = new UIntPtr(allocate(IntPtr.Size)) let hh = new UIntPtr(allocate(IntPtr.Size))
match binding.HookAddNoarg(_eng.[0], hh, Common.UC_HOOK_INTR, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, hookBegin, hookEnd) |> this.CheckResult with 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 -> () | Some e -> raise e | None -> ()
_interruptHooks.Add(callback, userData) _interruptHooks.Add(callback, userData)
@@ -202,7 +201,7 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) =
member this.HookDel(callback: InterruptHook) = member this.HookDel(callback: InterruptHook) =
hookDel _interruptHooks callback hookDel _interruptHooks callback
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) (addr: Int64) (size: Int32) (user: IntPtr) = let trampoline(u: IntPtr) (addr: Int64) (size: Int32) (user: IntPtr) =
_memReadHooks _memReadHooks
|> Seq.iter(fun (callback, userData) -> callback.Invoke(this, addr, size, userData)) |> Seq.iter(fun (callback, userData) -> callback.Invoke(this, addr, size, userData))
@@ -210,7 +209,7 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) =
if _memReadHooks |> Seq.isEmpty then if _memReadHooks |> Seq.isEmpty then
let funcPointer = Marshal.GetFunctionPointerForDelegate(new MemReadHookInternal(trampoline)) let funcPointer = Marshal.GetFunctionPointerForDelegate(new MemReadHookInternal(trampoline))
let hh = new UIntPtr(allocate(IntPtr.Size)) let hh = new UIntPtr(allocate(IntPtr.Size))
match binding.HookAddNoarg(_eng.[0], hh, Common.UC_HOOK_MEM_READ, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 beginAddr, uint64 endAddr) |> this.CheckResult with 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 -> () | Some e -> raise e | None -> ()
_memReadHooks.Add(callback, userData) _memReadHooks.Add(callback, userData)
@@ -218,15 +217,15 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) =
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) (addr: Int64) (size: Int32) (value: Int64) (user: IntPtr) = let trampoline(u: IntPtr) (addr: Int64) (size: Int32) (value: Int64) (user: IntPtr) =
_memWriteHooks _memWriteHooks
|> Seq.iter(fun (callback, userData) -> callback.Invoke(this, addr, size, value, userData)) |> Seq.iter(fun (callback, userData) -> callback.Invoke(this, addr, size, value, userData))
if _memWriteHooks |> Seq.isEmpty then if _memWriteHooks |> Seq.isEmpty then
let funcPointer = Marshal.GetFunctionPointerForDelegate(new MemWriteHookInternal(trampoline)) let funcPointer = Marshal.GetFunctionPointerForDelegate(new MemWriteHookInternal(trampoline))
let hh = new UIntPtr(allocate(IntPtr.Size)) let hh = new UIntPtr(allocate(IntPtr.Size))
match binding.HookAddNoarg(_eng.[0], hh, Common.UC_HOOK_MEM_WRITE, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 beginAddr, uint64 endAddr) |> this.CheckResult with 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 -> () | Some e -> raise e | None -> ()
_memWriteHooks.Add(callback, userData) _memWriteHooks.Add(callback, userData)
@@ -235,7 +234,7 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) =
hookDel _memWriteHooks callback hookDel _memWriteHooks callback
member this.AddEventMemHook(callback: EventMemHook, eventType: Int32, userData: Object) = member this.AddEventMemHook(callback: EventMemHook, eventType: Int32, userData: Object) =
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 _memEventHooks.Keys
|> Seq.filter(fun eventFlag -> (eventType &&& eventFlag) <> 0) |> Seq.filter(fun eventFlag -> (eventType &&& eventFlag) <> 0)
|> Seq.map(fun eventflag -> _memEventHooks.[eventflag]) |> Seq.map(fun eventflag -> _memEventHooks.[eventflag])
@@ -249,12 +248,12 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) =
|> Seq.filter(fun eventFlag -> _memEventHooks.[eventFlag] |> Seq.isEmpty) |> Seq.filter(fun eventFlag -> _memEventHooks.[eventFlag] |> Seq.isEmpty)
|> Seq.iter(fun eventFlag -> |> Seq.iter(fun eventFlag ->
let funcPointer = Marshal.GetFunctionPointerForDelegate(new EventMemHookInternal(trampoline)) let funcPointer = Marshal.GetFunctionPointerForDelegate(new EventMemHookInternal(trampoline))
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 0, uint64 0) |> this.CheckResult with match binding.HookAddNoarg(_eng.[0], hh, eventFlag, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 0, uint64 0) |> this.CheckResult with
| Some e -> raise e | None -> () | Some e -> raise e | None -> ()
) )
// register the callbacks // register the callbacks
_memEventHooks.Keys _memEventHooks.Keys
|> Seq.filter(fun eventFlag -> (eventType &&& eventFlag) <> 0) |> Seq.filter(fun eventFlag -> (eventType &&& eventFlag) <> 0)
|> Seq.iter(fun eventFlag -> _memEventHooks.[eventFlag].Add((callback, userData))) |> Seq.iter(fun eventFlag -> _memEventHooks.[eventFlag].Add((callback, userData)))
@@ -271,11 +270,11 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) =
_inHooks _inHooks
|> Seq.map(fun (callback, userData) -> callback.Invoke(this, port, size, userData)) |> Seq.map(fun (callback, userData) -> callback.Invoke(this, port, size, userData))
|> Seq.last |> Seq.last
if _inHooks |> Seq.isEmpty then if _inHooks |> Seq.isEmpty then
let funcPointer = Marshal.GetFunctionPointerForDelegate(new InHookInternal(trampoline)) let funcPointer = Marshal.GetFunctionPointerForDelegate(new InHookInternal(trampoline))
let hh = new UIntPtr(allocate(IntPtr.Size)) let hh = new UIntPtr(allocate(IntPtr.Size))
match binding.HookAddArg0(_eng.[0], hh, Common.UC_HOOK_INSN, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 0, uint64 0, X86.UC_X86_INS_IN) |> this.CheckResult with match binding.HookAddArg0(_eng.[0], hh, Common.UC_HOOK_INSN, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 0, uint64 0, X86.UC_X86_INS_IN) |> this.CheckResult with
| Some e -> raise e | None -> () | Some e -> raise e | None -> ()
_inHooks.Add(callback, userData) _inHooks.Add(callback, userData)
@@ -287,11 +286,11 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) =
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 _outHooks
|> Seq.iter(fun (callback, userData) -> callback.Invoke(this, port, size, value, userData)) |> Seq.iter(fun (callback, userData) -> callback.Invoke(this, port, size, value, userData))
if _outHooks |> Seq.isEmpty then if _outHooks |> Seq.isEmpty then
let funcPointer = Marshal.GetFunctionPointerForDelegate(new OutHookInternal(trampoline)) let funcPointer = Marshal.GetFunctionPointerForDelegate(new OutHookInternal(trampoline))
let hh = new UIntPtr(allocate(IntPtr.Size)) let hh = new UIntPtr(allocate(IntPtr.Size))
match binding.HookAddArg0(_eng.[0], hh, Common.UC_HOOK_INSN, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 0, uint64 0, X86.UC_X86_INS_OUT) |> this.CheckResult with match binding.HookAddArg0(_eng.[0], hh, Common.UC_HOOK_INSN, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 0, uint64 0, X86.UC_X86_INS_OUT) |> this.CheckResult with
| Some e -> raise e | None -> () | Some e -> raise e | None -> ()
_outHooks.Add(callback, userData) _outHooks.Add(callback, userData)
@@ -303,18 +302,18 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) =
let trampoline(u: IntPtr) (user: IntPtr) = let trampoline(u: IntPtr) (user: IntPtr) =
_syscallHooks _syscallHooks
|> Seq.iter(fun (callback, userData) -> callback.Invoke(this, userData)) |> Seq.iter(fun (callback, userData) -> callback.Invoke(this, userData))
if _syscallHooks |> Seq.isEmpty then if _syscallHooks |> Seq.isEmpty then
let funcPointer = Marshal.GetFunctionPointerForDelegate(new SyscallHookInternal(trampoline)) let funcPointer = Marshal.GetFunctionPointerForDelegate(new SyscallHookInternal(trampoline))
let hh = new UIntPtr(allocate(IntPtr.Size)) let hh = new UIntPtr(allocate(IntPtr.Size))
match binding.HookAddArg0(_eng.[0], hh, Common.UC_HOOK_INSN, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 0, uint64 0, X86.UC_X86_INS_SYSCALL) |> this.CheckResult with match binding.HookAddArg0(_eng.[0], hh, Common.UC_HOOK_INSN, new UIntPtr(funcPointer.ToPointer()), IntPtr.Zero, uint64 0, uint64 0, X86.UC_X86_INS_SYSCALL) |> this.CheckResult with
| Some e -> raise e | None -> () | Some e -> raise e | None -> ()
_syscallHooks.Add(callback, userData) _syscallHooks.Add(callback, userData)
member this.AddSyscallHook(callback: SyscallHook) = member this.AddSyscallHook(callback: SyscallHook) =
this.AddSyscallHook(callback, null) this.AddSyscallHook(callback, null)
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)
@@ -340,4 +339,4 @@ and Unicorn(arch: Int32, mode: Int32, binding: IBinding) =
interface IDisposable with interface IDisposable with
member this.Dispose() = member this.Dispose() =
this.Dispose() this.Dispose()

View File

@@ -1,56 +1,31 @@
<?xml version="1.0" encoding="utf-8"?> <Project Sdk="Microsoft.NET.Sdk">
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <TargetFramework>net6.0</TargetFramework>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>0c21f1c1-2725-4a46-9022-1905f85822a5</ProjectGuid>
<OutputType>Library</OutputType>
<RootNamespace>UnicornManaged</RootNamespace> <RootNamespace>UnicornManaged</RootNamespace>
<AssemblyName>UnicornManaged</AssemblyName> <AssemblyName>UnicornManaged</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion> <Copyright>Copyright © Antonio Parata 2016</Copyright>
<TargetFSharpCoreVersion>4.3.1.0</TargetFSharpCoreVersion> <RepositoryUrl>https://github.com/unicorn-engine/unicorn</RepositoryUrl>
<Version>2.0.0</Version>
<ProjectGuid>0c21f1c1-2725-4a46-9022-1905f85822a5</ProjectGuid>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Name>UnicornManaged</Name> <GenerateDocumentationFile>true</GenerateDocumentationFile>
<TargetFrameworkProfile />
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols> <PropertyGroup>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<Tailcalls>false</Tailcalls>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<WarningLevel>3</WarningLevel> <WarningLevel>3</WarningLevel>
<DocumentationFile>bin\Debug\UnicornManaged.XML</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<Tailcalls>true</Tailcalls>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<WarningLevel>3</WarningLevel>
<DocumentationFile>bin\Release\UnicornManaged.XML</DocumentationFile>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="mscorlib" />
<Reference Include="FSharp.Core, Version=$(TargetFSharpCoreVersion), Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Numerics" />
</ItemGroup>
<ItemGroup>
<Compile Include="AssemblyInfo.fs" />
<Compile Include="Const\Arm.fs" /> <Compile Include="Const\Arm.fs" />
<Compile Include="Const\Arm64.fs" /> <Compile Include="Const\Arm64.fs" />
<Compile Include="Const\Common.fs" /> <Compile Include="Const\Common.fs" />
<Compile Include="Const\M68k.fs" /> <Compile Include="Const\M68k.fs" />
<Compile Include="Const\Mips.fs" /> <Compile Include="Const\Mips.fs" />
<Compile Include="Const\Ppc.fs" />
<Compile Include="Const\Riscv.fs" />
<Compile Include="Const\S390x.fs" />
<Compile Include="Const\Sparc.fs" /> <Compile Include="Const\Sparc.fs" />
<Compile Include="Const\TriCore.fs" />
<Compile Include="Const\X86.fs" /> <Compile Include="Const\X86.fs" />
<Compile Include="Binding\IBinding.fs" /> <Compile Include="Binding\IBinding.fs" />
<Compile Include="Binding\MockBinding.fs" /> <Compile Include="Binding\MockBinding.fs" />
@@ -61,27 +36,4 @@
<Compile Include="ConvertUtility.fs" /> <Compile Include="ConvertUtility.fs" />
<Compile Include="Unicorn.fs" /> <Compile Include="Unicorn.fs" />
</ItemGroup> </ItemGroup>
<PropertyGroup> </Project>
<MinimumVisualStudioVersion Condition="'$(MinimumVisualStudioVersion)' == ''">11</MinimumVisualStudioVersion>
</PropertyGroup>
<Choose>
<When Condition="'$(VisualStudioVersion)' == '11.0'">
<PropertyGroup Condition="Exists('$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets')">
<FSharpTargetsPath>$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets</FSharpTargetsPath>
</PropertyGroup>
</When>
<Otherwise>
<PropertyGroup Condition="Exists('$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets')">
<FSharpTargetsPath>$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets</FSharpTargetsPath>
</PropertyGroup>
</Otherwise>
</Choose>
<Import Project="$(FSharpTargetsPath)" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/>
</startup>
</configuration>

View File

@@ -2,9 +2,9 @@
namespace UnicornSamples namespace UnicornSamples
{ {
class Program internal static class Program
{ {
static void Main(string[] args) private static void Main(string[] args)
{ {
// X86 tests 32bit // X86 tests 32bit
X86Sample32.X86Code32(); X86Sample32.X86Code32();

View File

@@ -1,36 +0,0 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("UnicornSamples")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("UnicornSamples")]
[assembly: AssemblyCopyright("Copyright © Antonio Parata 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("b80b5987-1e24-4309-8bf9-c4f91270f21c")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -1,24 +1,20 @@
using Gee.External.Capstone; using Gee.External.Capstone;
using Gee.External.Capstone.X86; using Gee.External.Capstone.X86;
using System; using System;
using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Text; using System.Text;
using System.Threading.Tasks;
using UnicornManaged; using UnicornManaged;
using UnicornManaged.Const; using UnicornManaged.Const;
namespace UnicornSamples namespace UnicornSamples
{ {
internal class ShellcodeSample internal static class ShellcodeSample
{ {
private const Int64 ADDRESS = 0x1000000; private const long ADDRESS = 0x1000000;
public static void X86Code32Self() public static void X86Code32Self()
{ {
Byte[] X86_CODE32_SELF = byte[] X86_CODE32_SELF =
{ {
0xeb, 0x1c, 0x5a, 0x89, 0xd6, 0x8b, 0x02, 0x66, 0x3d, 0xca, 0x7d, 0x75, 0x06, 0x66, 0x05, 0x03, 0x03, 0xeb, 0x1c, 0x5a, 0x89, 0xd6, 0x8b, 0x02, 0x66, 0x3d, 0xca, 0x7d, 0x75, 0x06, 0x66, 0x05, 0x03, 0x03,
0x89, 0x02, 0xfe, 0xc2, 0x3d, 0x41, 0x41, 0x41, 0x41, 0x75, 0xe9, 0xff, 0xe6, 0xe8, 0xdf, 0xff, 0xff, 0x89, 0x02, 0xfe, 0xc2, 0x3d, 0x41, 0x41, 0x41, 0x41, 0x75, 0xe9, 0xff, 0xe6, 0xe8, 0xdf, 0xff, 0xff,
@@ -31,7 +27,7 @@ namespace UnicornSamples
public static void X86Code32() public static void X86Code32()
{ {
Byte[] X86_CODE32 = byte[] X86_CODE32 =
{ {
0xeb, 0x19, 0x31, 0xc0, 0x31, 0xdb, 0x31, 0xd2, 0x31, 0xc9, 0xb0, 0x04, 0xb3, 0x01, 0x59, 0xb2, 0x05, 0xeb, 0x19, 0x31, 0xc0, 0x31, 0xdb, 0x31, 0xd2, 0x31, 0xc9, 0xb0, 0x04, 0xb3, 0x01, 0x59, 0xb2, 0x05,
0xcd, 0x80, 0x31, 0xc0, 0xb0, 0x01, 0x31, 0xdb, 0xcd, 0x80, 0xe8, 0xe2, 0xff, 0xff, 0xff, 0x68, 0x65, 0xcd, 0x80, 0x31, 0xc0, 0xb0, 0x01, 0x31, 0xdb, 0xcd, 0x80, 0xe8, 0xe2, 0xff, 0xff, 0xff, 0x68, 0x65,
@@ -41,39 +37,39 @@ namespace UnicornSamples
Run(X86_CODE32); Run(X86_CODE32);
} }
private static void Run(Byte[] code) private static void Run(byte[] code)
{ {
Console.WriteLine(); Console.WriteLine();
var stackTrace = new StackTrace(); var stackTrace = new StackTrace();
var stackFrame = stackTrace.GetFrames()[1]; var stackFrame = stackTrace.GetFrames()[1];
var methodName = stackFrame.GetMethod().Name; var methodName = stackFrame.GetMethod().Name;
Console.WriteLine("*** Start: " + methodName); Console.WriteLine($"*** Start: {methodName}");
RunTest(code, ADDRESS); RunTest(code, ADDRESS);
Console.WriteLine("*** End: " + methodName); Console.WriteLine($"*** End: {methodName}");
Console.WriteLine(); Console.WriteLine();
} }
private static void RunTest(Byte[] code, Int64 address) private static void RunTest(byte[] code, long address)
{ {
try try
{ {
using (var u = new Unicorn(Common.UC_ARCH_X86, Common.UC_MODE_32)) using (var u = new Unicorn(Common.UC_ARCH_X86, Common.UC_MODE_32))
using(var disassembler = CapstoneDisassembler.CreateX86Disassembler(DisassembleMode.Bit32)) using(var disassembler = CapstoneDisassembler.CreateX86Disassembler(X86DisassembleMode.Bit32))
{ {
Console.WriteLine("Unicorn version: {0}", u.Version()); Console.WriteLine($"Unicorn version: {u.Version()}");
// map 2MB of memory for this emulation // map 2MB of memory for this emulation
u.MemMap(address, 2 * 1024 * 1024, Common.UC_PROT_ALL); u.MemMap(address, 2 * 1024 * 1024, Common.UC_PROT_ALL);
// write machine code to be emulated to memory // write machine code to be emulated to memory
u.MemWrite(address, code); u.MemWrite(address, code);
// initialize machine registers // initialize machine registers
u.RegWrite(X86.UC_X86_REG_ESP, Utils.Int64ToBytes(address + 0x200000)); u.RegWrite(X86.UC_X86_REG_ESP, Utils.Int64ToBytes(address + 0x200000));
var regv = new Byte[4]; var regv = new byte[4];
u.RegRead(X86.UC_X86_REG_ESP, regv); u.RegRead(X86.UC_X86_REG_ESP, regv);
// tracing all instructions by having @begin > @end // tracing all instructions by having @begin > @end
@@ -84,7 +80,7 @@ namespace UnicornSamples
// handle SYSCALL // handle SYSCALL
u.AddSyscallHook(SyscallHookCallback); u.AddSyscallHook(SyscallHookCallback);
Console.WriteLine(">>> Start tracing code"); Console.WriteLine(">>> Start tracing code");
// emulate machine code in infinite time // emulate machine code in infinite time
@@ -98,44 +94,44 @@ namespace UnicornSamples
Console.Error.WriteLine("Emulation FAILED! " + ex.Message); Console.Error.WriteLine("Emulation FAILED! " + ex.Message);
} }
} }
private static void CodeHookCallback(
CapstoneDisassembler<X86Instruction, X86Register, X86InstructionGroup,X86InstructionDetail> disassembler,
Unicorn u,
Int64 addr,
Int32 size,
Object userData)
{
Console.Write("[+] 0x{0}: ", addr.ToString("X"));
var eipBuffer = new Byte[4]; private static void CodeHookCallback(
CapstoneX86Disassembler disassembler,
Unicorn u,
long addr,
int size,
object userData)
{
Console.Write($"[+] 0x{addr:X}: ");
var eipBuffer = new byte[4];
u.RegRead(X86.UC_X86_REG_EIP, eipBuffer); u.RegRead(X86.UC_X86_REG_EIP, eipBuffer);
var effectiveSize = Math.Min(16, size); var effectiveSize = Math.Min(16, size);
var tmp = new Byte[effectiveSize]; var tmp = new byte[effectiveSize];
u.MemRead(addr, tmp); u.MemRead(addr, tmp);
var sb = new StringBuilder(); var sb = new StringBuilder();
foreach (var t in tmp) foreach (var t in tmp)
{ {
sb.AppendFormat("{0} ", (0xFF & t).ToString("X")); sb.AppendFormat($"{(0xFF & t):X} ");
} }
Console.Write("{0,-20}", sb); Console.Write($"{sb,-20}");
Console.WriteLine(Utils.Disassemble(disassembler, tmp)); Console.WriteLine(Utils.Disassemble(disassembler, tmp));
} }
private static void SyscallHookCallback(Unicorn u, Object userData) private static void SyscallHookCallback(Unicorn u, object userData)
{ {
var eaxBuffer = new Byte[4]; var eaxBuffer = new byte[4];
u.RegRead(X86.UC_X86_REG_EAX, eaxBuffer); u.RegRead(X86.UC_X86_REG_EAX, eaxBuffer);
var eax = Utils.ToInt(eaxBuffer); var eax = Utils.ToInt(eaxBuffer);
Console.WriteLine("[!] Syscall EAX = 0x{0}", eax.ToString("X")); Console.WriteLine($"[!] Syscall EAX = 0x{eax:X}");
u.EmuStop(); u.EmuStop();
} }
private static void InterruptHookCallback(Unicorn u, Int32 intNumber, Object userData) private static void InterruptHookCallback(Unicorn u, int intNumber, object userData)
{ {
// only handle Linux syscall // only handle Linux syscall
if (intNumber != 0x80) if (intNumber != 0x80)
@@ -143,8 +139,8 @@ namespace UnicornSamples
return; return;
} }
var eaxBuffer = new Byte[4]; var eaxBuffer = new byte[4];
var eipBuffer = new Byte[4]; var eipBuffer = new byte[4];
u.RegRead(X86.UC_X86_REG_EAX, eaxBuffer); u.RegRead(X86.UC_X86_REG_EAX, eaxBuffer);
u.RegRead(X86.UC_X86_REG_EIP, eipBuffer); u.RegRead(X86.UC_X86_REG_EIP, eipBuffer);
@@ -155,19 +151,19 @@ namespace UnicornSamples
switch (eax) switch (eax)
{ {
default: default:
Console.WriteLine("[!] Interrupt 0x{0} num {1}, EAX=0x{2}", eip.ToString("X"), intNumber.ToString("X"), eax.ToString("X")); Console.WriteLine($"[!] Interrupt 0x{eip:X} num {intNumber:X}, EAX=0x{eax:X}");
break; break;
case 1: // sys_exit case 1: // sys_exit
Console.WriteLine("[!] Interrupt 0x{0} num {1}, SYS_EXIT", eip.ToString("X"), intNumber.ToString("X")); Console.WriteLine($"[!] Interrupt 0x{eip:X} num {intNumber:X}, SYS_EXIT");
u.EmuStop(); u.EmuStop();
break; break;
case 4: // sys_write case 4: // sys_write
// ECX = buffer address // ECX = buffer address
var ecxBuffer = new Byte[4]; var ecxBuffer = new byte[4];
// EDX = buffer size // EDX = buffer size
var edxBuffer = new Byte[4]; var edxBuffer = new byte[4];
u.RegRead(X86.UC_X86_REG_ECX, ecxBuffer); u.RegRead(X86.UC_X86_REG_ECX, ecxBuffer);
u.RegRead(X86.UC_X86_REG_EDX, edxBuffer); u.RegRead(X86.UC_X86_REG_EDX, edxBuffer);
@@ -177,16 +173,11 @@ namespace UnicornSamples
// read the buffer in // read the buffer in
var size = Math.Min(256, edx); var size = Math.Min(256, edx);
var buffer = new Byte[size]; var buffer = new byte[size];
u.MemRead(ecx, buffer); u.MemRead(ecx, buffer);
var content = Encoding.Default.GetString(buffer); var content = Encoding.Default.GetString(buffer);
Console.WriteLine( Console.WriteLine($"[!] Interrupt 0x{eip:X}: num {ecx:X}, SYS_WRITE. buffer = 0x{edx:X}, size = {size:X}, content = '{content}'");
"[!] Interrupt 0x{0}: num {1}, SYS_WRITE. buffer = 0x{2}, size = , content = '{3}'",
eip.ToString("X"),
ecx.ToString("X"),
edx.ToString("X"),
content);
break; break;
} }

View File

@@ -1,108 +1,29 @@
<?xml version="1.0" encoding="utf-8"?> <Project Sdk="Microsoft.NET.Sdk">
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <TargetFramework>net6.0</TargetFramework>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{B80B5987-1E24-4309-8BF9-C4F91270F21C}</ProjectGuid>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>UnicornSamples</RootNamespace> <RootNamespace>UnicornSamples</RootNamespace>
<AssemblyName>UnicornSamples</AssemblyName> <AssemblyName>UnicornSamples</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion> <Copyright>Copyright © Antonio Parata 2016</Copyright>
<FileAlignment>512</FileAlignment> <RepositoryUrl>https://github.com/unicorn-engine/unicorn</RepositoryUrl>
<Version>2.0.0</Version>
<ProjectGuid>{B80B5987-1E24-4309-8BF9-C4F91270F21C}</ProjectGuid>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<TargetFrameworkProfile />
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>x86</PlatformTarget> <PropertyGroup>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<UseVSHostingProcess>false</UseVSHostingProcess>
<CodeAnalysisIgnoreGeneratedCode>false</CodeAnalysisIgnoreGeneratedCode>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<Reference Include="Gee.External.Capstone, Version=1.2.2.0, Culture=neutral, processorArchitecture=x86">
<HintPath>..\packages\Gee.External.Capstone.1.2.2\lib\net45\Gee.External.Capstone.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ShellcodeSample.cs" />
<Compile Include="Utils.cs" />
<Compile Include="X86Sample32.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.5">
<Visible>False</Visible>
<ProductName>Microsoft .NET Framework 4.5 %28x86 and x64%29</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>false</Install>
</BootstrapperPackage>
</ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\UnicornManaged\UnicornManaged.fsproj"> <ProjectReference Include="..\UnicornManaged\UnicornManaged.fsproj">
<Project>{0c21f1c1-2725-4a46-9022-1905f85822a5}</Project> <Project>{0c21f1c1-2725-4a46-9022-1905f85822a5}</Project>
<Name>UnicornManaged</Name> <Name>UnicornManaged</Name>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Content Include="capstone.dll" /> <PackageReference Include="Gee.External.Capstone" Version="2.2.0" />
<Content Include="Gee.External.Capstone.Proxy.dll" />
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> </Project>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -1,45 +1,41 @@
using Gee.External.Capstone; using Gee.External.Capstone.X86;
using Gee.External.Capstone.X86;
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks;
namespace UnicornSamples namespace UnicornSamples
{ {
internal static class Utils internal static class Utils
{ {
public static Int64 ToInt(Byte[] val) public static long ToInt(byte[] val)
{ {
UInt64 res = 0; ulong res = 0;
for (var i = 0; i < val.Length; i++) for (var i = 0; i < val.Length; i++)
{ {
var v = val[i] & 0xFF; var v = val[i] & 0xFF;
res += (UInt64)(v << (i * 8)); res += (ulong)(v << (i * 8));
} }
return (Int64)res; return (long)res;
} }
public static Byte[] Int64ToBytes(Int64 intVal) public static byte[] Int64ToBytes(long intVal)
{ {
var res = new Byte[8]; var res = new byte[8];
var uval = (UInt64)intVal; var uval = (ulong)intVal;
for (var i = 0; i < res.Length; i++) for (var i = 0; i < res.Length; i++)
{ {
res[i] = (Byte)(uval & 0xff); res[i] = (byte)(uval & 0xff);
uval = uval >> 8; uval = uval >> 8;
} }
return res; return res;
} }
public static String Disassemble(CapstoneDisassembler<X86Instruction, X86Register, X86InstructionGroup, X86InstructionDetail> disassembler, Byte[] code) public static string Disassemble(CapstoneX86Disassembler disassembler, byte[] code)
{ {
var sb = new StringBuilder(); var sb = new StringBuilder();
var instructions = disassembler.DisassembleAll(code); var instructions = disassembler.Disassemble(code);
foreach (var instruction in instructions) foreach (var instruction in instructions)
{ {
sb.AppendFormat("{0} {1}{2}", instruction.Mnemonic, instruction.Operand, Environment.NewLine); sb.AppendFormat($"{instruction.Mnemonic} {instruction.Operand}{Environment.NewLine}");
} }
return sb.ToString().Trim(); return sb.ToString().Trim();
} }

View File

@@ -1,34 +1,30 @@
using Gee.External.Capstone; using Gee.External.Capstone;
using Gee.External.Capstone.X86; using Gee.External.Capstone.X86;
using System; using System;
using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Text; using System.Text;
using System.Threading.Tasks;
using UnicornManaged; using UnicornManaged;
using UnicornManaged.Const; using UnicornManaged.Const;
namespace UnicornSamples namespace UnicornSamples
{ {
internal class X86Sample32 internal static class X86Sample32
{ {
private const Int64 ADDRESS = 0x1000000; private const long ADDRESS = 0x1000000;
public static void X86Code32() public static void X86Code32()
{ {
Byte[] X86_CODE32 = byte[] X86_CODE32 =
{ {
// INC ecx; DEC edx // INC ecx; DEC edx
0x41, 0x4a 0x41, 0x4a
}; };
Run(X86_CODE32); Run(X86_CODE32);
} }
public static void X86Code32InvalidMemRead() public static void X86Code32InvalidMemRead()
{ {
Byte[] X86_CODE32_MEM_READ = byte[] X86_CODE32_MEM_READ =
{ {
// mov ecx,[0xaaaaaaaa]; INC ecx; DEC edx // mov ecx,[0xaaaaaaaa]; INC ecx; DEC edx
0x8B, 0x0D, 0xAA, 0xAA, 0xAA, 0xAA, 0x41, 0x4a 0x8B, 0x0D, 0xAA, 0xAA, 0xAA, 0xAA, 0x41, 0x4a
@@ -38,7 +34,7 @@ namespace UnicornSamples
public static void X86Code32InvalidMemWriteWithRuntimeFix() public static void X86Code32InvalidMemWriteWithRuntimeFix()
{ {
Byte[] X86_CODE32_MEM_WRITE = byte[] X86_CODE32_MEM_WRITE =
{ {
// mov [0xaaaaaaaa], ecx; INC ecx; DEC edx // mov [0xaaaaaaaa], ecx; INC ecx; DEC edx
0x89, 0x0D, 0xAA, 0xAA, 0xAA, 0xAA, 0x41, 0x4a 0x89, 0x0D, 0xAA, 0xAA, 0xAA, 0xAA, 0x41, 0x4a
@@ -48,7 +44,7 @@ namespace UnicornSamples
public static void X86Code32InOut() public static void X86Code32InOut()
{ {
Byte[] X86_CODE32_INOUT = byte[] X86_CODE32_INOUT =
{ {
// INC ecx; IN AL, 0x3f; DEC edx; OUT 0x46, AL; INC ebx // INC ecx; IN AL, 0x3f; DEC edx; OUT 0x46, AL; INC ebx
0x41, 0xE4, 0x3F, 0x4a, 0xE6, 0x46, 0x43 0x41, 0xE4, 0x3F, 0x4a, 0xE6, 0x46, 0x43
@@ -57,14 +53,14 @@ namespace UnicornSamples
} }
private static void Run(Byte[] code, Boolean raiseException = false) private static void Run(byte[] code, bool raiseException = false)
{ {
Console.WriteLine(); Console.WriteLine();
var stackTrace = new StackTrace(); var stackTrace = new StackTrace();
var stackFrame = stackTrace.GetFrames()[1]; var stackFrame = stackTrace.GetFrames()[1];
var methodName = stackFrame.GetMethod().Name; var methodName = stackFrame.GetMethod()?.Name;
Console.WriteLine("*** Start: " + methodName); Console.WriteLine($"*** Start: {methodName}");
Exception e = null; Exception e = null;
try try
{ {
@@ -84,93 +80,88 @@ namespace UnicornSamples
Console.WriteLine(); Console.WriteLine();
} }
private static void RunTest(Byte[] code, Int64 address, Int32 mode) private static void RunTest(byte[] code, long address, int mode)
{ {
using (var u = new Unicorn(Common.UC_ARCH_X86, mode)) using var u = new Unicorn(Common.UC_ARCH_X86, mode);
using (var disassembler = CapstoneDisassembler.CreateX86Disassembler(DisassembleMode.Bit32)) using var disassembler = CapstoneDisassembler.CreateX86Disassembler(X86DisassembleMode.Bit32);
{ Console.WriteLine($"Unicorn version: {u.Version()}");
Console.WriteLine("Unicorn version: {0}", u.Version());
// map 2MB of memory for this emulation // map 2MB of memory for this emulation
u.MemMap(address, 2 * 1024 * 1024, Common.UC_PROT_ALL); u.MemMap(address, 2 * 1024 * 1024, Common.UC_PROT_ALL);
// initialize machine registers // initialize machine registers
u.RegWrite(X86.UC_X86_REG_EAX, 0x1234); u.RegWrite(X86.UC_X86_REG_EAX, 0x1234);
u.RegWrite(X86.UC_X86_REG_ECX, 0x1234); u.RegWrite(X86.UC_X86_REG_ECX, 0x1234);
u.RegWrite(X86.UC_X86_REG_EDX, 0x7890); u.RegWrite(X86.UC_X86_REG_EDX, 0x7890);
// write machine code to be emulated to memory // write machine code to be emulated to memory
u.MemWrite(address, code); u.MemWrite(address, code);
// initialize machine registers // initialize machine registers
u.RegWrite(X86.UC_X86_REG_ESP, Utils.Int64ToBytes(address + 0x200000)); u.RegWrite(X86.UC_X86_REG_ESP, Utils.Int64ToBytes(address + 0x200000));
// handle IN & OUT instruction // handle IN & OUT instruction
u.AddInHook(InHookCallback); u.AddInHook(InHookCallback);
u.AddOutHook(OutHookCallback); u.AddOutHook(OutHookCallback);
// tracing all instructions by having @begin > @end // tracing all instructions by having @begin > @end
u.AddCodeHook((uc, addr, size, userData) => CodeHookCallback(disassembler, uc, addr, size, userData), 1, 0); u.AddCodeHook((uc, addr, size, userData) => CodeHookCallback(disassembler, uc, addr, size, userData), 1, 0);
// handle interrupt ourself // handle interrupt ourself
u.AddInterruptHook(InterruptHookCallback); u.AddInterruptHook(InterruptHookCallback);
// handle SYSCALL // handle SYSCALL
u.AddSyscallHook(SyscallHookCallback); u.AddSyscallHook(SyscallHookCallback);
// intercept invalid memory events // intercept invalid memory events
u.AddEventMemHook(MemMapHookCallback, Common.UC_HOOK_MEM_READ_UNMAPPED | Common.UC_HOOK_MEM_WRITE_UNMAPPED); u.AddEventMemHook(MemMapHookCallback, Common.UC_HOOK_MEM_READ_UNMAPPED | Common.UC_HOOK_MEM_WRITE_UNMAPPED);
Console.WriteLine(">>> Start tracing code"); Console.WriteLine(">>> Start tracing code");
// emulate machine code in infinite time // emulate machine code in infinite time
u.EmuStart(address, address + code.Length, 0u, 0u); u.EmuStart(address, address + code.Length, 0u, 0u);
// print registers // print registers
var ecx = u.RegRead(X86.UC_X86_REG_ECX); var ecx = u.RegRead(X86.UC_X86_REG_ECX);
var edx = u.RegRead(X86.UC_X86_REG_EDX); var edx = u.RegRead(X86.UC_X86_REG_EDX);
var eax = u.RegRead(X86.UC_X86_REG_EAX); var eax = u.RegRead(X86.UC_X86_REG_EAX);
Console.WriteLine("[!] EAX = {0}", eax.ToString("X")); Console.WriteLine($"[!] EAX = {eax:X}");
Console.WriteLine("[!] ECX = {0}", ecx.ToString("X")); Console.WriteLine($"[!] ECX = {ecx:X}");
Console.WriteLine("[!] EDX = {0}", edx.ToString("X")); Console.WriteLine($"[!] EDX = {edx:X}");
Console.WriteLine(">>> Emulation Done!"); Console.WriteLine(">>> Emulation Done!");
}
} }
private static Int32 InHookCallback(Unicorn u, Int32 port, Int32 size, Object userData) private static int InHookCallback(Unicorn u, int port, int size, object userData)
{ {
var eip = u.RegRead(X86.UC_X86_REG_EIP); var eip = u.RegRead(X86.UC_X86_REG_EIP);
Console.WriteLine("[!] Reading from port 0x{0}, size: {1}, address: 0x{2}", port.ToString("X"), size.ToString("X"), eip.ToString("X")); Console.WriteLine($"[!] Reading from port 0x{port:X}, size: {size:X}, address: 0x{eip:X}");
var res = 0; var res = size switch
switch (size)
{ {
case 1: 1 =>
// read 1 byte to AL // read 1 byte to AL
res = 0xf1; 0xf1,
break; 2 =>
case 2:
// read 2 byte to AX // read 2 byte to AX
res = 0xf2; 0xf2,
break; 4 =>
case 4:
// read 4 byte to EAX // read 4 byte to EAX
res = 0xf4; 0xf4,
break; _ => 0
} };
Console.WriteLine("[!] Return value: {0}", res.ToString("X")); Console.WriteLine($"[!] Return value: {res:X}");
return res; return res;
} }
private static void OutHookCallback(Unicorn u, Int32 port, Int32 size, Int32 value, Object userData) private static void OutHookCallback(Unicorn u, int port, int size, int value, object userData)
{ {
var eip = u.RegRead(X86.UC_X86_REG_EIP); var eip = u.RegRead(X86.UC_X86_REG_EIP);
Console.WriteLine("[!] Writing to port 0x{0}, size: {1}, value: 0x{2}, address: 0x{3}", port.ToString("X"), size.ToString("X"), value.ToString("X"), eip.ToString("X")); Console.WriteLine($"[!] Writing to port 0x{port:X}, size: {size:X}, value: 0x{value:X}, address: 0x{eip:X}");
// confirm that value is indeed the value of AL/ AX / EAX // confirm that value is indeed the value of AL/ AX / EAX
var v = 0L; var v = 0L;
var regName = String.Empty; var regName = string.Empty;
switch (size) switch (size)
{ {
case 1: case 1:
@@ -190,85 +181,81 @@ namespace UnicornSamples
break; break;
} }
Console.WriteLine("[!] Register {0}: {1}", regName, v.ToString("X")); Console.WriteLine("[!] Register {0}: {1:X}", regName, v);
} }
private static Boolean MemMapHookCallback(Unicorn u, Int32 eventType, Int64 address, Int32 size, Int64 value, Object userData) private static bool MemMapHookCallback(Unicorn u, int eventType, long address, int size, long value, object userData)
{ {
if (eventType == Common.UC_MEM_WRITE_UNMAPPED) if (eventType != Common.UC_MEM_WRITE_UNMAPPED) return false;
{
Console.WriteLine("[!] Missing memory is being WRITE at 0x{0}, data size = {1}, data value = 0x{2}. Map memory.", address.ToString("X"), size.ToString("X"), value.ToString("X")); Console.WriteLine($"[!] Missing memory is being WRITE at 0x{address:X}, data size = {size:X}, data value = 0x{value:X}. Map memory.");
u.MemMap(0xaaaa0000, 2 * 1024 * 1024, Common.UC_PROT_ALL); u.MemMap(0xaaaa0000, 2 * 1024 * 1024, Common.UC_PROT_ALL);
return true;
} return true;
else
{
return false;
}
} }
private static void CodeHookCallback1( private static void CodeHookCallback1(
CapstoneDisassembler<X86Instruction, X86Register, X86InstructionGroup, X86InstructionDetail> disassembler, CapstoneX86Disassembler disassembler,
Unicorn u, Unicorn u,
Int64 addr, long addr,
Int32 size, int size,
Object userData) object userData)
{ {
Console.Write("[+] 0x{0}: ", addr.ToString("X")); Console.Write($"[+] 0x{addr:X}: ");
var eipBuffer = new Byte[4]; var eipBuffer = new byte[4];
u.RegRead(X86.UC_X86_REG_EIP, eipBuffer); u.RegRead(X86.UC_X86_REG_EIP, eipBuffer);
var effectiveSize = Math.Min(16, size); var effectiveSize = Math.Min(16, size);
var tmp = new Byte[effectiveSize]; var tmp = new byte[effectiveSize];
u.MemRead(addr, tmp); u.MemRead(addr, tmp);
var sb = new StringBuilder(); var sb = new StringBuilder();
foreach (var t in tmp) foreach (var t in tmp)
{ {
sb.AppendFormat("{0} ", (0xFF & t).ToString("X")); sb.AppendFormat($"{(0xFF & t):X} ");
} }
Console.Write("{0,-20}", sb); Console.Write($"{sb,-20}");
Console.WriteLine(Utils.Disassemble(disassembler, tmp)); Console.WriteLine(Utils.Disassemble(disassembler, tmp));
} }
private static void CodeHookCallback( private static void CodeHookCallback(
CapstoneDisassembler<X86Instruction, X86Register, X86InstructionGroup, X86InstructionDetail> disassembler, CapstoneX86Disassembler disassembler,
Unicorn u, Unicorn u,
Int64 addr, long addr,
Int32 size, int size,
Object userData) object userData)
{ {
Console.Write("[+] 0x{0}: ", addr.ToString("X")); Console.Write($"[+] 0x{addr:X}: ");
var eipBuffer = new Byte[4]; var eipBuffer = new byte[4];
u.RegRead(X86.UC_X86_REG_EIP, eipBuffer); u.RegRead(X86.UC_X86_REG_EIP, eipBuffer);
var effectiveSize = Math.Min(16, size); var effectiveSize = Math.Min(16, size);
var tmp = new Byte[effectiveSize]; var tmp = new byte[effectiveSize];
u.MemRead(addr, tmp); u.MemRead(addr, tmp);
var sb = new StringBuilder(); var sb = new StringBuilder();
foreach (var t in tmp) foreach (var t in tmp)
{ {
sb.AppendFormat("{0} ", (0xFF & t).ToString("X")); sb.AppendFormat($"{(0xFF & t):X} ");
} }
Console.Write("{0,-20}", sb); Console.Write($"{sb,-20}");
Console.WriteLine(Utils.Disassemble(disassembler, tmp)); Console.WriteLine(Utils.Disassemble(disassembler, tmp));
} }
private static void SyscallHookCallback(Unicorn u, Object userData) private static void SyscallHookCallback(Unicorn u, object userData)
{ {
var eaxBuffer = new Byte[4]; var eaxBuffer = new byte[4];
u.RegRead(X86.UC_X86_REG_EAX, eaxBuffer); u.RegRead(X86.UC_X86_REG_EAX, eaxBuffer);
var eax = Utils.ToInt(eaxBuffer); var eax = Utils.ToInt(eaxBuffer);
Console.WriteLine("[!] Syscall EAX = 0x{0}", eax.ToString("X")); Console.WriteLine($"[!] Syscall EAX = 0x{eax:X}");
u.EmuStop(); u.EmuStop();
} }
private static void InterruptHookCallback(Unicorn u, Int32 intNumber, Object userData) private static void InterruptHookCallback(Unicorn u, int intNumber, object userData)
{ {
// only handle Linux syscall // only handle Linux syscall
if (intNumber != 0x80) if (intNumber != 0x80)
@@ -276,8 +263,8 @@ namespace UnicornSamples
return; return;
} }
var eaxBuffer = new Byte[4]; var eaxBuffer = new byte[4];
var eipBuffer = new Byte[4]; var eipBuffer = new byte[4];
u.RegRead(X86.UC_X86_REG_EAX, eaxBuffer); u.RegRead(X86.UC_X86_REG_EAX, eaxBuffer);
u.RegRead(X86.UC_X86_REG_EIP, eipBuffer); u.RegRead(X86.UC_X86_REG_EIP, eipBuffer);
@@ -288,19 +275,19 @@ namespace UnicornSamples
switch (eax) switch (eax)
{ {
default: default:
Console.WriteLine("[!] Interrupt 0x{0} num {1}, EAX=0x{2}", eip.ToString("X"), intNumber.ToString("X"), eax.ToString("X")); Console.WriteLine($"[!] Interrupt 0x{eip:X} num {intNumber:X}, EAX=0x{eax:X}");
break; break;
case 1: // sys_exit case 1: // sys_exit
Console.WriteLine("[!] Interrupt 0x{0} num {1}, SYS_EXIT", eip.ToString("X"), intNumber.ToString("X")); Console.WriteLine($"[!] Interrupt 0x{eip:X} num {intNumber:X}, SYS_EXIT");
u.EmuStop(); u.EmuStop();
break; break;
case 4: // sys_write case 4: // sys_write
// ECX = buffer address // ECX = buffer address
var ecxBuffer = new Byte[4]; var ecxBuffer = new byte[4];
// EDX = buffer size // EDX = buffer size
var edxBuffer = new Byte[4]; var edxBuffer = new byte[4];
u.RegRead(X86.UC_X86_REG_ECX, ecxBuffer); u.RegRead(X86.UC_X86_REG_ECX, ecxBuffer);
u.RegRead(X86.UC_X86_REG_EDX, edxBuffer); u.RegRead(X86.UC_X86_REG_EDX, edxBuffer);
@@ -310,16 +297,11 @@ namespace UnicornSamples
// read the buffer in // read the buffer in
var size = Math.Min(256, edx); var size = Math.Min(256, edx);
var buffer = new Byte[size]; var buffer = new byte[size];
u.MemRead(ecx, buffer); u.MemRead(ecx, buffer);
var content = Encoding.Default.GetString(buffer); var content = Encoding.Default.GetString(buffer);
Console.WriteLine( Console.WriteLine($"[!] Interrupt 0x{eip:X}: num {ecx:X}, SYS_WRITE. buffer = 0x{edx:X}, size = {size:X}, content = '{content}'");
"[!] Interrupt 0x{0}: num {1}, SYS_WRITE. buffer = 0x{2}, size = , content = '{3}'",
eip.ToString("X"),
ecx.ToString("X"),
edx.ToString("X"),
content);
break; break;
} }

View File

@@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Gee.External.Capstone" version="1.2.2" targetFramework="net45" />
</packages>