先來段簡單的,親測成功!!!
// test2.cpp : 定義控制臺應(yīng)用程序的入口點。
//#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注入技術(shù)的用途
DLL注入技術(shù)的用途是很廣泛的,這主要體現(xiàn)在:
1、假如你要操縱的對象涉及的數(shù)據(jù)不在進(jìn)程內(nèi);
2、你想對目標(biāo)進(jìn)程中的函數(shù)進(jìn)行攔截(甚至API函數(shù),嘿嘿,由此編寫個攔截timeGettime的過程,變速齒輪不就出來了么?改天我試試),比如對它所屬窗口進(jìn)行子類化。
3、你想編寫一些函數(shù)用于增強(qiáng)或增加目標(biāo)進(jìn)程功能,比如可以給目標(biāo)進(jìn)程的某個窗口插入個消息循環(huán)增加其響應(yīng)能力。(Mfc Windows程序設(shè)計稱之為消息泵)。
4、隱藏自己的程序,很多惡意程序都是這樣做的,即使你將惡意程序的進(jìn)程結(jié)束掉也毫無意義了,因為它自己已經(jīng)插入到很多進(jìn)程中去了,唯一有效的辦法只有注銷windows.。如果你是個愛搞破壞的人就更應(yīng)該掌握該技術(shù)了,不但可以利用該技術(shù)實現(xiàn)隱藏自己的進(jìn)程,還可以破壞某個目標(biāo)進(jìn)程。因為將破壞代碼插入到目標(biāo)進(jìn)程進(jìn)行破壞的話簡直易如反掌。不信試試?:(
二、實現(xiàn)DLL注入的另一種方法
1、將DLL注入進(jìn)程技術(shù)在實現(xiàn)Api函數(shù)的監(jiān)視程序中不可缺少的一項工作。其中最常見的就是用SetWindowsHookEx函數(shù)實現(xiàn)了。不過,該方法的缺點是被監(jiān)視的目標(biāo)進(jìn)程必須有窗口,這樣,SetWindowsHookEx才能將DLL注入目標(biāo)進(jìn)程中。而且,目標(biāo)程序已經(jīng)運(yùn)行了,那么,在窗口創(chuàng)建之前的Api函數(shù)就不能被Hook了。
2、另外一種方法用Debug方案,就可以實現(xiàn)在程序創(chuàng)建時監(jiān)視所有的Api了,缺點是必須是目標(biāo)進(jìn)程的Debug源,在監(jiān)視程序終了時,目標(biāo)進(jìn)程會無條件終了。最大的缺點就是無法調(diào)試注入的DLL。
3、還有其他多種方案也可以實現(xiàn)DLL的注入,在《Windows核心編程》一書中就介紹了8-9種,其中有一種采用CreateProcess的方法,實現(xiàn)起來比較復(fù)雜,但沒有上面幾種方法的局限性。且可以用其他工具(VC等)調(diào)試注入的DLL。下面進(jìn)行介紹。
原理如下:
1). 用CreateProcess(CREATE_SUSPENDED)啟動目標(biāo)進(jìn)程。
2).?找到目標(biāo)進(jìn)程的入口,用ImageHlp中的函數(shù)可以實現(xiàn)。
3). 將目標(biāo)進(jìn)程入口的代碼保存起來。
4).?在目標(biāo)進(jìn)程的入口寫入LoadLibrary(MyDll)實現(xiàn)Dll的注入。
5). 用ResumeThread運(yùn)行目標(biāo)進(jìn)程。
6).?目標(biāo)進(jìn)程就運(yùn)行了LoadLibrary(MyDll),實現(xiàn)DLL的注入。
7).?目標(biāo)進(jìn)程運(yùn)行完LoadLibrary(MyDll)后,將原來的代碼寫回目標(biāo)進(jìn)程的入口。
8).?目標(biāo)進(jìn)程Jmp至原來的入口,繼續(xù)運(yùn)行程序。
從原理上可以看出,DLL的注入在目標(biāo)進(jìn)程的開始就運(yùn)行了,而且不是用Debug的方案,這樣,就沒有上面方案的局限性了。該方案的關(guān)鍵在6,7,8三步,實現(xiàn)方法需要監(jiān)視進(jìn)程和DLL合作。下面,結(jié)合代碼進(jìn)行分析。
在監(jiān)視進(jìn)程中,創(chuàng)建FileMapping,用來保存目標(biāo)進(jìn)程的入口代碼,同時保證DLL中可以訪問。在第7步實現(xiàn)將原目標(biāo)代碼寫回目標(biāo)進(jìn)程的入口。
[cpp]?view plain
?copy ?? #pragma?pack?(push?,1)??//?保證下面的結(jié)構(gòu)體采用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)??
上面結(jié)構(gòu)體的代碼為匯編代碼,對應(yīng)的匯編為:
[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;??
準(zhǔn)備工作:
第一步:用CreateProcess(CREATE_SUSPENDED)啟動目標(biāo)進(jìn)程。
[cpp]?view plain
?copy CreateProcessA(0,?szRunFile,?0,?0,?FALSE,?CREATE_SUSPENDED?? 0,?NULL,?&stInfo,?? &m_proInfo)?;??
用CreateProcess啟動一個暫停的目標(biāo)進(jìn)程;
找到目標(biāo)進(jìn)程的入口點,函數(shù)如下
第二步:找到目標(biāo)進(jìn)程的入口,用ImageHlp中的函數(shù)可以實現(xiàn)。
[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;?? }??
// 創(chuàng)建FileMapping
[cpp]?view plain
?copy hMap?=?CreateFileMapping((HANDLE)0xFFFFFFFF,?NULL,?? PAGE_READWRITE,?0,?sizeof(SPY_MEM_SHARE),?“MyDllMapView”);??
// 保存目標(biāo)進(jìn)程的代碼
第三步:將目標(biāo)進(jìn)程入口的代碼保存起來。
[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;??
// 第四步:在目標(biāo)進(jìn)程的入口寫入LoadLibrary(MyDll)實現(xiàn)Dll的注入。
// 準(zhǔn)備注入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);??
// 繼續(xù)目標(biāo)進(jìn)程的運(yùn)行
第五步:用ResumeThread運(yùn)行目標(biāo)進(jìn)程。
[cpp]?view plain
?copy ResumeThread(m_proInfo.hThread);??
在監(jiān)視進(jìn)程中就結(jié)束了自己的任務(wù),剩下的第6,7,8步就需要在Dll的DllMain中進(jìn)行配合。
DLL中用來保存數(shù)據(jù)的結(jié)構(gòu)體
[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中調(diào)用InitApiSpy函數(shù)
// 在該函數(shù)中實現(xiàn)第6,7,8步
第六步:目標(biāo)進(jìn)程就運(yùn)行了LoadLibrary(MyDll),實現(xiàn)DLL的注入。
[cpp]?view plain
?copy int?WINAPI?DllMain(HINSTANCE?hInst,?DWORD?dwReason,?LPVOID?lpReserved)?? {?? switch(dwReason)?? {?? case?DLL_PROCESS_ATTACH:?? ????return?InitApiSpy();?? ????……??
// InitApiSpy函數(shù)的實現(xiàn)
[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)?? ????????{??
第七步:目標(biāo)進(jìn)程運(yùn)行完LoadLibrary(MyDll)后,將原來的代碼寫回目標(biāo)進(jìn)程的入口。
[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?? }??
?
第八步:目標(biāo)進(jìn)程Jmp至原來的入口,繼續(xù)運(yùn)行程序。
[cpp]?view plain
?copy ?? _asm?popad?? _asm?jmp?_lpCode.lpEntryPoint?? }??
這樣就實現(xiàn)了原來的目標(biāo),將DLL的注入放在目標(biāo)進(jìn)程的入口運(yùn)行,實現(xiàn)了目標(biāo)進(jìn)程運(yùn)行之前運(yùn)行我們的注入Dll的功能。
總結(jié)
以上是生活随笔為你收集整理的CreateProcess启动游戏注入DLL的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。