#include #include #include #include #include #define log(msg, ...) printf(msg "\n", ##__VA_ARGS__) #define NEW_STREAM L":CROW" extern "C" { extern DWORD CustomError(void); extern DWORD BeingDebugged(void); } BOOL CheckDebugger() { return BeingDebugged() != 0; } int SelfDelete() { WCHAR ProgramPath[MAX_PATH * 2] = { 0 }; if (GetModuleFileNameW(NULL, ProgramPath, MAX_PATH * 2) == 0 ) { log("Error GetModuleFileNameW: %ld", CustomError()); return -1; } { // Rename file, to move data to an alternate data stream DWORD rename_size = sizeof(FILE_RENAME_INFO) + sizeof(NEW_STREAM); PFILE_RENAME_INFO PFRI = (PFILE_RENAME_INFO)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, rename_size); if (PFRI == NULL) { log("Failed HeapAlloc: %ld", CustomError()); return -1; } PFRI->ReplaceIfExists = FALSE; PFRI->RootDirectory = NULL; PFRI->FileNameLength = sizeof(NEW_STREAM) - 2; memcpy(PFRI->FileName, NEW_STREAM, sizeof(NEW_STREAM) - 2); HANDLE file = CreateFileW(ProgramPath, (DELETE | SYNCHRONIZE), FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL); if (file == INVALID_HANDLE_VALUE) { log("Failed 1 CreateFileW: %ld", CustomError()); return -1; } if (!SetFileInformationByHandle(file, FileRenameInfo, PFRI, rename_size)) { log("Failed SetFileInformationByHandle: %ld", CustomError()); } CloseHandle(file); HeapFree(GetProcessHeap(), 0, PFRI); } { // Delete the alternate data stream HANDLE file = CreateFileW(ProgramPath, (DELETE | SYNCHRONIZE), FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL); if (file == INVALID_HANDLE_VALUE) { log("Failed 2 CreateFileW: %ld", CustomError()); return -1; } FILE_DISPOSITION_INFO set_delete = { 0 }; set_delete.DeleteFile = TRUE; if (!SetFileInformationByHandle(file, FileDispositionInfo, &set_delete, sizeof(FILE_DISPOSITION_INFO))) { log("Failed SetFileInformationByHandle: %ld", CustomError()); } CloseHandle(file); } log("Deleted self"); return 0; } int main() { if (!CheckDebugger()) { MessageBoxW(NULL, L"KEK", L"KEK", MB_ICONEXCLAMATION); } else { SelfDelete(); } return 0; }