The routine below deletes its own exe.
#include <windows.h> // for API's used
int MAXPATH = MAX_PATH;
int stack_code_size = 9;
int __declspec(naked) stack_code(void)
{
// bytes
_asm("popl %eax"); // 1
_asm("call %eax"); // 2 // call FreeLibrary()
_asm("popl %eax"); // 1
_asm("call %eax"); // 2 // call DeleteFileA()
_asm("ret $265"); // 3 // MAXPATH + stack_code_size - 4
}
int main (void)
{
_asm("subl $269,%esp");
// MAXPATH + stack_code_size
_asm("movl %esp,%edi");
// alloc buffer in stack
_asm("movl %edi,%ebx");
_asm("movl %stack_code_size,%ecx"); // stack_code_size
_asm("leal %stack_code,%esi");
_asm("rep");
_asm("movsb");
// copy code to stack buffer
_asm("pushl %MAXPATH");
_asm("pushl %edi");
// copy EXE name to stack buffer (after code)
_asm("pushl %ecx");
// 0
_asm("call %GetModuleFileNameA");
_asm("leal %ExitProcess,%eax"); // to push the real API address, we get
// the offset of the JMP in end of .CODE
_asm("movl 2(%eax),%eax");
// to the import table
_asm("pushl (%eax)");
// and get the real address of the API
_asm("pushl %edi");
// parameter to DeleteFileA()
_asm("leal %DeleteFileA,%eax");
_asm("movl 2(%eax),%eax");
_asm("pushl (%eax)");
_asm("pushl $0");
_asm("call %GetModuleHandleA");
_asm("pushl %eax");
// paramter to FreeLibrary()
_asm("leal %FreeLibrary,%eax");
_asm("movl 2(%eax),%eax");
_asm("pushl (%eax)");
_asm("jmp %ebx");
// jmp to code in stack
return 0;
}