相关视频教程下载链接:http://pan.baidu.com/s/1cs8TQm 密码:pgyr
相关文档和代码下载链接:http://pan.baidu.com/s/1hrJkQJa 密码:bwln
(3)遍历快照,找到动态库的模块
通过Module32First()和Module32Next()函数遍历“快照”中的所有模块。这两个函数的使用方法与“3.2.2 遍历进程并显示”中介绍的Process32First()与Process32Next()函数的用法类似。
memset(&me32, 0, sizeof(MODULEENTRY32));
me32.dwSize = sizeof(MODULEENTRY32);
if (!Module32First(module_handle, &me32))
{
CloseHandle(module_handle);
MessageBox(_T("无法找到指定进程"));
return false;
}
bool is_found = false;
do
{
is_found = (_tcsicmp(me32.szModule, dllname) == 0 || _tcsicmp(me32.szExePath, dllname) == 0);
if (is_found)
{
break;
}
} while (Module32Next(module_handle, &me32));
return is_found;
其中,通过Module32First()函数找到“快照”中的第一个模块,之后通过do...while()循环语句遍历“快照”中的所有模块,该循环语句的条件是Module32Next()函数的返回值;is_found是是否找到动态库句柄的标志,通过比较“快照”中模块的名称me32.szModule或者me32.szExePath与函数的参数dllname来查找动态库模块,me32.szModule是模块的名称,me32.szExePath是模块的绝对路径。
回到OnBnClickedButtonUninject()函数中,调用自定义函数GetModule()函数获取动态库模块在指定进程中的地址。
if (GetModule(inject_process_name, inject_dll_name, me32))
{
........
}
如果GetModule()函数返回值是true,则说明找到了动态库的地址,且该地址保存在了me32中。
3.4.3 创建远程线程释放动态库
创建远程线程释放动态库的基本原理与“3.3.3 创建远程线程注入动态库”类似。首先获取远程进程的ID与远程进程句柄,之后获取远程线程函数的地址,最后通过CreateRemoteThread()函数创建远程线程。
(1)获取远程进程ID
调用自定义函数GetProcessID()函数获取指定远程进程的ID。
DWORD remote_thread_id = GetProcessID(inject_process_name);
(2)获取远程进程句柄
调用OpenProcess()函数获取远程进程的句柄。
HANDLE hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE, FALSE, remote_thread_id);
if (NULL == hProcess)
{
MessageBox(_T("打开远程进程失败!"));
return;
}
(3)获取FreeLibrary()函数的地址
获取FreeLibrary()函数的地址的基本原理与“3.3.3 创建远程线程注入动态库”中介绍的获取LoadLibrary()函数的地址类似。
LPVOID remote_thread_func = FreeLibrary;
(4)创建远程线程释放动态库
调用CreateRemoteThread()函数创建远程线程。
HANDLE remote_thread_handle = CreateRemoteThread(
hProcess
, NULL
, 0
, (LPTHREAD_START_ROUTINE)remote_thread_func
, (LPVOID)me32.modBaseAddr
, 0
, NULL);
CreateRemoteThread()函数的参数remote_thread_func是在“(3)获取FreeLibrary()函数的地址”中获取到的FreeLibrary()函数的地址;me32.modBaseAddress是动态库模块在远程进程中的地址。
(5)等待线程结束
调用WaitForSingleObject()函数等待释放动态库的线程结束。
WaitForSingleObject(remote_thread_handle, INFINITE);
MessageBox(_T("释放动态库成功"));
在释放了动态库之后,弹出对话框显示“释放动态库成功”。此时,就可以再点击“注入”按键,实现动态库的再次注入了。
3.4.4 释放资源
调用CloseHandle()函数,关闭新创建的线程句柄和远程进程句柄。
CloseHandle(remote_thread_handle);
CloseHandle(hProcess);