主线程调⽤(通过修改线程上下⽂实现)
思路:将主线程挂起后获取到主线程的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小时内删除。