Wie forkt man ein Win32 Setup?
-
Ich habe ein Problem und bin bei Google nicht fündig geworden. Deswegen versuch ich hier mal mein Glück.
Dieses C++ Programm lädt eine Win32 .exe von der Festplatte in den Arbeitsspeicher und führt sie dort aus (engl. forken). Das funktioniert auch mit allen .exe Dateien bis auf die meisten (nicht alle) Setups. Wenn ich z.B. das 7zip Setup verwende, bricht der Prozess nach kurzer Zeit ab und startet neu (Endlosschleife). Mit dem Winshark Setup gibt es keine Probleme. Ich wäre über jede noch so kleine Information dankbar. Win32 ist für mich Neuland
Wichtig: Das GUI vom geforkten Prozess ist in der aktuellen Fassung nicht sichtbar. Ich verwende den Task Manager als Erfolgsindikator.
#define APIENTRY WINAPI #define _CRT_SECURE_NO_DEPRECATE #include <windows.h> #include <wininet.h> #include <fstream> void RunFromMemory(char* pImage,char* pPath) { DWORD dwWritten = 0; DWORD dwHeader = 0; DWORD dwImageSize = 0; DWORD dwSectionCount = 0; DWORD dwSectionSize = 0; DWORD firstSection = 0; DWORD previousProtection = 0; DWORD jmpSize = 0; IMAGE_NT_HEADERS INH; IMAGE_DOS_HEADER IDH; IMAGE_SECTION_HEADER Sections[1000]; PROCESS_INFORMATION peProcessInformation; STARTUPINFO peStartUpInformation; CONTEXT pContext; SECURITY_ATTRIBUTES secAttrib; char* pMemory; char* pFile; memcpy(&IDH,pImage,sizeof(IDH)); memcpy(&INH,(void*)((DWORD)pImage+IDH.e_lfanew),sizeof(INH)); dwImageSize = INH.OptionalHeader.SizeOfImage; pMemory = (char*)malloc(dwImageSize); memset(pMemory,0,dwImageSize); pFile = pMemory; dwHeader = INH.OptionalHeader.SizeOfHeaders; firstSection = (DWORD)(((DWORD)pImage+IDH.e_lfanew) + sizeof(IMAGE_NT_HEADERS)); memcpy(Sections,(char*) (firstSection),sizeof(IMAGE_SECTION_HEADER)*INH.FileHeader.NumberOfSections); memcpy(pFile,pImage,dwHeader); if((INH.OptionalHeader.SizeOfHeaders % INH.OptionalHeader.SectionAlignment)==0) { jmpSize = INH.OptionalHeader.SizeOfHeaders; } else { jmpSize = INH.OptionalHeader.SizeOfHeaders / INH.OptionalHeader.SectionAlignment; jmpSize += 1; jmpSize *= INH.OptionalHeader.SectionAlignment; } pFile = (char*)((DWORD)pFile + jmpSize); for(dwSectionCount = 0; dwSectionCount < INH.FileHeader.NumberOfSections; dwSectionCount++) { jmpSize = 0; dwSectionSize = Sections[dwSectionCount].SizeOfRawData; memcpy(pFile,(char*)(pImage + Sections[dwSectionCount].PointerToRawData),dwSectionSize); if((Sections[dwSectionCount].Misc.VirtualSize % INH.OptionalHeader.SectionAlignment)==0) { jmpSize = Sections[dwSectionCount].Misc.VirtualSize; } else { jmpSize = Sections[dwSectionCount].Misc.VirtualSize / INH.OptionalHeader.SectionAlignment; jmpSize += 1; jmpSize *= INH.OptionalHeader.SectionAlignment; } pFile = (char*)((DWORD)pFile + jmpSize); } memset(&peStartUpInformation,0,sizeof(STARTUPINFO)); memset(&peProcessInformation,0,sizeof(PROCESS_INFORMATION)); memset(&pContext,0,sizeof(CONTEXT)); peStartUpInformation.cb = sizeof(peStartUpInformation); if(CreateProcess(NULL,pPath,&secAttrib,NULL,false,CREATE_SUSPENDED, NULL,NULL,&peStartUpInformation,&peProcessInformation)) { pContext.ContextFlags = CONTEXT_FULL; GetThreadContext(peProcessInformation.hThread,&pContext); VirtualProtectEx(peProcessInformation.hProcess,(void*) ((DWORD)INH.OptionalHeader.ImageBase),dwImageSize,PAGE_EXECUTE_READWRITE,&previousProtection); WriteProcessMemory(peProcessInformation.hProcess,(void*)((DWORD)INH.OptionalHeader.ImageBase),pMemory,dwImageSize,&dwWritten); WriteProcessMemory(peProcessInformation.hProcess,(void*)((DWORD)pContext.Ebx + 8),&INH.OptionalHeader.ImageBase,4,&dwWritten); pContext.Eax = INH.OptionalHeader.ImageBase + INH.OptionalHeader.AddressOfEntryPoint; SetThreadContext(peProcessInformation.hThread,&pContext); VirtualProtectEx(peProcessInformation.hProcess,(void*)((DWORD)INH.OptionalHeader.ImageBase),dwImageSize,previousProtection,0); ResumeThread(peProcessInformation.hThread); } free(pMemory); } int main(int argc, char * argv[]) { FILE *fp = fopen("Setup.exe", "rb"); long lSize; char *buffer; size_t result; if( !fp) { fputs("File error\n", stderr); exit(1); } //Dateigröße ermitteln fseek(fp, 0, SEEK_END); lSize = ftell(fp); rewind(fp); //Arbeitsspeicher resevieren buffer = (char *) malloc(sizeof(char) * lSize); if( !buffer) { fputs("Memory error\n",stderr); exit(2); } //Datei in den Arbeitsspeicher kopieren result = fread(buffer, 1, lSize, fp); if( result != lSize) { fputs("Reading error\n", stderr); exit(3); } //Datei ausführen RunFromMemory(buffer, argv[0]); return 0; } #pragma comment(linker, "/SUBSYSTEM:windows /ENTRY:mainCRTStartup")
-
Wie forkt (...)
Am besten gar nicht.
-
IMAGE_SECTION_HEADER Sections[1000]; //... memcpy(Sections,(char*) (firstSection),sizeof(IMAGE_SECTION_HEADER)*INH.FileHeader.NumberOfSections); // Oh je. Hier würde ich mal auf einen möglichen Buffer Overflow testen.
Ich gehe jetzt mal davon aus, dass das Ganze nur Neugier ist. Effektiv ist so was gar nicht, da so manches Setup riesig ist.
Und da kommen wir schon zu einer Frage. Wie reagiert ein Setup im RAM, wenn es auf eine Datei .\Setup.ini drauf zugreifen möchte? Das müsste man mal mit einem selbstgeschriebenen Setup ausprobieren.
-
GetModuleFileName(0, ...)
wird auch lustig. Aber darum geht's ja wohl nicht.Eher dafür dass es im Prinzip keinen guten Gründe gibt das machen zu wollen was der OP machen will. Aber klar, er will das ganz sicher nur aus Neugier wissen
-
Ja hast ja Recht. Die Anzeichen sind da. Man möchte etwas unkonventionielles machen, benötigt tiefes Fachwissen, hat selbst wenig Ahnung vom Fach und eine typische C Sauklaue.
Habe etwas in die Richtung RAM-Festplatte vermutet. Ist wohl eher mal wieder sowas wie DLL Injection.