dll注入及卸载实践
三种方法:具体详见《逆向工程核心原理》。
1、创建远程线程CreateRemoteThread()
2、使用注册表AppInit_DLLs
3、消息钩取SetWindowsHookEx()
一、远程线程(注意将szPATH数组建在函数中会出现栈溢出,需要建立全局变量)
#include "windows.h" #include "tchar.h" #pragma comment(lib, "urlmon.lib") HMODULE g_hMod = NULL; TCHAR szPath[MAX_PATH] = { 0, }; DWORD WINAPI ThreadProc(LPVOID lParam) { if (!GetModuleFileName(g_hMod, szPath, MAX_PATH)) return FALSE; TCHAR *p = _tcsrchr(szPath, '\\'); if (!p) return FALSE; _tcscpy_s(p + 1, MAX_PATH, L"index.html"); URLDownloadToFile(NULL, L"http://www.xidian.edu.cn", szPath, 0, NULL); return 0; } BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { HANDLE hThread = NULL; g_hMod = (HMODULE)hinstDLL; switch (fdwReason) { case DLL_PROCESS_ATTACH: hThread = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL); CloseHandle(hThread); break; } return TRUE; }
#include "windows.h" #include "tchar.h" BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege) { TOKEN_PRIVILEGES tp; HANDLE hToken; LUID luid; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) { _tprintf(L"OpenProcessToken error: %u\n", GetLastError()); return FALSE; } if (!LookupPrivilegeValue(NULL, // lookup privilege on local system lpszPrivilege, // privilege to lookup &luid)) // receives LUID of privilege { _tprintf(L"LookupPrivilegeValue error: %u\n", GetLastError()); return FALSE; } tp.PrivilegeCount = 1; tp.Privileges[0].Luid = luid; if (bEnablePrivilege) tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; else tp.Privileges[0].Attributes = 0; // Enable the privilege or disable all privileges. if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES)NULL, (PDWORD)NULL)) { _tprintf(L"AdjustTokenPrivileges error: %u\n", GetLastError()); return FALSE; } if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) { _tprintf(L"The token does not have the specified privilege. \n"); return FALSE; } return TRUE; } BOOL InjectDll(DWORD dwPID, LPCTSTR szDllPath) { HANDLE hProcess = NULL, hThread = NULL; HMODULE hMod = NULL; LPVOID pRemoteBuf = NULL; DWORD dwBufSize = (DWORD)(lstrlen(szDllPath) + 1) * sizeof(TCHAR); LPTHREAD_START_ROUTINE pThreadProc; // 获得dwPID进程ID对应的目标进程句柄 if (!(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID))) return FALSE; // 在目标进程地址空间中为DLL路径名szDllPath开辟一块存储空间,将szDllPath路径字符串写入该空间 pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize, MEM_COMMIT, PAGE_READWRITE); WriteProcessMemory(hProcess, pRemoteBuf, (LPVOID)szDllPath, dwBufSize, NULL); // 获取当前进程地址空间中LoadLibraryW()函数的地址,该函数由kernel32.dll导入 hMod = GetModuleHandle(L"kernel32.dll"); pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hMod, "LoadLibraryW"); // 在目标进程中运行线程,该线程执行LoadLibraryW()函数并传入被注入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) { _tprintf(L"USAGE : %s <pid> <dll_path>\n", argv[0]); return 1; } if (!SetPrivilege(SE_DEBUG_NAME, TRUE)) 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; }
卸载:
// EjectDll.exe #include "windows.h" #include "tlhelp32.h" #include "tchar.h" //由进程名找到进程id号 DWORD FindProcessID(LPCTSTR szProcessName) { DWORD dwPID = 0xFFFFFFFF; HANDLE hSnapShot = INVALID_HANDLE_VALUE; PROCESSENTRY32 pe; // 获得系统进程的快照 pe.dwSize = sizeof(PROCESSENTRY32); hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, NULL); Process32First(hSnapShot, &pe); do { if (!_tcsicmp(szProcessName, (LPCTSTR)pe.szExeFile)) { dwPID = pe.th32ProcessID; break; } } while (Process32Next(hSnapShot, &pe)); CloseHandle(hSnapShot); return dwPID; } BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege) { TOKEN_PRIVILEGES tp; HANDLE hToken; LUID luid; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) return FALSE; if (!LookupPrivilegeValue(NULL, // lookup privilege on local system lpszPrivilege, // privilege to lookup &luid)) // receives LUID of privilege return FALSE; tp.PrivilegeCount = 1; tp.Privileges[0].Luid = luid; if (bEnablePrivilege) tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; else tp.Privileges[0].Attributes = 0; // Enable the privilege or disable all privileges. if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES)NULL, (PDWORD)NULL)) return FALSE; if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) return FALSE; return TRUE; } BOOL EjectDll(DWORD dwPID, LPCTSTR szDllName) { BOOL bMore = FALSE, bFound = FALSE; HANDLE hSnapshot, hProcess, hThread; HMODULE hModule = NULL; MODULEENTRY32 me = { sizeof(me) }; LPTHREAD_START_ROUTINE pThreadProc; // dwPID = notepad进程的id号 // 使用TH32CS_SNAPMODULE参数,获得加载到notepad进程地址空间的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))) return FALSE; hModule = GetModuleHandle(L"kernel32.dll"); pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hModule, "FreeLibrary"); hThread = CreateRemoteThread(hProcess, NULL, 0, pThreadProc, me.modBaseAddr, 0, NULL); WaitForSingleObject(hThread, INFINITE); CloseHandle(hThread); CloseHandle(hProcess); CloseHandle(hSnapshot); return TRUE; } int _tmain(int argc, TCHAR* argv[]) { DWORD dwPID = 0xFFFFFFFF; dwPID = FindProcessID(L"notepad.exe"); if (dwPID == 0xFFFFFFFF) //没有找到notepad进程 return 1; // 更改特权 if (!SetPrivilege(SE_DEBUG_NAME, TRUE)) return 1; // 卸载DLL if (EjectDll(dwPID, L"myhack.dll")) _tprintf(L"EjectDll(%d, \"%s\") success!!!\n", dwPID, L"myhack.dll"); else _tprintf(L"EjectDll(%d, \"%s\") failed!!!\n", dwPID, L"myhack.dll"); return 0; }
二、使用注册表(调用进程执行程序)
修改AppInit_DLLs和LoadAppInit_DLLs,路径名使用单右斜杠
#include "windows.h" #include "tchar.h" 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 = STARTF_USESHOWWINDOW; si.wShowWindow = SW_HIDE; switch (fdwReason) { case DLL_PROCESS_ATTACH: //获得当前DLL被装载到的进程的可执行文件的路径到szPath中 if (!GetModuleFileName(NULL, szPath, MAX_PATH)) break; if (!(p = _tcsrchr(szPath, '\\'))) break; if (lstrcmpi(p + 1, _T("notepad.exe"))) break; //当前DLL被加载到的进程的可执行文件为notepad.exe,调用IE访问www.xidian.edu.cn wsprintf(szCmd, _T("%s %s"), _T("C:\\Users\\Administrator\\AppData\\Local\\Google\\Chrome\\Application\\chrome.exe"), _T("http://www.xidian.edu.cn")); 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; }
三、消息钩取
详见12.24逆向工程上机作业