Qt:Windows编程—代码注入
前言
? 這里所說的代碼注入和上篇的DLL注入有類似之處。DLL文件的注入與卸載在上篇中都完成了,整個注入與卸載的過程其實就是讓遠程線程執行一次LoadLibrary函數或者FreeLibrary函數。遠程線程裝載或者卸載一個DLL文件,通過dllMain()調用DLL中具體功能代碼,這樣注入DLL以后就可以讓DLL做很多事情了。
? 是否可以不依賴DLL文件直接向目標進程寫入要執行的代碼,完成特定的功能呢?當然是可以的。這節我們就來實現代碼注入到指定的進程中。
代碼注入思路
? 要在目標進程中完成一定的特定功能,就需要使用相關的API函數,不同的API函數實現在不同的DLL中。Kernel32.dll文件在每個進程中的地址是相同的,但是并不代表其他的DLL文件在每個進程中的地址都是一樣的。這樣,在目標進程中調用每一個API函數時,必須使用LoadLibrary(或GetModuleHandle)函數和GetProcAddress函數動態導出用到的每個API函數(必需的)。把想要使用的API函數及API函數所在的DLL文件都封裝進一個結構體 (作為寫的函數代碼的參數),直接寫入目標進程的空間中。直接把要在遠程執行的代碼也寫入到目標進程的內存空間中,最后調用CreateRemoteThread函數即可將其運行。
界面效果
有圖有真相!我們往QQ.exe進程中 注入代碼。
核心代碼
選擇注入的進程,這里主要是用到了進程遍歷,可以參考 Qt:Windows編程—Qt實現進程管理 這篇博文。
封裝的結構體
這個數據類型就是要傳遞 線程回調函數的參數,也就是我們注入的函數代碼的參數。
#define STRLEN 20 typedef struct _mydata{// 4個不變函數的函數地址DWORD dwLoadLibrary;DWORD dwGetProcAddress;DWORD dwGetModuleFileName;DWORD dwGetModuleHandle;char user32dll[STRLEN]; // user32.dll 含有MessageBoxA函數char MessageBoxFun[STRLEN]; // "MessageBoxA" 字符串char msvcrtdll[STRLEN]; // MSVCRT.DLL 微軟運行庫 含有strcat函數char strcatFun[STRLEN]; // "strcat" 字符串char caption[STRLEN]; // 消息框標題 "Inject Code!"char content[MAX_PATH]; // 消息框內容 }MyData;注入的代碼
// 注入的可執行代碼,執行彈框功能 DWORD WINAPI CodeFunc(LPVOID param) {MyData* data = (MyData*)param;// 定義函數指針類型 方便下面的類型轉換typedef HMODULE (__stdcall *MyLoadLibrary)(LPCSTR);typedef FARPROC (__stdcall *MyGetProcAddress)(HMODULE,LPCSTR);typedef DWORD (__stdcall *MyGetModuleFileName)(HMODULE,LPSTR,DWORD);typedef HMODULE (*MyGetModuleHandle)(LPCSTR);typedef int (__stdcall *MyMessageBox)(HWND,LPCSTR,LPCSTR,UINT);typedef char*(*Mystrcat)(char *dest, const char *src);// 獲取函數地址MyLoadLibrary myLoadLibrary = (MyLoadLibrary)data->dwLoadLibrary;MyGetProcAddress myGetProcAddress = (MyGetProcAddress)data->dwGetProcAddress;MyGetModuleFileName myGetModuleFileName = (MyGetModuleFileName)data->dwGetModuleFileName;MyGetModuleHandle myGetModuleHandle = (MyGetModuleHandle)data->dwGetModuleHandle;// 所有用的函數,都需像下面一樣 導出函數地址然后再使用,包括標準庫函數也一樣// 筆者剛開始就犯了一個錯,直接使用sprintf、strcat 等函數,這樣是不行!因為我們自己注入的代碼,函數地址需要我們自己確定!HMODULE user32dll = myLoadLibrary(data->user32dll);HMODULE msvcrtdll = myGetModuleHandle(data->msvcrtdll);// msvcrt.dll 微軟運行庫,可直接獲取MyMessageBox myMessageBox = (MyMessageBox)myGetProcAddress(user32dll,data->MessageBoxFun);Mystrcat mystrcat = (Mystrcat)myGetProcAddress(msvcrtdll,data->strcatFun);// 調用獲取到的函數char curFile[MAX_PATH] = {0};myGetModuleFileName(NULL,curFile,MAX_PATH);mystrcat(data->content,curFile);myMessageBox(NULL, data->content ,data->caption, MB_OK);return 0; }注入代碼操作
// 注入Code操作 void WorkerThread::injectCode() {HANDLE targetProc = OpenProcess(PROCESS_ALL_ACCESS,FALSE,m_pId);if( targetProc == NULL ){qDebug() << "OpenProcess error";return;}MyData data = {0};strcpy(data.user32dll,"user32.dll");strcpy(data.msvcrtdll,"msvcrt.dll");strcpy(data.MessageBoxFun,"MessageBoxA");strcpy(data.strcatFun,"strcat");strcpy(data.caption,"Inject Code!");strcpy(data.content,"current process:");// 這里使用中文會亂碼HMODULE module = GetModuleHandleA("kernel32.dll");data.dwLoadLibrary = (DWORD)GetProcAddress(module,"LoadLibraryA");data.dwGetProcAddress = (DWORD)GetProcAddress(module,"GetProcAddress");data.dwGetModuleFileName = (DWORD)GetProcAddress(module,"GetModuleFileNameA");data.dwGetModuleHandle = (DWORD)GetProcAddress(module,"GetModuleHandleA");int dataLen = sizeof(MyData);// 1.目標進程申請空間 存放data數據,也就是注入的 可執行代碼函數 的參數LPVOID pData = VirtualAllocEx(targetProc,NULL,dataLen,MEM_COMMIT | MEM_RESERVE,PAGE_READWRITE );if( pData == NULL ){qDebug() << "VirtualAllocEx error 1";return;}int ret = WriteProcessMemory(targetProc,pData,&data,dataLen,NULL);if( ret == 0 ){qDebug() << "WriteProcessMemory error 1";return;}// 2.目標進程申請空間 存放CodeFunc可執行代碼函數int codeLen = 0x4000; // 4 * 16^3 = 16KB足夠了// 第5個參數,數據具有可執行權限LPVOID pCode = VirtualAllocEx(targetProc,NULL,codeLen,MEM_COMMIT,PAGE_EXECUTE_READWRITE );if( pCode == NULL ){qDebug() << "VirtualAllocEx error 2";return;}ret = WriteProcessMemory(targetProc,pCode,(LPCVOID)&CodeFunc,codeLen,NULL);if( ret == 0 ){qDebug() << "WriteProcessMemory error 2";return;}// 3.創建遠程線程 執行可執行代碼HANDLE tHandle = CreateRemoteThread(targetProc,NULL,NULL,(LPTHREAD_START_ROUTINE)pCode,pData,NULL,NULL);if(tHandle == NULL){qDebug() << "CreateRemoteThread error";return ;}qDebug() << "注入,wait ..." ;WaitForSingleObject(tHandle,INFINITY);CloseHandle(tHandle);CloseHandle(targetProc);qDebug() << "注入,finish ...";emit doInjectFinish(); }完整代碼
完整代碼工程請在這里下載。
總結
以上是生活随笔為你收集整理的Qt:Windows编程—代码注入的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 线性表:链栈算法实现
- 下一篇: 12. OD-XOFTSPY监控系统软件