Advertisement
Guest User

Untitled

a guest
May 24th, 2017
70
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.71 KB | None | 0 0
  1. BOOL PatchProcessToLoadDLL(const char* szPath, const char* szDll, const char* szFunc)
  2. {
  3. // Gotta open the file and find the OEP, can do that quite easily...
  4. HANDLE file = CreateFile(szPath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  5.  
  6. switch (GetLastError())
  7. {
  8. case ERROR_SUCCESS:
  9. {
  10.  
  11. } break;
  12.  
  13. case ERROR_FILE_NOT_FOUND:
  14. {
  15. MessageBox(0, "The file you're trying to patch doesn't exist", "Error!", MB_ICONWARNING);
  16.  
  17. return FALSE;
  18.  
  19. } break;
  20.  
  21. default:
  22. {
  23. MessageBox(0, "Unable to open the server, therefore the patch couldn't be applied.", "Error!", MB_ICONERROR | MB_ICONINFORMATION);
  24.  
  25. return FALSE;
  26. }
  27. }
  28.  
  29. // PE header is the first data in the file.
  30. BYTE PEHeader[4096] = {0};
  31.  
  32. // Read the pe header into our buffer
  33. DWORD BytesRead = 0;
  34.  
  35. if (ReadFile(file, PEHeader, sizeof(PEHeader), &BytesRead, 0) == 0)
  36. {
  37. MessageBox(0, "Failed to read the PE Header of the selected executable file.", "Error!", MB_ICONWARNING);
  38.  
  39. CloseHandle(file);
  40.  
  41. return FALSE;
  42. }
  43.  
  44. // Get the offset the the info that we're actually interested in.
  45. DWORD OffsetToPE = 0;
  46. OffsetToPE = *(DWORD*)(PEHeader + 0x3C);
  47.  
  48. printf("The offset to the PE signature is: %08X\n", OffsetToPE);
  49.  
  50. // Let's get the OEP of the file
  51. DWORD AddressOfEntryPoint = *(DWORD*)(PEHeader + OffsetToPE + 0x28);
  52.  
  53. printf("OEP: %08X\n", AddressOfEntryPoint);
  54.  
  55. // Let's find the base of code (usually right after pe) and the size of the code section
  56. // from there we can write the code at the end of the code minus say, 300 bytes
  57. DWORD BaseOfCode = *(DWORD*)(PEHeader + OffsetToPE + 0x2C);
  58. DWORD SizeOfCode = *(DWORD*)(PEHeader + OffsetToPE + 0x1C);
  59. DWORD ImageBase = *(DWORD*)(PEHeader + OffsetToPE + 0x34);
  60.  
  61. DWORD AddressOfCodecave = BaseOfCode + SizeOfCode - 300;
  62.  
  63. printf("Base of code: %08X\nSize of code: %08X\nAddress of codecave: %08X\n", BaseOfCode, SizeOfCode, AddressOfCodecave);
  64.  
  65. // Close the file so that we can execute the exe
  66. CloseHandle(file);
  67.  
  68. // We need to backup the file
  69. char newFile[MAX_PATH] = {0};
  70. memcpy(newFile, szPath, sizeof(newFile));
  71.  
  72. // Replace the extension with .bak
  73. int len = strlen(newFile);
  74.  
  75. newFile[len-3] = 'b'; newFile[len-2] = 'a'; newFile[len-1] = 'k';
  76.  
  77. if (!CopyFile(szPath, newFile, TRUE))
  78. {
  79. // The backup already exists, ask the user if we should overwrite it.
  80. 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);
  81.  
  82. if (decision == IDYES)
  83. CopyFile(szPath, newFile, FALSE);
  84. }
  85.  
  86. PROCESS_INFORMATION pi = {0};
  87. STARTUPINFO si = {0};
  88.  
  89. si.cb = sizeof(STARTUPINFO);
  90.  
  91. // Create the process with DEBUG_PROCESS while allows us to debug the process (obviously).
  92. if (!CreateProcess(szPath, 0, NULL, NULL, FALSE, DEBUG_PROCESS | CREATE_NO_WINDOW , NULL, NULL, &si, &pi))
  93. {
  94. MessageBox(0, "Unable to create the process in order to fetch IAT information.", "Error!", 0);
  95.  
  96. return FALSE;
  97. }
  98.  
  99. BYTE INT3[1] = {0xCC};
  100.  
  101. // Set a breakpoint at the entry point
  102. WriteProcessMemory(pi.hProcess, UlongToPtr(AddressOfEntryPoint + ImageBase), &INT3, 1, NULL);
  103.  
  104. DWORD LoadLibraryAddress = 0;
  105. DWORD GetProcAddress_Addr = 0;
  106. DWORD MessageBoxAddress = 0;
  107. DWORD ExitProcessAddress = 0;
  108.  
  109. bool dwContinueDebugging = true;
  110.  
  111. // Debugging loop
  112. while (dwContinueDebugging)
  113. {
  114. DEBUG_EVENT debug_event = {0};
  115.  
  116. if (!WaitForDebugEvent(&debug_event, INFINITE))
  117. return FALSE;
  118.  
  119. DWORD dwContinueStatus = DBG_CONTINUE;
  120.  
  121. switch (debug_event.dwDebugEventCode)
  122. {
  123. case EXCEPTION_DEBUG_EVENT:
  124. {
  125. EXCEPTION_DEBUG_INFO& exception = debug_event.u.Exception;
  126. switch(exception.ExceptionRecord.ExceptionCode)
  127. {
  128. case STATUS_BREAKPOINT: // Same value as EXCEPTION_BREAKPOINT
  129. {
  130. printf("The executing of the process has reached the entry point.\nAnalyzing the import table.\n");
  131.  
  132. DWORD IATAddress = *(DWORD*)(PEHeader + (OffsetToPE + 0xD8)) + ImageBase;
  133. DWORD IATSize = *(DWORD*)(PEHeader + (OffsetToPE + 0xDC));
  134.  
  135. // Read the IAT
  136. IATInfo iat;
  137. iat.size = IATSize;
  138. iat.address = IATAddress;
  139. iat.data = new BYTE[IATSize + 1];
  140.  
  141. if (iat.data != 0)
  142. {
  143. ReadProcessMemory(pi.hProcess, UlongToPtr(iat.address), iat.data, iat.size, NULL);
  144.  
  145. HMODULE kernel32 = LoadLibrary("kernel32.dll");
  146. HMODULE user32 = LoadLibrary("user32.dll");
  147.  
  148. // Get our functions
  149. FARPROC loadlibrary = GetProcAddress(kernel32, "LoadLibraryA");
  150. FARPROC getprocaddr = GetProcAddress(kernel32, "GetProcAddress");
  151. FARPROC exitprocaddr = GetProcAddress(kernel32, "ExitProcess");
  152. FARPROC msgboxaddr = GetProcAddress(user32, "MessageBoxA");
  153.  
  154. LoadLibraryAddress = SearchIATForAddress((unsigned long)loadlibrary, &iat);
  155. GetProcAddress_Addr = SearchIATForAddress((unsigned long)getprocaddr, &iat);
  156. MessageBoxAddress = SearchIATForAddress((unsigned long) msgboxaddr, &iat);
  157. ExitProcessAddress = SearchIATForAddress((unsigned long) exitprocaddr, &iat);
  158.  
  159. delete[] iat.data;
  160.  
  161. FreeLibrary(kernel32);
  162. FreeLibrary(user32);
  163. }
  164.  
  165. TerminateProcess(pi.hProcess, 0);
  166.  
  167. } break;
  168.  
  169. default:
  170. {
  171. dwContinueStatus = DBG_EXCEPTION_NOT_HANDLED;
  172. } break;
  173. }
  174.  
  175. } break;
  176.  
  177. case EXIT_PROCESS_DEBUG_EVENT:
  178. {
  179. dwContinueDebugging = false;
  180. }
  181. break;
  182. }
  183.  
  184. ContinueDebugEvent(debug_event.dwProcessId, debug_event.dwThreadId, dwContinueStatus);
  185. }
  186.  
  187. WaitForSingleObject(pi.hProcess, 1000);
  188.  
  189. CloseHandle(pi.hProcess);
  190. CloseHandle(pi.hThread);
  191.  
  192. if (LoadLibraryAddress == 0 || GetProcAddress_Addr == 0 || MessageBoxAddress == 0 || ExitProcessAddress == 0)
  193. {
  194. MessageBox(0, "Unable to find all the required imports within the import table. The patcher cannot continue.", "Error!", MB_ICONERROR);
  195.  
  196. return FALSE;
  197. }
  198.  
  199. // This will give us 300 bytes to make the exe load our dll
  200. BYTE workspace[300] = {0};
  201. int wrIndex = 0;
  202.  
  203. // Need to write the dll name to memory
  204. memcpy(workspace, szDll, strlen(szDll));
  205. wrIndex += strlen(szDll);
  206.  
  207. // Strings need to be null-terminated
  208. workspace[wrIndex++] = 0;
  209.  
  210. // Address of the function name
  211. DWORD MemOfFuncName = wrIndex + AddressOfCodecave + ImageBase;
  212.  
  213. memcpy(workspace + wrIndex, szFunc, strlen(szFunc));
  214. wrIndex += strlen(szFunc);
  215.  
  216. workspace[wrIndex++] = 0;
  217.  
  218. // Let's save the original code
  219. DWORD MemOfOldData = AddressOfCodecave + ImageBase + wrIndex;
  220.  
  221. // Reopen the file
  222. file = CreateFile(szPath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  223.  
  224. // Set the stream to the address of the entry point and save the current 5 bytes
  225. SetFilePointer(file, AddressOfEntryPoint, 0, FILE_BEGIN);
  226.  
  227. if (ReadFile(file, workspace + wrIndex, 5, &BytesRead, 0) == 0)
  228. {
  229. MessageBox(0, "Failed to read the current bytes at the OEP of the executable file.", "Error!", MB_ICONWARNING);
  230.  
  231. CloseHandle(file);
  232.  
  233. return FALSE;
  234. }
  235.  
  236. // Do a simple check to see the file isn't already patched.
  237. if (*(BYTE*)(workspace + wrIndex) == 0xE9)
  238. {
  239. MessageBox(0, "This file has already been patched.", "Error!", MB_ICONERROR);
  240.  
  241. CloseHandle(file);
  242.  
  243. return FALSE;
  244. }
  245.  
  246. wrIndex += 5;
  247.  
  248. // Write the error messages
  249. DWORD MessageBoxTitle = AddressOfCodecave + ImageBase + wrIndex;
  250. memcpy(workspace + wrIndex, "Error!", 6);
  251. wrIndex += 6;
  252.  
  253. workspace[wrIndex++] = 0;
  254.  
  255. // Error 1
  256. DWORD MessageBox_Error1 = AddressOfCodecave + ImageBase + wrIndex;
  257. memcpy(workspace + wrIndex, "LoadLibraryA failed.", 20);
  258. wrIndex += 20;
  259.  
  260. workspace[wrIndex++] = 0;
  261.  
  262. // Error 2
  263. DWORD MessageBox_Error2 = AddressOfCodecave + ImageBase + wrIndex;
  264. memcpy(workspace + wrIndex, "GetProcAddress failed.", 22);
  265. wrIndex += 22;
  266.  
  267. workspace[wrIndex++] = 0;
  268.  
  269. workspace[wrIndex++] = 0xCC;
  270. workspace[wrIndex++] = 0xCC;
  271. workspace[wrIndex++] = 0xCC;
  272.  
  273. DWORD MemOfDllName = AddressOfCodecave + ImageBase;
  274. DWORD AddressOfMyCode = AddressOfCodecave + wrIndex + ImageBase;
  275. DWORD MemAddrOfEntry = AddressOfEntryPoint + ImageBase;
  276.  
  277. // PUSHAD
  278. workspace[wrIndex++] = 0x60;
  279.  
  280. // PUSH [dll name]
  281. workspace[wrIndex++] = 0x68;
  282. memcpy(workspace + wrIndex, &MemOfDllName, 4);
  283. wrIndex += 4;
  284.  
  285. // CALL DWORD PTR DS: [LoadLibraryA]
  286. workspace[wrIndex++] = 0xFF;
  287. workspace[wrIndex++] = 0x15;
  288.  
  289. memcpy(workspace + wrIndex, &LoadLibraryAddress, 4);
  290. wrIndex += 4;
  291.  
  292. // CMP EAX, 0
  293. workspace[wrIndex++] = 0x83;
  294. workspace[wrIndex++] = 0xF8;
  295. workspace[wrIndex++] = 0x00;
  296.  
  297. // JNZ + 0x1C (past error check).
  298. workspace[wrIndex++] = 0x75;
  299. workspace[wrIndex++] = 0x1C;
  300.  
  301. // PUSH 0x10
  302. workspace[wrIndex++] = 0x6A;
  303. workspace[wrIndex++] = 0x10;
  304.  
  305. // Push MessageBoxTitle
  306. workspace[wrIndex++] = 0x68;
  307. memcpy(workspace + wrIndex, &MessageBoxTitle, 4);
  308. wrIndex += 4;
  309.  
  310. // Push MessageBox_Error1
  311. workspace[wrIndex++] = 0x68;
  312. memcpy(workspace + wrIndex, &MessageBox_Error1, 4);
  313. wrIndex += 4;
  314.  
  315. // PUSH 0
  316. workspace[wrIndex++] = 0x6A;
  317. workspace[wrIndex++] = 0x00;
  318.  
  319. // CALL DWORD PTR DS: [MessageBoxA]
  320. workspace[wrIndex++] = 0xFF;
  321. workspace[wrIndex++] = 0x15;
  322.  
  323. memcpy(workspace + wrIndex, &MessageBoxAddress, 4);
  324. wrIndex += 4;
  325.  
  326. // PUSH 0
  327. workspace[wrIndex++] = 0x6A;
  328. workspace[wrIndex++] = 0x00;
  329.  
  330. // CALL DWORD PTR DS: [ExitProcess]
  331. workspace[wrIndex++] = 0xFF;
  332. workspace[wrIndex++] = 0x15;
  333.  
  334. memcpy(workspace + wrIndex, &ExitProcessAddress, 4);
  335. wrIndex += 4;
  336.  
  337. // Push szFunc
  338. workspace[wrIndex++] = 0x68;
  339. memcpy(workspace + wrIndex, &MemOfFuncName, 4);
  340. wrIndex += 4;
  341.  
  342. // Push EAX (address of module)
  343. workspace[wrIndex++] = 0x50;
  344.  
  345. // CALL DWORD PTR DS: [GetProcAddress]
  346. workspace[wrIndex++] = 0xFF;
  347. workspace[wrIndex++] = 0x15;
  348.  
  349. memcpy(workspace + wrIndex, &GetProcAddress_Addr, 4);
  350. wrIndex += 4;
  351.  
  352. // CMP EAX, 0
  353. workspace[wrIndex++] = 0x83;
  354. workspace[wrIndex++] = 0xF8;
  355. workspace[wrIndex++] = 0x00;
  356.  
  357. // JNZ + 0x1C (past error check).
  358. workspace[wrIndex++] = 0x75;
  359. workspace[wrIndex++] = 0x1C;
  360.  
  361. // PUSH 0x10
  362. workspace[wrIndex++] = 0x6A;
  363. workspace[wrIndex++] = 0x10;
  364.  
  365. // Push MessageBoxTitle
  366. workspace[wrIndex++] = 0x68;
  367. memcpy(workspace + wrIndex, &MessageBoxTitle, 4);
  368. wrIndex += 4;
  369.  
  370. // Push MessageBox_Error2
  371. workspace[wrIndex++] = 0x68;
  372. memcpy(workspace + wrIndex, &MessageBox_Error2, 4);
  373. wrIndex += 4;
  374.  
  375. // PUSH 0
  376. workspace[wrIndex++] = 0x6A;
  377. workspace[wrIndex++] = 0x00;
  378.  
  379. // CALL DWORD PTR DS: [MessageBoxA]
  380. workspace[wrIndex++] = 0xFF;
  381. workspace[wrIndex++] = 0x15;
  382.  
  383. memcpy(workspace + wrIndex, &MessageBoxAddress, 4);
  384. wrIndex += 4;
  385.  
  386. // PUSH 0
  387. workspace[wrIndex++] = 0x6A;
  388. workspace[wrIndex++] = 0x00;
  389.  
  390. // CALL DWORD PTR DS: [ExitProcess]
  391. workspace[wrIndex++] = 0xFF;
  392. workspace[wrIndex++] = 0x15;
  393.  
  394. memcpy(workspace + wrIndex, &GetProcAddress_Addr, 4);
  395. wrIndex += 4;
  396.  
  397. // mov ecx, address of orig code
  398. workspace[wrIndex++] = 0xB9;
  399. memcpy(workspace + wrIndex, &MemOfOldData, 4);
  400. wrIndex += 4;
  401.  
  402. // push ecx
  403. workspace[wrIndex++] = 0x51;
  404.  
  405. // mov ecx, ep
  406. workspace[wrIndex++] = 0xB9;
  407. memcpy(workspace + wrIndex, &MemAddrOfEntry, 4);
  408. wrIndex += 4;
  409.  
  410. // push ecx
  411. workspace[wrIndex++] = 0x51;
  412.  
  413. // Call EAX, which is the szFunc function. This func has the responsibility of replacing
  414. // the code that our codecave overwrote
  415. workspace[wrIndex++] = 0xFF;
  416. workspace[wrIndex++] = 0xD0;
  417.  
  418. // POPAD
  419. workspace[wrIndex++] = 0x61;
  420.  
  421. // Let's build the data we need for our jmp back
  422. DWORD curAddr = AddressOfCodecave + ImageBase + wrIndex;
  423.  
  424. DWORD offset = (PtrToUlong(MemAddrOfEntry) - curAddr) - 5;
  425.  
  426. // JMP OEP
  427. workspace[wrIndex++] = 0xE9;
  428. memcpy(workspace + wrIndex, &offset, 4);
  429. wrIndex += 4;
  430.  
  431. // Save our patch to the executable
  432. SetFilePointer(file, AddressOfCodecave, 0, FILE_BEGIN);
  433.  
  434. if (WriteFile(file, workspace, wrIndex + 1, &BytesRead, 0) == 0)
  435. {
  436. MessageBox(0, "WriteFile() failed while attempting to write the execution patch.", "Error!", MB_ICONERROR);
  437.  
  438. CloseHandle(file);
  439.  
  440. return FALSE;
  441. }
  442.  
  443. // Let's set the stream to the ep
  444. SetFilePointer(file, AddressOfEntryPoint, 0, FILE_BEGIN);
  445.  
  446. BYTE patch[5] = {0};
  447. offset = (PtrToUlong(AddressOfMyCode) - MemAddrOfEntry) - 5;
  448.  
  449. patch[0] = 0xE9;
  450. memcpy(patch + 1, &offset, 4);
  451.  
  452. if (WriteFile(file, patch, 5, &BytesRead, 0) == 0)
  453. {
  454. MessageBox(0, "WriteFile() failed while attempting to write the routing patch.", "Error!", MB_ICONERROR);
  455.  
  456. CloseHandle(file);
  457.  
  458. return FALSE;
  459. }
  460.  
  461. CloseHandle(file);
  462.  
  463. MessageBox(0, "The executable has been patched successfully! Ensure Roulette.dll is in your server directory.", "Success!", MB_ICONINFORMATION);
  464.  
  465. return TRUE;
  466. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement