La filosofía es recorrer los procesos en ejecución, encontrar la ruta del archivo ejecutable y calcular su hash md5 para compararlo con el que buscamos y matar dicho proceso. Eventualmente, también podemos borrar el archivo ejecutable y desinstalarlo del registro de Windows.
La desinstalación del registro se realiza buscando el proceso en la clave:
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\run\
en el ejemplo se muestra como recorrer el registro y puede variarse para buscar en HKEY_LOCAL_MACHINE u otras. En mi caso bastó con lo expuesto.
Dejo una aplicación de consola que realiza la tarea. Usa como parámetro la cadena MD5 del archivo buscado. En ella está la función para calcular el hash md5 con la API de Windows, la función para encontrar y terminar el proceso y la función para recorrer el registro. Dicho código no encierra grandes complicaciones y puede ser útil para fines como el que me llevó a escribirlo.
El código original lo escribí en C/C++ y en realidad es algo mas complejo del que presento pues incluía un Hook a la API CreateProcessInternalW para, además, evitar la ejecución del proceso viral (o el que se tercie). En este aspecto quisiera recordar el hilo que abrió enecumene Prevenir que aplicación se ejecute
#include <windows.h> #include <Shlwapi.h> #include <Tlhelp32.h> #include <stdio.h> #include <conio.h> #pragma hdrstop //--------------------------------------------------------------------------- #define MD5LEN 16 #define BUFSIZE 1024 typedef CHAR TMD5[33]; void GetMD5FromFile(CHAR* FileName, CHAR *MD5) { HANDLE hFile = 0; HCRYPTPROV hProv = 0; HCRYPTHASH hHash = 0; BYTE Hash[MD5LEN]; DWORD bHash = 0; DWORD bRead = 0; BYTE* Buffer = (BYTE*)VirtualAlloc(0, BUFSIZE, MEM_COMMIT, PAGE_READWRITE); hFile = CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); if(hFile != INVALID_HANDLE_VALUE){ if(CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)){ if(CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash)){ while (1) { ReadFile(hFile, Buffer, BUFSIZE, &bRead, NULL); if(!bRead) break; CryptHashData(hHash, Buffer, bRead, 0); } bHash = MD5LEN; if(CryptGetHashParam(hHash, HP_HASHVAL, Hash, &bHash, 0)){ for(int i=0; i<2*MD5LEN; i++){ MD5[i] = (0x0F & Hash[i/2] >> 4*((i+1)%2)) + 48; if(MD5[i] > '9') MD5[i] += 7; } MD5[32] = 0; } } CryptDestroyHash(hHash); } CryptReleaseContext(hProv, 0); } CloseHandle(hFile); VirtualFree(Buffer, 0, MEM_RELEASE); } //--------------------------------------------------------------------------- // Desinstala una App de la clave HKEY_CURRENT_USER\...\run bool RegDesinstall(CHAR *App) { CHAR* RunKey = "Software\\Microsoft\\Windows\\CurrentVersion\\run\\"; HKEY hKey = 0; CHAR* Value = 0; CHAR ValueName[256]; DWORD dwValueName = sizeof(ValueName); DWORD Type; CHAR Data[256]; DWORD dwData = sizeof(Data); int Index; bool Result = false; // Si es un Path a una sunblave enumeramos los valores Index = 0; if(RegOpenKeyEx(HKEY_CURRENT_USER, RunKey, 0, KEY_READ | KEY_SET_VALUE, &hKey) == ERROR_SUCCESS){ int ErrorCode = RegEnumValue(hKey, Index++, ValueName, &dwValueName, NULL, &Type, (PBYTE)Data, &dwData); while(ErrorCode != ERROR_NO_MORE_ITEMS){ if(StrStrI(Data, App)){ Result = (RegDeleteValue(hKey, ValueName) == ERROR_SUCCESS); break; } DWORD dwValueName = sizeof(ValueName); DWORD dwData = sizeof(Data); ErrorCode = RegEnumValue(hKey, Index++, ValueName, &dwValueName, NULL, &Type, (PBYTE)Data, &dwData); } RegCloseKey(hKey); } return Result; } //--------------------------------------------------------------------------- // Termina los procesos conociendo el nombre del exe o su Hash MD5 void TerminateMD5_Process(TMD5 FileHash, bool Terminate = true, bool DeleteProcess = false) { TMD5 MD5; HANDLE Process = 0; PROCESSENTRY32 proc = { sizeof(proc) }; // Nos Damos privilegios debug HANDLE hToken; TOKEN_PRIVILEGES priv = {1, {0, 0, SE_PRIVILEGE_ENABLED}}; LookupPrivilegeValue(0, SE_DEBUG_NAME, &priv.Privileges[0].Luid); OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken); AdjustTokenPrivileges (hToken, FALSE, &priv, sizeof priv, 0, 0); HANDLE hSysSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if(hSysSnapshot != INVALID_HANDLE_VALUE && Process32First(hSysSnapshot, &proc)){ do{ HANDLE hSnapshot; MODULEENTRY32 ModuleEntry = {sizeof(MODULEENTRY32)}; hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, proc.th32ProcessID); if(hSnapshot != (HANDLE)-1){ if(Module32First(hSnapshot, &ModuleEntry)){ GetMD5FromFile(ModuleEntry.szExePath, MD5); if(!stricmp(FileHash, MD5)){ Process = OpenProcess(PROCESS_TERMINATE, false, proc.th32ProcessID); if(Terminate && Process){ if(TerminateProcess(Process, 0)) printf(ModuleEntry.szExePath); printf("\n"); CloseHandle(Process); } if(DeleteProcess){ SetFileAttributes(ModuleEntry.szExePath, FILE_ATTRIBUTE_ARCHIVE); DeleteFile(ModuleEntry.szExePath); RegDesinstall(ModuleEntry.szExePath); } } } CloseHandle(hSnapshot); } }while(Process32Next(hSysSnapshot, &proc)); } CloseHandle(hSysSnapshot); // Retirar los privilegios debug priv.Privileges[0].Attributes = 0; AdjustTokenPrivileges (hToken, FALSE, &priv, sizeof priv, 0, 0); CloseHandle (hToken); } #pragma argsused int main(int argc, char* argv[]) { if(argc > 1){ printf("Terminando procesos...\n"); TerminateMD5_Process(argv[1], true, false); }else printf("Se necesita un parámetro MD5 que identifique un archivo.\n"); printf("Pulse una tecla para terminar."); getch(); return 0; } //---------------------------------------------------------------------------
Espero que este ejemplo sea de utilidad.
Saludos.
Edito para arreglar etiquetas de código y resubir adjunto perdido.