消息钩子
Windows操作系统GUI将键盘敲击,鼠标移动和点击,窗口大小和位置改变都看成事件(Event).消息传递过程大致为
- 事件发生时,首先将这个事件添加到系统的[OS message queue]中
- OS判断这个事件是在哪个应用程序中产生的,然后将这个事件添加到应用程序的消息队列中
- 应用程序对这些消息进行处理
消息钩子就在这个传递链过程中添加一些函数,这些函数可以侦听事件甚至修改事件的参数。
SetWindowsHookEx
这个API可以实现消息钩子,它的定义如下
HHOOK SetWindowsHookEx { int idHoook HOOKPROC lpfn HINSTANCE hMod DOWRD dwThreadId }
|
DLL注入
DLL注入指的是想运行中的进程强制插入DLL文件。具体来讲就是让其他进程调用LoadLibrary().
具体方法
创建远程线程
bool inject_dll(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; if(!(hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, dwPID))) { __tprintf(L"OpenProcess(&d) failed!!!", dwPID, GetLastError()); return false; } pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize, MEM_COMMIT, PAGE_READWRITE); WriteProcessMemory(hProcess, pRemoteBuf, (LPVOID)szDllPath, dwBufSize, NULL); hMod = GetModuleHandle(L"kernel32.dll"); pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hMod, "LoadLibraryW"); hThread = CreateRemoteThread(hProcess, NULL, 0, pThreadProc, pRemoteBuf, 0, NULL); WaitForSingleObject(hTread, INFIINITE); CloseHandle(hTread); CloseHandle(hProcess); return true; }
int main(int argc, char *argv[]) { if(argc != 3) { _tprintf(L"USAGE : %S PID dll_path\n", argv[0]); return 1; } 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; }
|
- OpenProcess(PROCESS_ALL_ACCESS, false, dwPID): 获得目标进程句柄.第一个参数是获得所有权限,最后一个是程序运行时传过来的
- VirtualAllocEx, WriteProcessMemory: 将dll写入进程
- GetModuleHandle, GetProceAddress: 获得LoadLibraryW()API的地址
- CreateRemoteThread: 远程运行线程
使用注册表
Windows操作系统中默认提供AppInit_DLLs和LoadAppInit_DLLs两个注册表项
大致过程为将要注入的DLL的路径字符串吸入AppInit_DLLs项目,然后把LoadAppInit_DLLs项目值设为1.
#define DEF_CMD L"c:\\Program Files\\Internet Explorer\\iexplore.exe" #define DEF_ADDR L"http://www.naver.com" #define DEF_DST_PROC L"notepad.exe"
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReaseved) { TCHAR szCmd[MAX_PATH] = {0, }; TCHAR szPath[MAX_PATH] = {0, }; TCHAR *p = NULL; STARTUPINFO si = {0,}; si.cb = sizeof(STARTUPINFO); si.dwFlags = STARTF_SUESHOWWINDOW; si.wShowWindow = SW_HIDE; switch(fdwReason) { case DLL_PROCESS_ATTACH: if(!GetModuleFileName(NULL, szPath, MAX_PATH)) { break; } if(!(p == _tcsrchr(szPath, '\\'))) { break; } if(_tcsicmp(p+1, DEF_DST_PROC)) { break; } wsprintf(szCmd, L"%s %s", DEF_CMD, DEF_ADDR); if(!CreateProcess(NULL, (LPTSTR)(LPCTSTR)szCmd, NULL, NULL, false, NORMAL_PRIOPRITY_CLASS, NULL, NULL, &si, &pi)) { break; } if(pi.hProcess != NULL) { CloseHandle(pi.hProcess); } break; } return true; }
|
这段代码的作用是判断当前加载进程是否是notepad.exe,如果是就运行IE链接网址
接下来要做的就是将DLL信息写进注册表项中。
DLL卸载
DLL卸载就是要让进程调用FreeLibrary()API。
- CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID): 这个函数的作用是获得加载到进程的DLL信息。返回值是一个句柄,传递给Module32First(返回值, &information)后,就可以在information中获得dll相关信息
typedef struct tagMODULEENTRY32 { DWORD dwSize DWORD th32ModuleID DWORD th32ProcessID DWORD GlblcntUsage DWORD ProccntUsage BYTE *modBaseAddr DWORD modBaseSize HMODULE hModule char szModule[MAX_MODULE_NAME32 + 1] CHAR szExePath[MAX_PATH] }MODULEENTRY32
|
上面就是information结构体的具体内容。szModule是这个dll的名称
- OpenProcess(PROCESS_ALL_ACCESS, FLASE, dwPID): 获得目标进程的句柄
- GetModuleHandle(“kernel32.dll”)
- (LPTHREAD_START_ROUNTINE)GetProcAddress(hModule, “FreeLibrary”):上面两个是获取FreeeLibrary的地址
- CreateRemoteThread(hProcess, NULL, 0, pThreadProc, information.modBaseAddr, 0, NULL): hThreadProc是FreeLibrary的API地址, modBaseAddr是需要卸载的API地址