先來段簡單的,親測成功!!!
// test2.cpp : 定義控制臺應用程序的入口點。
//#include "stdafx.h"
#include <Windows.h>
#include<iostream>
#include<stdlib.h>using namespace std;int _tmain(int argc, _TCHAR* argv[])
{TCHAR szDll[] = TEXT("d:\\zlib1.dll"); STARTUPINFO si = {0}; PROCESS_INFORMATION pi = {0}; si.cb = sizeof(si); si.dwFlags = STARTF_USESHOWWINDOW; si.wShowWindow = SW_SHOW; TCHAR szCommandLine[MAX_PATH] = TEXT("D:\\軟件目錄\\dll查看器\\ViewApi.exe"); CreateProcess(NULL, szCommandLine, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi); LPVOID Param = VirtualAllocEx(pi.hProcess, NULL, MAX_PATH, MEM_COMMIT, PAGE_EXECUTE_READWRITE); WriteProcessMemory(pi.hProcess, Param, (LPVOID)szDll, _tcslen(szDll)*2+sizeof(TCHAR), NULL); HANDLE hThread = CreateRemoteThread(pi.hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibraryW,Param, CREATE_SUSPENDED, NULL); ResumeThread(pi.hThread); if (hThread) { ResumeThread(hThread); WaitForSingleObject(hThread, INFINITE); } return 0;
}
==============================================================================================
一、DLL注入技術的用途
DLL注入技術的用途是很廣泛的,這主要體現在:
1、假如你要操縱的對象涉及的數據不在進程內;
2、你想對目標進程中的函數進行攔截(甚至API函數,嘿嘿,由此編寫個攔截timeGettime的過程,變速齒輪不就出來了么?改天我試試),比如對它所屬窗口進行子類化。
3、你想編寫一些函數用于增強或增加目標進程功能,比如可以給目標進程的某個窗口插入個消息循環增加其響應能力。(Mfc Windows程序設計稱之為消息泵)。
4、隱藏自己的程序,很多惡意程序都是這樣做的,即使你將惡意程序的進程結束掉也毫無意義了,因為它自己已經插入到很多進程中去了,唯一有效的辦法只有注銷windows.。如果你是個愛搞破壞的人就更應該掌握該技術了,不但可以利用該技術實現隱藏自己的進程,還可以破壞某個目標進程。因為將破壞代碼插入到目標進程進行破壞的話簡直易如反掌。不信試試?:(
二、實現DLL注入的另一種方法
1、將DLL注入進程技術在實現Api函數的監視程序中不可缺少的一項工作。其中最常見的就是用SetWindowsHookEx函數實現了。不過,該方法的缺點是被監視的目標進程必須有窗口,這樣,SetWindowsHookEx才能將DLL注入目標進程中。而且,目標程序已經運行了,那么,在窗口創建之前的Api函數就不能被Hook了。
2、另外一種方法用Debug方案,就可以實現在程序創建時監視所有的Api了,缺點是必須是目標進程的Debug源,在監視程序終了時,目標進程會無條件終了。最大的缺點就是無法調試注入的DLL。
3、還有其他多種方案也可以實現DLL的注入,在《Windows核心編程》一書中就介紹了8-9種,其中有一種采用CreateProcess的方法,實現起來比較復雜,但沒有上面幾種方法的局限性。且可以用其他工具(VC等)調試注入的DLL。下面進行介紹。
原理如下:
1). 用CreateProcess(CREATE_SUSPENDED)啟動目標進程。
2).?找到目標進程的入口,用ImageHlp中的函數可以實現。
3). 將目標進程入口的代碼保存起來。
4).?在目標進程的入口寫入LoadLibrary(MyDll)實現Dll的注入。
5). 用ResumeThread運行目標進程。
6).?目標進程就運行了LoadLibrary(MyDll),實現DLL的注入。
7).?目標進程運行完LoadLibrary(MyDll)后,將原來的代碼寫回目標進程的入口。
8).?目標進程Jmp至原來的入口,繼續運行程序。
從原理上可以看出,DLL的注入在目標進程的開始就運行了,而且不是用Debug的方案,這樣,就沒有上面方案的局限性了。該方案的關鍵在6,7,8三步,實現方法需要監視進程和DLL合作。下面,結合代碼進行分析。
在監視進程中,創建FileMapping,用來保存目標進程的入口代碼,同時保證DLL中可以訪問。在第7步實現將原目標代碼寫回目標進程的入口。
[cpp]?view plain
?copy ?? #pragma?pack?(push?,1)??//?保證下面的結構體采用BYTE對齊(必須)?? typedef?struct??? {?? ????BYTE?int_PUSHAD;?????? ????BYTE?int_PUSH;???????? ????DWORD?push_Value;????? ????BYTE?int_MOVEAX;?????? ????DWORD?eax_Value;?????? ????WORD?call_eax;???????? ????BYTE?jmp_MOVEAX;?????? ????DWORD?jmp_Value;?????? ????WORD?jmp_eax;????????? ????char?szDLL[MAX_PATH];??? }INJECT_LOADLIBRARY_CODE,?*LPINJECT_CODE;?? #pragma?pack?(pop?,?1)??
上面結構體的代碼為匯編代碼,對應的匯編為:
[cpp]?view plain
?copy pushad?? push?szDll?? mov?eax,?&LoadLibraryA?? call?eax?????????????????????????????????? mov?eax,?oldentry?? jmp?eax??????????????????????????????????? ?? typedef?struct??? {?? ????LPBYTE?lpEntryPoint;?????????????????? ????BYTE?oldcode[sizeof(INJECT_CODE)];???? }SPY_MEM_SHARE,?*?LPSPY_MEM_SHARE;??
準備工作:
第一步:用CreateProcess(CREATE_SUSPENDED)啟動目標進程。
[cpp]?view plain
?copy CreateProcessA(0,?szRunFile,?0,?0,?FALSE,?CREATE_SUSPENDED?? 0,?NULL,?&stInfo,?? &m_proInfo)?;??
用CreateProcess啟動一個暫停的目標進程;
找到目標進程的入口點,函數如下
第二步:找到目標進程的入口,用ImageHlp中的函數可以實現。
[cpp]?view plain
?copy pEntryPoint?=?GetExeEntryPoint(szRunFile);?? LPBYTE?GetExeEntryPoint(char?*filename)?? {?? ????PIMAGE_NT_HEADERS?pNTHeader;?? ????DWORD?pEntryPoint;?? ????PLOADED_IMAGE?pImage;?? ????pImage?=?ImageLoad(filename,?NULL);?? ????if(pImage?==?NULL)?? ????????return?NULL;?? ????pNTHeader?=?pImage->FileHeader;?? ????pEntryPoint?=?pNTHeader->OptionalHeader.AddressOfEntryPoint?+?pNTHeader->OptionalHeader.ImageBase;?? ????ImageUnload(pImage);?? ????return?(LPBYTE)pEntryPoint;?? }??
// 創建FileMapping
[cpp]?view plain
?copy hMap?=?CreateFileMapping((HANDLE)0xFFFFFFFF,?NULL,?? PAGE_READWRITE,?0,?sizeof(SPY_MEM_SHARE),?“MyDllMapView”);??
// 保存目標進程的代碼
第三步:將目標進程入口的代碼保存起來。
[cpp]?view plain
?copy LPSPY_MEM_SHARE?lpMap?=?pMapViewOfFile(hMap,?FILE_MAP_ALL_ACCESS,0,?0,?0);?? ReadProcessMemory(m_proInfo.hProcess,?pEntryPoint,&lpMap->oldcode,?sizeof(INJECT_CODE),&cBytesMoved);?? lpMap->lpEntryPoint?=?pEntryPoint;??
// 第四步:在目標進程的入口寫入LoadLibrary(MyDll)實現Dll的注入。
// 準備注入DLL的代碼
[cpp]?view plain
?copy INJECT_CODE?newCode;?? ?? lstrcpy(newCode.szDLL,?szMyDll);?? ?? newCode.int_PUSHAD?=?0x60;??? newCode.int_PUSH?=?0x68;?? newCode.int_MOVEAX?=?0xB8;?? newCode.call_eax?=?0xD0FF;?? newCode.jmp_MOVEAX?=?0xB8;?? newCode.jmp_eax?=?0xE0FF;?? newCode.eax_Value?=?(DWORD)&LoadLibrary;?? newCode.push_Value=(pEntryPoint?+?offsetof(INJECT_CODE,szDLL));?? ?? ?? DWORD?dwNewFlg,?dwOldFlg;?? dwNewFlg?=?PAGE_READWRITE;?? VirtualProtectEx(m_proInfo.hProcess,?(LPVOID)pEntryPoint,?sizeof(DWORD),?dwNewFlg,?&dwOldFlg);?? WriteProcessMemory(m_proInfo.hProcess,?pEntryPoint,&newCode,?sizeof(newCode),?NULL);?? VirtualProtectEx(proInfo.hProcess,?(LPVOID)pEntryPoint,?sizeof(DWORD),?dwOldFlg,?&dwNewFlg);?? ?? UnmapViewOfFile(lpMap);??
// 繼續目標進程的運行
第五步:用ResumeThread運行目標進程。
[cpp]?view plain
?copy ResumeThread(m_proInfo.hThread);??
在監視進程中就結束了自己的任務,剩下的第6,7,8步就需要在Dll的DllMain中進行配合。
DLL中用來保存數據的結構體
[cpp]?view plain
?copy typedef?struct?? {?? ????DWORD?lpEntryPoint;?? ????DWORD?OldAddr;?? ????DWORD?OldCode[4];????? }JMP_CODE,*?LPJMP_CODE;?? static?JMP_CODE?_lpCode;??
// 在DllMain的DLL_PROCESS_ATTACH中調用InitApiSpy函數
// 在該函數中實現第6,7,8步
第六步:目標進程就運行了LoadLibrary(MyDll),實現DLL的注入。
[cpp]?view plain
?copy int?WINAPI?DllMain(HINSTANCE?hInst,?DWORD?dwReason,?LPVOID?lpReserved)?? {?? switch(dwReason)?? {?? case?DLL_PROCESS_ATTACH:?? ????return?InitApiSpy();?? ????……??
// InitApiSpy函數的實現
[cpp]?view plain
?copy BOOL?WINAPI?InitApiSpy()?? {?? ????HANDLE?hMap;?? ????LPSPY_MEM_SHARE?lpMem;?? ????DWORD?dwSize;?? ????BOOL?rc;?? ????BYTE*?lpByte;?? ?????? ????hMap?=?OpenFileMapping(FILE_MAP_ALL_ACCESS,?0,?“MyDllMapView”);?? ????if(hMap)?? ????{?? ????????lpMem?=?(LPSPY_MEM_SHARE)MapViewOfFile(hMap,FILE_MAP_ALL_ACCESS,0,?0,?0);?? ????????if(lpMem)?? ????????{??
第七步:目標進程運行完LoadLibrary(MyDll)后,將原來的代碼寫回目標進程的入口。
[cpp]?view plain
?copy BOOL?WINAPI?InitApiSpy()?? {?? ????HANDLE?hMap;?? ????LPSPY_MEM_SHARE?lpMem;?? ????DWORD?dwSize;?? ????BOOL?rc;?? ????BYTE*?lpByte;?? ?????? ????hMap?=?OpenFileMapping(FILE_MAP_ALL_ACCESS,?0,?“MyDllMapView”);?? ????if(hMap)?? ????{?? ????????lpMem?=?(LPSPY_MEM_SHARE)MapViewOfFile(hMap,FILE_MAP_ALL_ACCESS,0,?0,?0);?? ????????if(lpMem)?? ????????{?? ?? ?????????????? ?????????????? ????????????_lpCode.OldAddr?=?(DWORD)((BYTE*)lpMem->lpEntryPoint?+?offsetof(INJECT_CODE,?jmp_MOVEAX));?? ????????????_lpCode.lpEntryPoint?=?(DWORD)lpMem->lpEntryPoint;?? ?????????????? ????????????memcpy(&_lpCode.OldCode,?(BYTE*)lpMem->oldcode?+?offsetof(INJECT_CODE,?jmp_MOVEAX),?2*sizeof(DWORD));?? ?????????????? ????????????rc?=?WriteProcessMemory(GetCurrentProcess(),?lpMem->lpEntryPoint,?lpMem->oldcode,?sizeof(INJECT_CODE),?&dwSize);?? ????????????lpByte?=?(BYTE*)lpMem->lpEntryPoint?+?offsetof(INJECT_CODE,?jmp_MOVEAX);?? ????????????UnmapViewOfFile(lpMem);?? ????????}?? ????????CloseHandle(hMap);?? ????}?? ?????? ?????? ?????? ?????? ?????? ????{?? ????????BYTE*?lpMovEax;?? ????????DWORD*?lpMovEaxValu;?? ????????WORD*?lpJmp;?? ????????DWORD?fNew,?fOld;?? ????????fNew?=?PAGE_READWRITE;?? ????????lpMovEax?=?lpByte;?? ????????VirtualProtect(lpMovEax,?2*sizeof(DWORD),?fNew,?&fOld);?? ????????*lpMovEax?=?0xB8;?? ????????lpMovEaxValu?=?(DWORD*)(lpMovEax?+?1);?? ????????*lpMovEaxValu?=?(DWORD)&DoJmpEntryPoint;?? ????????lpJmp?=?(WORD*)(lpMovEax?+?5);?? ????????*lpJmp?=?0xE0FF;??? ????????VirtualProtect(lpMovEax,?2*sizeof(DWORD),?fOld,?&fNew);?? ????}?? ????return?TRUE;?? }??
?
[cpp]?view plain
?copy ?? DWORD*?lpMovEax;?? DWORD?fNew,?fOld;?? void?__declspec(naked)?DoJmpEntryPoint?()?? {?? ?????? ????_gfNew?=?PAGE_READWRITE;?? ????_glpMovEax?=?(DWORD*)_lpCode.OldAddr;?? ????VirtualProtect(_glpMovEax,?2*sizeof(DWORD),?_gfNew,?&_gfOld);?? ????*_glpMovEax?=?_lpCode.OldCode[0];?? ????*(_glpMovEax?+?1)?=?_lpCode.OldCode[1];?? ????VirtualProtect(_glpMovEax,?2*sizeof(DWORD),?_gfOld,?&_gfNew);?? ?? ?? _asm?popad?? _asm?jmp?_lpCode.lpEntryPoint?? }??
?
第八步:目標進程Jmp至原來的入口,繼續運行程序。
[cpp]?view plain
?copy ?? _asm?popad?? _asm?jmp?_lpCode.lpEntryPoint?? }??
這樣就實現了原來的目標,將DLL的注入放在目標進程的入口運行,實現了目標進程運行之前運行我們的注入Dll的功能。
總結
以上是生活随笔為你收集整理的CreateProcess启动游戏注入DLL的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。