0

I got 3 files (selfdelxp.c, selfdelxp.h and main.cpp)

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

The problem comes when I try to compile it throwing the error undefined reference to 'SelfDelete()'

How can I make it work? What am I doing wrong? What I'm trying to do is to be able to use that function (SelfDelete()) in a program written 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 <stdbool.h>
 bool SelfDelete(void);

 #endif // SELFDELETE_H_

main.cpp

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

int main()
{
    SelfDelete();
    return 0;
}
user
  • 1
  • 1

1 Answers1

1

You're getting caught out by C++ name mangling. Note selfdelxp.c is presumably compiled as C code. You need to add extern "C" { ... } around the SelfDelete() deceleration or try compiled selfdelxp.c as cpp (e.g. rename it).

Here is how you would do it with the first approach.

#include <windows.h>

extern "C" {
    BOOL SelfDelete();
}

(You could also declare that using C++ bool and probably be okay but afik it is better to include windows.h and use the same type)

Jarra McIntyre
  • 1,265
  • 8
  • 13
  • In which of these three files should I replace it? I tried on main.cpp and .h and still get error by the compiler – user Mar 07 '16 at 09:35
  • You need to replace the definition in your header to tell the c++ compiler that the name SelfDelete should not be mangled. Using the above definition you also need to include windows.h prior to the declaration (Just edited the answer to reflect this). – Jarra McIntyre Mar 07 '16 at 09:37
  • I didn't see your edit, sorry about that. Anyways, it still doesn't work out – user Mar 07 '16 at 09:43
  • Assuming you didn't also rename selfdelxp to selfdelxp.cpp in which case you do _not_ need the above, this sounds like the linker isn't being called correctly. – Jarra McIntyre Mar 07 '16 at 11:04
  • No, I didn't rename as .cpp. I'm using CodeBlocks on Windows 7 When I try to compile I just compile the main.cpp file assuming that it will link and compile everything properly – user Mar 07 '16 at 18:43
  • You need to also compile selfdelxp.c and link the two result .o object files. – Jarra McIntyre Mar 07 '16 at 20:51