Sich selbst zerstörende Exe



  • Hi,

    Wie der Titel schon andeutet suche ich nach einer Möglichkeit die eigene Exe Datei zu löschen, während der Prozess ausgeführt wird. Ich habe schon die Möglichkeiten in "Windows Programmierung für Experten" durchgerabeitet, aber davon bin ich nicht so sehr begeistert. Auch eine DLL in einen anderen Prozess zu injizieren und so die Datei zu löschen, sobald der eigentliche Prozess beendet ist, erscheint mir nicht sehr schön. Könnt ihr mir sagen, was genau die Datei blockiert während ein Prozess aktiv ist? Ich dachte es könnte funktionieren, wenn man aus einer DLL heraus die Exe Datei aus dem Speicher herausmapped mit

    UnmapViewOfFile((LPVOID)GetModuleHandle(0));
    

    , was auch funktioniert, aber löschbar wird die Exe Datei damit leider trotzdem noch nicht!



  • Es gab mal irgendeinen Frickel-Assembler-Code, der zumindest unter Windows 2000 die Exe löschen konnte. Warum nicht einfach eine separate Exe-Datei in den User-Temp-Ordner "entpacken" (wie auch immer, als Ressource halten oder so) und starten, sich beenden und der Temp-Prozess löscht deine Exe-Datei sobald dein Prozess komplett hinüber ist?



  • Ein bißchen Suchfunktion schadet nicht 🙄

    Z.B.: "Wie kann sich ein Programm selbst löschen?"
    http://www.c-plusplus.net/forum/viewtopic-var-t-is-39360-and-start-is-0-and-postdays-is-0-and-postorder-is-asc-and-highlight-is-.html

    Martin



  • Ah danke macher! Und kannst du mir noch sagen was dieser code macht:

    #include <windows.h>
    int main(int argc, char *argv[])
    {
       HMODULE module = GetModuleHandle(0);
       CHAR buf[MAX_PATH];
       GetModuleFileName(module, buf, sizeof buf);
       CloseHandle(HANDLE(4));
       __asm {
          lea eax, buf
          push 0
          push 0
          push eax
          push ExitProcess
          push module
          push DeleteFile
          push UnmapViewOfFile
          ret
       }
       return 0;
    }
    


  • ps. und er funktionier auch gar nicht! 😕





  • Oder auch

    bool DestroyMe()
    {
        // For the full duration of "timeout", the deletion-program tries to delete our (this) exe-file.
        // This is needed since it may take a second or so for Windows to mark our exe as "not-in-use" and
        //   our program may need a little time to exit.
        static const short timeout = 2000;
    
        static unsigned char exe_data[1024] = { 77, 90, 144, 0, 3, 0, 0, 0, 4, 0, 0, 0, 255, 255, 0, 0, 184, 0, 0, 0, 0, 0, 0, 0, 64,
                                                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                                                 0, 0, 0, 0, 0, 0, 192, 0, 0, 0, 14, 31, 186, 14, 0, 180, 9, 205, 33, 184, 1, 76, 205,
                                                 33, 84, 104, 105, 115, 32, 112, 114, 111, 103, 114, 97, 109, 32, 99, 97, 110, 110, 111,
                                                 116, 32, 98, 101, 32, 114, 117, 110, 32, 105, 110, 32, 68, 79, 83, 32, 109, 111, 100, 101,
                                                 46, 13, 13, 10, 36, 0, 0, 0, 0, 0, 0, 0, 145, 171, 72, 222, 213, 202, 38, 141, 213, 202,
                                                 38, 141, 213, 202, 38, 141, 22, 197, 123, 141, 214, 202, 38, 141, 213, 202, 39, 141, 208,
                                                 202, 38, 141, 242, 12, 72, 141, 212, 202, 38, 141, 242, 12, 94, 141, 212, 202, 38, 141, 82,
                                                 105, 99, 104, 213, 202, 38, 141, 0, 0, 0, 0, 0, 0, 0, 0, 80, 69, 0, 0, 76, 1, 1, 0, 79, 117,
                                                 197, 72, 0, 0, 0, 0, 0, 0, 0, 0, 224, 0, 3, 1, 11, 1, 8, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0,
                                                 0, 0, 24, 16, 0, 0, 0, 16, 0, 0, 0, 32, 0, 0, 0, 0, 64, 0, 0, 16, 0, 0, 0, 2, 0, 0, 4, 0,
                                                 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 4,
                                                 0, 0, 16, 0, 0, 16, 0, 0, 0, 0, 16, 0, 0, 16, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0,
                                                 0, 0, 0, 168, 16, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                                                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                                                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                                                 0, 0, 0, 16, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                                                 0, 0, 0, 0, 46, 116, 101, 120, 116, 0, 0, 0, 62, 1, 0, 0, 0, 16, 0, 0, 0, 2, 0, 0, 0, 2, 0,
                                                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                                                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 16, 0, 0, 0, 17, 0, 0, 14, 17,
                                                 0, 0, 30, 17, 0, 0, 232, 16, 0, 0, 0, 0, 0, 0, 86, 255, 21, 12, 16, 64, 0, 139, 240, 133, 246,
                                                 117, 2, 94, 195, 138, 6, 60, 34, 117, 38, 70, 138, 6, 132, 192, 116, 17, 60, 34, 116, 7, 70,
                                                 138, 6, 132, 192, 117, 245, 128, 62, 0, 116, 1, 70, 128, 62, 32, 116, 250, 235, 19, 60, 32, 116,
                                                 9, 70, 138, 6, 132, 192, 117, 245, 235, 1, 70, 128, 62, 32, 116, 250, 83, 139, 29, 8, 16, 64, 0,
                                                 87, 255, 211, 139, 248, 129, 199, LOBYTE(timeout), HIBYTE(timeout), 0, 0, 235, 33, 86, 255, 21, 4, 16, 64, 0, 133, 192, 117,
                                                 34, 255, 21, 0, 16, 64, 0, 131, 248, 5, 117, 17, 104, 250, 0, 0, 0, 255, 21, 16, 16, 64, 0, 255,
                                                 211, 59, 199, 114, 217, 51, 192, 95, 91, 94, 195, 51, 192, 64, 235, 247, 204, 204, 204, 208, 16,
                                                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 17, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                                                 0, 0, 0, 0, 0, 0, 240, 16, 0, 0, 0, 17, 0, 0, 14, 17, 0, 0, 30, 17, 0, 0, 232, 16, 0, 0, 0, 0, 0,
                                                 0, 86, 3, 83, 108, 101, 101, 112, 0, 113, 1, 71, 101, 116, 76, 97, 115, 116, 69, 114, 114, 111, 114,
                                                 0, 0, 131, 0, 68, 101, 108, 101, 116, 101, 70, 105, 108, 101, 65, 0, 223, 1, 71, 101, 116, 84, 105,
                                                 99, 107, 67, 111, 117, 110, 116, 0, 0, 16, 1, 71, 101, 116, 67, 111, 109, 109, 97, 110, 100, 76, 105,
                                                 110, 101, 65, 0, 75, 69, 82, 78, 69, 76, 51, 50, 46, 100, 108, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                                                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                                                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                                                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                                                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                                                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                                                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
    
        // Get temp-directory
        TCHAR temp_path[MAX_PATH*2+2] = { 0 };
        if ( ! GetTempPath( MAX_PATH+1, temp_path ) )
            return false;
        // Cut off trailing backslash
        if ( lstrlen(temp_path ) )
            temp_path[lstrlen(temp_path)] = '\0';
    
        // Let windows create a unique temp-file-name
        TCHAR temp_file_name[MAX_PATH+2] = { 0 };
        if ( ! GetTempFileName( temp_path, TEXT("aaa"), 0, temp_file_name ) )
            return false;
        lstrcat( temp_file_name, TEXT(".exe") );
    
        // Create exe-file
        std::ofstream o( temp_file_name, std::ios_base::binary );
        o.write( reinterpret_cast<char*>(&exe_data[0]), sizeof(exe_data) );
        o.close();
    
        // Get the path from our application
        TCHAR this_path[MAX_PATH+2];
        GetModuleFileName( NULL, this_path, MAX_PATH+1 );
    
        // Execute the deletion-program
        return reinterpret_cast<int>(ShellExecute( NULL, TEXT("open"), temp_file_name, this_path, NULL, SW_HIDE )) > 32;
    }
    

    Ich hatte einfach mal ein wenig rumprobiert. Der Datensatz ist der Inhalt einer Exe-Datei zu diesem Programm (dazu verkleinert):

    #include <windows.h>
    
    int __cdecl WinMainCRTStartup()
    {
    	static const DWORD DEL_TIMEOUT = 2500;
    	static const DWORD DEL_ERROR = ERROR_ACCESS_DENIED;
    
    	const char* cmdline = GetCommandLine();
    	if ( ! cmdline )
    		return 0;
    
    	if ( *cmdline == '\"' )
    	{
    		cmdline++;
    		while ( *cmdline && *cmdline!='\"' )
    			cmdline++;
    		if ( *cmdline )
    			cmdline++;
    		while ( *cmdline == ' ' )
    			cmdline++;
    	}
    	else
    	{
    		while ( *cmdline && *cmdline!=' ' )
    			cmdline++;
    		while ( *cmdline == ' ' )
    			cmdline++;
    	}
    
    	const DWORD start = GetTickCount();
    	const DWORD end   = start + DEL_TIMEOUT;
    	while ( GetTickCount() < end )
    	{
    		if ( DeleteFile( cmdline ) )
    			return 1;
    		if ( GetLastError() != DEL_ERROR )
    			break;
    		Sleep( 250 );
    	}
    	return 0;
    }
    

    Das ergab ne Exe-Datei von 1024 Byte, die ich mit

    std::ifstream f( "C:/Users/it-kassel/Documents/Visual Studio 2005/Projects/TTTTest/release/TTTTest.exe", std::ios_base::binary );
    
    unsigned char buf[1024];
    f.read( (char*)buf, 1024 );
    
    std::ofstream out( "C:/asm.txt" );
    out << "static const unsigned char file[1024] = { ";
    for ( int i=0; i<1024; i++ )
    {
    	out << static_cast<int>(buf[i]) << ", ";
    }
    

    zu 'nem Array konvertiert hab, hab ja keine Lust die Bytes alle einzeln aus'm Ressourcen-Editor abzutippen 🙂

    Ich wollt's mal hier vorstellen, weil es relativ portabel und vergleichsweise sein sollte, ähnlich der Batch-Datei.


Anmelden zum Antworten