R3修改线程上下文EIP实现的无模块注入
http://blog.csdn.net/zfdyq0/article/details/40890521
- #include "stdafx.h"
- #include <windows.h>
- #include <iostream>
- using std::cin;
- DWORD dwOldEip = 0;
- DWORD funRemote = 0;
- BYTE shellCode[25] = {
- 0x68, 0x78, 0x56, 0x34, 0x12, //push 12345678h
- 0x9C, //pushfd
- 0x60, //pushad
- 0x6A, 0x00, //push 0
- 0x6A, 0x00, //push 0
- 0x6A, 0x00, //push 0
- 0x6A, 0x00, //push 0
- 0xB8, 0x78, 0x56, 0x34, 0x12, //mov eax, 12345678h
- 0xFF, 0xD0, //call eax
- 0x61, //popad
- 0x9D, //popfd
- 0xC3, //ret
- };
- BOOL ThreadContextTest(DWORD dwProcessId, DWORD dwMemSize)
- {
- HWND hwnd = FindWindow(NULL, L"Dependency Walker");
- if (!hwnd)
- return FALSE;
- printf("hwnd:%p\n", hwnd);
- // 打开进程
- HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
- if (!hProcess)
- return FALSE;
- // 获取主线程ID
- DWORD dwThreadId = GetWindowThreadProcessId(hwnd, NULL);
- printf("dwThreadId:%d\n", dwThreadId);
- HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, dwThreadId);
- // 暂停主线程
- DWORD dwSuspendCount = SuspendThread(hThread);
- printf("暂停线程,任意键恢复线程,dwSuspendCount:%d\n", dwSuspendCount);
- CONTEXT stcContext = { CONTEXT_FULL };
- if (!GetThreadContext(hThread, &stcContext))
- return FALSE;
- HMODULE hModule = LoadLibrary(L"User32.dll");
- funRemote = (DWORD)GetProcAddress(hModule, "MessageBoxA");
- // 获取原始EIP
- dwOldEip = stcContext.Eip;
- printf("stcContext.Eip:%p\n", stcContext.Eip);
- // 申请内存
- LPVOID lpAddr = VirtualAllocEx(hProcess, NULL, dwMemSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
- if (!lpAddr)
- return FALSE;
- printf("lpAddr:%p\n", lpAddr);
- // 构造shellCode
- memcpy(&shellCode[16], &funRemote, 4);
- memcpy(&shellCode[1], &dwOldEip, 4);
- // 写入内存
- BOOL bRet = WriteProcessMemory(hProcess, lpAddr, shellCode, dwMemSize, NULL);
- if (!bRet)
- return FALSE;
- // 设置EIP
- stcContext.Eip = (DWORD)lpAddr;
- SetThreadContext(hThread, &stcContext);
- //system("pause");
- DWORD dwResumeCount = ResumeThread(hThread);
- printf("恢复线程,dwResumeCount:%d\n", dwResumeCount);
- return TRUE;
- }
- int _tmain(int argc, _TCHAR* argv[])
- {
- DWORD dwLen = sizeof(shellCode);
- DWORD dwProcessId = 0;
- cin >> dwProcessId;
- ThreadContextTest(dwProcessId, dwLen);
- system("pause");
- return 0;
- }
我把执行的代码写成了ShellCode,就是弹一个 MessageBox,但是前面一句和最后一句是重点,第一句是把当前EIP 压栈,最后的RET就是
返回到正确EIP 这个是必须有的,在这里RET指令的内部操作是:栈顶字单元出栈,其值赋给IP寄存器。即实现了一个程序的转移,将栈顶字单元保存
的偏移地址作为下一条指令的偏移地址。
当然也可以把你自己的执行代码写成函数,遇到的问题就是计算函数的大小,一般方法就是搜索特征码Ret(高老湿说滴),然后特征码地址减
去,函数地址,就是大小~~
由于EIP必须在运行的时候才能得到,所以我把获得的EIP直接MEMCOPY到相应shellCode位置。
运行结果: