0

When I try to compile main.cpp the compiler throws the undefined reference to 'SelfDelete()' error.

I don't know what's wrong in the code as I tried to do everything related to this problem to solve it (e.g extern "C" {...}, #include <windows.h>)

NOTE: selfdelxp.c was copied from http://blogorama.nerdworks.in/selfdeletingexecutables/ and I removed the main function as I try to use the SelfDelete() function in main.cpp

selfdelxp.c

//
//  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;
}*/

selfdelxp.h

#ifndef SELFDELETE_H
#define SELFDELETE_H

#include <windows.h>
#ifdef __cplusplus

extern "C"{
#endif
    BOOL SelfDelete();
#ifdef __cplusplus
}
#endif

#endif // SELFDELETE_H

main.cpp

#include <iostream>
#include "selfdelxp.h"
using namespace std;

int main()
{
    cout << "This .exe will be removed at the end the execution..." << endl;
    SelfDelete();
    return 0;
}
Weather Vane
  • 33,872
  • 7
  • 36
  • 56
  • @mah: That could be it, although the `.c` extension suggests that the source file shouldn't be using C++ mangling. Of course, the root cause is failure to include the header file from `selfdelxp.c`, which is always a good idea because it lets the compiler automatically compare all declarations and catch incompatibilities. – Ben Voigt Mar 07 '16 at 19:35
  • Is `selfdelxp.c` being compiled in C language mode or C++ language mode? Did you link with it? – Ben Voigt Mar 07 '16 at 19:37
  • 1
    @mah : If selfdelxp.c is compiled as C code (as would be the default from the extension), then `extern "C"` would be invalid as it is C++. The file already has C linkage by virtue of being C compiled. It might be simpler however to just compile the code as C++. – Clifford Mar 07 '16 at 19:38
  • "Undefined reference" is a linker error. The most likely cause is that you have not added selfdelxp.c to your project (or makefile or whatever). It must be separately compiled and linked. If you are not using a project manager, IDE or makefile, you will need to issue and appropriate linker command. – Clifford Mar 07 '16 at 19:40
  • @Clifford ahh yes, well that's an excellent point isn't it! – mah Mar 07 '16 at 19:40
  • @BenVoigt I open main.cpp with CodeBlocks and compile it (I assume it compiles and links everything in C++ mode, but I'm not 100% sure as I'm playing around with programming, I'm not an expert in this) – user123456 Mar 07 '16 at 19:42

0 Answers0