www.pudn.com > 将DLL注入到其他进程中.rar > ForceLibrary.cpp


////// 
/////                        -=[ ForceLibrary.dll ]=- 
////                                by yoda/f2f 
///                                version: 1.3 
// 
//     Please report any bugs/comments/suggestions to yoda_f2f@gmx.net 
// 
 
#define  WIN32_LEAN_AND_MEAN 
#include  
#include  
#include  
#include  
#include "th32.h" 
 
#pragma comment(linker,"/FILEALIGN:0x200 /MERGE:.rdata=.text /MERGE:.data=.text /SECTION:.text,EWR /IGNORE:4078") 
#pragma pack(1) // very important ! 
 
// these code structs load the dll 
//#define INJ_CODE_DBG 
 
typedef struct 
{ 
#ifdef INJ_CODE_DBG 
    BYTE  Int3;     
#endif 
	BYTE  PushOpc;           // 0x68     = push (dword) 
	DWORD PushAddr;          // address of dll name 
	BYTE  CallOpc;           // 0xE8     = call (dword) 
	DWORD CallAddr;          // address of LoadLibraryAPI 
	WORD  jmp_$;             // 0xEBFE   = jmp eip 
} sLibLoadCode; 
 
typedef struct 
{ 
	BYTE  PushOpc;      // 0x68 = push (dword) 
	DWORD PushAddr;     // address of dll name 
	BYTE  CallOpc;      // 0xE8 = call (dword) 
	DWORD CallAddr;     // address of LoadLibraryAPI 
	BYTE  Int3;         // end of code 
	char  LibPath[256]; // path of the dll to load 
} sLibLoadCodeDBG; 
 
typedef struct 
{ 
	DWORD  dwImageBase; 
	DWORD  dwSizeOfImage; 
	DWORD  dwEntryPointVA; 
} sProcessPEInfo; 
 
// API prototypes 
typedef void* (WINAPI* fVirtualAllocEx)( 
	HANDLE hProcess, 
    LPVOID lpAddress, 
    DWORD dwSize, 
    DWORD flAllocationType, 
    DWORD flProtect 
); 
 
typedef BOOL (WINAPI* fVirtualFreeEx)( 
    HANDLE hProcess, 
    LPVOID lpAddress, 
    DWORD dwSize, 
    DWORD dwFreeType 
); 
 
// function prototypes 
BOOL   IsNT(); 
BOOL   InitCodeStruct(sLibLoadCode *LibLoaderCode, DWORD dwCodeStart, void *pDllPath); 
BOOL   InitCodeStructDBG(sLibLoadCodeDBG *LibLoaderCode,CHAR* szTargetLib,DWORD dwCodeStart); 
BOOL   GetProcessPEInfo(HANDLE hProc, void* pAddr, sProcessPEInfo *PEI); 
void*  GetProcessEntryPoint(DWORD PID); 
void*  GetProcessMem(HANDLE hProc, DWORD dwSize, DWORD dwAccess); 
BOOL   FreeProcessMem(HANDLE hProc, void* pAddr, DWORD dwSize); 
DWORD  ForceLibrary(CHAR* szDll,PROCESS_INFORMATION* pPI); 
BOOL   __stdcall TrapEntry(DWORD dwEntryPoint,PROCESS_INFORMATION *pPI); 
BOOL   __stdcall ForceLibraryDBG(CHAR* szTargetLib,DWORD dwEntryPoint,PROCESS_INFORMATION *pPI); 
DWORD  __stdcall PerformCleanup(DWORD dwEntryPoint,PROCESS_INFORMATION *pPI); 
 
// constants 
#define                        HEADER_SIZE         0x1000 
#define                        VA_SHARED           0x8000000 
#define                        LOADCODESIZEDBG     sizeof(sLibLoadCodeDBG) 
#define                        NT_PROCESS_ACCESS   PROCESS_VM_READ | PROCESS_QUERY_INFORMATION 
 
const BYTE                     Int3                = 0xCC; 
 
// global variables 
sLibLoadCodeDBG           LibLoadCodeDBG; 
DWORD                     dwLibBase; 
DWORD                     dwCodeStart,dwCodeEnd,dwBytesWritten,dwBytesRead; 
CONTEXT                   TestRegs; 
 
VOID*                     pCodeEntry; 
DWORD                     dwOldProt,dwNewProt; 
CONTEXT                   Regs,InitRegs; 
BYTE                      bOrgEntry; 
BOOL                      bNT; 
 
