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.
1. Windows
To compile the code open the UnicornSln.sln with Microsoft Visual 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 Studio 12 or with a newer version and just press Ctrl+Shift+B to build
the solution. the solution.
You need to have installed at least version 4.5 of the .NET framework. 2. Linux
[Linux] To compile the code open a terminal in this directory
TODO 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,6 +1,5 @@
namespace UnicornManaged.Binding namespace UnicornManaged.Binding
open System
module BindingFactory = module BindingFactory =
let mutable _instance = NativeBinding.instance let mutable _instance = NativeBinding.instance
@@ -10,4 +9,3 @@ module BindingFactory =
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

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>
<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> </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,28 +37,28 @@ 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);
@@ -73,7 +69,7 @@ namespace UnicornSamples
// 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
@@ -100,42 +96,42 @@ namespace UnicornSamples
} }
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)
@@ -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" />
<!-- 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> </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,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 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
@@ -28,7 +24,7 @@ namespace UnicornSamples
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,12 +80,11 @@ 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);
@@ -130,47 +125,43 @@ namespace UnicornSamples
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>