常见的几种DLL注入技术
看雪论坛作者ID:1900
1
简介
| ul_reason_for_call的值 | 代表的状态 |
| DLL_PROCESS_ATTACH | Dll刚刚映射到进程空间中 |
| DLL_THREAD_ATTACH | 进程中有新线程创建 |
| DLL_THREAD_DETACH | 进程中有新线程销毁 |
Dll从进程空间中接触映射 |
// dllmain.cpp : 定义 DLL 应用程序的入口点。#include <Windows.h>#include <Shlobj.h>#pragma comment(lib, "shell32.lib") #define FILE_NAME "result.txt" DWORD WINAPI ThreadProc(LPVOID lpParameter){ HANDLE hFile = NULL; CHAR szDesktopFile[MAX_PATH] = { 0 }; //保存系统桌面路径 CHAR szFullFilePath[MAX_PATH] = { 0 }; //保存完成的加载DLL文件的文件路径 DWORD dwRetLen = 0, dwFileLen = 0; BOOL bRet = TRUE; //获取桌面路径 bRet = SHGetSpecialFolderPath(NULL, szDesktopFile, CSIDL_DESKTOP, TRUE); if (bRet) { strcat(szDesktopFile, "\\"); strcat(szDesktopFile, FILE_NAME); while (TRUE) { hFile = CreateFile( szDesktopFile, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) //打开文件错误 { if (GetLastError() == 32) //错误码是不是其他进程正在使用这个文件,是的话等待一会在继续打开 { Sleep(200); continue; } else break; } else { GetModuleFileName(NULL, szFullFilePath, MAX_PATH); //获取加载DLL的进程的完整路径 dwFileLen = strlen(szFullFilePath); szFullFilePath[dwFileLen] = '\r'; //由于是在WIN7运行,换行符是\r\n szFullFilePath[dwFileLen + 1] = '\n'; SetFilePointer(hFile, 0, NULL, FILE_END); WriteFile(hFile, szFullFilePath, dwFileLen + 2, &dwRetLen, NULL); if (hFile) CloseHandle(hFile); break; } } } return 0;} BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ){ switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: { HANDLE hThread = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL); if (hThread) CloseHandle(hThread); break; } case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE;}2
代码框架
#include <cstdio>#include <Windows.h>#include <TlHelp32.h> #define PROCESS_NAME "taskmgr.exe" //要注入的进程名,这个是任务管理器的进程名#define DLL_NAME "InjectDll.dll" //要注入的DLL的名称 BOOL InjectDll(DWORD dwPid, CHAR szDllName[]); //注入DLLDWORD GetPID(PCHAR pProName); //根据进程名获取PIDVOID ShowError(PCHAR msg); //打印错误信息BOOL EnbalePrivileges(HANDLE hProcess, char *pszPrivilegesName); //提升进程权限 int main(){ CHAR szDllPath[MAX_PATH] = { 0 }; //保存要注入的DLL的路径 DWORD dwPID = 0; //保存要注入的进程的PID // 提升当前进程令牌权限 if (!EnbalePrivileges(GetCurrentProcess(), SE_DEBUG_NAME)) { printf("权限提升失败\n"); } dwPID = GetPID(PROCESS_NAME); if (dwPID == 0) { printf("没有找到要注入的进程\n"); goto exit; } GetCurrentDirectory(MAX_PATH, szDllPath); //获取程序的目录 strcat(szDllPath, "\\"); strcat(szDllPath, DLL_NAME); //与DLL名字拼接得到DLL的完整路径 printf("要注入的进程名:%s PID:%d\n", PROCESS_NAME, dwPID); printf("要注入的DLL的完整路径%s\n", szDllPath); if (InjectDll(dwPID, szDllPath)) { printf("Dll注入成功\n"); }exit: system("pause"); return 0;} BOOL InjectDll(DWORD dwPid, CHAR szDllName[]){ BOOL bRet = TRUE; return bRet;} DWORD GetPID(PCHAR pProName){ PROCESSENTRY32 pe32 = { 0 }; HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); BOOL bRet = FALSE; DWORD dwPID = 0; if (hSnap == INVALID_HANDLE_VALUE) { printf("CreateToolhelp32Snapshot process %d\n", GetLastError()); goto exit; } pe32.dwSize = sizeof(pe32); bRet = Process32First(hSnap, &pe32); while (bRet) { if (lstrcmp(pe32.szExeFile, pProName) == 0) { dwPID = pe32.th32ProcessID; break; } bRet = Process32Next(hSnap, &pe32); } CloseHandle(hSnap);exit: return dwPID;} VOID ShowError(PCHAR msg){ printf("%s Error %d\n", msg, GetLastError());} BOOL EnbalePrivileges(HANDLE hProcess, char *pszPrivilegesName){ HANDLE hToken = NULL; LUID luidValue = { 0 }; TOKEN_PRIVILEGES tokenPrivileges = { 0 }; BOOL bRet = FALSE; DWORD dwRet = 0; // 打开进程令牌并获取具有 TOKEN_ADJUST_PRIVILEGES 权限的进程令牌句柄 if (!OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken)) { ShowError("OpenProcessToken"); goto exit; } // 获取本地系统的 pszPrivilegesName 特权的LUID值 if (!LookupPrivilegeValue(NULL, pszPrivilegesName, &luidValue)) { ShowError("LookupPrivilegeValue"); goto exit; } // 设置提升权限信息 tokenPrivileges.PrivilegeCount = 1; tokenPrivileges.Privileges[0].Luid = luidValue; tokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; // 提升进程令牌访问权限 if (!AdjustTokenPrivileges(hToken, FALSE, &tokenPrivileges, 0, NULL, NULL)) { ShowError("AdjustTokenPrivileges"); goto exit; } else { // 根据错误码判断是否特权都设置成功 dwRet = ::GetLastError(); if (ERROR_SUCCESS == dwRet) { bRet = TRUE; goto exit; } else if (ERROR_NOT_ALL_ASSIGNED == dwRet) { ShowError("ERROR_NOT_ALL_ASSIGNED"); goto exit; } }exit: return bRet;}3
远程线程注入
HANDLE WINAPI CreateRemoteThread( __in HANDLE hProcess, __in LPSECURITY_ATTRIBUTES lpThreadAttributes, __in SIZE_T dwStackSize, __in LPTHREAD_START_ROUTINE lpStartAddress, __in LPVOID lpParameter, __in DWORD dwCreationFlags, __out LPDWORD lpThreadId);| 参数 | 说明 |
| hProcess | 要创建线程的进程句柄 |
| lpThreadAttributes | 新线程的安全描述符 |
| dwStackSize | 堆栈起始大小,为0表示默认大小 |
| lpStartAddress | 表示要运行线程的起始地址 |
| lpParameter | 保存要传递给线程参数的地址 |
| dwCreationFlags | 控制线程创建的标志,为0表示创建后立即执行 |
| lpThreadId | 指向接收线程标识符变量的指针。为NULL表示不返回线程标识符 |
(1)hProcess用来指定在哪个进程中创建新线程。
(2)lpStartAddress用来指定将进程中的哪个地址开始作为新线程运行的起始地址。
(3)lpParameter保存的也是一个地址,这个地址中保存的就是新线程要用到的参数。
HMODULE WINAPI LoadLibrary(__in LPCTSTR lpFileName);BOOL InjectDll(DWORD dwPid, CHAR szDllName[]){ BOOL bRet = TRUE; HANDLE hProcess = NULL, hRemoteThread = NULL; HMODULE hKernel32 = NULL; DWORD dwSize = 0; LPVOID pDllPathAddr = NULL; PVOID pLoadLibraryAddr = NULL; // 打开注入进程,获取进程句柄 hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid); if (NULL == hProcess) { ShowError("OpenProcess"); bRet = FALSE; goto exit; } // 在注入进程中申请可以容纳DLL完成路径名的内存空间 dwSize = 1 + strlen(szDllName); pDllPathAddr = VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT, PAGE_READWRITE); if (!pDllPathAddr) { ShowError("VirtualAllocEx"); bRet = FALSE; goto exit; } // 把DLL完整路径名写入进程中 if (!WriteProcessMemory(hProcess, pDllPathAddr, szDllName, dwSize, NULL)) { ShowError("WriteProcessMemory"); bRet = FALSE; goto exit; } hKernel32 = LoadLibrary("kernel32.dll"); if (hKernel32 == NULL) { ShowError("LoadLibrary"); bRet = FALSE; goto exit; } // 获取LoadLibraryA函数地址 pLoadLibraryAddr = GetProcAddress(hKernel32, "LoadLibraryA"); if (pLoadLibraryAddr == NULL) { ShowError("GetProcAddress "); bRet = FALSE; goto exit; } //创建远程线程进行DLL注入 hRemoteThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pLoadLibraryAddr, pDllPathAddr, 0, NULL); if (hRemoteThread == NULL) { ShowError("CreateRemoteThread"); bRet = FALSE; goto exit; } exit: if (hKernel32) FreeLibrary(hKernel32); if (hProcess) CloseHandle(hProcess); if (hRemoteThread) CloseHandle(hRemoteThread); return bRet;}4
加强版远程线程注入
typedef DWORD(WINAPI *pFnZwCreateThreadEx)( PHANDLE ThreadHandle, ACCESS_MASK DesiredAccess, LPVOID ObjectAttributes, HANDLE ProcessHandle, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, BOOL CreateSuspended, DWORD dwStackSize, DWORD dw1, DWORD dw2, LPVOID pUnkown);typedef DWORD(WINAPI *pFnZwCreateThreadEx)( PHANDLE ThreadHandle, ACCESS_MASK DesiredAccess, LPVOID ObjectAttributes, HANDLE ProcessHandle, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, ULONG CreateThreadFlags, SIZE_T ZeroBits, SIZE_T StackSize, SIZE_T MaximumStackSize, LPVOID pUnkown);typedef DWORD(WINAPI *pFnZwCreateThreadEx)(PHANDLE, ACCESS_MASK, LPVOID, HANDLE, LPTHREAD_START_ROUTINE, LPVOID, BOOL, DWORD, DWORD, DWORD, LPVOID); BOOL InjectDll(DWORD dwPid, CHAR szDllName[]){ BOOL bRet = TRUE; HANDLE hProcess = NULL, hRemoteThread = NULL; HMODULE hKernel32 = NULL, hNtDll = NULL; DWORD dwSize = 0; LPVOID pDllPathAddr = NULL; PVOID pLoadLibraryAddr = NULL; pFnZwCreateThreadEx ZwCreateThreadEx = NULL; // 打开注入进程,获取进程句柄 hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid); if (NULL == hProcess) { ShowError("OpenProcess"); bRet = FALSE; goto exit; } // 在注入进程中申请可以容纳DLL完成路径名的内存空间 dwSize = 1 + strlen(szDllName); pDllPathAddr = VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT, PAGE_READWRITE); if (!pDllPathAddr) { ShowError("VirtualAllocEx"); bRet = FALSE; goto exit; } // 把DLL完成路径名写入进程中 if (!WriteProcessMemory(hProcess, pDllPathAddr, szDllName, dwSize, NULL)) { ShowError("WriteProcessMemory"); bRet = FALSE; goto exit; } hKernel32 = LoadLibrary("kernel32.dll"); if (hKernel32 == NULL) { ShowError("LoadLibrary kernel32"); bRet = FALSE; goto exit; } // 获取LoadLibraryA函数地址 pLoadLibraryAddr = GetProcAddress(hKernel32, "LoadLibraryA"); if (pLoadLibraryAddr == NULL) { ShowError("GetProcAddress LoadLibraryA"); bRet = FALSE; goto exit; } hNtDll = LoadLibrary("ntdll.dll"); if (hNtDll == NULL) { ShowError("LoadLibrary ntdll"); bRet = FALSE; goto exit; } ZwCreateThreadEx = (pFnZwCreateThreadEx)GetProcAddress(hNtDll, "ZwCreateThreadEx"); if (!ZwCreateThreadEx) { ShowError("GetProcAddress ZwCreateThreadEx"); bRet = FALSE; goto exit; } ZwCreateThreadEx(&hRemoteThread, PROCESS_ALL_ACCESS, NULL, hProcess, (LPTHREAD_START_ROUTINE)pLoadLibraryAddr, pDllPathAddr, 0, 0, 0, 0, NULL); if (hRemoteThread == NULL) { ShowError("ZwCreateThreadEx"); bRet = FALSE; goto exit; }exit: if (hKernel32) FreeLibrary(hKernel32); if (hNtDll) FreeLibrary(hNtDll); if (hProcess) CloseHandle(hProcess); if (hRemoteThread) CloseHandle(hRemoteThread); return bRet;}5
APC注入
DWORD WINAPI QueueUserAPC( __in PAPCFUNC pfnAPC, __in HANDLE hThread, __in ULONG_PTR dwData);BOOL InjectDll(DWORD dwPid, CHAR szDllName[]){ BOOL bRet = TRUE; HANDLE hProcess = NULL, hThread = NULL, hSnap = NULL; HMODULE hKernel32 = NULL; DWORD dwSize = 0; PVOID pDllPathAddr = NULL; PVOID pLoadLibraryAddr = NULL; THREADENTRY32 te32 = { 0 }; // 打开注入进程,获取进程句柄 hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid); if (NULL == hProcess) { ShowError("OpenProcess"); bRet = FALSE; goto exit; } // 在注入进程中申请可以容纳DLL完成路径名的内存空间 dwSize = 1 + strlen(szDllName); pDllPathAddr = VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT, PAGE_READWRITE); if (!pDllPathAddr) { ShowError("VirtualAllocEx"); bRet = FALSE; goto exit; } // 把DLL完成路径名写入进程中 if (!WriteProcessMemory(hProcess, pDllPathAddr, szDllName, dwSize, NULL)) { ShowError("WriteProcessMemory"); bRet = FALSE; goto exit; } hKernel32 = LoadLibrary("kernel32.dll"); if (hKernel32 == NULL) { ShowError("LoadLibrary"); bRet = FALSE; goto exit; } // 获取LoadLibraryA函数地址 pLoadLibraryAddr = GetProcAddress(hKernel32, "LoadLibraryA"); if (pLoadLibraryAddr == NULL) { ShowError("GetProcAddress"); bRet = FALSE; goto exit; } //获得线程快照 hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); if (!hSnap) { ShowError("CreateToolhelp32Snapshot"); bRet = FALSE; goto exit; } //遍历线程 te32.dwSize = sizeof(te32); if (Thread32First(hSnap, &te32)) { do { //这个线程的进程ID是不是要注入的进程的PID if (te32.th32OwnerProcessID == dwPid) { hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, te32.th32ThreadID); if (hThread) { QueueUserAPC((PAPCFUNC)pLoadLibraryAddr, hThread, (ULONG_PTR)pDllPathAddr); CloseHandle(hThread); hThread = NULL; } else { ShowError("OpenThread"); bRet = FALSE; goto exit; } } } while (Thread32Next(hSnap, &te32)); }exit: if (hKernel32) FreeLibrary(hKernel32); if (hProcess) CloseHandle(hProcess); if (hThread) CloseHandle(hThread); return bRet;}6
AppInit_DLLs注入
BOOL InjectDll(DWORD dwPid, CHAR szDllName[]){ BOOL bRet = TRUE; HKEY hKey = NULL; CHAR szAppKeyName[] = { "AppInit_DLLs" }; CHAR szLoadAppKeyName[] = { "LoadAppInit_DLLs" }; DWORD dwLoadAppInit = 1; //设置LoadAppInit_DLLs的值 //打开相应注册表键 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows", 0, KEY_ALL_ACCESS, &hKey) != ERROR_SUCCESS) { ShowError("RegOpenKeyEx"); bRet = FALSE; goto exit; } //设置AppInit_DLLs为相应的DLL路径 if (RegSetValueEx(hKey, szAppKeyName, 0, REG_SZ, (PBYTE)szDllName, strlen(szDllName) + 1) != ERROR_SUCCESS) { ShowError("RegSetValueEx"); bRet = FALSE; goto exit; } //将LoadAppInit_DLLs的值设为1 if (RegSetValueEx(hKey, szLoadAppKeyName, 0, REG_DWORD, (PBYTE)&dwLoadAppInit, sizeof(dwLoadAppInit)) != ERROR_SUCCESS) { ShowError("RegSetValueEx"); bRet = FALSE; goto exit; }exit: return bRet;}7
全局钩子注入
HHOOK SetWindowsHookEx(int idHook, HOOKPROC lpfn, HINSTANCE hMod, DWORD dwThreadId);extern HMODULE g_hDllModule;// 设置全局钩子BOOL SetGlobalHook(){ g_hHook = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)GetMsgProc, g_hDllModule, 0); if (NULL == g_hHook) { return FALSE; } return TRUE;}// 钩子回调函数LRESULT GetMsgProc( int code, WPARAM wParam, LPARAM lParam){ return CallNextHookEx(g_hHook, code, wParam, lParam);}// 卸载钩子BOOL UnSetGlobalHook(){ if (g_hHook) { UnhookWindowsHookEx(g_hHook); } return TRUE;}// 共享内存#pragma data_seg("mydata")HHOOK g_hHook = NULL;#pragma data_seg()#pragma comment(linker, "/SECTION:mydata,RWS")BOOL InjectDll(DWORD dwPid, CHAR szDllName[]){ BOOL bRet = TRUE; HMODULE hDll = NULL; pFnSetGlobalHook SetGlobalHook = NULL; pFnUnSetGlobalHook UnSetGlobalHook = NULL; hDll = LoadLibrary(szDllName); if (hDll == NULL) { ShowError("LoadLibrary"); bRet = FALSE; goto exit; } SetGlobalHook = (pFnSetGlobalHook)GetProcAddress(hDll, "SetGlobalHook"); if (SetGlobalHook == NULL) { ShowError("GetProcAddress SetGlobalHook"); bRet = FALSE; goto exit; } if (!SetGlobalHook()) { printf("钩子安装失败\n"); bRet = FALSE; goto exit; } printf("钩子安装成功,按回车卸载钩子\n"); system("pause"); UnSetGlobalHook = (pFnUnSetGlobalHook)GetProcAddress(hDll, "UnSetGlobalHook"); if (UnSetGlobalHook == NULL) { ShowError("GetProcAddress UnSetGlobalHook"); bRet = FALSE; goto exit; } if (UnSetGlobalHook()) { printf("已将全局钩子卸载\n"); }exit: return bRet;}8
实验结果
看雪ID:1900
https://bbs.pediy.com/user-home-835440.htm
# 往期推荐
5.进程隐藏技术
球分享
球点赞
球在看
点击“阅读原文”,了解更多!