【C语言】编写的DLL注入工具
本帖最后由 wushaominkk 于 2018-4-26 11:11 编辑现已更新附件,之前的代码有个地方有问题,EjectDll.c中第77行return 1;之前加上一句
((PFFREELIBRARY)pParam->pFunc)(hModule);
再编译生成一下,否则不执行用户输入的卸载时执行函数就无法卸载DLL。
最近学习了几种DLL注入的方式,这里分享一个我写的DLL注入工具(ring3),编译平台是windows7 32位+VS2013,含32位和64位,win10上测试了一下也能运行。
注入方式使用的是代码注入,参考了《逆向工程核心原理》中的相关代码。代码注入占用内存少并难以查找痕迹,在代码量小的时候比较合适。
不过这边有一个问题就是在执行用户选择的启动函数时我选择让目标进程使用CreateThread来调用dll的导出函数,这样做是否合适?测试了一些暂时还没发现什么问题
// 参数类型
typedef struct _INJECTTHREAD_PARAM
{
FARPROC pFunc;
char szBuf;
} INJECTTHREAD_PARAM, *PINJECTTHREAD_PARAM;
// 此函数以代码形式注入目标进程
DWORD WINAPI InjectThreadProc(LPVOID param)
{
PINJECTTHREAD_PARAM pParam = (PINJECTTHREAD_PARAM)param;
HMODULE hModule;
FARPROC pFunc;
HANDLE hThread;
// 注入的代码里不能直接调用API函数
// LoadLibraryA(szDllPath)
hModule = ((PFLOADLIBRARYA)pParam->pFunc)(pParam->szBuf);
if (!hModule)
{
return 1;
}
// GetProcAddress(hModule, szFunc)
pFunc = ((PFGETPROCADDRESS)pParam->pFunc)(hModule, pParam->szBuf);
if (!pFunc)
{
return 1;
}
// CreateThread()执行加载时要运行的函数, 不知道使用这种方式合不合适
hThread = ((PFCREATETHREAD)pParam->pFunc)(NULL, 0, (LPTHREAD_START_ROUTINE)pFunc, NULL, 0, NULL);
return 0;
}
BOOL InjectDll(DWORD dwPID, LPCSTR szDllPath, LPCSTR szFunc)
{
HMODULE hModule;
INJECTTHREAD_PARAM param;
HANDLE hProcess;
HANDLE hThread;
LPVOID pRemoteBuf;
DWORD dwSize;
hModule = GetModuleHandleW(L"kernel32.dll");
memset(¶m, 0, sizeof(INJECTTHREAD_PARAM));
// 要进行代码注入, 就必需要把要调用参数先写入目标进程
param.pFunc = GetProcAddress(hModule, "LoadLibraryA");
param.pFunc = GetProcAddress(hModule, "GetProcAddress");
param.pFunc = GetProcAddress(hModule, "CreateThread");
strcpy_s(param.szBuf, strlen(szDllPath) + 1, szDllPath);
strcpy_s(param.szBuf, strlen(szFunc) + 1, szFunc);
if (!(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)))
{
return FALSE;
}
// 判断环境
if (Is64BitProcess(GetCurrentProcess()) != Is64BitProcess(hProcess))
{
MessageBox(NULL, TEXT("打开动态链接库文件失败"), TEXT("提示"), MB_ICONERROR | MB_OK);
CloseHandle(hProcess);
return FALSE;
}
dwSize = sizeof(INJECTTHREAD_PARAM);
if (!(pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT, PAGE_READWRITE)))
{
return FALSE;
}
// 将全部的参数作为结构体整个写入
if (!WriteProcessMemory(hProcess, pRemoteBuf, (LPVOID)¶m, dwSize, NULL))
{
return FALSE;
}
dwSize = (DWORD)InjectDll - (DWORD)InjectThreadProc;
if (!(pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE)))
{
return FALSE;
}
// 再将InjectThreadProc的函数代码写入目标进程
if (!WriteProcessMemory(hProcess, pRemoteBuf, (LPVOID)InjectThreadProc, dwSize, NULL))
{
return FALSE;
}
// pRemoteBuf就是InjectThreadProc在目标进程中的起始地址, 已经被写入, pRemoteBuf则是写入的参数地址
if (!(hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pRemoteBuf, pRemoteBuf, 0, NULL)))
{
return FALSE;
}
WaitForSingleObject(hThread, INFINITE);
VirtualFreeEx(hProcess, pRemoteBuf, 0, MEM_RELEASE);
VirtualFreeEx(hProcess, pRemoteBuf, 0, MEM_RELEASE);
CloseHandle(hThread);
CloseHandle(hProcess);
return TRUE;
} AIDONG 发表于 2018-5-14 00:11
加载时执行函数 要怎么填 。。。。。。
填你编写的DLL里的导出函数名字来执行你的函数代码,没有就不填了:lol 个问题就是在执行用户选择的启动函数时我选择让目标进程使用CreateThread来调用dll的导出函数,这样做是否 感谢分享源码,研究一下 感谢楼主热心分享。 {:17_1068:}下载学习一下,谢谢楼主分享。 明天试试,注入能检测到不 谢谢分享 学习学习 感谢无私的分享!! 感谢分享源码 {:1_893:}
多谢楼主分享哟 小白来学习了。谢谢代码。