DLL注入
DLL注入:向运行中的其他进程强制插入特定的DLL文件。
DLL被加载到进程后会自动运行DllMain()函数。
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpvReserved){
switch(dwReason){
case DLL_PROCESS_ATTACH:
//添加想执行的代码
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCRSS_DETACH:
break;
}
return TRUE;
}
DLL注入的作用
- 改善功能与修复Bug
- 消息钩取
- API钩取
- 监视、管理PC用户的应用程序
- 恶意代码
DLL注入的实现方法
- 创建远程线程(CreatRemoteThread() API)
- 使用注册表(AppInit_DLLs值)
- 消息钩取(SetWindowsHookEx() API)
CreatRemoteThread()
将myhack.dll注入notepad.exe:
- myhack.dll:被注入的DLL,http://www.naver.com/index.html
- InjectDll.exe:向目标注入DLL文件的实用小程序
流程
- 运行notepad.exe程序,查看其PID
- 运行InjectDll.exe对程序进行注入
- 运行DebugView,查看注入是否成功
源码分析
- myhack.dll
#include "windows.h"
#include "tchar.h"
#pragma comment(lib, "urlmon.lob")
#define DEF_URL (L"http://www.naver.com/index.html")
#define DEF_FILE_NAME (L"index.html")
HMODULE g_hMod=NULL;
DWORD WINAPI ThreadProc(LPVOID lParam){
TCHAR szPath[_MAX_PATH]={0,};
if(!GetModuleFileName(g_hMod, szPath, MAX_PATH))
return FALSE;
TCHAR *p=_tcsrchr(szPath, '\\');
if(!p)
return FALSE;
_tcscpy_s(p+1, _MAX_PATH, DEF_FILE_NME);
URLDownloadToFile(NULL, DEF_URL, szPath, 0, NULL); //从指定网站下载index.html文件
return 0;
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved){
HANDLE hThread=NULL;
g_hMod=(HMODULE)hinstDLL;
switch(fdwReason){
case DLL_PROCESS_ATTACH:
OutputDebugString(L"myhack.dll Injection!!!"); //输出调试字符串
hThread=CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL); //创建线程调用函数
CloseHandle(hThread);
break;
}
return TRUE;
}
- InjectDll.exe
#include "windows.h"
#include "tchar.h"
BOOL InjectDll(DWORD dwPID, LPCTSTR szDllPath){
HANDLE hProcess=NULL, hThread=NULL;
HMODULE hMod=NULL;
LPVOID pRemoteBuf=NULL;
DWORD dwBufSize=(DWORD)(_tcslen(szDllPath)+1)* sizeof(TCHAR);
LPTHREAD_START_ROUTINE pThreadProc;
//使用dwPID获取目标进程(notepad.exe)句柄
if(!(hProcess=OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID))){
_tprintf(L"OpenProcess(%d) failed!!! [%d]\n", dwPID, GetLastError());
return FALSE;
}
//在目标进程内存中分配szDllName大小的内存
pRemoteBuf=VirtualAllocEx(hProcess, NULL, dwBufSize, MEM_COMMIT, PAGE_READWRITE);
//将myhack.dll路径写入分配的内存
WriteProcessMemory(hProcess, pRemoteBuf, (LPVOID)szDllPath, dwBufSize, NULL);
//获取LoadLibraryW() API的地址【此处获取的是InjectDll.exe的LoadLibraryW的地址,因为在Windows下,kernel32.dll在每个进程中的加载地址相同】
hMod=GetModuleHandle(L"kernel32.dll");
pThreadPrc=(LPTHREAD_START_ROUTINE)GetProcAddress(hMod, "LoadLibraryW");
//在notepad.exe进程中运行线程
hThread=CreateRemoteThread(hProcess, //hProcess,目标进程句柄
NULL, //lpThreadAttributes
0, //dwStackSize
pThreadProc, //lpStartAddress,线程函数地址
pRemoteBuf, //lpParameter,线程参数地址
0, //dwCreationFlags
NULL); //lpThreadId
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
CloseHandle(hProcess);
return TURE;
}
int _tmain(int argc, TCHAR * argv[]){
if(argc!=3){
_tprintf(L"USAGE: %s pid dll_path\n", argv[0]);
return 1;
}
//inject dll
if(InjectDll((DWORD)_tstol(argv[1]),argv[2]))
_tprintf(L"InjectDll(\"%s\") success!!!\n",argv[2]);
else
_tprintf(L"InjectDll(\"%s\") failed!!!\n",argv[2]);
return 0;
}
在Windows下,kernel32.dll在每个进程中的加载地址相同
AppInit_DLLs
Windows操作系统的注册表中默认提供了AppInt_DLLs与LoadAppInit_DLLs两个注册表项:
- AppInit_DLLs:注入的DLL的路径字符串
- LoadAppInit_DLLs:设置为1
重启后,指定DLL就会注入所有运行的进程。
示例代码
#include "windows.h"
#include "tchar.h"
#define DEF_CMD L"c:\\Program Files\\Internet Explorer\\iexplore.exe"
#define DEF_ADDR L"http://www.naver.com"
#define DEF_DST_PROC L"notepad.exe"
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved){
TCHAR szCmd[MAX_PATH]={0,};
TCHAR szPath[MAX_PATH]={0,};
TCHAR *p=NULL;
STARTUPINFO si={0,};
PROCESS_INFORMATION pi={0,};
si.cb=sizeof(STARTUPINFO);
si.dwFlags=START_USESHOWWINDPW;
si.wShowWindow=SA_HIDE;
switch(fdwReason){
case DLL_PEOCESS_ATTACH:
if(!GetModuleFileName(NULL, szPath, MAX_PATH))
break;
if(!(p=_tcsrchr(szPath,'\\')))
break;
if(_tcsicmp(p+1, DEF_DST_PROC))
break;
wsprintf(szCmd, L"%s %s", DEF_CMD, DEF_ADDR);
if(!CreateProcess(NULL, (LPTSTR)(LPCTSTR)szCmd,
NULL, NULL, FALSE,
NORMAL_PRIORITY_CLASS,
NULL, NULL, &si, &pi"
))
break;
if(pi.hProcess!=NULL)
CloseHandle(pi.hProcess);
break;
}
return TRUE;
}
SetWindowsHookEx()
参考文献
《逆向工程核心原理》