-1

I found this code on the Internet but it says that is to be run on Windows XP. I tried to run it on Windows 7 and it worked, but I wonder if it is safe, not just running this code, but also doing it on Windows 7.

//
//  Self-deleting exe under Windows XP
//
#include <windows.h>
#include <tchar.h>

// get this right!
#define EXPLORER_PID 1444

typedef UINT  (WINAPI * WAIT_PROC)(HANDLE, DWORD);  // WaitForSingleObject
typedef BOOL  (WINAPI * CLOSE_PROC)(HANDLE);        // CloseHandle
typedef BOOL  (WINAPI * DELETE_PROC)(LPCTSTR);      // DeleteFile
typedef VOID  (WINAPI * EXIT_PROC)(DWORD);          // ExitProcess

typedef struct
{
    WAIT_PROC   fnWaitForSingleObject;
    CLOSE_PROC  fnCloseHandle;
    DELETE_PROC fnDeleteFile;
    EXIT_PROC   fnExitProcess;

    HANDLE      hProcess;
    TCHAR       szFileName[MAX_PATH];

} INJECT;

#pragma optimize("gsy", off)
#pragma check_stack(off)        // doesn't work :-(

DWORD WINAPI RemoteThread(INJECT *remote)
{
    remote->fnWaitForSingleObject(remote->hProcess, INFINITE);
    remote->fnCloseHandle(remote->hProcess);
    remote->fnDeleteFile(remote->szFileName);
    remote->fnExitProcess(0);

    return 0;
}

#pragma check_stack

HANDLE GetRemoteProcess()
{
    STARTUPINFO         si = { sizeof(si) };
    PROCESS_INFORMATION pi;

    //return OpenProcess(PROCESS_ALL_ACCESS, FALSE, EXPLORER_PID);

    if(CreateProcess(0, "explorer.exe", 0, 0, FALSE, CREATE_SUSPENDED|CREATE_NO_WINDOW|IDLE_PRIORITY_CLASS, 0, 0, &si, &pi))
    {
        CloseHandle(pi.hThread);
        return pi.hProcess;
    }
    else
    {
        return 0;
    }
}

PVOID GetFunctionAddr(PVOID func)
{
#ifdef _DEBUG

    // get address of function from the JMP <relative> instruction
    DWORD *offset = (BYTE *)func + 1;
    return (PVOID)(*offset + (BYTE *)func + 5);

#else

    return func;

#endif
}

BOOL SelfDelete()
{
    INJECT local, *remote;
    BYTE   *code;
    HMODULE hKernel32;
    HANDLE  hRemoteProcess;
    HANDLE  hCurProc;

    DWORD   dwThreadId;
    HANDLE  hThread = 0;

    char ach[80];

    hRemoteProcess = GetRemoteProcess();

    if(hRemoteProcess == 0)
        return FALSE;

    // Allocate memory in remote process
    code = VirtualAllocEx(hRemoteProcess, 0, sizeof(INJECT) + 128, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE);

    if(code == 0)
    {
        CloseHandle(hRemoteProcess);
        return FALSE;
    }

    hKernel32 = GetModuleHandle(_T("kernel32.dll"));

    // setup remote structure
    remote = (INJECT *)(code + 128);

    local.fnWaitForSingleObject  = (WAIT_PROC)GetProcAddress(hKernel32,  "WaitForSingleObject");
    local.fnCloseHandle          = (CLOSE_PROC)GetProcAddress(hKernel32, "CloseHandle");
    local.fnExitProcess          = (EXIT_PROC)GetProcAddress(hKernel32, "ExitProcess");

#ifdef UNICODE
    local.fnDeleteFile            = (DELETE_PROC)GetProcAddress(hKernel32, "DeleteFileW");
#else
    local.fnDeleteFile            = (DELETE_PROC)GetProcAddress(hKernel32, "DeleteFileA");
#endif

    // duplicate our own process handle for remote process to wait on
    hCurProc = GetCurrentProcess();
    DuplicateHandle(hCurProc, hCurProc, hRemoteProcess, &local.hProcess, 0, FALSE, DUPLICATE_SAME_ACCESS);

    // find name of current executable
    GetModuleFileName(NULL, local.szFileName, MAX_PATH);

    // write in code to execute, and the remote structure
    WriteProcessMemory(hRemoteProcess, code,    GetFunctionAddr(RemoteThread), 128, 0);
    WriteProcessMemory(hRemoteProcess, remote, &local, sizeof(local), 0);

    wsprintf(ach, "%x %x\n", code, remote);
    OutputDebugString(ach);

    // execute the code in remote process
    hThread = CreateRemoteThread(hRemoteProcess, 0, 0, code, remote, 0, &dwThreadId);

    if(hThread != 0)
    {
        CloseHandle(hThread);
    }

    return TRUE;
}

int main(void)
{
    SelfDelete();

    return 0;
}

By the way, how could this be used as a library in C/C++? My goal is to just use, for example,

#include "selfdel.h" so I can use just the function SelfDelete() in a C++ program.

Enzo
  • 1
  • 1

1 Answers1

0

You should realize what this code is. It's an injection of a code into another process which will be executed as that process and then the process will exit. It should just work (though look at the comments below). I think the author of this code snippet had written it before Win Vista was released, therefore the concern you have.

You can declare SelfDelete() in your "selfdel.h". Calling this function and exiting right away should do the trick.

The implementation doesn't require any input from user of the library since it gets everything it needs.

// duplicate our own process handle for remote process to wait on
hCurProc = GetCurrentProcess();
...
// find name of current executable
GetModuleFileName(NULL, local.szFileName, MAX_PATH);

Some comments:

  • Your process should have enough rights to create the other one
  • Such activity may be treated as suspicious by anti-virus software
  • Don't forget that "zombie" process will wait as long as your process lives after calling SelfDelete()
  • Consider other approaches: How can a program delete its own executable
Community
  • 1
  • 1
Dania
  • 331
  • 1
  • 2
  • 7
  • I tried this but it won't work: #ifndef SELFDELETE_H_ #define SELFDELETE_H_ BOOL SelfDelete(); #endif // SELFDELETE_H_ – Enzo Mar 06 '16 at 13:33
  • Are you saying the code works as it is, but when you include it to another project it stops working? I have tried it and it works fine for me on Win10 + MSVC 2015. The only problem is that 'SelfDelete()' crashes "explorer.exe" (or any other) if you compile it with /RTCs (which is enabled if you compile it as debug). Perhaps this is why you put `#pragma check_stack(off) // doesn't work :-(` ? – Dania Mar 06 '16 at 19:23