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; }