DLL注入
DLL注入是指向运行中的其他进程强制插入特点的DLL文件。DLL注入命令其他进程自行调用LoadLibrary()API,加载用户指定的DLL文件,此时该DLL的DllMain()函数就会被调用执行。
DLL注入的实现方法
- 创建远程线程(CreateRemoteThread() API)
- 使用注册表(AppInit_DLLs值)
- 消息钩取(SetWindowsHookEx()API)
CreateRemoteThread()
首先看一下myhack.dll源代码
myhack.dll
#include "pch.h"
#include<Windows.h>
#include<tchar.h>
#pragma comment(lib,"urlmon.lib")
#include <Urlmon.h>
#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) {
//第三个参数填需要下载文件的地址
URLDownloadToFile(NULL, DEF_URL, L"C:\\Users\\rkvir\\Desktop\\hook\\index.html", 0, NULL);
return 0;
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
HANDLE hThread = NULL;
g_hMod = hModule;
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
OutputDebugString(L"myhack.dll Injection!");
hThread = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
CloseHandle(hThread);
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
我们可以看到该DLL被加载时,先输出一个字符串myhack.dll Injection!,然后创建线程调用函数,通过URLDownloadToFile()API下载指定网站的文件。
InjectDll.exe
当我们有了实现功能的DLL文件,现在还需要一个能够将DLL注入到进程中的工具
#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;
//1.使用dwPid获取 目标进程(notepad.exe)句柄
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);
if (!hProcess)
{
_tprintf(L"OpenProcess(%d)v failed!!! [%d]\n", dwPid, GetLastError());
return FALSE;
}
//2.在目标进程(notepad.exe)中分配szDllName大小的内存,dll文件的路径
pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize, MEM_COMMIT, PAGE_READWRITE);
//3.将myhack.dll路径写入分配的内存
WriteProcessMemory(hProcess, pRemoteBuf, (LPVOID)szDllPath, dwBufSize, NULL);
//4.获取LoadLibraryW()API的地址
hMod = GetModuleHandle(L"kernel32.dll");
pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hMod, "LoadLibraryW");
//5.在notepad.exe进程中运行线程
//pThreadProc为notepa.exe进程内存中的LoadLibraryW地址
//pRemoteBuf为写入到notepa.exe进程内存中的myhack.dll字符串地址
hThread = CreateRemoteThread(hProcess, NULL, 0, pThreadProc, pRemoteBuf, 0, NULL);
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
CloseHandle(hProcess);
return TRUE;
}
int _tmain(int argc, TCHAR* argv[]) {
if (argc!=3)
{
//检查输入程序的参数是否为3个
_tprintf(L"USAGE: %s Pid Dll_Path \n", argv[0]);
}
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;
}
其实这里面最主要的就是CreateRemoteThread,通过这个API,我们可以在notepad.exe进程中创建一个实现DLL加载的LoadLibrary线程.CreateRemoteThread的第四个参数原本是指向线程函数地址,我们指向LoadLibrary,同时第五个参数就是LoadLibrary的参数,我们传入需要加载的DLL的路径。
AppInit_DLLS
将要注入的DLL的路径字符串写入AppInit_DLLs项目,然后将LoadAppInit_DLLs的项目置为1,就可以实现注入
原理
User32.dll被加载到进程中时,会读取AppInit_DLLs注册表项,若有值,则调用LoadLibrary()API加载用户DLL。严格意义上说,dll只会加载到加载User32.dll的进程。
实验
我们实现注入myhack2.dll
1.首先修改AppInit_DLLs的值
2.将LoadAppInit_DLLs的值修改为1
3.重启系统,使修改生效
已经注入进去了,只要加载user32.dll的进程都会被注入,但是只有进程为notepad.exe才会进行操作
SetWindowsHookEx()
这个API安装好消息钩子后,由OS将指定的DLL强制注入到相应的进程
DLL卸载
利用了FreeLibrary()API,仅适用于卸载自己强制注入的DLL文件,和通过CreateRemoteThread原理一样,这里只是把第四个参数改为FreeLibrary的地址,第五个参数为DLL加载地址。
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 767778848@qq.com