fVirtualAllocEx           _VirtualAllocEx; 
fVirtualFreeEx            _VirtualFreeEx; 
 
 
BOOL APIENTRY DllMain( HANDLE hModule,  
                       DWORD  fdwReason,  
                       LPVOID lpReserved 
					 ) 
{ 
	HINSTANCE hK32; 
 
	switch(fdwReason) 
	{ 
	case DLL_PROCESS_ATTACH: 
		bNT = IsNT(); 
 
		// load some API's dynamically 
		hK32 = GetModuleHandle("kernel32"); 
		_VirtualAllocEx = (fVirtualAllocEx)GetProcAddress(hK32, "VirtualAllocEx"); 
		_VirtualFreeEx = (fVirtualFreeEx)GetProcAddress(hK32, "VirtualFreeEx"); 
		break; 
	} 
    return TRUE; 
} 
 
BOOL IsNT() 
{ 
	DWORD dwVer; 
 
	dwVer = GetVersion(); 
	dwVer >>= 31; 
 
	return (dwVer == 0); 
} 
 
BOOL InitCodeStruct(sLibLoadCode   *LibLoaderCode, 
					DWORD          dwCodeStart, 
					void           *pDllPath) 
{ 
	DWORD dwLoadLibApiAddr; 
 
	dwLoadLibApiAddr = (DWORD)GetProcAddress( 
		GetModuleHandle("kernel32.dll"), 
		"LoadLibraryA"); 
	if (!dwLoadLibApiAddr) 
		return FALSE; 
	 
#ifdef INJ_CODE_DBG 
    LibLoaderCode->Int3             = Int3; 
#endif 
	LibLoaderCode->PushOpc          = 0x68; 
	LibLoaderCode->CallOpc          = 0xE8; 
	LibLoaderCode->CallAddr         = dwLoadLibApiAddr - dwCodeStart - offsetof(sLibLoadCode,jmp_$); 
	LibLoaderCode->PushAddr         = (DWORD)pDllPath; 
	LibLoaderCode->jmp_$            = 0xFEEB; 
 
	return TRUE; 
} 
 
BOOL InitCodeStructDBG(sLibLoadCodeDBG *LibLoaderCode,CHAR* szTargetLib,DWORD dwCodeStart) 
{ 
	DWORD dwLoadLibApiAddr; 
 
	LibLoaderCode->Int3 = Int3; 
	LibLoaderCode->PushOpc = 0x68; 
	LibLoaderCode->CallOpc = 0xE8; 
	dwLoadLibApiAddr = (DWORD)GetProcAddress( 
		GetModuleHandle("kernel32.dll"), 
		"LoadLibraryA"); 
	if (!dwLoadLibApiAddr) 
		return FALSE; 
	LibLoaderCode->CallAddr = dwLoadLibApiAddr - dwCodeStart - offsetof(sLibLoadCodeDBG,Int3); 
	strcpy(LibLoaderCode->LibPath,szTargetLib); 
	LibLoaderCode->PushAddr = dwCodeStart + offsetof(sLibLoadCodeDBG,LibPath); 
	return TRUE; 
} 
 
BOOL GetProcessPEInfo(HANDLE hProc, void* pAddr, sProcessPEInfo *PEI) 
{ 
	void*               pMem; 
	DWORD               dwBuff; 
	PIMAGE_NT_HEADERS   pNT; 
	BOOL                bRet     = FALSE; 
 
	pMem = malloc(HEADER_SIZE); 
	if (!pMem) 
		return FALSE; 
 
	if (!ReadProcessMemory( 
		hProc, 
		pAddr, 
		pMem, 
		HEADER_SIZE, 
		&dwBuff)) 
		goto Cleanup; 
 
	pNT = ImageNtHeader(pMem); 
	if (!pNT) 
		goto Cleanup; 
 
	PEI->dwImageBase    = pNT->OptionalHeader.ImageBase; 
	PEI->dwEntryPointVA = pNT->OptionalHeader.AddressOfEntryPoint + pNT->OptionalHeader.ImageBase; 
	PEI->dwSizeOfImage  = pNT->OptionalHeader.SizeOfImage; 
	bRet = TRUE; 
 
Cleanup: 
	free(pMem); 
	return bRet; 
} 
 
// returns... 
// 0 - error 
// else returns EntryPoint VA 
void* GetProcessEntryPoint(DWORD PID) 
{ 
 
#define MAX_SEARCH_BASE 0x80000000 
 
	HANDLE                     hSnap; 
	MODULEENTRY32              ModuleInfo; 
	PROCESSENTRY32             ProcInfo; 
	sProcessPEInfo             ProcPEInfo; 
	MEMORY_BASIC_INFORMATION   MBI; 
	CHAR                       ProcPath[256]; 
	DWORD                      dwMemSize,dwPEHeaderAddr; 
	VOID*                      pHeader; 
	HANDLE                     hProc; 
	void*                      p; 
 
	ProcPEInfo.dwEntryPointVA = 0; 
 
	if (!bNT) 
	{	// WIN 9X/ME 
 
		// get ToolHelp32 addresses 
		if (!GetTh32()) 
			return FALSE; 
 
		// I - get the process filename 
		hSnap = _CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0); 
		if (hSnap == INVALID_HANDLE_VALUE) 
			return 0; 
 
		// init the ProcInfo struct 
		ZeroMemory(&ProcInfo,sizeof(ProcInfo)); 
		ProcInfo.dwSize = sizeof(ProcInfo); 
 
		// find the to the PID corresponding file path 
		ProcPath[0] = 0; 
		_Process32First(hSnap,&ProcInfo); 
		do 
		{ 
			if (ProcInfo.th32ProcessID == PID) 
			{ 
				strcpy((LPTSTR)&ProcPath,ProcInfo.szExeFile); 
				break; 
			} 
		} while (_Process32Next(hSnap,&ProcInfo)); 
		CloseHandle(hSnap); 
		if (ProcPath[0] == 0) 
			return 0; 
 
		// II - find the ImageBase/SizeOfImage 
		hSnap = _CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,PID); 
		if (hSnap == INVALID_HANDLE_VALUE) 
			return 0; 
 
		// init the ModuleInfo struct 
		ZeroMemory(&ModuleInfo,sizeof(ModuleInfo)); 
		ModuleInfo.dwSize = sizeof(ModuleInfo); 
 
		ProcPEInfo.dwImageBase = 0; 
 
		_Module32First(hSnap,&ModuleInfo); 
		do 
		{ 
			if (stricmp((LPCTSTR)&ModuleInfo.szExePath,(LPCTSTR)&ProcPath) == 0) 
			{ 
				ProcPEInfo.dwImageBase = (DWORD)ModuleInfo.modBaseAddr; 
				ProcPEInfo.dwSizeOfImage = ModuleInfo.modBaseSize; 
				break; 
			} 
		} while (_Module32Next(hSnap,&ModuleInfo)); 
		CloseHandle(hSnap); 
 
		if (!ProcPEInfo.dwImageBase) 
			return 0; 
 
		// ...got BASE and IMAGESIZE 
 
		// get the EntryPoint 
		if (ProcPEInfo.dwSizeOfImage < HEADER_SIZE) 
			dwMemSize = ProcPEInfo.dwSizeOfImage; 
		else 
			dwMemSize = HEADER_SIZE; 
		if (!(hProc = OpenProcess(PROCESS_VM_READ,FALSE,PID))) 
			return 0; 
		if (!(pHeader = malloc(dwMemSize))) 
		{ 
			CloseHandle(hProc); 
			return 0; 
		} 
		if (!ReadProcessMemory( 
			hProc, 
			(PVOID)ProcPEInfo.dwImageBase, 
			pHeader, 
			dwMemSize, 
			&dwBytesRead)) 
			goto Cleanup; 
 
		if (!ImageNtHeader(pHeader)) 
			goto Cleanup; 
					 
		dwPEHeaderAddr = ((PIMAGE_DOS_HEADER)pHeader)->e_lfanew; 
		ProcPEInfo.dwEntryPointVA = ((PIMAGE_NT_HEADERS)(dwPEHeaderAddr + (DWORD)pHeader))->OptionalHeader \ 
			.AddressOfEntryPoint + ProcPEInfo.dwImageBase; 
 
Cleanup: 
		free(pHeader); 
		CloseHandle(hProc); 
	} 
	else 
	{	// WIN NT4/NT5 
		hProc = OpenProcess(NT_PROCESS_ACCESS, FALSE, PID); 
		if (!hProc) 
			return 0; 
 
		if (!GetProcessPEInfo(hProc, (void*)0x400000, &ProcPEInfo)) 
		{ 
			// check whole process memory for PE header 
			p = (void*)0x10000; 
			while ((DWORD)p < MAX_SEARCH_BASE) 
			{ 
				if (!VirtualQueryEx(hProc, p, &MBI, sizeof(MBI))) 
					goto Cleanup2; 
 
				if (MBI.State == MEM_COMMIT) 
					if (GetProcessPEInfo(hProc, p, &ProcPEInfo)) 
						break; 
				p = (void*)(0x10000 + (DWORD)p); 
			} 
 
			if ((DWORD)p == MAX_SEARCH_BASE) 
				goto Cleanup2; 
		} 
 
Cleanup2: 
		CloseHandle(hProc); 
	} 
 
	return (void*)ProcPEInfo.dwEntryPointVA; 
} 
 
void* GetProcessMem(HANDLE hProc, DWORD dwSize, DWORD dwAccess) 
{ 
	if (bNT) 
	{ 
		if (!_VirtualAllocEx) 
			return NULL; 
		return _VirtualAllocEx(hProc, NULL, dwSize, MEM_COMMIT, dwAccess); 
	} 
	else 
		return VirtualAlloc(NULL, dwSize, MEM_COMMIT + VA_SHARED, dwAccess); 
} 
 
BOOL FreeProcessMem(HANDLE hProc, void* pAddr, DWORD dwSize) 
{ 
	if (bNT) 
	{ 
		if (!_VirtualFreeEx) 
			return FALSE; 
		return _VirtualFreeEx(hProc, pAddr, dwSize, MEM_DECOMMIT); 
	} 
	else 
		return VirtualFree(pAddr, dwSize, MEM_DECOMMIT); 
} 
 
DWORD ForceLibrary(CHAR* szDll,PROCESS_INFORMATION* pPI) 
{ 
	CONTEXT                   c         = {CONTEXT_CONTROL | CONTEXT_INTEGER}; 
	void                      *pEntry, *pEntryBckp, *pDllPath; 
	sLibLoadCode              InjCode; 
	DWORD                     dwBuff, dwCodeEnd, dwDllBase, dwOldProt, dwDllPathLength; 
 
	dwDllBase = 0; 
	dwDllPathLength = lstrlen(szDll) + 1; 
 
	if (!(pEntry = GetProcessEntryPoint(pPI->dwProcessId))) 
		return 0; 
 
	// get memory for dll path 
	// ( I don't write the dll path also to the EntryPoint because of files whose sections 
	//   are merged and just have some bytes of code. The Import Table will be over- 
	//   written with the injected code, so NT won't be able to initialize the 
	//   it !!!) 
	pDllPath = GetProcessMem(pPI->hProcess, dwDllPathLength, PAGE_EXECUTE_READWRITE); 
	if (!pDllPath) 
		return 0; 
	if (!WriteProcessMemory( 
		pPI->hProcess, 
		pDllPath, 
		(void*)szDll, 
		dwDllPathLength, 
		&dwBuff)) 
	goto Cleanup; 
 
	InitCodeStruct(&InjCode, (DWORD)pEntry, pDllPath); 
 
	// write injection code to entrypoint 
	if (!VirtualProtectEx(pPI->hProcess, pEntry, sizeof(InjCode), PAGE_EXECUTE_READWRITE, 
		&dwOldProt)) 
		goto Cleanup; 
 
	pEntryBckp = malloc(sizeof(InjCode)); 
	if (!pEntryBckp) 
		goto Cleanup; 
 
	if (!ReadProcessMemory( 
		pPI->hProcess, 
		pEntry, 
		pEntryBckp, 
		sizeof(InjCode), 
		&dwBuff)) 
	{ 
		free(pEntryBckp); 
		goto Cleanup; 
	} 
 
	if (!WriteProcessMemory( 
		pPI->hProcess, 
		pEntry, 
		&InjCode, 
		sizeof(InjCode), 
		&dwBuff)) 
	{ 
		free(pEntryBckp); 
		goto Cleanup; 
	} 
 
	// execute the thread and wait... 
	dwCodeEnd = (DWORD)pEntry + offsetof(sLibLoadCode, jmp_$); 
	ResumeThread(pPI->hThread); 
	do 
	{ 
		Sleep(50); 
		GetThreadContext(pPI->hThread, &c); 
	} while (c.Eip != dwCodeEnd); 
	dwDllBase = c.Eax; 
 
	// suspend main thread 
	SuspendThread(pPI->hThread); 
 
	// restore Eip 
	c.Eip = (DWORD)pEntry; 
	SetThreadContext(pPI->hThread, &c); 
 
	// restore original Entrypoint code and page access 
	WriteProcessMemory(pPI->hProcess, pEntry, pEntryBckp, sizeof(InjCode), &dwBuff); 
	free(pEntryBckp); 
	VirtualProtectEx(pPI->hProcess, pEntry, sizeof(InjCode), dwOldProt, &dwBuff); 
 
Cleanup: 
	FreeProcessMem(pPI->hProcess, pDllPath, dwDllPathLength); 
 
	return dwDllBase; 
} 
 
