// ma_uninstaller.cpp : Diese Datei enthält die Funktion "main". Hier beginnt und endet die Ausführung des Programms. // //todo: /* remove folders * remove background task */ #include #include #include #include #include #include #pragma comment(lib, "taskschd.lib") //check if programm is run as admin bool is_admin() { BOOL fIsRunAsAdmin = FALSE; PSID pAdminSID = NULL; SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY; if (AllocateAndInitializeSid(&NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &pAdminSID)) { if (!CheckTokenMembership(NULL, pAdminSID, &fIsRunAsAdmin)) { fIsRunAsAdmin = FALSE; } FreeSid(pAdminSID); } return (fIsRunAsAdmin != 0); } bool run_as_admin() { wchar_t szPath[MAX_PATH]; if (GetModuleFileName(NULL, szPath, ARRAYSIZE(szPath))) { // Launch itself as admin SHELLEXECUTEINFO sei = { sizeof(sei) }; sei.lpVerb = L"runas"; sei.lpFile = szPath; sei.hwnd = NULL; sei.nShow = SW_NORMAL; if (!ShellExecuteEx(&sei)) { DWORD dwError = GetLastError(); if (dwError == ERROR_CANCELLED) { // The user refused to allow privileges elevation. return false; } } else { // End the calling process. User allowd admin rights return true; } } return false; } bool remove_dir(const std::wstring& path) { // Remove the directory and its contents recursively if (!RemoveDirectory(path.c_str())) { DWORD error = GetLastError(); if (error != ERROR_DIR_NOT_EMPTY) { // Failed to remove the directory std::wcerr << L"Error removing directory '" << path << L"'. Error code: " << error << std::endl; return false; } // The directory is not empty, so we need to remove its contents first WIN32_FIND_DATA findFileData; HANDLE hFind = FindFirstFile((path + L"\\*").c_str(), &findFileData); if (hFind == INVALID_HANDLE_VALUE) { std::wcerr << L"Error finding files in directory '" << path << L"'. Error code: " << GetLastError() << std::endl; return false; } do { if (wcscmp(findFileData.cFileName, L".") != 0 && wcscmp(findFileData.cFileName, L"..") != 0) { std::wstring filePath = path + L"\\" + findFileData.cFileName; if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { // Recursively remove subdirectories if (!remove_dir(filePath)) { FindClose(hFind); return false; } } else { // Delete files in the directory if (DeleteFile(filePath.c_str()) == FALSE) { std::wcerr << L"Error deleting file '" << filePath << L"'. Error code: " << GetLastError() << std::endl; FindClose(hFind); return false; } } } } while (FindNextFile(hFind, &findFileData) != 0); FindClose(hFind); // Try to remove the directory again after its contents have been deleted if (!RemoveDirectory(path.c_str())) { std::wcerr << L"Error removing directory '" << path << L"'. Error code: " << GetLastError() << std::endl; return false; } } return true; } bool remove_scheduled_task(const std::wstring& taskName) { HRESULT hr; // Initialize COM hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); if (FAILED(hr)) { std::cerr << "COM initialization failed with error code: " << hr << std::endl; return false; } // Create an instance of the Task Service ITaskService* pService = NULL; hr = CoCreateInstance(CLSID_TaskScheduler, NULL, CLSCTX_INPROC_SERVER, IID_ITaskService, (void**)&pService); if (FAILED(hr)) { std::cerr << "Failed to create an instance of ITaskService: " << hr << std::endl; CoUninitialize(); return false; } // Connect to the task service hr = pService->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t()); if (FAILED(hr)) { std::cerr << "ITaskService::Connect failed with error code: " << hr << std::endl; pService->Release(); CoUninitialize(); return false; } // Get the root task folder ITaskFolder* pRootFolder = NULL; hr = pService->GetFolder(_bstr_t(L"\\"), &pRootFolder); if (FAILED(hr)) { std::cerr << "Cannot get Root Folder pointer: " << hr << std::endl; pService->Release(); CoUninitialize(); return false; } // Delete the task hr = pRootFolder->DeleteTask(_bstr_t(taskName.c_str()), 0); if (FAILED(hr)) { std::cerr << "Failed to delete the task: " << hr << std::endl; pRootFolder->Release(); pService->Release(); CoUninitialize(); return false; } // Release COM objects pRootFolder->Release(); pService->Release(); CoUninitialize(); return true; } int main() { printf("Welcome to the Cyberhex uninstaller!\n"); int error = 0; if (!is_admin()) { printf("We are not administrator, requesting UAC\n"); if (!run_as_admin()) { printf("We did not get administrative rights. Please restart the uninstaller!\n"); MessageBox(NULL, L"Please start the uninstaller with amdin privileges!", L"Error", MB_OK); exit(1); } else { //we started the app as admin. This process can be terminated now exit(0); } } else { printf("Stopping cyberhex"); system("taskkill /F /IM cyberhex.exe"); Sleep(1000); printf("Removing directorys\n"); printf("Removing directory for application\n"); error = remove_dir(L"C:\\Program Files\\Cyberhex"); if (error == 0) error = 4; else error = 0; if (error == 0) { printf("Removing background task\n"); if (!remove_scheduled_task(L"CyberhexBackgroundTask")) { error = 5; } } } switch (error) { case 0: printf("Uninstall finished successfully!\n"); MessageBox(NULL, L"Uninstall finished successfully!", L"Success", MB_OK); break; case 1: printf("Failed to open service control manager.\n"); MessageBox(NULL, L"Failed to open service control manager!", L"Error", MB_OK); break; case 2: printf("Failed to open service.\n"); MessageBox(NULL, L"Failed to open service!", L"Error", MB_OK); break; case 3: printf("Failed to delete service.\n"); MessageBox(NULL, L"Failed to delete service!", L"Error", MB_OK); break; case 4: printf("Failed to remove directory.\n"); MessageBox(NULL, L"Failed to remove directory!", L"Error", MB_OK); default: printf("Unknown error\n"); MessageBox(NULL, L"Unknown error!", L"Error", MB_OK); break; } }