<>背景

也叫进程内存替换,就是指将一个进程的内存数据清空,写入任意我们想写入的数据,并更改执行顺序,执行我们写入的数据代码。

简单过程就是:

* 创建一个挂起主线程的进程(也可以直接挂起目标进程,不自己创建)
* 在新进程的地址空间内申请一块内存,写入我们的 Shellcode
* 更改新进程执行顺序,执行我们的 Shellcode 代码
<>函数介绍
// 获取线程上下文 BOOL WINAPI GetThreadContext( _In_ HANDLE hThread, _Inout_
LPCONTEXT lpContext); // 设置线程上下文 BOOL WINAPI SetThreadContext( _In_ HANDLE
hThread, _In_ const CONTEXT *lpContext ); // 恢复线程运行 DWORD WINAPI ResumeThread(
_In_ HANDLE hThread);
<>详细过程

* 首先,使用 CreateProcess 函数创建进程,并且设置创建进程的标志为 CREATE_SUSPENDED,即表示新进程的主线程被挂起。
* 然后,使用 VirtualAllocEx 函数在新进程中申请一块可读、可写、可执行的内存,并使用 WriteProcessMemory
函数写入Shellcode 数据。
* 接着,使用 GetThreadContext,设置获取标志为 CONTEXT_FULL,即获取新进程中所有的线程上下文。并修改线程上下文的指令指针
EIP 的值,更改主线程的执行顺序。再将修改过的线程上下文设置回主线程中。
* 最后,我们调用 ResumeThread 恢复主线程,让进程按照修改后的 EIP 继续运行,执行我们的 Shellcode 代码。
要注意的是,在使用 GetThreadContext 获取线程上下文的时候,一定要对 CONTEXT 机构中的 ContextFlags
成员赋值,表示指明要检索线程的上下文的哪些部分,否则会导致程序实现不到想要的效果。我们可以指明 CONTEXT_FULL,表示获取所有的线程上下文信息。

<>代码
// 创建进程并替换进程内存数据, 更改执行顺序 BOOL ReplaceProcess(char *pszFilePath, PVOID
pReplaceData, DWORD dwReplaceDataSize, DWORD dwRunOffset) { STARTUPINFO si = { 0
}; PROCESS_INFORMATION pi = { 0 }; CONTEXT threadContext = { 0 }; BOOL bRet =
FALSE; ::RtlZeroMemory(&si, sizeof(si)); ::RtlZeroMemory(&pi, sizeof(pi)); ::
RtlZeroMemory(&threadContext, sizeof(threadContext)); si.cb = sizeof(si); //
创建进程并挂起主线程 bRet = ::CreateProcess(pszFilePath, NULL, NULL, NULL, FALSE,
CREATE_SUSPENDED, NULL, NULL, &si, &pi); if (FALSE == bRet) { ShowError(
"CreateProcess"); return FALSE; } // 在替换的进程中申请一块内存 LPVOID lpDestBaseAddr = ::
VirtualAllocEx(pi.hProcess, NULL, dwReplaceDataSize, MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE); if (NULL == lpDestBaseAddr) { ShowError(
"VirtualAllocEx"); return FALSE; } // 写入替换的数据 bRet = ::WriteProcessMemory(pi.
hProcess, lpDestBaseAddr, pReplaceData, dwReplaceDataSize, NULL); if (FALSE ==
bRet) { ShowError("WriteProcessError"); return FALSE; } // 获取线程上下文 //
注意此处标志,一定要写!!! threadContext.ContextFlags = CONTEXT_FULL; bRet = ::
GetThreadContext(pi.hThread, &threadContext); if (FALSE == bRet) { ShowError(
"GetThreadContext"); return FALSE; } // 修改进程的PE文件的入口地址以及映像大小,先获取原来进程PE结构的加载基址
threadContext.Eip = (DWORD)lpDestBaseAddr + dwRunOffset; // 设置挂起进程的线程上下文 bRet =
::SetThreadContext(pi.hThread, &threadContext); if (FALSE == bRet) { ShowError(
"SetThreadContext"); return FALSE; } // 恢复挂起的进程的线程 ::ResumeThread(pi.hThread);
return TRUE; }
<>测试

技术
©2019-2020 Toolsou All rights reserved,
Chrome OS,对程序员和Windows意味着什么?,互联网营销C#中字典的排序方法face_recognition的5个应用实例精准手机号抓取,运营商大数据蚂蚁集团香港IPO获得中国证监会批准连硅谷都撑不住了?远程办公的技术人员可能被减薪创建数据mysql库流程访客手机抓取方法程序员python表白代码你不知道的鸿蒙——HarmonyOS