主线程调⽤(通过修改线程上下⽂实现)
思路:将主线程挂起后获取到主线程的eip,然后将eip修改为shellcode的地址恢复线程运⾏,当shellcode执⾏完成后跳转到旧eip处继续执⾏。
1 typedef VOID(__stdcall *PFN_CALL)(const VOID *pvIn, VOID *pvOut);
2
3 BOOL CallForThread(DWORD dwThreadId, PFN_CALL pfnCall, const VOID *pvIn, VOID *pvOut)
4 {
5 _ASSERT(pfnCall != NULL);
6 _ASSERT(dwThreadId != ::GetCurrentThreadId());
7
8// 打开线程
9 HANDLE hThread = ::OpenThread(THREAD_ALL_ACCESS, FALSE, dwThreadId);
10
11if (hThread == NULL)
12 {
13return FALSE;
14 }
15
16// 获取线程上下⽂
17 CONTEXT context = { 0 };
18
19 ::SuspendThread(hThread);
20 context.ContextFlags = CONTEXT_ALL;
21 ::GetThreadContext(hThread, &context);
22
23// 申请shellcode空间
24 VOID *pvShellCode = ::VirtualAlloc(NULL, 0x1000, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
25
26if (pvShellCode == NULL)
27 {
28 ::ResumeThread(hThread);
29 ::CloseHandle(hThread);
30 hThread = NULL;
31
32return FALSE;
33 }
34
35// 填充shellcode
36 DWORD dwExecuteFinishFlag = 0;
37 BYTE bShellCode[] = {
380x60, // pushad
390x68, 0x00, 0x00, 0x00, 0x00, // push pvOut
400x68, 0x00, 0x00, 0x00, 0x00, // push pvIn
410xB8, 0x00, 0x00, 0x00, 0x00, // mov eax, pfnCall
420xFF, 0xD0, // call eax
430xC7, 0x05, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, // mov dword ptr [执⾏完成标志指针], 1
440x61, // popad
450x68, 0x00, 0x00, 0x00, 0x00, // push 线程旧Eip
460xC3// ret
47 };
48
49 *(DWORD *)(&bShellCode[2]) = (DWORD)pvOut;
50 *(DWORD *)(&bShellCode[7]) = (DWORD)pvIn;
51 *(DWORD *)(&bShellCode[12]) = (DWORD)pfnCall;
52 *(DWORD *)(&bShellCode[20]) = (DWORD)&dwExecuteFinishFlag;
53 *(DWORD *)(&bShellCode[30]) = context.Eip;
54 memcpy_s(pvShellCode, 0x1000, bShellCode, sizeof (bShellCode));
55
56// 修改Eip执⾏
57 context.Eip = (DWORD)pvShellCode;
58 context.ContextFlags = CONTEXT_ALL;
59 ::SetThreadContext(hThread, &context);
60 ::ResumeThread(hThread);
61 ::PostThreadMessage(dwThreadId, 0, (WPARAM)0, (LPARAM)0);
62
63// 等待执⾏完成标志置位
64while (dwExecuteFinishFlag == 0)
65 {
66 ::Sleep(10);
67 }
68
69// 判断ShellCode代码是否全部执⾏完成
70 DWORD dwShellCodeBeg = (DWORD)pvShellCode;
71 DWORD dwShellCodeEnd = (DWORD)pvShellCode + sizeof (bShellCode)-1;
72
73while (TRUE)/*while-1*/
74 {
75// 获取Eip
postthreadmessage
76 context.ContextFlags = CONTEXT_ALL;
77 ::GetThreadContext(hThread, &context);
78
79// 检查当前Eip是否在shellcode中
80if (context.Eip < dwShellCodeBeg || context.Eip > dwShellCodeEnd) 81 {
82break;
83 }
84else
85 {
86 ::Sleep(10);
87 }
88 }/*end of while-1*/
89
90 ::VirtualFree(pvShellCode, 0x1000, MEM_FREE);
91 pvShellCode = NULL;
92 ::CloseHandle(hThread);
93 hThread = NULL;
94
95return TRUE;
96 }
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论