• Facebook
  • Google Plus
  • Delphiaccess Feed
  • Twitter
  • YouTube


Autor Tema: TerminateMD5_Process, a la caza de un virus...  (Leído 619 veces)

Conectado escafandra

  • Moderadores
  • ******
  • Gracias
  • -Dados: 100
  • -Recibidos: 687
  • Mensajes: 2,414
  • Calificaciones: +728/-0
  • Sexo: Masculino
TerminateMD5_Process, a la caza de un virus...
« en: 27 de Abril de 2012, 13:36:54 »
En ocasiones nos vemos en la necesidad de matar una aplicación desde código. Ya existen en el foro ejemplos de como hacerlo, bien por su nombre su id de proceso o el puerto que usa una App en red. En esta ocasión me vi en la necesidad de matar un proceso especial, se trataba de un virus de pendrive cuyo nombre variaba y no así el archivo. La solución fue usar el Hash md5 para localizarlo.

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:
Código: [Seleccionar]
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

Código CPP
  1. #include <windows.h>
  2. #include <Shlwapi.h>
  3. #include <Tlhelp32.h>
  4. #include <stdio.h>
  5. #include <conio.h>
  6.  
  7. #pragma hdrstop
  8.  
  9. //---------------------------------------------------------------------------
  10. #define MD5LEN  16
  11. #define BUFSIZE 1024
  12. typedef CHAR TMD5[33];
  13.  
  14.  
  15. void GetMD5FromFile(CHAR* FileName, CHAR *MD5)
  16. {
  17.   HANDLE hFile = 0;
  18.   HCRYPTPROV hProv = 0;
  19.   HCRYPTHASH hHash = 0;
  20.   BYTE Hash[MD5LEN];
  21.   DWORD bHash = 0;
  22.   DWORD bRead = 0;
  23.   BYTE* Buffer = (BYTE*)VirtualAlloc(0, BUFSIZE, MEM_COMMIT, PAGE_READWRITE);
  24.   hFile = CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN,
  25.  
  26. NULL);
  27.   if(hFile != INVALID_HANDLE_VALUE){
  28.     if(CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)){
  29.       if(CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash)){
  30.         while (1) {
  31.           ReadFile(hFile, Buffer, BUFSIZE, &bRead, NULL);
  32.           if(!bRead) break;
  33.           CryptHashData(hHash, Buffer, bRead, 0);
  34.         }
  35.         bHash = MD5LEN;
  36.         if(CryptGetHashParam(hHash, HP_HASHVAL, Hash, &bHash, 0)){
  37.           for(int i=0; i<2*MD5LEN; i++){
  38.             MD5[i] = (0x0F & Hash[i/2] >> 4*((i+1)%2)) + 48;
  39.             if(MD5[i] > '9') MD5[i] += 7;
  40.           }
  41.           MD5[32] = 0;
  42.         }
  43.       }
  44.       CryptDestroyHash(hHash);
  45.     }
  46.     CryptReleaseContext(hProv, 0);
  47.   }
  48.   CloseHandle(hFile);
  49.   VirtualFree(Buffer, 0, MEM_RELEASE);
  50. }
  51.  
  52.  
  53. //---------------------------------------------------------------------------
  54. // Desinstala una App de la clave HKEY_CURRENT_USER\...\run
  55. bool RegDesinstall(CHAR *App)
  56. {
  57.    CHAR* RunKey = "Software\\Microsoft\\Windows\\CurrentVersion\\run\\";
  58.    HKEY hKey  = 0;
  59.    CHAR* Value = 0;
  60.    CHAR  ValueName[256];
  61.    DWORD dwValueName = sizeof(ValueName);
  62.    DWORD Type;
  63.    CHAR  Data[256];
  64.    DWORD dwData = sizeof(Data);
  65.    int Index;
  66.    bool Result = false;
  67.  
  68.    // Si es un Path a una sunblave enumeramos los valores
  69.    Index = 0;
  70.    if(RegOpenKeyEx(HKEY_CURRENT_USER, RunKey, 0, KEY_READ | KEY_SET_VALUE, &hKey) == ERROR_SUCCESS){
  71.      int ErrorCode = RegEnumValue(hKey, Index++, ValueName, &dwValueName, NULL, &Type, (PBYTE)Data, &dwData);
  72.      while(ErrorCode != ERROR_NO_MORE_ITEMS){
  73.        if(StrStrI(Data, App)){
  74.          Result = (RegDeleteValue(hKey, ValueName) == ERROR_SUCCESS);
  75.          break;
  76.        }
  77.        DWORD dwValueName = sizeof(ValueName);
  78.        DWORD dwData = sizeof(Data);
  79.        ErrorCode = RegEnumValue(hKey, Index++, ValueName, &dwValueName, NULL, &Type, (PBYTE)Data, &dwData);
  80.      }
  81.      RegCloseKey(hKey);
  82.    }
  83.    return Result;
  84. }
  85.  
  86. //---------------------------------------------------------------------------
  87. // Termina los procesos conociendo el nombre del exe o su Hash MD5
  88. void TerminateMD5_Process(TMD5 FileHash, bool Terminate = true, bool DeleteProcess = false)
  89. {
  90.    TMD5 MD5;
  91.    HANDLE Process = 0;
  92.    PROCESSENTRY32 proc = { sizeof(proc) };
  93.  
  94.    // Nos Damos privilegios debug
  95.    HANDLE hToken;
  96.    TOKEN_PRIVILEGES priv = {1, {0, 0, SE_PRIVILEGE_ENABLED}};
  97.    LookupPrivilegeValue(0, SE_DEBUG_NAME, &priv.Privileges[0].Luid);
  98.    OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken);
  99.    AdjustTokenPrivileges (hToken, FALSE, &priv, sizeof priv, 0, 0);
  100.  
  101.    HANDLE hSysSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  102.    if(hSysSnapshot != INVALID_HANDLE_VALUE && Process32First(hSysSnapshot, &proc)){
  103.      do{
  104.        HANDLE hSnapshot;
  105.        MODULEENTRY32 ModuleEntry = {sizeof(MODULEENTRY32)};
  106.        hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, proc.th32ProcessID);
  107.        if(hSnapshot != (HANDLE)-1){
  108.          if(Module32First(hSnapshot, &ModuleEntry)){
  109.            GetMD5FromFile(ModuleEntry.szExePath, MD5);
  110.            if(!stricmp(FileHash, MD5)){
  111.              Process = OpenProcess(PROCESS_TERMINATE, false, proc.th32ProcessID);
  112.              if(Terminate && Process){
  113.                if(TerminateProcess(Process, 0))
  114.                  printf(ModuleEntry.szExePath); printf("\n");
  115.                CloseHandle(Process);
  116.              }
  117.              if(DeleteProcess){
  118.                SetFileAttributes(ModuleEntry.szExePath, FILE_ATTRIBUTE_ARCHIVE);
  119.                DeleteFile(ModuleEntry.szExePath);
  120.                RegDesinstall(ModuleEntry.szExePath);
  121.              }  
  122.            }
  123.          }
  124.          CloseHandle(hSnapshot);
  125.        }
  126.      }while(Process32Next(hSysSnapshot, &proc));
  127.    }
  128.    CloseHandle(hSysSnapshot);
  129.  
  130.    // Retirar los privilegios debug
  131.    priv.Privileges[0].Attributes = 0;
  132.    AdjustTokenPrivileges (hToken, FALSE, &priv, sizeof priv, 0, 0);
  133.    CloseHandle (hToken);
  134. }
  135.  
  136.  
  137. #pragma argsused
  138. int main(int argc, char* argv[])
  139. {
  140.    if(argc > 1){
  141.      printf("Terminando procesos...\n");
  142.      TerminateMD5_Process(argv[1], true, false);
  143.    }else
  144.      printf("Se necesita un parámetro MD5 que identifique un archivo.\n");
  145.  
  146.    printf("Pulse una tecla para terminar.");
  147.    getch();
  148.    return 0;
  149. }
  150. //---------------------------------------------------------------------------
  151.  




Espero que este ejemplo sea de utilidad.


Saludos.