**************************************************DLL注入**************************************************
介绍 : 以DLL的方式通过向正在运行的进程注入代码, DLL在进程运行的时候按需加载
注入方法 :
原理分析 :
打开进程OpenProcess
在进程中申请存储dll路径的内存空间
将dll路径写入到进程内存空间
执行远程调用让进程加载该dll
卸载类似
1、创建远程线程 : CreateRemoteThread() API
//########################inject.exe#######################
#include "stdafx.h"
#include
#include
#include "tlhelp32.h"
BOOL InjectDll(DWORD dwPID, LPCTSTR szDllPath)
{
HANDLE hProcess = NULL;
HANDLE hThread = NULL;
HMODULE hMod = NULL;
LPVOID pRemoteBuf = NULL; // 存储在目标进程申请的内存地址
DWORD dwBufSize = (DWORD)(_tcslen(szDllPath) + 1) * sizeof(TCHAR); // 存储DLL文件路径所需的内存空间大小
LPTHREAD_START_ROUTINE pThreadProc;
if (!(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID))) {
_tprintf(L"OpenProcess(%d) failed!!! [%d]\n", dwPID, GetLastError());
return FALSE;
}
pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize, MEM_COMMIT, PAGE_READWRITE); // 在目标进程空间中申请内存
WriteProcessMemory(hProcess, pRemoteBuf, (LPVOID)szDllPath, dwBufSize, NULL); // 向在目标进程申请的内存空间中写入DLL文件的路径
hMod = GetModuleHandle(L"kernel32.dll");
pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hMod, "LoadLibraryW"); // 获得LoadLibrary()函数的地址
hThread = CreateRemoteThread(hProcess, NULL, 0, pThreadProc, pRemoteBuf, 0, NULL);
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
CloseHandle(hProcess);
return TRUE;
}
BOOL UnInjectDll(DWORD dwPID, LPCTSTR szDllName)
{
BOOL bMore = FALSE, bFound = FALSE;
HANDLE hSnapshot = NULL;
HANDLE hProcess = NULL;
HANDLE hThread = NULL;
HMODULE hModule = NULL;
MODULEENTRY32 me = { sizeof(me) };
LPTHREAD_START_ROUTINE pThreadProc;
//获得进程的快照,查找有没有对应的dll,以便卸载掉
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID);
bMore = Module32First(hSnapshot, &me);
for (; bMore; bMore = Module32Next(hSnapshot, &me))
{
if (!_tcsicmp((LPCTSTR)me.szModule, szDllName) ||
!_tcsicmp((LPCTSTR)me.szExePath, szDllName))
{
bFound = TRUE;
break;
}
}
if (!bFound)
{
CloseHandle(hSnapshot);
return FALSE;
}
if (!(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)))
{
_tprintf(L"OpenProcess(%d) failed!!", dwPID);
CloseHandle(hSnapshot);
return FALSE;
}
hModule = GetModuleHandle(L"kernel32.dll");
pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hModule, "FreeLibrary"); // 获得LoadLibrary()函数的地址
hThread = CreateRemoteThread(hProcess, NULL, 0,
pThreadProc, me.modBaseAddr,
0, NULL);
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
CloseHandle(hProcess);
return TRUE;
}
int _tmain(int argc, TCHAR *argv[])
{
if (argc != 4) {
_tprintf(L"USAGE : %s i/u pid dll_path\n", argv[0]);
return 1;
}
if (argv[1][0] == 'i')
{
if (InjectDll((DWORD)_tstol(argv[2]), argv[3]))
_tprintf(L"InjectDll(\"%s\") success!!!\n", argv[2]);
else
_tprintf(L"InjectDll(\"%s\") failed!!!\n", argv[2]);
}
else if (argv[1][0] == 'u')
{
if (UnInjectDll((DWORD)_tstol(argv[2]), argv[3]))
_tprintf(L"UnInjectDll(\"%s\") success!!!\n", argv[3]);
else
_tprintf(L"UnInjectDll(\"%s\") failed!!!\n", argv[3]);
}
return 0;
}
//################################inject.dll##################################
#include "stdafx.h"
#include
#include
#include
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
MessageBox(NULL, TEXT("Dll Inject Success!!!"), TEXT("info"), MB_OK); // 被进程加载时弹出MessageBox("Dll Inject Success!!!")
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
MessageBox(NULL, TEXT("Dll unInject Ok!!!"), TEXT("info"), MB_OK); // 被进程卸载时弹出MessageBox("Dll unInject Ok!!!")
break;
break;
}
return TRUE;
}
2、使用注册表 : AppInit_DLLs 值
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows
AppInit_DLLs : dll路径
LoadAppInit_DLLs : 设置为1, PC重启后, 所有进程都将被注入AppInit_DLLs
3、消息钩取 : SetWindowsHookEx() API
4代码注入
原理分析 :
打开进程
将函数地址保存到结构体中param中
在进程中申请内存将param写入
远程调用执行对应的函数
#include "stdafx.h"
#include
#include
#include "tlhelp32.h"
//LoadLibraryA
typedef HMODULE(WINAPI *FPLOADLIBRARYA)
(
LPCSTR pLibFileName
);
//GetProcAddress()
typedef FARPROC (WINAPI *FPGETPROCADDRESS)
(
HMODULE hModule,
LPCSTR lpProcName
);
//MessageBoxA()
typedef int (WINAPI *PFMESSAGEBOXA)
(
HWND hWnd,
LPCSTR lpText,
LPCSTR lpCaption,
UINT uType
);
typedef struct _THREAD_PARAM
{
FARPROC pFunc[2];
char szBuf[4][128];
}THREAD_PARAM, *PTHREAD_PARAM;
DWORD WINAPI ThreadProc(LPVOID lParam)
{
PTHREAD_PARAM pParam = (PTHREAD_PARAM)lParam;
HMODULE hMod = NULL;
FARPROC pFunc = NULL;
hMod = ((FPLOADLIBRARYA)pParam->pFunc[0])(pParam->szBuf[0]);
pFunc = (FARPROC)((FPGETPROCADDRESS)pParam->pFunc[1])(hMod, pParam->szBuf[1]);
((PFMESSAGEBOXA)pFunc)(NULL, pParam->szBuf[2], pParam->szBuf[3], MB_OK);
return 0;
}
BOOL InjectCode(DWORD dwPID)
{
HMODULE hMod = NULL;
THREAD_PARAM param = { 0 };
HANDLE hProcess = NULL;
HANDLE hThread = NULL;
LPVOID pRemoteBuf[2] = { 0 };
DWORD dwSize = 0;
hMod = GetModuleHandleA("kernel32.dll");
param.pFunc[0] = GetProcAddress(hMod, "LoadLibraryA");
param.pFunc[1] = GetProcAddress(hMod, "GetProcAddress");
strcpy_s(param.szBuf[0], "user32.dll");
strcpy_s(param.szBuf[1], "MessageBoxA");
strcpy_s(param.szBuf[2], "xxxxxxxx");
strcpy_s(param.szBuf[3], "eeeeeeeeee");
if (!(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID))) {
_tprintf(L"OpenProcess(%d) failed!!! [%d]\n", dwPID, GetLastError());
return FALSE;
}
dwSize = sizeof(THREAD_PARAM);
pRemoteBuf[0] = VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT, PAGE_READWRITE);
WriteProcessMemory(hProcess, pRemoteBuf[0], (LPVOID)¶m, dwSize, NULL);
dwSize = (DWORD)InjectCode - (DWORD)ThreadProc;
pRemoteBuf[1] = VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
WriteProcessMemory(hProcess, pRemoteBuf[1], (LPVOID)ThreadProc, dwSize, NULL);
hThread = CreateRemoteThread(hProcess, NULL, 0,
(LPTHREAD_START_ROUTINE)pRemoteBuf[1], pRemoteBuf[0], 0, NULL);
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
CloseHandle(hProcess);
return TRUE;
}
int _tmain(int argc, TCHAR *argv[])
{
if (argc != 2) {
_tprintf(L"USAGE : %s pid \n", argv[0]);
return 1;
}
if (InjectCode((DWORD)_tstol(argv[1])))
_tprintf(L"InjectCode success!!!\n");
else
_tprintf(L"InjectCode failed!!!\n");
return 0;
}
API钩子
可执行文件注入(PE注入)
进程hollow(又名进程替换和RunPE)
线程执行劫持(又名挂起、注入并恢复)
通过SetWindowsHookEx钩子注入
APC注入和AtomBombing
通过SetWindowLong的窗口内存注入(EWMI)
使用Shims注入
IAT hook和Inline hook(应用层rootkit)