相关视频教程下载链接:http://pan.baidu.com/s/1cs8TQm 密码:pgyr
3.4 远程释放动态库
在远程注入动态库之后,必须要在远程进程中释放该动态库,否则不能实现多次注入。远程释放动态库的基本原理与注入动态库类似,都是在远程进程中创建新的线程,只不过释放动态库时,线程函数为FreeLibrary(),而该函数的参数是已经注入的动态库模块在远程进程中的地址。
首先,在VS2015的“资源编辑器”中,双击“释放”按键,为该按键添加消息响应函数OnBnClickedButtonUninject()。当点击了“释放”按键,注入程序就会调用该函数。
3.4.1 判断输入信息是否有效
在释放动态库时,需要获取指定的远程进程名称和要释放的动态库名称。因此,和“3.3.1判断输入信息是否有效”中相似,在OnBnClickedButtonUninject()函数中首先需要判断输入的信息是否有效。
CString inject_process_name;
m_ProcessesName.GetWindowTextW(inject_process_name);
if (inject_process_name.IsEmpty())
{
MessageBox(_T("请选择要注入的进程"));
return;
}
CString inject_dll_name;
m_DLLName.GetWindowTextW(inject_dll_name);
if (inject_dll_name.IsEmpty())
{
MessageBox(_T("请输入要注入的动态库名称"));
return;
}
3.4.2 在远程进程中查找动态库模块的地址
要通过FreeLibrary()函数释放动态库模块,就必须要知道动态库模块在远程进程中的地址。可以通过CreateToolhelp32Snapshot()函数获取指定进程中所有模块的“快照”,之后通过Module32First()和Module32Next()函数遍历“快照”中的所有模块,在找到动态库模块后,将该模块的所有信息保存在MODULEENTRY32结构的对象中,其中就包含了模块的地址信息。
为对话框类添加一个成员函数GetModule(),其访问权限为private。该函数的作用是获取指定进程中指定模块的信息。
bool GetModule(CString processname, CString dllname, MODULEENTRY32& me32);
其中,函数参数processname是指定进程的名称;dllname是指定模块的名称;me32是保存动态库信息的对象。
(1)获取指定进程ID
在GetModule()函数中,首先通过自定义函数GetProcessID()获取指定进程的ID。该自定义函数在“3.3.2 写入动态库名称”中已经详细介绍。
DWORD process_id = GetProcessID(processname);
(2)获取指定进程中模块的“快照”
通过CreateToolhelp32Snapshot()函数获取指定进程中所有模块的“快照”。该函数在“3.2.1 获取当前进程“快照””中已经详细介绍。
HANDLE module_handle = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, process_id);
if (INVALID_HANDLE_VALUE == module_handle)
{
MessageBox(_T("获取进程模块快照失败"));
return false;
}
CreateToolhelp32Snapshot()函数的参数TH32CS_SNAPMODULE表示要获取的是模块的“快照”,process_id是在“(1)获取指定进程ID”中获取到的指定进程的ID。通过以上代码,指定进程中所有模块的“快照”句柄即保存到了变量module_handle中。