最近在网上找到一篇介绍DLL远程注入的文章《DLL远程注入技术》,通过DLL注入,可以让你的进程不独立运行,而是隐藏到一个普通的已经运行的进程中,很多木马好像就是这么实现的。感觉挺有趣的,所以就自己实践了下。主要用到的相关函数有:
1. CreateToolhelp32Snapshot 进程快照,找出想要注入的进程
2. OpenProcess 获得进程句柄
3. VirtualAllocEx 在远程进程中分配虚拟空间
4. WriteProcessMemory 写远程进程内存空间
5. CreateRemoteThread 在远程进程中创建线程
6. LoadLibrary 装载DLL
7. FreeLibrary 卸载DLL
8. GetModuleHandle 获得DLL的句柄
9. GetExitCodeThread 获得线程退出代码
特别注意这个函数,当以线程里面就只有一个函数时,线程的退出代码,就是函数的返回值。
DLL注入的思想方法:
1. 调用CreateToolhelp32Snapshot ,获得想要注入的目标进程ID
2. 调用OpenProcess获得目标进程句柄
3. 在VirtualAllocEx中,为目标进程分配保存DLL名称的大小虚拟空间
4. 调用WriteProcessMemory将 DLL 名称 写入到新申请的虚拟空间中,因为本线程的空间不能被目标进程使用。这也是要调用VirturalAllocEx分配空间的原因。
5. 调用CreateRemoteThread函数,为目标进程创建一个新的线程,线程函数为LoadLibrary ,参数为 新申请的虚拟内存地址,这样这个函数就可以执行了。
DLL卸载的思想方法:
前4步跟DLL注入式一样的,接下来不同的是:
5.调用CreateRemoteThread函数,为目标进程创建的新线程,但是调用的函数为
GetModuleHandle,目的是去的要卸载的DLL的模块句柄。
6. 调用WaitForSingleObject等待刚才新建线程退出,然后调用GetExitCodeThread函数,获得刚才线程的推出代码。即函数GetModuleHandle的返回值。
7. 再调用CreteRemoteThread函数,调用FreeLibrary函数,参数为刚才的GetModuleHandle的返回值。
8. 这样,卸载DLL的任务已经完成。
在编程过程中遇到的一些小问题,当时发现当目标进程就是本进程时没有问题,当要注入到一些其他的进程时,发现可以正确在目标进程中创建线程,但是没有注入DLL。后来发现是目标进程找不到目标DLL,当把目标DLL拷贝到C盘下面的Windows系统目录下面时,就可以正确注入目标进程了。
下面是我为了实现注入与注销的一个简单封装的DllManager类:
DllManager.h文件
#include "Tlhelp32.h"
class DllManager
{
public:
DllManager(void);
public:
~DllManager(void);
public:
DllManager(CString strProcessName,CString strDllName);
public:
// 要注入的进程名称
CString m_strProcessName;
public:
// 要注入的DLL名称
CString m_strDllName;
public:
// 装载Dll到指定的进程
bool LoadDll(void);
public:
// 找到指定的进程,返回进程ID
DWORD FindTargetProcess(CString processName);
public:
// 设置要注入的进程名称
void SetProcessName(CString ProcessName);
public:
// 设置要注入的DLL 名称
void SetDllName(CString DllName);
public:
// 卸载DLL函数
bool UnLoadDll();
};
DllManger.cpp文件:
DllManager::DllManager(void)
: m_strProcessName(_T(""))
, m_strDllName(_T(""))
{
}
DllManager::DllManager(CString strProcessName,CString strDllName)
{
m_strProcessName=strProcessName;
m_strDllName=strDllName;
}
DllManager::~DllManager(void)
{
}
// 装载Dll到指定的进程
bool DllManager::LoadDll(void)
{
//判断进程名和DLL名是否为空
m_strProcessName.Trim();
m_strDllName.Trim();
if (m_strProcessName=="" || m_strProcessName.IsEmpty())
{
AfxMessageBox("进程名不能为空");
return false;
}
if (m_strDllName=="" || m_strDllName.IsEmpty())
{
AfxMessageBox("DLL名不能为空");
return false;
}
//遍历进程快照,找到指定的进程
DWORD processId=FindTargetProcess(m_strProcessName);
if (processId==0)//如果没有找到
{
AfxMessageBox("没有找到指定的进程");
return FALSE;
}
//打开指定的进程
HANDLE hprocess=OpenProcess(PROCESS_CREATE_THREAD|
PROCESS_VM_OPERATION|
PROCESS_VM_READ|
PROCESS_VM_WRITE,
FALSE,
processId);
if (hprocess==NULL)//如果打开进程失败
{
AfxMessageBox("进程打开失败");
return FALSE;
}
//在指定进程空间申请虚拟内存空间,为了存放DLL名称
char dllName[20];
strcpy(dllName,m_strDllName);
DWORD dwSize=strlen(dllName)+1;
DWORD dwWritten=0;
LPVOID buffer;
buffer=VirtualAllocEx(hprocess,NULL,dwSize,MEM_COMMIT,PAGE_READWRITE);
if (buffer==NULL)//如果内存申请失败
{
//关闭进程句柄
CloseHandle(hprocess);
return FALSE;
}
//将DLL名称写入到指定进程的刚申请的虚拟内存空间
bool bRet=WriteProcessMemory(hprocess,buffer,(LPVOID)dllName,dwSize,&dwWritten);
if (bRet==FALSE)
{
//释放内存空间
VirtualFreeEx(hprocess,buffer,dwSize,MEM_DECOMMIT);
CloseHandle(hprocess);
return FALSE;
}
if (dwSize!=dwWritten)
{
//释放内存空间
VirtualFreeEx(hprocess,buffer,dwSize,MEM_DECOMMIT);
//关闭进程句柄
CloseHandle(hprocess);
return FALSE;
}
//动态装载指定的DLL文件
HANDLE hthread=CreateRemoteThread(hprocess,NULL,0,(LPTHREAD_START_ROUTINE)LoadLibrary,buffer,0,0);
if (hthread==NULL)//创建加载DLL的线程失败
{
//释放内存空间
VirtualFreeEx(hprocess,buffer,dwSize,MEM_DECOMMIT);
//关闭进程句柄
CloseHandle(hprocess);
return FALSE;
}
WaitForSingleObject(hthread,INFINITE);
AfxMessageBox("成功注入DLL");
//释放资源
VirtualFreeEx(hprocess,buffer,dwSize,MEM_DECOMMIT);
CloseHandle(hthread);
CloseHandle(hprocess);
return TRUE;
}
// 找到指定的进程,返回进程ID,如果没有找到,返回
DWORD DllManager::FindTargetProcess(CString processName)
{
HANDLE hsnapshot;
//进程快照
hsnapshot=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
PROCESSENTRY32 processentry;
processentry.dwSize=sizeof(PROCESSENTRY32);
Process32First(hsnapshot,&processentry);
do
{
if (processName==processentry.szExeFile)
{
return processentry.th32ProcessID;
}
}
while(Process32Next(hsnapshot,&processentry));
return 0;
}
// 设置进程名称
void DllManager::SetProcessName(CString ProcessName)
{
m_strProcessName=ProcessName;
}
// 设置DLL 名称
void DllManager::SetDllName(CString DllName)
{
m_strDllName=DllName;
}
// 卸载DLL函数
bool DllManager::UnLoadDll()
{
//判断进程名和DLL名是否为空
m_strProcessName.Trim();
m_strDllName.Trim();
if (m_strProcessName=="" || m_strProcessName.IsEmpty())
{
AfxMessageBox("进程名不能为空");
return false;
}
if (m_strDllName=="" || m_strDllName.IsEmpty())
{
AfxMessageBox("DLL名不能为空");
return false;
}
//遍历进程快照,找到指定的进程
DWORD processId=FindTargetProcess(m_strProcessName);
if (processId==0)//如果没有找到
{
AfxMessageBox("没有找到指定的进程");
return FALSE;
}
//打开指定的进程
HANDLE hprocess=OpenProcess(PROCESS_CREATE_THREAD|
PROCESS_VM_OPERATION|
PROCESS_VM_READ|
PROCESS_VM_WRITE,
FALSE,
processId);
if (hprocess==NULL)//如果打开进程失败
{
return FALSE;
}
//在指定进程空间申请虚拟内存空间,为了存放DLL名称
char dllName[20];
strcpy(dllName,m_strDllName);
DWORD dwSize=strlen(dllName)+1;
DWORD dwWritten=0;
LPVOID buffer;
buffer=VirtualAllocEx(hprocess,NULL,dwSize,MEM_COMMIT,PAGE_READWRITE);
if (buffer==NULL)//如果内存申请失败
{
//关闭进程句柄
CloseHandle(hprocess);
return FALSE;
}
//将DLL名称写入到指定进程的刚申请的虚拟内存空间
bool bRet=WriteProcessMemory(hprocess,buffer,(LPVOID)dllName,dwSize,&dwWritten);
if (bRet==FALSE)
{
//释放内存空间
VirtualFreeEx(hprocess,buffer,dwSize,MEM_DECOMMIT);
CloseHandle(hprocess);
return FALSE;
}
if (dwSize!=dwWritten)
{
//释放内存空间
VirtualFreeEx(hprocess,buffer,dwSize,MEM_DECOMMIT);
//关闭进程句柄
CloseHandle(hprocess);
return FALSE;
}
//获得DLL对应的HMODULE
HANDLE hthread=CreateRemoteThread(hprocess,NULL,0,(LPTHREAD_START_ROUTINE)GetModuleHandle,buffer,0,0);
if (hthread==NULL)//创建卸载DLL的线程失败
{
//释放内存空间
VirtualFreeEx(hprocess,buffer,dwSize,MEM_DECOMMIT);
CloseHandle(hprocess);
return FALSE;
}
//获得远程线程GetModuleHandle的执行结果
WaitForSingleObject(hthread,INFINITE);
DWORD hmodule=0;
bRet=GetExitCodeThread(hthread,&hmodule);
if (bRet==FALSE)
{
return FALSE;
}
TRACE("hmodule=%d/n",hmodule);
if (hmodule==0)
{
AfxMessageBox("目标DLL不存在");
//释放资源
VirtualFreeEx(hprocess,buffer,dwSize,MEM_DECOMMIT);
CloseHandle(hthread);
CloseHandle(hprocess);
return FALSE;
}
//释放资源
VirtualFreeEx(hprocess,buffer,dwSize,MEM_DECOMMIT);
CloseHandle(hthread);
//卸载DLL
hthread=CreateRemoteThread(hprocess,NULL,0,(LPTHREAD_START_ROUTINE)FreeLibrary,(LPVOID)hmodule,0,0);
if(hthread==NULL)
{
//释放资源
CloseHandle(hprocess);
return false;
}
WaitForSingleObject(hthread,INFINITE);
//释放资源
AfxMessageBox("成功卸载DLL");
CloseHandle(hthread);
CloseHandle(hprocess);
return TRUE;
}