Last active
October 29, 2023 16:48
-
-
Save vadimpiven/0f6e50474eee21909026a3a5c7abf1ce to your computer and use it in GitHub Desktop.
Executable self delete (WinAPI, C++ 17) - works only if executable is located on NTFS partition
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: MIT | |
// MIT Software License: https://opensource.org/licenses/MIT | |
// Copyright Vadim Piven <[email protected]> | |
#include <Windows.h> | |
#include <algorithm> | |
#include <array> | |
#include <cstddef> | |
#include <filesystem> | |
#include <iostream> | |
#include <iterator> | |
#include <memory> | |
#include <stdexcept> | |
#include <string> | |
#include <vector> | |
namespace { | |
[[nodiscard]] inline std::filesystem::path GetExecutablePath() | |
{ | |
std::vector<wchar_t> path(MAX_PATH); | |
while (!::GetModuleFileNameW(nullptr, path.data(), static_cast<DWORD>(path.size()))) | |
path.resize(2 * path.size()); | |
return {path.data()}; | |
} | |
inline void UnbindNtfsDataStream(const std::filesystem::path & path) | |
{ | |
auto const handle = ::CreateFileW(path.c_str(), DELETE | SYNCHRONIZE, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr); | |
if (INVALID_HANDLE_VALUE == handle) | |
throw std::runtime_error("CreateFileW failed, error: " + std::to_string(::GetLastError())); | |
const auto file = std::unique_ptr<void, decltype(&::CloseHandle)>(handle, &::CloseHandle); | |
constexpr wchar_t const Label[]{L":UNBOUND"}; | |
std::array<std::byte, sizeof(FILE_RENAME_INFO) + sizeof(Label)> info{}; | |
auto renameInfo = new(info.data()) FILE_RENAME_INFO({.FileNameLength = sizeof(Label) - sizeof(L'\0')}); | |
std::copy(std::begin(Label), std::end(Label), std::begin(renameInfo->FileName)); | |
if (!::SetFileInformationByHandle(file.get(), FileRenameInfo, renameInfo, static_cast<DWORD>(info.size()))) | |
throw std::runtime_error("SetFileInformationByHandle failed, error: " + std::to_string(::GetLastError())); | |
} | |
} // namespace | |
void TryDeleteExecutable() noexcept | |
{ | |
try | |
{ | |
const auto path = GetExecutablePath(); | |
UnbindNtfsDataStream(path); | |
std::filesystem::remove(path); | |
} | |
catch (const std::exception & err) | |
{ | |
std::clog << err.what(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Credits to https://habr.com/ru/companies/ru_mts/articles/767078/