PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Problem; PE Image loader fehler



pommes08
20.06.2010, 20:23
Hallo,
Ich habe mich jetzt seit zwei wochen mit exe cryptern auseinandergesetzt. Mein builder + stub sind fast fertig , nur die stub arbeitet nicht nach meinen "wünschen". das problem ist das die stub mein testapp nicht als prozess laden kann.

Hier meine funktion um die PE image aus dem memory zu laden.



/*
--_--_--_--_--_--_--_--_--_--_--_--_--_--_--_--_--_--_--_--_--_--_--_--_
runPE(
dosheader ptr,
ntheader ptr,
sectionheader ptr,
ptr to exebuffer,
DWORD SizeOfImage(Alignment fixed))
_--_--_--_--_--_--_--_--_--_--_--_--_--_--_--_--_--_--_--_--_--_--_--_--
*/
int runPE2(IMAGE_DOS_HEADER* pDOS,IMAGE_NT_HEADERS * pNT,IMAGE_SECTION_HEADER * pSection,char* pData,DWORD szImage)
{
STARTUPINFO si = {0};
PROCESS_INFORMATION pi;
CONTEXT ctx;

if(CreateProcess(NULL,szFileName,NULL, NULL, 0, CREATE_SUSPENDED, NULL, NULL, &si,&pi))
{
ctx.ContextFlags = CONTEXT_FULL;
if(!GetThreadContext(pi.hThread,&ctx))
{
MessageBoxA(0,"GetThreadContext Error!","Error",0);
}
DWORD dwImagebase = NULL;
DWORD dwBytesRead = NULL;
DWORD dwByteswritten = NULL;
DWORD dwOldProtection = NULL;

if(!ReadProcessMemory(pi.hProcess,(LPVOID)(ctx.Ebx + 8),&dwImagebase,sizeof(DWORD),&dwBytesRead))
{
MessageBoxA(0,"RPM Error!","Error",0);
}
VirtualProtect(&pNT->OptionalHeader.ImageBase,sizeof(DWORD),PAGE_READWR ITE,&dwOldProtection);
pNT->OptionalHeader.ImageBase = dwImagebase;
VirtualProtect(&pNT->OptionalHeader.ImageBase,sizeof(DWORD),dwOldProtec tion,&dwOldProtection);


UnmapViewOfSection_ pZwUnmapViewOfSection = (UnmapViewOfSection_)GetProcAddress(GetModuleHandl e("ntdll.dll"), "ZwUnmapViewOfSection");

if(pZwUnmapViewOfSection(pi.hProcess, (LPVOID)dwImagebase) != 0)
{
MessageBoxA(0,"Unmaping Error!","Error",0);
}

void* newBase = VirtualAllocEx(pi.hProcess, (LPVOID)pNT->OptionalHeader.ImageBase,szImage, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if(!newBase)
{
MessageBoxA(0,"Allocting Error!","Error",0);
}

if(!WriteProcessMemory(pi.hProcess,(LPVOID)(ctx.Eb x + 8),newBase, sizeof(DWORD), &dwByteswritten))
{
MessageBoxA(0,"WPM Imagebase Error!","Error",0);
}

if(!WriteProcessMemory(pi.hProcess,newBase,pData,p NT->OptionalHeader.SizeOfHeaders, &dwByteswritten))
{
MessageBoxA(0,"WPM SizeOfHeaders Error!","Error",0);
}

for(int i = 0; i < pNT->FileHeader.NumberOfSections; i++)
{
pSection = (PIMAGE_SECTION_HEADER)((char*)(pData + pDOS->e_lfanew + sizeof(IMAGE_NT_HEADERS) + sizeof(IMAGE_SECTION_HEADER) * i));
if(!WriteProcessMemory(pi.hProcess,(char*)(pNT->OptionalHeader.ImageBase + pSection->VirtualAddress),(char*)(pData + pSection->PointerToRawData),pSection->SizeOfRawData, &dwByteswritten))
{
MessageBoxA(0,"WPM in LOOP Error!","Error",0);
}
}

ctx.Eax = (DWORD)newBase + pNT->OptionalHeader.AddressOfEntryPoint; // eax holds new entry point

if(!SetThreadContext(pi.hThread,&ctx))
{
MessageBoxA(0,"SetThreadContext Error!","Error",0);
}

if(!ResumeThread(pi.hThread))
{
MessageBoxA(0,"ResumeThread Error!","Error",0);
}

CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);

//TerminateProcess(pi.hProcess,0);

return 1;
}
return -1;
}


Nach dem Aufruf von ResumeThread bekomme ich die fehlermeldung "The application was unable to start correctly (0xc0000005)"

Informationen:
Windows 7
compiler VC++ 2010
ziel; "Hello World" Programm; win32 console

Vielen Dank fürs durchlesen

blackberry
20.06.2010, 21:19
Bevor du dir anschaust, was der Fehler war, möchte ich dich warnen es nicht zu tun.
Du würdest dir den Kopf solange gegen die Wand schlagen, bis du umfällst...
Nein - wirklich - ich meine es ernst - das ist es was du tun wirst...
Ok, genug Scheiße gelabert - hier ist der Fehler:

if(!WriteProcessMemory(pi.hProcess,(LPVOID)(ctx.Eb x + 8),&newBase, sizeof(DWORD), &dwByteswritten))Du musst WriteProcessMemory einen Zeiger auf das übergeben, dass du beschreiben willst; das hat bei dir zu keinem Fehler geführt, weil newBase als Adresse interpretiert auf den Anfang von dem DOS Header des laufenden Prozesses zeigt und dieser Bereich lesbar ist -- also gibt es keinen direkten Fehler an der Stelle; es wird halt nur was falsches geschrieben!

Achso - btw:
Um das zu debuggen habe ich gleich mal ein Testprojekt gemacht.
Download:
RapidShare: 1-CLICK Web hosting - Easy Filehosting (http://rapidshare.com/files/401109662/pinject.rar.html)

Sonst habe ich noch NtUnmapViewOfSection statisch gelinkt. Die Definition findest du in
#include <ddk/ntddk.h>
und die Funktion ist in libntdll.a (zumindest bei Dev-C++ heißt die Lib so...).
Das hat mir erspart die Typdefinition rauszusuchen, weil du UnmapViewOfSection_ nicht angegeben hast...


MfG. BlackBerry

EDIT:
btw #2:
Wäre übringens echt leichter gewesen deine Funktion zu testen, wenn die eigenständiger wäre; wenn man dir schon nen Pointer auf IMAGE_DOS_HEADER übergibt, dann kannst du dir auch gleich IMAGE_NT_HEADERS dazu finden; außerdem ist die Angabe des Buffers dann auch nicht mehr notwenig, da IMAGE_DOS_HEADER direkt am Anfang des Buffers ist; d.h. die Zeiger haben beide den selben Inhalt - das ganze ist also redundant.
Zudem solltest du das IMAGE_SECTION_HEADER Ding als lokale Funktionsvariable implementieren, weil du das gar nicht als Parameter verwendest - ich habe mich zu aller erst gefragt was das als Parameter sein soll und nach CTRL+F und pSection habe ich dann erstmal nicht schlecht gestaunt als du dem gleich einen Wert zugewiesen hast, ohne dich darum zu kümmern was da drin war.
Beim Aufruf im Testprogramm habe ich da jetzt einfach 0 übergeben... ich würde dir aber empfehlen das nochmal zu überarbeiten.

pommes08
20.06.2010, 23:23
Hey Blackberry vielen dank für deine hilfe.. Doch jetzt ist noch ein problem aufgetreten und zwar lädt meine stub.exe ja die EXEdatei aus einer resource, also muss der prozess name also der "dummy" prozesss ja die stub.exe sein. Iwie funktioniert das nicht :S. Hab mich denn mit olly debugger rangesetzt und rausgefunden das die ziel exe startet doch das IAT ist falsch :( muss jetzt erstmal off..

blackberry
21.06.2010, 16:30
Was heißt der IAT ist falsch?
Der befindet sich in einer Section und du schreibst ja alle Sections in den Speicher.
Beim ResumeThread übernimmt Windows alle weiteren Sachen, wie u.a. laden der DLLs und das Füllen des IT mit den richtigen Adressen.

Das einzige was mir noch auffällt, ist das der Code einen Fehler gibt, wenn man eine Section mit der größe 0 schreiben will (was bei einigen .EXEn teilweise wirklich vorkommt...)

Fix:
if (!pSection->SizeOfRawData) continue;
vor
if(!WriteProcessMemory(pi.hProcess,(char*)(pNT->OptionalHeader.ImageBase + pSection->VirtualAddress),(char*)(pData + pSection->PointerToRawData),pSection->SizeOfRawData, &dwByteswritten))

Ansonsten habe ich keine Ahnung was du jetzt genau meinst...

pommes08
21.06.2010, 18:02
Hab mri nen VB src geholt umgeschrieben und paar fixes aus "dynamic win32 exe forking" geholt. Läuft perfekt ;) Danke Blackberry , jetzt waren meine zwei wochen arbeit nicht umsonst.

Auch nochmal danke für den SizeOfRawData fix :)

kann geclosed werden

blackberry
21.06.2010, 19:03
Wo lag denn nun der Fehler, wenn ich fragen darf? :>