BOOL __stdcall TrapEntry(DWORD dwEntryPoint,PROCESS_INFORMATION *pPI) 
{ 
	// simply set a 0CCh at the EntryPoint 
	VirtualProtectEx( 
		pPI->hProcess, 
		(VOID*)dwEntryPoint, 
		1, 
		PAGE_EXECUTE_READWRITE, 
		&dwOldProt); 
	if (!ReadProcessMemory( 
		pPI->hProcess, 
		(VOID*)dwEntryPoint, 
		(VOID*)&bOrgEntry, 
		1, 
		&dwBytesRead)) 
		return FALSE; 
	if (!WriteProcessMemory( 
		pPI->hProcess, 
		(VOID*)dwEntryPoint, 
		(VOID*)&Int3, 
		1, 
		&dwBytesWritten)) 
		return FALSE; 
	VirtualProtectEx( 
		pPI->hProcess, 
		(VOID*)dwEntryPoint, 
		1, 
		dwOldProt, 
		&dwNewProt); 
	return TRUE; 
} 
 
BOOL __stdcall ForceLibraryDBG(CHAR* szTargetLib, 
									   DWORD dwEntryPoint, 
									   PROCESS_INFORMATION *pPI) 
{ 
	// save the regs 
	Regs.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL; 
	if (!GetThreadContext(pPI->hThread,&Regs)) 
		return FALSE; 
	Regs.Eip = dwEntryPoint; 
	InitRegs = Regs; 
 
	// init the LibLoadCodeDBG struct 
	if (!InitCodeStructDBG(&LibLoadCodeDBG, szTargetLib, dwEntryPoint)) 
		return FALSE; 
 
	VirtualProtectEx( 
		pPI->hProcess, 
		(VOID*)dwEntryPoint, 
		LOADCODESIZEDBG, 
		PAGE_EXECUTE_READWRITE, 
		&dwOldProt); 
 
	// restore the EntryPoint-byte 
	if (!WriteProcessMemory( 
		pPI->hProcess, 
		(VOID*)dwEntryPoint, 
		&bOrgEntry, 
		1, 
		&dwBytesWritten)) 
		return FALSE; 
 
	// save the code at the EntryPoint 
	pCodeEntry = GlobalAlloc(GMEM_FIXED,LOADCODESIZEDBG); 
	if (!pCodeEntry) 
		return FALSE; 
	if (!ReadProcessMemory( 
		pPI->hProcess, 
		(VOID*)dwEntryPoint, 
		pCodeEntry, 
		LOADCODESIZEDBG, 
		&dwBytesRead)) 
	{ 
		GlobalFree(pCodeEntry); 
		return FALSE; 
	} 
	 
	// write the loader code to the EntryPoint and restore protection of the code page 
	if (!WriteProcessMemory( 
		pPI->hProcess, 
		(VOID*)dwEntryPoint, 
		&LibLoadCodeDBG, 
		LOADCODESIZEDBG, 
		&dwBytesWritten)) 
	{ 
		GlobalFree(pCodeEntry); 
		return FALSE; 
	} 
 
	// prepare the execution of the copied code 
	SetThreadContext(pPI->hThread,&Regs); 
	return TRUE; 
} 
 
DWORD __stdcall PerformCleanup(DWORD dwEntryPoint,PROCESS_INFORMATION *pPI) 
{ 
	// grab the result of the "LoadLibraryA" call 
	GetThreadContext(pPI->hThread,&Regs); 
	dwLibBase = Regs.Eax; 
 
	// restore all ! 
	if (!WriteProcessMemory( 
		pPI->hProcess, 
		(VOID*)dwEntryPoint, 
		pCodeEntry, 
		LOADCODESIZEDBG, 
		&dwBytesWritten)) 
	{ 
		GlobalFree(pCodeEntry); 
		return 0; 
	} 
	GlobalFree(pCodeEntry); 
	VirtualProtectEx( 
		pPI->hProcess, 
		(VOID*)dwEntryPoint, 
		LOADCODESIZEDBG, 
		dwOldProt, 
		&dwNewProt); 
	if (!SetThreadContext(pPI->hThread,&InitRegs)) 
		return 0; 
	return dwLibBase; 
}