PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [C++] Example_Loader



Zer0Flag
15.09.2010, 13:21
Hey,

Ich habe hier einen kleinen Loader für ein reverseMe von Lena151 gemacht. Bei diesem Target wäre ein Patch wohl einfacher gewesen aber ich dachte mir Übung schadet nie :). Hoffe iwer anderst kann mit dem Source auch noch etwas anfangen. Im Anhang befindet sich der Loader sowie das reverseME.




#include <Windows.h>

#define WIN32_LEAN_AND_MEAN
#define VC_EXTRALEAN

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {

/*
CPU Disasm
Address Hex dump Command Comments
0040107B EB 1D JMP SHORT reverseMe.0040109A
0040107D . 6A 00 PUSH 0 ; Type = MB_OK|MB_DEFBUTTON1|MB_APPLMODAL
0040107F . 68 00204000 PUSH OFFSET reverseMe.00402000 ; Caption = " Key File ReverseMe"
00401084 . 68 17204000 PUSH OFFSET reverseMe.00402017 ; Text = "Evaluation period out of date. Purchase new license"
00401089 . 6A 00 PUSH 0 ; hOwner = NULL
0040108B . E8 D7020000 CALL <JMP.&USER32.MessageBoxA> ; Jump to USER32.MessageBoxA
00401090 . E8 24020000 CALL <JMP.&KERNEL32.ExitProcess> ; KERNEL32.ExitProcess
00401095 . E9 83010000 JMP reverseMe.0040121D
0040109A > 6A 00 PUSH 0 ; pOverlapped = NULL
0040109C . 68 73214000 PUSH OFFSET reverseMe.00402173 ; pBytesRead = reverseMe.402173 -> 0
004010A1 . 6A 46 PUSH 46 ; Size = 70.
004010A3 . 68 1A214000 PUSH OFFSET reverseMe.0040211A ; Buffer = reverseMe.40211A -> 00
004010A8 . 50 PUSH EAX ; hFile
004010A9 . E8 2F020000 CALL <JMP.&KERNEL32.ReadFile> ; KERNEL32.ReadFile
004010AE . 85C0 TEST EAX,EAX
004010B0 EB 02 JMP SHORT reverseMe.004010B4
004010B2 . EB 43 JMP SHORT reverseMe.004010F7
004010B4 > 33DB XOR EBX,EBX
004010B6 . 33F6 XOR ESI,ESI
004010B8 . 833D 73214000 1 CMP DWORD PTR DS:[reverseMe.402173],10
004010BF 90 NOP
004010C0 90 NOP
004010C1 > 8A83 1A214000 MOV AL,BYTE PTR DS:[EBX+reverseMe.40211A
004010C7 . 3C 00 CMP AL,0
004010C9 EB 08 JMP SHORT reverseMe.004010D3
004010CB . 3C 47 CMP AL,47
004010CD . 75 01 JNE SHORT reverseMe.004010D0
004010CF . 46 INC ESI
004010D0 > 43 INC EBX
004010D1 . EB EE JMP SHORT reverseMe.004010C1
004010D3 > 83FE 08 CMP ESI,8
004010D6 90 NOP
004010D7 90 NOP
*/
CONTEXT* tCONTEXT = 0;
STARTUPINFO* tSTARTUPINFO = 0;
PROCESS_INFORMATION* tPROCESS_INFORMATION = 0;

DWORD Patch1 = 0x40107B;
DWORD Patch2 = 0x4010B0;
DWORD Patch3 = 0x4010BF;
DWORD Patch4 = 0x4010C9;
DWORD Patch5 = 0x4010D6;

UCHAR PatchVal1[] = "\xEB\x1D";
UCHAR PatchVal2[] = "\xEB\x02";
UCHAR PatchVal3[] = "\x90\x90";
UCHAR PatchVal4[] = "\xEB\x08";
UCHAR PatchVal5[] = "\x90\x90";

char* cCommandLine = GetCommandLine();

tCONTEXT = (CONTEXT*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CONTEXT));
tSTARTUPINFO = (STARTUPINFO*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(STARTUPINFO));
tPROCESS_INFORMATION = (PROCESS_INFORMATION*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PROCESS_INFORMATION));

tCONTEXT->ContextFlags = CONTEXT_FULL;
tSTARTUPINFO->cb = sizeof(STARTUPINFO);


if(CreateProcessA("reverseMe.exe", cCommandLine, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, tSTARTUPINFO, tPROCESS_INFORMATION)){

WriteProcessMemory(tPROCESS_INFORMATION->hProcess, (LPVOID)Patch1, &PatchVal1, sizeof(PatchVal1)-1, NULL);
WriteProcessMemory(tPROCESS_INFORMATION->hProcess, (LPVOID)Patch2, &PatchVal2, sizeof(PatchVal2)-1, NULL);
WriteProcessMemory(tPROCESS_INFORMATION->hProcess, (LPVOID)Patch3, &PatchVal3, sizeof(PatchVal3)-1, NULL);
WriteProcessMemory(tPROCESS_INFORMATION->hProcess, (LPVOID)Patch4, &PatchVal4, sizeof(PatchVal4)-1, NULL);
WriteProcessMemory(tPROCESS_INFORMATION->hProcess, (LPVOID)Patch5, &PatchVal5, sizeof(PatchVal5)-1, NULL);


ResumeThread(tPROCESS_INFORMATION->hThread);
}

return 0;
}



Download:
http://www.multiupload.com/YKCNJU4Y38

~Zer0Flag

l0dsb
15.09.2010, 14:16
Erst einmal Danke für das Posten (auch wenn ich den Post vorher schon auf drei anderen (RCE-)Boards sah :)). Ich hoffe, die konstruktive Kritik hilft dir weiter:

Wieso allokierst du CONTEXT-, STARTUP- und PROCESS_INFORMATION-Strukturen auf dem Heap? Wie Op schon sagte, wäre da new (und ein passendes delete, bei dir vermisse ich HeapFree) angebracht.

Selbst dann ist es doch viel einfacher, das ganze auf dem Stack zu allokieren - die Strukturen sind nicht wirklich groß und die Stackvariante ist wesentlich einfacher zu schreiben und letzten Endes vermutlich noch performanter (kein Memory-Leak ;)).

Du solltest dir noch im Klaren darüber sein, dass GetCommandLine auch den Pfad der eigenen Anwendung beinhaltet, diesen müsstest du also zuerst "rausschneiden" - oder einfach den passenden Parameter von WinMain verwenden.

VC_EXTRALEAN und WIN32_LEAN_AND_MEAN sind bei so einem Projekt unnötig, selbst bei größeren konnte ich nie einen wirklichen Unterschied in der Build-Geschwindigkeit feststellen. Die würde ich weglassen, zusätzliche Schreibarbeit. :)

Zuletzt wären noch Fehlerabfragen bei WriteProcessMemory sinnvoll und natürlich die Überprüfung per ReadProcessMemory, ob die zu patchende Location auch den richtigen Wert beinhaltet (bzw. für ganz paranoide noch eine Checksum über die ganze Binary).

Die Patches selbst (Adressen, alte und neue Werte) kann man prima in ein Array verlagern, somit spart man sich das Kopieren des WriteProcessMemory-Aufrufs und muss lediglich einen neuen Datensatz einfügen.