Skip to content

Instantly share code, notes, and snippets.

@vsetka
Last active February 23, 2024 07:32
Show Gist options
  • Save vsetka/f10d94c03750a46e126604e7c6fe813e to your computer and use it in GitHub Desktop.
Save vsetka/f10d94c03750a46e126604e7c6fe813e to your computer and use it in GitHub Desktop.
Self deleting executable - Windows
#ifndef CLEANUP_H
#define CLEANUP_H
#include <windows.h>
#include <tchar.h>
#include <string>
#include <iostream>
#include <conio.h>
#endif
extern "C" BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD reason, LPVOID);
extern "C" __declspec(dllexport) void CALLBACK SelfDel(HWND, HINSTANCE, LPTSTR lpCmdLine, int);
extern "C" __declspec(dllexport) void CALLBACK UninstallMSI(HWND, HINSTANCE, LPTSTR lpCmdLine, int);
#include "Cleanup.h"
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
HMODULE g_hmodDLL;
std::string trueRootDirectory;
int DeleteDirectory(const std::string &refcstrRootDirectory, bool bDeleteSubdirectories = true)
{
bool bSubdirectory = false; // Flag, indicating whether subdirectories have been found
HANDLE hFile; // Handle to directory
std::string strFilePath; // Filepath
std::string strPattern; // Pattern
WIN32_FIND_DATA FileInformation; // File information
strPattern = refcstrRootDirectory + _T("\\*.*");
hFile = ::FindFirstFile(strPattern.c_str(), &FileInformation);
if(hFile != INVALID_HANDLE_VALUE)
{
do
{
if (hFile == INVALID_HANDLE_VALUE)
break;
if(FileInformation.cFileName[0] != '.')
{
strFilePath.erase();
strFilePath = refcstrRootDirectory + _T("\\") + FileInformation.cFileName;
if(FileInformation.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if(bDeleteSubdirectories)
{
// Delete subdirectory
int iRC = DeleteDirectory(strFilePath, bDeleteSubdirectories);
if(iRC)
return iRC;
}
else
bSubdirectory = true;
}
else
{
if (strFilePath.find(_T("Cleanup.dll")) == std::string::npos) // Do not delete self, we'll do that later
{
// Set file attributes
if(::SetFileAttributes(strFilePath.c_str(), FILE_ATTRIBUTE_NORMAL) == FALSE)
return ::GetLastError();
// Delete file
if(::DeleteFile(strFilePath.c_str()) == FALSE)
return ::GetLastError();
}
}
}
} while(::FindNextFile(hFile, &FileInformation) == TRUE);
// Close handle
::FindClose(hFile);
DWORD dwError = ::GetLastError();
if(dwError != ERROR_NO_MORE_FILES)
{
return dwError;
}
// Do not delete the root directory
else if (trueRootDirectory != refcstrRootDirectory)
{
if(!bSubdirectory)
{
// Set directory attributes
if(::SetFileAttributes(refcstrRootDirectory.c_str(), FILE_ATTRIBUTE_NORMAL) == FALSE)
return ::GetLastError();
// Delete directory
if(::RemoveDirectory(refcstrRootDirectory.c_str()) == FALSE)
return ::GetLastError();
}
}
}
return 0;
}
extern "C" BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD reason, LPVOID)
{
if (reason == DLL_PROCESS_ATTACH)
g_hmodDLL = hinstDLL;
return TRUE;
}
extern "C" __declspec(dllexport) void CALLBACK UninstallMSI(HWND, HINSTANCE, LPTSTR productCode, int)
{
// delete the executable file that created this process
Sleep(5000);
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );
TCHAR windir[255];
TCHAR directory[255];
TCHAR filename[255];
TCHAR np_name[255];
GetSystemWindowsDirectory(windir, 148);
_stprintf(np_name, _T("%s\\system32\\msiexec.exe /x %s /q"), windir,productCode);
/*::MessageBoxA(NULL,np_name,"",MB_OK);*/
LPTSTR szCmdline = _tcsdup(np_name);
CreateProcess(NULL, szCmdline,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi);
free(szCmdline);
// Name of self
TCHAR filenameDLL[MAX_PATH];
GetModuleFileName(g_hmodDLL, filenameDLL, sizeof(filenameDLL));
// Assembler magic to unload from rundll32
__asm
{
lea eax, filenameDLL
push 0
push 0
push eax
push ExitProcess
push FreeLibrary
ret
}
}
extern "C" __declspec(dllexport) void CALLBACK SelfDel(HWND, HINSTANCE, LPTSTR lpCmdLine, int)
{
// delete the executable file that created this process
Sleep(5000);
trueRootDirectory = std::string(lpCmdLine);
int iRC = DeleteDirectory(lpCmdLine);
if(iRC)
{
std::cout << "Error " << iRC << std::endl;
return;
}
// Name of self
TCHAR filenameDLL[MAX_PATH];
GetModuleFileName(g_hmodDLL, filenameDLL, sizeof(filenameDLL));
// Assembler magic to delete itself and unload from rundll32
__asm
{
lea eax, filenameDLL
push 0
push 0
push eax
push ExitProcess
push g_hmodDLL
push DeleteFile
push FreeLibrary
ret
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment