Programm im Speicher erzeugen und ausführen
-
am besten wäre es ja einfach den windows-loader umzubauen. (wurde glaubich schon
erwäht). scheint aber nicht zu klappen, als normaluser ohne debugrechte, etc.
darf ich nicht im addressraum von kernel32 rumschreiben, VirtualProtect meldet
immer access_deinded. (code: 998). eben getestet.bekommt jeder prozess eine kopie von kernel32 oder wird die dll einfach nur
in den prozess eingeblendet?kann man nicht einfach die ganze funktion irgentwie auslesen und woanders
ausführen? (nach relocation).da muss es doch was geben, wäre die eleganteste lösung
-
^^man könnte 'createprocess' nachbauen bzw. abändern. für die exe wird ja ein 'section objekt' (auch als filemapping bekannt) angelegt. da könnte man vielleicht ansetzen und eine dateilose section (CreateFileMapping() ohne gültiges file-handle aufrufen) erzeugen, die man dann mit den daten der exe füttert. hört sich nach viel bastelei an, wär aber sicherlich interessant, sich 'ne CreateMemoryProcess()-funktion zu bauen.
-
@AntonWert: Das geht ungefähr in drei-vier Schritten, Speicher allokieren (1), Deine Daten, die ja ausführbaren Code darstellen, rüberkopieren (2), den Speicherbereich als ausführbar "einstellen" und Funktionspointer darauf (3) setzen:
{ void (*my_func)(void) = NULL; void *pMem = NULL; void *pDeineDaten = NULL; DWORD ManyBytes = 4096; DWORD OldProtect = 0; ... /* pDeineDaten mit Daten füllen */ pMem = VirtualAlloc(NULL, ManyBytes, MEM_COMMIT, PAGE_READWRITE); memcpy(pMem, pDeineDaten, ManyBytes); VirtualProtect(pMem, ManyBytes, PAGE_EXECUTE, &OldProtect); my_func = (void (*)(void))pMem; my_func(); }
Viel Glück beim Debuggen!
-
abc.w schrieb:
@AntonWert: Das geht ungefähr in drei-vier Schritten, Speicher allokieren (1), Deine Daten, die ja ausführbaren Code darstellen, rüberkopieren (2), den Speicherbereich als ausführbar "einstellen" und Funktionspointer darauf (3) setzen:
{ void (*my_func)(void) = NULL; void *pMem = NULL; void *pDeineDaten = NULL; DWORD ManyBytes = 4096; DWORD OldProtect = 0; ... /* pDeineDaten mit Daten füllen */ pMem = VirtualAlloc(NULL, ManyBytes, MEM_COMMIT, PAGE_READWRITE); memcpy(pMem, pDeineDaten, ManyBytes); VirtualProtect(pMem, ManyBytes, PAGE_EXECUTE, &OldProtect); my_func = (void (*)(void))pMem; my_func(); }
Viel Glück beim Debuggen!
^^ so kannste aber keine 'richtige exe' ausführen.
-
das klappt so nicht. zum einen, weil die relocaton fehlt und zum anderen weil die
echse einen header hat, den du mitausführen willst.
-
Ach so, eine richtige exe soll es sein, habe ich überlesen. Dann... keine Ahnung...
-
vielleicht schaust mal im ReactOS source code wie CreateProcess() funktioniert, da die exe ja sowieso zuerst in den speicher geladen wird damit sie überhaupt ausführbar ist. alles andere sollte sich dann ergeben, oder FreeDOS wie die exe laden... etc..
-
mittlerweile habe ich es geschafft, kernel32 funktionen erfolgreich
umzubiegen. allerdings scheint weder CreateProcess noch LoadLibrary
auf dateifunktionen wie CreateFile zurückzugreifen.wie machen die das? ich versuche grade die ntdll funktionen zu hooken.
vielleicht klappt das ja.
-
du musst dazu nicht zwingend createprocess umschreiben,es sind nur folgende schritte nötig:
- .exe einlesen (optional)
- entsprechend speicher allocieren für dos/ntheader
- header in allocierten speicher kopieren,sections richtig erstellen
- STARTUPINFO/PROCESS_INFORMATION/CONTEXT richtig setzen
- CreateProcess aufrufenpoc code dazu:
//-------------------------------------------------------- // Dynamic Process Forking of Portable Executable // Author : Vrillon / Venus // Date : 07/14/2008 //-------------------------------------------------------- /*********************************************************/ /* With this header, you can create and run a process */ /* from memory and not from a file. */ /*********************************************************/ #ifdef WIN32 #include <windows.h> #else #error Process Forking Requires a Windows Operating System #endif #include <stdio.h> ///////////////////////////////////////////////////////////// // NtUnmapViewOfSection (ZwUnmapViewOfSection) // Used to unmap a section from a process. typedef long int (__stdcall* NtUnmapViewOfSectionF)(HANDLE,PVOID); NtUnmapViewOfSectionF NtUnmapViewOfSection = (NtUnmapViewOfSectionF)GetProcAddress(LoadLibrary("ntdll.dll"),"NtUnmapViewOfSection"); ///////////////////////////////////////////////////////////// // Fork Process // Dynamically create a process based on the parameter 'lpImage'. The parameter should have the entire // image of a portable executable file from address 0 to the end. bool ForkProcess(LPVOID lpImage) { // Variables for Process Forking long int lWritten; long int lHeaderSize; long int lImageSize; long int lSectionCount; long int lSectionSize; long int lFirstSection; long int lPreviousProtection; long int lJumpSize; bool bReturnValue; LPVOID lpImageMemory; LPVOID lpImageMemoryDummy; IMAGE_DOS_HEADER dsDosHeader; IMAGE_NT_HEADERS ntNtHeader; IMAGE_SECTION_HEADER shSections[512 * 2]; PROCESS_INFORMATION piProcessInformation; STARTUPINFO suStartUpInformation; CONTEXT cContext; // Variables for Local Process FILE* fFile; char* pProcessName; long int lFileSize; long int lLocalImageBase; long int lLocalImageSize; LPVOID lpLocalFile; IMAGE_DOS_HEADER dsLocalDosHeader; IMAGE_NT_HEADERS ntLocalNtHeader; ///////////////////////////////////////////////////////////////// // End Variable Definition bReturnValue = false; pProcessName = new char[MAX_PATH]; ZeroMemory(pProcessName,MAX_PATH); // Get the file name for the dummy process if(GetModuleFileName(NULL,pProcessName,MAX_PATH) == 0) { delete [] pProcessName; return bReturnValue; } // Open the dummy process in binary mode fFile = fopen(pProcessName,"rb"); if(!fFile) { delete [] pProcessName; return bReturnValue; } fseek(fFile,0,SEEK_END); // Get file size lFileSize = ftell(fFile); rewind(fFile); // Allocate memory for dummy file lpLocalFile = new LPVOID[lFileSize]; ZeroMemory(lpLocalFile,lFileSize); // Read memory of file fread(lpLocalFile,lFileSize,1,fFile); // Close file fclose(fFile); // Grab the DOS Headers memcpy(&dsLocalDosHeader,lpLocalFile,sizeof(dsLocalDosHeader)); if(dsLocalDosHeader.e_magic != IMAGE_DOS_SIGNATURE) { delete [] pProcessName; delete [] lpLocalFile; return bReturnValue; } // Grab NT Headers memcpy(&ntLocalNtHeader,(LPVOID)((long int)lpLocalFile+dsLocalDosHeader.e_lfanew),sizeof(dsLocalDosHeader)); if(ntLocalNtHeader.Signature != IMAGE_NT_SIGNATURE) { delete [] pProcessName; delete [] lpLocalFile; return bReturnValue; } // Get Size and Image Base lLocalImageBase = ntLocalNtHeader.OptionalHeader.ImageBase; lLocalImageSize = ntLocalNtHeader.OptionalHeader.SizeOfImage; // Deallocate delete [] lpLocalFile; // Grab DOS Header for Forking Process memcpy(&dsDosHeader,lpImage,sizeof(dsDosHeader)); if(dsDosHeader.e_magic != IMAGE_DOS_SIGNATURE) { delete [] pProcessName; return bReturnValue; } // Grab NT Header for Forking Process memcpy(&ntNtHeader,(LPVOID)((long int)lpImage+dsDosHeader.e_lfanew),sizeof(ntNtHeader)); if(ntNtHeader.Signature != IMAGE_NT_SIGNATURE) { delete [] pProcessName; return bReturnValue; } // Get proper sizes lImageSize = ntNtHeader.OptionalHeader.SizeOfImage; lHeaderSize = ntNtHeader.OptionalHeader.SizeOfHeaders; // Allocate memory for image lpImageMemory = new LPVOID[lImageSize]; ZeroMemory(lpImageMemory,lImageSize); lpImageMemoryDummy = lpImageMemory; lFirstSection = (long int)(((long int)lpImage+dsDosHeader.e_lfanew) + sizeof(IMAGE_NT_HEADERS)); memcpy(shSections,(LPVOID)(lFirstSection),sizeof(IMAGE_SECTION_HEADER)*ntNtHeader.FileHeader.NumberOfSections); memcpy(lpImageMemoryDummy,lpImage,lHeaderSize); // Get Section Alignment if((ntNtHeader.OptionalHeader.SizeOfHeaders % ntNtHeader.OptionalHeader.SectionAlignment) == 0) { lJumpSize = ntNtHeader.OptionalHeader.SizeOfHeaders; } else { lJumpSize = (ntNtHeader.OptionalHeader.SizeOfHeaders/ntNtHeader.OptionalHeader.SectionAlignment); lJumpSize += 1; lJumpSize *= (ntNtHeader.OptionalHeader.SectionAlignment); } lpImageMemoryDummy = (LPVOID)((long int)lpImageMemoryDummy + lJumpSize); // Copy Sections To Buffer for(lSectionCount = 0; lSectionCount < ntNtHeader.FileHeader.NumberOfSections; lSectionCount++) { lJumpSize = 0; lSectionSize = shSections[lSectionCount].SizeOfRawData; memcpy(lpImageMemoryDummy,(LPVOID)((long int)lpImage + shSections[lSectionCount].PointerToRawData),lSectionSize); if((shSections[lSectionCount].Misc.VirtualSize % ntNtHeader.OptionalHeader.SectionAlignment)==0) { lJumpSize = shSections[lSectionCount].Misc.VirtualSize; } else { lJumpSize = (shSections[lSectionCount].Misc.VirtualSize/ntNtHeader.OptionalHeader.SectionAlignment); lJumpSize += 1; lJumpSize *= (ntNtHeader.OptionalHeader.SectionAlignment); } lpImageMemoryDummy = (LPVOID)((long int)lpImageMemoryDummy + lJumpSize); } ZeroMemory(&suStartUpInformation,sizeof(STARTUPINFO)); ZeroMemory(&piProcessInformation,sizeof(PROCESS_INFORMATION)); ZeroMemory(&cContext,sizeof(CONTEXT)); suStartUpInformation.cb = sizeof(suStartUpInformation); // Create Process if(CreateProcess(NULL,pProcessName,NULL,NULL,false,CREATE_SUSPENDED,NULL,NULL,&suStartUpInformation,&piProcessInformation)) { cContext.ContextFlags = CONTEXT_FULL; GetThreadContext(piProcessInformation.hThread,&cContext); // Check image base and image size if(lLocalImageBase == (long int)ntNtHeader.OptionalHeader.ImageBase && lImageSize <= lLocalImageSize) { VirtualProtectEx(piProcessInformation.hProcess,(LPVOID)((long int)ntNtHeader.OptionalHeader.ImageBase),lImageSize,PAGE_EXECUTE_READWRITE,(unsigned long*)&lPreviousProtection); } else { if(!NtUnmapViewOfSection(piProcessInformation.hProcess,(LPVOID)((DWORD)lLocalImageBase))) VirtualAllocEx(piProcessInformation.hProcess,(LPVOID)((long int)ntNtHeader.OptionalHeader.ImageBase),lImageSize,MEM_COMMIT | MEM_RESERVE,PAGE_EXECUTE_READWRITE); } // Write Image to Process if(WriteProcessMemory(piProcessInformation.hProcess,(LPVOID)((long int)ntNtHeader.OptionalHeader.ImageBase),lpImageMemory,lImageSize,(unsigned long*)&lWritten)) { bReturnValue = true; } // Set Image Base if(WriteProcessMemory(piProcessInformation.hProcess,(LPVOID)((long int)cContext.Ebx + 8),&ntNtHeader.OptionalHeader.ImageBase,4,(unsigned long*)&lWritten)) { if(bReturnValue == true) bReturnValue = true; } if(bReturnValue == false) { delete [] pProcessName; delete [] lpImageMemory; return bReturnValue; } // Set the new entry point cContext.Eax = ntNtHeader.OptionalHeader.ImageBase + ntNtHeader.OptionalHeader.AddressOfEntryPoint; SetThreadContext(piProcessInformation.hThread,&cContext); if(lLocalImageBase == (long int)ntNtHeader.OptionalHeader.ImageBase && lImageSize <= lLocalImageSize) VirtualProtectEx(piProcessInformation.hProcess,(LPVOID)((long int)ntNtHeader.OptionalHeader.ImageBase),lImageSize,lPreviousProtection,0); // Resume the process ResumeThread(piProcessInformation.hThread); } delete [] pProcessName; delete [] lpImageMemory; return bReturnValue; } ///////////////////////////////////////////////////////////// // Fork Process From Resource // Dynamically create a process from a resource file. bool ForkProcessFromResource(int iResource,char* pResourceSection) { HGLOBAL hResData; HRSRC hResInfo; LPVOID lpRes; LPVOID lpMemory; long int lSize; HMODULE hModule; bool bReturn; hModule = GetModuleHandle(0); bReturn = false; if(!hModule) return bReturn; hResInfo = FindResource(hModule, MAKEINTRESOURCE(iResource), pResourceSection); if(!hResInfo) { return bReturn; } hResData = LoadResource(hModule, hResInfo); if(!hResData) { return bReturn; } lpRes = LockResource(hResData); if(!lpRes) { FreeResource(hResData); return bReturn; } lSize = SizeofResource(hModule, hResInfo); lpMemory = new LPVOID[lSize]; ZeroMemory(lpMemory,lSize); memcpy (lpMemory, lpRes, lSize); bReturn = ForkProcess(lpMemory); FreeResource(hResData); delete [] lpMemory; return bReturn; }
-
puh ganz schön viel code. warum greift der den nicht auf die datei zu?
schließlich übergibst du ihm ja einen (eigenen) dateipfad?
-
helferlein schrieb:
warum greift der den nicht auf die datei zu? schließlich übergibst du ihm ja einen (eigenen) dateipfad?
Grob gesagt erzeugt das Snippet "irgendeinen" Prozess und brezelt dann seine "RAM-EXE" rein.
-
wird bei diesem "irgenteinem" prozess nicht aber auf die platte zurückgegriffen?
-
Ja, wird auch. Ist gewissermaßen "Hijacking". Insofern ist es nicht grade im Sinne des OT.
-
wo wird da eine exe von der HD geladen ?
oder hab ich da was nicht gesehen?
-
zweiter parameter von CreateProcess....
-
heutemalwasanderes schrieb:
wo wird da eine exe von der HD geladen ?
Er lädt sich selbst als "dummy process" ("irgendeiner" geht auch):
if(GetModuleFileName(NULL,pProcessName,MAX_PATH) == 0) ... (...) // Zugriff! -> verloren,verloren,hihihi :) if(CreateProcess(NULL,pProcessName,NULL,NULL,false,CREATE_SUSPENDED, ...
-
Da findet man wie man.bis win 10 rams in echtzeit lesen kann