#include #include #include /* PROCESSENTRY32 */ #include /* _getch() */ #include /* StrStrI */ #include /* FindTopWindow */ #pragma comment(lib, "shlwapi.lib") /* unresolved external symbol __imp__StrStrIW@8 */ typedef HMODULE(WINAPI *pLoadLibraryA)(LPCSTR); typedef FARPROC(WINAPI *pGetProcAddress)(HMODULE, LPCSTR); typedef BOOL(WINAPI *PDLL_MAIN)(HMODULE, DWORD, PVOID); typedef struct _MANUAL_INJECT { PVOID ImageBase; PIMAGE_NT_HEADERS NtHeaders; PIMAGE_BASE_RELOCATION BaseRelocation; PIMAGE_IMPORT_DESCRIPTOR ImportDirectory; pLoadLibraryA fnLoadLibraryA; pGetProcAddress fnGetProcAddress; }MANUAL_INJECT, *PMANUAL_INJECT; DWORD WINAPI LoadDll(PVOID p) { PMANUAL_INJECT ManualInject; HMODULE hModule; DWORD i, Function, count, delta; PDWORD ptr; PWORD list; PIMAGE_BASE_RELOCATION pIBR; PIMAGE_IMPORT_DESCRIPTOR pIID; PIMAGE_IMPORT_BY_NAME pIBN; PIMAGE_THUNK_DATA FirstThunk, OrigFirstThunk; PDLL_MAIN EntryPoint; ManualInject = (PMANUAL_INJECT)p; pIBR = ManualInject->BaseRelocation; delta = (DWORD)((LPBYTE)ManualInject->ImageBase - ManualInject->NtHeaders->OptionalHeader.ImageBase); // Calculate the delta // Relocate the image while (pIBR->VirtualAddress) { if (pIBR->SizeOfBlock >= sizeof(IMAGE_BASE_RELOCATION)) { count = (pIBR->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD); list = (PWORD)(pIBR + 1); for (i = 0; iImageBase + (pIBR->VirtualAddress + (list[i] & 0xFFF))); *ptr += delta; } } } pIBR = (PIMAGE_BASE_RELOCATION)((LPBYTE)pIBR + pIBR->SizeOfBlock); } pIID = ManualInject->ImportDirectory; // Resolve DLL imports while (pIID->Characteristics) { OrigFirstThunk = (PIMAGE_THUNK_DATA)((LPBYTE)ManualInject->ImageBase + pIID->OriginalFirstThunk); FirstThunk = (PIMAGE_THUNK_DATA)((LPBYTE)ManualInject->ImageBase + pIID->FirstThunk); hModule = ManualInject->fnLoadLibraryA((LPCSTR)ManualInject->ImageBase + pIID->Name); if (!hModule) { return FALSE; } while (OrigFirstThunk->u1.AddressOfData) { if (OrigFirstThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG) { // Import by ordinal Function = (DWORD)ManualInject->fnGetProcAddress(hModule, (LPCSTR)(OrigFirstThunk->u1.Ordinal & 0xFFFF)); if (!Function) { return FALSE; } FirstThunk->u1.Function = Function; } else { // Import by name pIBN = (PIMAGE_IMPORT_BY_NAME)((LPBYTE)ManualInject->ImageBase + OrigFirstThunk->u1.AddressOfData); Function = (DWORD)ManualInject->fnGetProcAddress(hModule, (LPCSTR)pIBN->Name); if (!Function) { return FALSE; } FirstThunk->u1.Function = Function; } OrigFirstThunk++; FirstThunk++; } pIID++; } if (ManualInject->NtHeaders->OptionalHeader.AddressOfEntryPoint) { EntryPoint = (PDLL_MAIN)((LPBYTE)ManualInject->ImageBase + ManualInject->NtHeaders->OptionalHeader.AddressOfEntryPoint); return EntryPoint((HMODULE)ManualInject->ImageBase, DLL_PROCESS_ATTACH, NULL); // Call the entry point } return TRUE; } DWORD WINAPI LoadDllEnd() { return 0; } HWND FindTopWindow(DWORD pid) { std::pair params = { 0, pid }; // Enumerate the windows using a lambda to process each window BOOL bResult = EnumWindows([](HWND hwnd, LPARAM lParam) -> BOOL { auto pParams = (std::pair*)(lParam); DWORD processId; if (GetWindowThreadProcessId(hwnd, &processId) && processId == pParams->second) { // Stop enumerating SetLastError(-1); pParams->first = hwnd; return FALSE; } // Continue enumerating return TRUE; }, (LPARAM)¶ms); if (!bResult && GetLastError() == -1 && params.first) { return params.first; } return 0; } DWORD GetTargetThreadIDFromProcName(const char * ProcName) { PROCESSENTRY32 pe; HANDLE thSnapShot; BOOL retval, ProcFound = false; thSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (thSnapShot == INVALID_HANDLE_VALUE) { //MessageBox(NULL, "Error: Unable to create toolhelp snapshot!", "2MLoader", MB_OK); printf("Error: Unable to create toolhelp snapshot!"); return false; } pe.dwSize = sizeof(PROCESSENTRY32); retval = Process32First(thSnapShot, &pe); while (retval) { if (StrStrI(pe.szExeFile, ProcName)) { return pe.th32ProcessID; } retval = Process32Next(thSnapShot, &pe); } return 0; } DWORD ProcessId; int wmain(int argc, wchar_t* argv[]) { PIMAGE_DOS_HEADER pIDH; PIMAGE_NT_HEADERS pINH; PIMAGE_SECTION_HEADER pISH; HANDLE hProcess, hThread, hFile, hToken; PVOID buffer, image, mem; DWORD i, FileSize, ExitCode, read; TOKEN_PRIVILEGES tp; MANUAL_INJECT ManualInject; if (OpenProcessToken((HANDLE)-1, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) { tp.PrivilegeCount = 1; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; tp.Privileges[0].Luid.LowPart = 20; tp.Privileges[0].Luid.HighPart = 0; AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL); CloseHandle(hToken); } printf("\nOpening the DLL.\n"); hFile = CreateFile("AO.dll", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); // Open the DLL if (hFile == INVALID_HANDLE_VALUE) { printf("\nError: Unable to open the DLL (%d)\n", GetLastError()); return -1; } FileSize = GetFileSize(hFile, NULL); buffer = VirtualAlloc(NULL, FileSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); if (!buffer) { printf("\nError: Unable to allocate memory for DLL data (%d)\n", GetLastError()); CloseHandle(hFile); return -1; } // Read the DLL if (!ReadFile(hFile, buffer, FileSize, &read, NULL)) { printf("\nError: Unable to read the DLL (%d)\n", GetLastError()); VirtualFree(buffer, 0, MEM_RELEASE); CloseHandle(hFile); return -1; } CloseHandle(hFile); pIDH = (PIMAGE_DOS_HEADER)buffer; if (pIDH->e_magic != IMAGE_DOS_SIGNATURE) { printf("\nError: Invalid executable image.\n"); VirtualFree(buffer, 0, MEM_RELEASE); return -1; } pINH = (PIMAGE_NT_HEADERS)((LPBYTE)buffer + pIDH->e_lfanew); if (pINH->Signature != IMAGE_NT_SIGNATURE) { printf("\nError: Invalid PE header.\n"); VirtualFree(buffer, 0, MEM_RELEASE); return -1; } if (!(pINH->FileHeader.Characteristics & IMAGE_FILE_DLL)) { printf("\nError: The image is not DLL.\n"); VirtualFree(buffer, 0, MEM_RELEASE); return -1; } // Retrieve process ID ProcessId = 0; char buf[MAX_PATH] = { 0 }; do { PROCESSENTRY32 entry; entry.dwSize = sizeof(PROCESSENTRY32); HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); if (Process32First(snapshot, &entry)) while (Process32Next(snapshot, &entry)) { if (StrStrI(entry.szExeFile, "Multi Theft Auto.exe")) { ProcessId = entry.th32ProcessID; } } CloseHandle(snapshot); //ProcessId = GetTargetThreadIDFromProcName("Multi Theft Auto.exe"); Sleep(100); } while (!ProcessId); printf("Multi Theft Auto.exe ProcessId = %d\n", ProcessId); printf("\nOpening target process.\n"); hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessId); if (!hProcess) { printf("\nError: Unable to open target process (%d)\n", GetLastError()); VirtualFree(buffer, 0, MEM_RELEASE); CloseHandle(hProcess); return -1; } printf("\nAllocating memory for the DLL.\n"); image = VirtualAllocEx(hProcess, NULL, pINH->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); // Allocate memory for the DLL if (!image) { printf("\nError: Unable to allocate memory for the DLL (%d)\n", GetLastError()); VirtualFree(buffer, 0, MEM_RELEASE); CloseHandle(hProcess); return -1; } // Copy the header to target process printf("\nCopying headers into target process.\n"); if (!WriteProcessMemory(hProcess, image, buffer, pINH->OptionalHeader.SizeOfHeaders, NULL)) { printf("\nError: Unable to copy headers to target process (%d)\n", GetLastError()); VirtualFreeEx(hProcess, image, 0, MEM_RELEASE); CloseHandle(hProcess); VirtualFree(buffer, 0, MEM_RELEASE); return -1; } pISH = (PIMAGE_SECTION_HEADER)(pINH + 1); // Copy the DLL to target process printf("\nCopying sections to target process.\n"); for (i = 0; iFileHeader.NumberOfSections; i++) { WriteProcessMemory(hProcess, (PVOID)((LPBYTE)image + pISH[i].VirtualAddress), (PVOID)((LPBYTE)buffer + pISH[i].PointerToRawData), pISH[i].SizeOfRawData, NULL); } printf("\nAllocating memory for the loader code.\n"); mem = VirtualAllocEx(hProcess, NULL, 4096, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); // Allocate memory for the loader code if (!mem) { printf("\nError: Unable to allocate memory for the loader code (%d)\n", GetLastError()); VirtualFreeEx(hProcess, image, 0, MEM_RELEASE); CloseHandle(hProcess); VirtualFree(buffer, 0, MEM_RELEASE); return -1; } printf("\nLoader code allocated at %#x\n", mem); memset(&ManualInject, 0, sizeof(MANUAL_INJECT)); ManualInject.ImageBase = image; ManualInject.NtHeaders = (PIMAGE_NT_HEADERS)((LPBYTE)image + pIDH->e_lfanew); ManualInject.BaseRelocation = (PIMAGE_BASE_RELOCATION)((LPBYTE)image + pINH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress); ManualInject.ImportDirectory = (PIMAGE_IMPORT_DESCRIPTOR)((LPBYTE)image + pINH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); ManualInject.fnLoadLibraryA = LoadLibraryA; ManualInject.fnGetProcAddress = GetProcAddress; printf("\nWriting loader code to target process.\n"); WriteProcessMemory(hProcess, mem, &ManualInject, sizeof(MANUAL_INJECT), NULL); // Write the loader information to target process WriteProcessMemory(hProcess, (PVOID)((PMANUAL_INJECT)mem + 1), LoadDll, (DWORD)LoadDllEnd - (DWORD)LoadDll, NULL); // Write the loader code to target process printf("\nExecuting loader code.\n"); hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)((PMANUAL_INJECT)mem + 1), mem, 0, NULL); // Create a remote thread to execute the loader code if (!hThread) { printf("\nError: Unable to execute loader code (%d)\n", GetLastError()); VirtualFreeEx(hProcess, mem, 0, MEM_RELEASE); VirtualFreeEx(hProcess, image, 0, MEM_RELEASE); CloseHandle(hProcess); VirtualFree(buffer, 0, MEM_RELEASE); return -1; } WaitForSingleObject(hThread, INFINITE); GetExitCodeThread(hThread, &ExitCode); if (!ExitCode) { VirtualFreeEx(hProcess, mem, 0, MEM_RELEASE); VirtualFreeEx(hProcess, image, 0, MEM_RELEASE); CloseHandle(hThread); CloseHandle(hProcess); VirtualFree(buffer, 0, MEM_RELEASE); return -1; } CloseHandle(hThread); VirtualFreeEx(hProcess, mem, 0, MEM_RELEASE); CloseHandle(hProcess); printf("\nDLL injected at %#x\n", image); if (pINH->OptionalHeader.AddressOfEntryPoint) { printf("\nDLL entry point: %#x\n", (PVOID)((LPBYTE)image + pINH->OptionalHeader.AddressOfEntryPoint)); } VirtualFree(buffer, 0, MEM_RELEASE); return 0; }