Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- BOOL PatchProcessToLoadDLL(const char* szPath, const char* szDll, const char* szFunc)
- {
- // Gotta open the file and find the OEP, can do that quite easily...
- HANDLE file = CreateFile(szPath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- switch (GetLastError())
- {
- case ERROR_SUCCESS:
- {
- } break;
- case ERROR_FILE_NOT_FOUND:
- {
- MessageBox(0, "The file you're trying to patch doesn't exist", "Error!", MB_ICONWARNING);
- return FALSE;
- } break;
- default:
- {
- MessageBox(0, "Unable to open the server, therefore the patch couldn't be applied.", "Error!", MB_ICONERROR | MB_ICONINFORMATION);
- return FALSE;
- }
- }
- // PE header is the first data in the file.
- BYTE PEHeader[4096] = {0};
- // Read the pe header into our buffer
- DWORD BytesRead = 0;
- if (ReadFile(file, PEHeader, sizeof(PEHeader), &BytesRead, 0) == 0)
- {
- MessageBox(0, "Failed to read the PE Header of the selected executable file.", "Error!", MB_ICONWARNING);
- CloseHandle(file);
- return FALSE;
- }
- // Get the offset the the info that we're actually interested in.
- DWORD OffsetToPE = 0;
- OffsetToPE = *(DWORD*)(PEHeader + 0x3C);
- printf("The offset to the PE signature is: %08X\n", OffsetToPE);
- // Let's get the OEP of the file
- DWORD AddressOfEntryPoint = *(DWORD*)(PEHeader + OffsetToPE + 0x28);
- printf("OEP: %08X\n", AddressOfEntryPoint);
- // Let's find the base of code (usually right after pe) and the size of the code section
- // from there we can write the code at the end of the code minus say, 300 bytes
- DWORD BaseOfCode = *(DWORD*)(PEHeader + OffsetToPE + 0x2C);
- DWORD SizeOfCode = *(DWORD*)(PEHeader + OffsetToPE + 0x1C);
- DWORD ImageBase = *(DWORD*)(PEHeader + OffsetToPE + 0x34);
- DWORD AddressOfCodecave = BaseOfCode + SizeOfCode - 300;
- printf("Base of code: %08X\nSize of code: %08X\nAddress of codecave: %08X\n", BaseOfCode, SizeOfCode, AddressOfCodecave);
- // Close the file so that we can execute the exe
- CloseHandle(file);
- // We need to backup the file
- char newFile[MAX_PATH] = {0};
- memcpy(newFile, szPath, sizeof(newFile));
- // Replace the extension with .bak
- int len = strlen(newFile);
- newFile[len-3] = 'b'; newFile[len-2] = 'a'; newFile[len-1] = 'k';
- if (!CopyFile(szPath, newFile, TRUE))
- {
- // The backup already exists, ask the user if we should overwrite it.
- int decision = MessageBox(0, "The backup file already exists, do you want to overwrite or continue without a backup?\n\nYes to replace, No to continue.", "A backup already exists!", MB_YESNO | MB_ICONINFORMATION);
- if (decision == IDYES)
- CopyFile(szPath, newFile, FALSE);
- }
- PROCESS_INFORMATION pi = {0};
- STARTUPINFO si = {0};
- si.cb = sizeof(STARTUPINFO);
- // Create the process with DEBUG_PROCESS while allows us to debug the process (obviously).
- if (!CreateProcess(szPath, 0, NULL, NULL, FALSE, DEBUG_PROCESS | CREATE_NO_WINDOW , NULL, NULL, &si, &pi))
- {
- MessageBox(0, "Unable to create the process in order to fetch IAT information.", "Error!", 0);
- return FALSE;
- }
- BYTE INT3[1] = {0xCC};
- // Set a breakpoint at the entry point
- WriteProcessMemory(pi.hProcess, UlongToPtr(AddressOfEntryPoint + ImageBase), &INT3, 1, NULL);
- DWORD LoadLibraryAddress = 0;
- DWORD GetProcAddress_Addr = 0;
- DWORD MessageBoxAddress = 0;
- DWORD ExitProcessAddress = 0;
- bool dwContinueDebugging = true;
- // Debugging loop
- while (dwContinueDebugging)
- {
- DEBUG_EVENT debug_event = {0};
- if (!WaitForDebugEvent(&debug_event, INFINITE))
- return FALSE;
- DWORD dwContinueStatus = DBG_CONTINUE;
- switch (debug_event.dwDebugEventCode)
- {
- case EXCEPTION_DEBUG_EVENT:
- {
- EXCEPTION_DEBUG_INFO& exception = debug_event.u.Exception;
- switch(exception.ExceptionRecord.ExceptionCode)
- {
- case STATUS_BREAKPOINT: // Same value as EXCEPTION_BREAKPOINT
- {
- printf("The executing of the process has reached the entry point.\nAnalyzing the import table.\n");
- DWORD IATAddress = *(DWORD*)(PEHeader + (OffsetToPE + 0xD8)) + ImageBase;
- DWORD IATSize = *(DWORD*)(PEHeader + (OffsetToPE + 0xDC));
- // Read the IAT
- IATInfo iat;
- iat.size = IATSize;
- iat.address = IATAddress;
- iat.data = new BYTE[IATSize + 1];
- if (iat.data != 0)
- {
- ReadProcessMemory(pi.hProcess, UlongToPtr(iat.address), iat.data, iat.size, NULL);
- HMODULE kernel32 = LoadLibrary("kernel32.dll");
- HMODULE user32 = LoadLibrary("user32.dll");
- // Get our functions
- FARPROC loadlibrary = GetProcAddress(kernel32, "LoadLibraryA");
- FARPROC getprocaddr = GetProcAddress(kernel32, "GetProcAddress");
- FARPROC exitprocaddr = GetProcAddress(kernel32, "ExitProcess");
- FARPROC msgboxaddr = GetProcAddress(user32, "MessageBoxA");
- LoadLibraryAddress = SearchIATForAddress((unsigned long)loadlibrary, &iat);
- GetProcAddress_Addr = SearchIATForAddress((unsigned long)getprocaddr, &iat);
- MessageBoxAddress = SearchIATForAddress((unsigned long) msgboxaddr, &iat);
- ExitProcessAddress = SearchIATForAddress((unsigned long) exitprocaddr, &iat);
- delete[] iat.data;
- FreeLibrary(kernel32);
- FreeLibrary(user32);
- }
- TerminateProcess(pi.hProcess, 0);
- } break;
- default:
- {
- dwContinueStatus = DBG_EXCEPTION_NOT_HANDLED;
- } break;
- }
- } break;
- case EXIT_PROCESS_DEBUG_EVENT:
- {
- dwContinueDebugging = false;
- }
- break;
- }
- ContinueDebugEvent(debug_event.dwProcessId, debug_event.dwThreadId, dwContinueStatus);
- }
- WaitForSingleObject(pi.hProcess, 1000);
- CloseHandle(pi.hProcess);
- CloseHandle(pi.hThread);
- if (LoadLibraryAddress == 0 || GetProcAddress_Addr == 0 || MessageBoxAddress == 0 || ExitProcessAddress == 0)
- {
- MessageBox(0, "Unable to find all the required imports within the import table. The patcher cannot continue.", "Error!", MB_ICONERROR);
- return FALSE;
- }
- // This will give us 300 bytes to make the exe load our dll
- BYTE workspace[300] = {0};
- int wrIndex = 0;
- // Need to write the dll name to memory
- memcpy(workspace, szDll, strlen(szDll));
- wrIndex += strlen(szDll);
- // Strings need to be null-terminated
- workspace[wrIndex++] = 0;
- // Address of the function name
- DWORD MemOfFuncName = wrIndex + AddressOfCodecave + ImageBase;
- memcpy(workspace + wrIndex, szFunc, strlen(szFunc));
- wrIndex += strlen(szFunc);
- workspace[wrIndex++] = 0;
- // Let's save the original code
- DWORD MemOfOldData = AddressOfCodecave + ImageBase + wrIndex;
- // Reopen the file
- file = CreateFile(szPath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- // Set the stream to the address of the entry point and save the current 5 bytes
- SetFilePointer(file, AddressOfEntryPoint, 0, FILE_BEGIN);
- if (ReadFile(file, workspace + wrIndex, 5, &BytesRead, 0) == 0)
- {
- MessageBox(0, "Failed to read the current bytes at the OEP of the executable file.", "Error!", MB_ICONWARNING);
- CloseHandle(file);
- return FALSE;
- }
- // Do a simple check to see the file isn't already patched.
- if (*(BYTE*)(workspace + wrIndex) == 0xE9)
- {
- MessageBox(0, "This file has already been patched.", "Error!", MB_ICONERROR);
- CloseHandle(file);
- return FALSE;
- }
- wrIndex += 5;
- // Write the error messages
- DWORD MessageBoxTitle = AddressOfCodecave + ImageBase + wrIndex;
- memcpy(workspace + wrIndex, "Error!", 6);
- wrIndex += 6;
- workspace[wrIndex++] = 0;
- // Error 1
- DWORD MessageBox_Error1 = AddressOfCodecave + ImageBase + wrIndex;
- memcpy(workspace + wrIndex, "LoadLibraryA failed.", 20);
- wrIndex += 20;
- workspace[wrIndex++] = 0;
- // Error 2
- DWORD MessageBox_Error2 = AddressOfCodecave + ImageBase + wrIndex;
- memcpy(workspace + wrIndex, "GetProcAddress failed.", 22);
- wrIndex += 22;
- workspace[wrIndex++] = 0;
- workspace[wrIndex++] = 0xCC;
- workspace[wrIndex++] = 0xCC;
- workspace[wrIndex++] = 0xCC;
- DWORD MemOfDllName = AddressOfCodecave + ImageBase;
- DWORD AddressOfMyCode = AddressOfCodecave + wrIndex + ImageBase;
- DWORD MemAddrOfEntry = AddressOfEntryPoint + ImageBase;
- // PUSHAD
- workspace[wrIndex++] = 0x60;
- // PUSH [dll name]
- workspace[wrIndex++] = 0x68;
- memcpy(workspace + wrIndex, &MemOfDllName, 4);
- wrIndex += 4;
- // CALL DWORD PTR DS: [LoadLibraryA]
- workspace[wrIndex++] = 0xFF;
- workspace[wrIndex++] = 0x15;
- memcpy(workspace + wrIndex, &LoadLibraryAddress, 4);
- wrIndex += 4;
- // CMP EAX, 0
- workspace[wrIndex++] = 0x83;
- workspace[wrIndex++] = 0xF8;
- workspace[wrIndex++] = 0x00;
- // JNZ + 0x1C (past error check).
- workspace[wrIndex++] = 0x75;
- workspace[wrIndex++] = 0x1C;
- // PUSH 0x10
- workspace[wrIndex++] = 0x6A;
- workspace[wrIndex++] = 0x10;
- // Push MessageBoxTitle
- workspace[wrIndex++] = 0x68;
- memcpy(workspace + wrIndex, &MessageBoxTitle, 4);
- wrIndex += 4;
- // Push MessageBox_Error1
- workspace[wrIndex++] = 0x68;
- memcpy(workspace + wrIndex, &MessageBox_Error1, 4);
- wrIndex += 4;
- // PUSH 0
- workspace[wrIndex++] = 0x6A;
- workspace[wrIndex++] = 0x00;
- // CALL DWORD PTR DS: [MessageBoxA]
- workspace[wrIndex++] = 0xFF;
- workspace[wrIndex++] = 0x15;
- memcpy(workspace + wrIndex, &MessageBoxAddress, 4);
- wrIndex += 4;
- // PUSH 0
- workspace[wrIndex++] = 0x6A;
- workspace[wrIndex++] = 0x00;
- // CALL DWORD PTR DS: [ExitProcess]
- workspace[wrIndex++] = 0xFF;
- workspace[wrIndex++] = 0x15;
- memcpy(workspace + wrIndex, &ExitProcessAddress, 4);
- wrIndex += 4;
- // Push szFunc
- workspace[wrIndex++] = 0x68;
- memcpy(workspace + wrIndex, &MemOfFuncName, 4);
- wrIndex += 4;
- // Push EAX (address of module)
- workspace[wrIndex++] = 0x50;
- // CALL DWORD PTR DS: [GetProcAddress]
- workspace[wrIndex++] = 0xFF;
- workspace[wrIndex++] = 0x15;
- memcpy(workspace + wrIndex, &GetProcAddress_Addr, 4);
- wrIndex += 4;
- // CMP EAX, 0
- workspace[wrIndex++] = 0x83;
- workspace[wrIndex++] = 0xF8;
- workspace[wrIndex++] = 0x00;
- // JNZ + 0x1C (past error check).
- workspace[wrIndex++] = 0x75;
- workspace[wrIndex++] = 0x1C;
- // PUSH 0x10
- workspace[wrIndex++] = 0x6A;
- workspace[wrIndex++] = 0x10;
- // Push MessageBoxTitle
- workspace[wrIndex++] = 0x68;
- memcpy(workspace + wrIndex, &MessageBoxTitle, 4);
- wrIndex += 4;
- // Push MessageBox_Error2
- workspace[wrIndex++] = 0x68;
- memcpy(workspace + wrIndex, &MessageBox_Error2, 4);
- wrIndex += 4;
- // PUSH 0
- workspace[wrIndex++] = 0x6A;
- workspace[wrIndex++] = 0x00;
- // CALL DWORD PTR DS: [MessageBoxA]
- workspace[wrIndex++] = 0xFF;
- workspace[wrIndex++] = 0x15;
- memcpy(workspace + wrIndex, &MessageBoxAddress, 4);
- wrIndex += 4;
- // PUSH 0
- workspace[wrIndex++] = 0x6A;
- workspace[wrIndex++] = 0x00;
- // CALL DWORD PTR DS: [ExitProcess]
- workspace[wrIndex++] = 0xFF;
- workspace[wrIndex++] = 0x15;
- memcpy(workspace + wrIndex, &GetProcAddress_Addr, 4);
- wrIndex += 4;
- // mov ecx, address of orig code
- workspace[wrIndex++] = 0xB9;
- memcpy(workspace + wrIndex, &MemOfOldData, 4);
- wrIndex += 4;
- // push ecx
- workspace[wrIndex++] = 0x51;
- // mov ecx, ep
- workspace[wrIndex++] = 0xB9;
- memcpy(workspace + wrIndex, &MemAddrOfEntry, 4);
- wrIndex += 4;
- // push ecx
- workspace[wrIndex++] = 0x51;
- // Call EAX, which is the szFunc function. This func has the responsibility of replacing
- // the code that our codecave overwrote
- workspace[wrIndex++] = 0xFF;
- workspace[wrIndex++] = 0xD0;
- // POPAD
- workspace[wrIndex++] = 0x61;
- // Let's build the data we need for our jmp back
- DWORD curAddr = AddressOfCodecave + ImageBase + wrIndex;
- DWORD offset = (PtrToUlong(MemAddrOfEntry) - curAddr) - 5;
- // JMP OEP
- workspace[wrIndex++] = 0xE9;
- memcpy(workspace + wrIndex, &offset, 4);
- wrIndex += 4;
- // Save our patch to the executable
- SetFilePointer(file, AddressOfCodecave, 0, FILE_BEGIN);
- if (WriteFile(file, workspace, wrIndex + 1, &BytesRead, 0) == 0)
- {
- MessageBox(0, "WriteFile() failed while attempting to write the execution patch.", "Error!", MB_ICONERROR);
- CloseHandle(file);
- return FALSE;
- }
- // Let's set the stream to the ep
- SetFilePointer(file, AddressOfEntryPoint, 0, FILE_BEGIN);
- BYTE patch[5] = {0};
- offset = (PtrToUlong(AddressOfMyCode) - MemAddrOfEntry) - 5;
- patch[0] = 0xE9;
- memcpy(patch + 1, &offset, 4);
- if (WriteFile(file, patch, 5, &BytesRead, 0) == 0)
- {
- MessageBox(0, "WriteFile() failed while attempting to write the routing patch.", "Error!", MB_ICONERROR);
- CloseHandle(file);
- return FALSE;
- }
- CloseHandle(file);
- MessageBox(0, "The executable has been patched successfully! Ensure Roulette.dll is in your server directory.", "Success!", MB_ICONINFORMATION);
- return TRUE;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement