Creación de vacunas en C/C++

Iniciado por ghastlyX, 17 Marzo 2008, 15:33 PM

0 Miembros y 1 Visitante están viendo este tema.

ghastlyX

Últimamente cada vez abundan más los gusanos que se propagan por MSN, por lo que me he decidido a escribir este manual sobre como programar vacunas específicas para este tipo de malware (aunque se puede extrapolar a otros). Mi objetivo es que haya más gente con capacidad de lanzar vacunas para estos gusanos cutres pero que se propagan como la espuma.

El lenguaje de programación que usaremos será C/C++ con el compilador Dev-C++, utilizando APIs. Si no sabéis que son preguntad a Google o a Wikipedia. Empezaré desde cero y ya adelanto que no voy a hacer un tutorial demasiado avanzado, puesto que quiero que lo entienda todo el mundo. Las APIs que use las explicaré por encima, para una mayor explicación podéis consultar en MSDN:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winprog/winprog/functions_in_alphabetical_order.asp

Análisis del código maligno
Bien, explicaré el método más sencillo. Este consiste en utilizar una máquina virtual y con un programa llamado Regshot mirar que cambios ha realizado en el sistema tras su ejecución. No es el mejor método porque un programa bien hecho puede evitar ser registrado por programas así, pero es mucho más sencillo que el otro método (desensamblarlo) y como este manual pretende ser básico, será el método que usaremos.

Lo primero de todo será instalar un programa para crear máquinas virtuales, yo personalmente uso para eso VMWare. No voy a explicar como se crea una máquina virtual, para eso mirad el siguiente enlace:
http://foro.elhacker.net/index.php/topic,158384.0.html

Una vez tenemos nuestra máquina virtual con el sistema operativo instalado (Windows) ya tan sólo hay que deshabilitar las conexiones (no queremos que se propague el malware ni que ataque a otros sitios mientras lo analizamos) y cerrar todo programa no imprescindible. Hacemos una primera foto con Regshot y luego otra después de haber ejecutado el malware. Entonces hacemos que compare y tendremos nuestra lista de cambios :)

Comencemos a programar
Antes que nada tenéis que tener instalado Dev-C++ o vuestro compilador si usáis otro, una vez hecho, vayamos al grano. Todo programa en C/C++ se divide en funciones, que son trozos de código a los que se puede llamar. Pueden devolver una salida o no (void). En C/C++ hay una función imprescindible que es main, aquella por la que empieza el programa cuando lo ejecutamos. Tiene la siguiente estructura:
Código (cpp) [Seleccionar]
int main()
{
    ...
}


La función main es la que menos utilizaremos, puesto que borraremos el gusano con funciones aparte, que llamaremos desde el main. Será necesario utilizar APIs, por lo que habrá que incluir el header (archivo de cabecera) que permite usarlas, que es windows.h. También queremos comunicarnos con el usuario, por lo que hace falta stdio.h (Standard Input/Output). También nos hará falta Tlhelp32.h y ctype.h (por la función toupper). Para incluir headers hay que poner las siguientes líneas al principio del código, antes que ninguna función:
Código (cpp) [Seleccionar]
#include <stdio.h>
#include <windows.h>
#include <Tlhelp32.h>
#include <ctype.h>


Matando procesos y eliminando archivos concretos
Para poder eliminar un archivo que se está ejecutando, es necesario matar antes su proceso. Para ello haremos una función que llamaremos KillProcess, que recibirá como entrada una cadena con el nombre del archivo al que hay que matar el proceso. Las funciones (excepto main) se declaran antes de poner el código de otra función y después de los headers incluidos.

Como salida nuestra función devolvera un entero (un número) indicando si ha tenido éxito o no. Para declarar la función habría que usar la sentencia siguiente:
Código (cpp) [Seleccionar]
int KillProcess(LPCTSTR lpfilename);

Luego también tendríamos que poner la función en sí, por lo que hasta ahora tendríamos que tener el código así:
Código (cpp) [Seleccionar]
#include <stdio.h>
#include <windows.h>
#include <Tlhelp32.h>
#include <ctype.h>

int KillProcess(LPCTSTR lpfilename);

int KillProcess(LPCTSTR lpfilename)
{
       ...
}

int main()
{
    ...
}


Ahora veamos como matar el proceso de un archivo. Hay que declarar una serie de variables que usaremos:
Código (cpp) [Seleccionar]
     WIN32_FIND_DATA Win32FindData;
     HANDLE handle;
     DWORD exitcode;
     PROCESSENTRY32 pe32;

Estas son las que necesitaremos para poder matar el proceso. No hace falta que los nombres de variable (la segunda palabra) sea la misma, estos son los que usaré yo aquí. Los tipos de variable no los podéis cambiar y tened en cuenta que C/C++ distingue mayúsculas de minúsculas.

Ahora tenemos que hacer como si fuera una foto de todos los procesos que se ejecutan, para ello usaremos la API CreateToolhelp32Snapshot, que tiene la siguiente forma:
Código (cpp) [Seleccionar]
HANDLE WINAPI CreateToolhelp32Snapshot(
  __in  DWORD dwFlags,
  __in  DWORD th32ProcessID
);


Luego recorremos los procesos con las APIs Process32First (para el primero) y Process32Next (para los siguientes). Tienen la siguiente forma:
Código (cpp) [Seleccionar]
BOOL WINAPI Process32First(
  __in     HANDLE hSnapshot,
  __inout  LPPROCESSENTRY32 lppe
);

BOOL WINAPI Process32Next(
  __in   HANDLE hSnapshot,
  __out  LPPROCESSENTRY32 lppe
);


Harán falta otras APIs:
Código (cpp) [Seleccionar]
//Cierra un handle abierto
BOOL WINAPI CloseHandle(
  __in  HANDLE hObject
);

//Abre un proceso
HANDLE WINAPI OpenProcess(
  __in  DWORD dwDesiredAccess,
  __in  BOOL bInheritHandle,
  __in  DWORD dwProcessId
);

//Devuelve el estado de finalización del proceso
BOOL WINAPI GetExitCodeProcess(
  __in   HANDLE hProcess,
  __out  LPDWORD lpExitCode
);

//Termina un proceso y sus threads
BOOL WINAPI TerminateProcess(
  __in  HANDLE hProcess,
  __in  UINT uExitCode
);

Para hacer todo esto, traducido a código hay que hacer lo siguiente:
Código (cpp) [Seleccionar]
     handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);  //Guardamos en nuestra variable de tipo HANDLE la "foto"
     if(handle == INVALID_HANDLE_VALUE) return ERROR_LISTAR;    //Si no es correcta la "foto" se acaba la funcion y se devuelve un error         
     pe32.dwSize = sizeof(PROCESSENTRY32); //Definimos la medida de nuestra estructura PROCESSENTRY32
     if(!Process32First(handle, &pe32)) //Si hay un error al mirar el primer proceso
     {
          CloseHandle(handle); //Cierra el HANDLE que usamos
          return ERROR_PROCESO; //Acaba la funcion devolviendo un error
     }
     int i; //Declaramos un par de variables más que hacen falta para pasar a mayusculas dos cadenas
     char lpfilename2[strlen(lpfilename) + 1];
     strcpy(lpfilename2, lpfilename);
     for(i = 0; pe32.szExeFile[i] != '\0'; i++) pe32.szExeFile[i] = toupper(pe32.szExeFile[i]); //Pasamos a mayúsculas las dos cadenas a comparar para que si no son exactamente iguales en cuanto a mayusculas o minusculas, también mate el proceso
     for(i = 0; lpfilename2[i] != '\0'; i++) lpfilename2[i] = toupper(lpfilename2[i]);
     while(strcmp(pe32.szExeFile,lpfilename2))  /Mientras el proceso no coincida con el que buscamos...
     {                                   
          if(!Process32Next(handle, &pe32))  //Va mirando el siguiente, acabando la funcion si hay errores
          {
                  CloseHandle(handle);
                  return ERROR_PROCESO;
          }
          for(i = 0; pe32.szExeFile[i] != '\0'; i++) pe32.szExeFile[i] = toupper(pe32.szExeFile[i]); //Pasa a mayusculas por lo que he dicho antes
     }
/**Una vez hemos encontrado el proceso**//
     handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID);  //Abrimos el proceso
     if(handle == NULL) //Si sale mal, damos error y salimos de la funcion
     {
               CloseHandle(handle);
               return ERROR_PROCESO;
     }
     else           //Si no sale mal...                               
     {
          GetExitCodeProcess(handle, &exitcode); //Cogemos el exitcode del proceso y lo guardamos en nuestra variable destinada a ese cometido
          TerminateProcess(handle, exitcode); //Matamos el proceso
          CloseHandle(handle);  //Cerramos el HANDLE que habiamos usado
          return 0; //Devolvemos el valor 0, que es el que indicara que todo va bien y acaba la funcion
     }


Como ya supongo que habréis supuesto, return se utiliza para terminar la función y devolver un valor. La doble barra sirve para introducir comentarios de una línea y también son comentario todo aquello entre /* y */. Además, también podéis ver que excepto el cero del final, los return devuelven cosas como ERROR_PROCESO. Esto sirve para llamar de una forma más recordable a una salida, en vez de usar un número. Para usar estos nombres, hay que definirlos antes,  en la zona de los headers. Veamos todo lo que llevamos de código, incluyendo estas definiciones:
Código (cpp) [Seleccionar]

#define ERROR_LISTAR 1
#define ERROR_PROCESO 2

#include <stdio.h>
#include <windows.h>
#include <Tlhelp32.h>
#include <ctype.h>

int KillProcess(LPCTSTR lpfilename);

int KillProcess(LPCTSTR lpfilename)
{
     WIN32_FIND_DATA Win32FindData;
     HANDLE handle;
     DWORD exitcode;
     PROCESSENTRY32 pe32;
     handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
     if(handle == INVALID_HANDLE_VALUE) return ERROR_LISTAR;             
     pe32.dwSize = sizeof(PROCESSENTRY32);
     if(!Process32First(handle, &pe32))
     {
          CloseHandle(handle);
          return ERROR_PROCESO;
     }
     int i;
     char lpfilename2[strlen(lpfilename) + 1];
     strcpy(lpfilename2, lpfilename);
     for(i = 0; pe32.szExeFile[i] != '\0'; i++) pe32.szExeFile[i] = toupper(pe32.szExeFile[i]);
     for(i = 0; lpfilename2[i] != '\0'; i++) lpfilename2[i] = toupper(lpfilename2[i]);
     while(strcmp(pe32.szExeFile,lpfilename2))
     {                                   
          if(!Process32Next(handle, &pe32))
          {
                  CloseHandle(handle);
                  return ERROR_PROCESO;
          }
          for(i = 0; pe32.szExeFile[i] != '\0'; i++) pe32.szExeFile[i] = toupper(pe32.szExeFile[i]);
     }
     handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID);
     if(handle == NULL)
     {
               CloseHandle(handle);
               return ERROR_PROCESO;
     }
     else                                         
     {
          GetExitCodeProcess(handle, &exitcode);
          TerminateProcess(handle, exitcode);
          CloseHandle(handle);
          return 0;
     }
}

int main()
{
    ...
}


Bueno, ahora que ya está hecha la función de matar el proceso, vayamos con la de borrar el archivo. Usaremos una función con la misma estructura, recibe como parámetro un archivo y de salida devuelve un entero. Para seguir poniendo de manifiesto mi gran originalidad, la llamaremos FileDelete. La declaración que habría que poner junto con la de la otra función, quedaría así:
Código (cpp) [Seleccionar]
int FileDelete(LPCTSTR lpfilename);

Para la función es muy sencillo, tan sólo hay que ver una API, que es DeleteFile:
Código (cpp) [Seleccionar]
BOOL WINAPI DeleteFile(
  __in  LPCTSTR lpFileName
);


El código de la función quedaría así:
Código (cpp) [Seleccionar]
int FileDelete(LPCTSTR lpfilename)
{
     return DeleteFile(lpfilename);
}


Y el código total por ahora:
Código (cpp) [Seleccionar]
#define ERROR_LISTAR 1
#define ERROR_PROCESO 2

#include <stdio.h>
#include <windows.h>
#include <Tlhelp32.h>
#include <ctype.h>

int KillProcess(LPCTSTR lpfilename);
int FileDelete(LPCTSTR lpfilename);

int KillProcess(LPCTSTR lpfilename)
{
     WIN32_FIND_DATA Win32FindData;
     HANDLE handle;
     DWORD exitcode;
     PROCESSENTRY32 pe32;
     handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
     if(handle == INVALID_HANDLE_VALUE) return ERROR_LISTAR;             
     pe32.dwSize = sizeof(PROCESSENTRY32);
     if(!Process32First(handle, &pe32))
     {
          CloseHandle(handle);
          return ERROR_PROCESO;
     }
     int i;
     char lpfilename2[strlen(lpfilename) + 1];
     strcpy(lpfilename2, lpfilename);
     for(i = 0; pe32.szExeFile[i] != '\0'; i++) pe32.szExeFile[i] = toupper(pe32.szExeFile[i]);
     for(i = 0; lpfilename2[i] != '\0'; i++) lpfilename2[i] = toupper(lpfilename2[i]);
     while(strcmp(pe32.szExeFile,lpfilename2))
     {                                   
          if(!Process32Next(handle, &pe32))
          {
                  CloseHandle(handle);
                  return ERROR_PROCESO;
          }
          for(i = 0; pe32.szExeFile[i] != '\0'; i++) pe32.szExeFile[i] = toupper(pe32.szExeFile[i]);
     }
     handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID);
     if(handle == NULL)
     {
               CloseHandle(handle);
               return ERROR_PROCESO;
     }
     else                                         
     {
          GetExitCodeProcess(handle, &exitcode);
          TerminateProcess(handle, exitcode);
          CloseHandle(handle);
          return 0;
     }
}

int FileDelete(LPCTSTR lpfilename)
{
     return DeleteFile(lpfilename);
}

int main()
{
    ...
}


Realmente la función FileDelete es inútil, podríamos llamar directamente a la API, que es lo único que hace la función. Si no hago esto es porque más adelante (en próximos capítulos xD) ampliaremos esta función.


Borrando valores del registro
Este será el último apartado de este capítulo, el borrado de valores del registro, para por ejemplo borrar una entrada que pueda usar un gusano para autoejecutarse al inicio. Llamaremos a nuestra función RegKill, que será así:
Código (cpp) [Seleccionar]
long RegKill(HKEY hkey, LPCTSTR lpSubKey, LPCTSTR lpValueName);

Devolverá un entero largo y como parámetros recibe un HKEY, que será en este caso  HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE o HKEY_USERS, que son valores predefinidos; como segundo parámetro una cadena que indica la ruta de la clave donde está el valor a borrar y como tercer parámetro otra cadena que indica el nombre del valor a borrar.

Usaremos tres APIs para esta función. La primera es RegOpenKeyEx, que abre una clave del registro y tiene la siguiente forma:
Código (cpp) [Seleccionar]
LONG WINAPI RegOpenKeyEx(
  __in        HKEY hKey,
  __in_opt    LPCTSTR lpSubKey,
  __reserved  DWORD ulOptions,
  __in        REGSAM samDesired,
  __out       PHKEY phkResult
);


La segunda API es RegDeleteValue, que elimina un valor de una clave del registro y tiene la siguiente forma:
Código (cpp) [Seleccionar]
LONG WINAPI RegDeleteValue(
  __in      HKEY hKey,
  __in_opt  LPCTSTR lpValueName
);


La última es RegCloseKey, que cierra el handle abierto y tiene esta forma:
Código (cpp) [Seleccionar]
LONG WINAPI RegCloseKey(
  __in  HKEY hKey
);


El código de la función quedaría así:
Código (cpp) [Seleccionar]
long RegKill(HKEY hkey, LPCTSTR lpSubKey, LPCTSTR lpValueName)
{
     HKEY hregkey; //Definimos la variable donde guardaremos la ruta entera de la clave
     long vuelta; //Definimos la variable donde guardaremos el valor a devolver
     if(RegOpenKeyEx(hkey, lpSubKey, 0, KEY_ALL_ACCESS, &hregkey) == ERROR_SUCCESS) //Si consigue abrir la clave...
     {
          vuelta = RegDeleteValue(hregkey, lpValueName); //Borra el valor de la clave y guarda el resultado en "vuelta"
          RegCloseKey(hregkey);  //Cierra el handle que hemos usado
          return vuelta; //Devuelve "vuelta"
     }
     else return ERROR_OPEN_REG;  //Si no consigue abrir la clave, devuelve este error
}


Hace falta definir al inicio ERROR_OPEN_REG. Definiendo eso e incorporando el código, queda así:
Código (cpp) [Seleccionar]
#define ERROR_LISTAR 1
#define ERROR_PROCESO 2
#define ERROR_OPEN_REG 3

#include <stdio.h>
#include <windows.h>
#include <Tlhelp32.h>
#include <ctype.h>

int KillProcess(LPCTSTR lpfilename);
int FileDelete(LPCTSTR lpfilename);
long RegKill(HKEY hkey, LPCTSTR lpSubKey, LPCTSTR lpValueName);

int KillProcess(LPCTSTR lpfilename)
{
     WIN32_FIND_DATA Win32FindData;
     HANDLE handle;
     DWORD exitcode;
     PROCESSENTRY32 pe32;
     handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
     if(handle == INVALID_HANDLE_VALUE) return ERROR_LISTAR;             
     pe32.dwSize = sizeof(PROCESSENTRY32);
     if(!Process32First(handle, &pe32))
     {
          CloseHandle(handle);
          return ERROR_PROCESO;
     }
     int i;
     char lpfilename2[strlen(lpfilename) + 1];
     strcpy(lpfilename2, lpfilename);
     for(i = 0; pe32.szExeFile[i] != '\0'; i++) pe32.szExeFile[i] = toupper(pe32.szExeFile[i]);
     for(i = 0; lpfilename2[i] != '\0'; i++) lpfilename2[i] = toupper(lpfilename2[i]);
     while(strcmp(pe32.szExeFile,lpfilename2))
     {                                   
          if(!Process32Next(handle, &pe32))
          {
                  CloseHandle(handle);
                  return ERROR_PROCESO;
          }
          for(i = 0; pe32.szExeFile[i] != '\0'; i++) pe32.szExeFile[i] = toupper(pe32.szExeFile[i]);
     }
     handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID);
     if(handle == NULL)
     {
               CloseHandle(handle);
               return ERROR_PROCESO;
     }
     else                                         
     {
          GetExitCodeProcess(handle, &exitcode);
          TerminateProcess(handle, exitcode);
          CloseHandle(handle);
          return 0;
     }
}

int FileDelete(LPCTSTR lpfilename)
{
     return DeleteFile(lpfilename);
}

long RegKill(HKEY hkey, LPCTSTR lpSubKey, LPCTSTR lpValueName)
{
     HKEY hregkey;
     long vuelta;
     if(RegOpenKeyEx(hkey, lpSubKey, 0, KEY_ALL_ACCESS, &hregkey) == ERROR_SUCCESS)
     {
          vuelta = RegDeleteValue(hregkey, lpValueName);
          RegCloseKey(hregkey);
          return vuelta;
     }
     else return ERROR_OPEN_REG;
}

int main()
{
    ...
}


Ahora que ya tenemos las funciones, falta ver que poner en el main. Esto variará según qué malware queramos eliminar. Imaginemos que tenemos un malware que crea el archivo siguiente:
C:\gusano.exe

Y se autoejecuta a cada inicio con la siguiente clave:
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run\Soy un gusano malo y propagador

La función main deberá llamar a las tres funciones que hemos hecho: primero tendrá que matar el proceso, luego eliminar el archivo y después borrar el valor del registro. Quedaría así nuestro main de forma cutre:
Código (cpp) [Seleccionar]
int main()
{
    KillProcess("gusano");
    FileDelete("C:\\gusano");
    RegKill(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Run", "Soy un gusano malo y propagador");
    return 0;
}


Pero si nos hemos molestado en poner diferentes valores a las salidas es para tenerlos en cuenta, no para pasar de ellos. Hagamos un main que mire también como les va a nuestras funciones xDD:
Código (cpp) [Seleccionar]
int main()
{
    long salida;
   
    salida = KillProcess("gusano.exe");
    if(salida == ERROR_LISTAR) printf("Error al listar los procesos\n");
    else if((salida == ERROR_PROCESO) && (GetLastError() == ERROR_NO_MORE_FILES)) printf("El proceso no existe\n");
    else if(salida == ERROR_PROCESO) printf("Error al manejar los procesos\n");
    else printf("Proceso finalizado correctamente\n");
   
    salida = FileDelete("C:\\gusano.exe");
    if(salida == ERROR_FILE_NOT_FOUND) printf("Archivo no encontrado\n");
    else if(salida == ERROR_ACCESS_DENIED) printf("Acceso denegado\n");
    else if(salida) printf("Archivo eliminado correctamente\n");
    else printf("Error al eliminar el archivo\n");
   
    salida = RegKill(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Run", "Soy un gusano malo y propagador");
    if(salida == ERROR_OPEN_REG) printf("Error al abrir el registro\n");
    else if(salida == ERROR_SUCCESS) printf("Valor borrado del registro\n");
    else printf("Error al borrar valor del registro\n");
   
    return 0;
}

El hecho de que las contrabarras aparezcan duplicadas es porque la contrabarra se usa en C/C++ para las secuencias de escape (\n simboliza un salto de línea). Para poner una contrabarra, se ponen dos. Y el código entero sería así:
Código (cpp) [Seleccionar]
#define ERROR_LISTAR 1
#define ERROR_PROCESO 2
#define ERROR_OPEN_REG 3

#include <stdio.h>
#include <windows.h>
#include <Tlhelp32.h>
#include <ctype.h>

int KillProcess(LPCTSTR lpfilename);
int FileDelete(LPCTSTR lpfilename);
long RegKill(HKEY hkey, LPCTSTR lpSubKey, LPCTSTR lpValueName);

int KillProcess(LPCTSTR lpfilename)
{
     WIN32_FIND_DATA Win32FindData;
     HANDLE handle;
     DWORD exitcode;
     PROCESSENTRY32 pe32;
     handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
     if(handle == INVALID_HANDLE_VALUE) return ERROR_LISTAR;             
     pe32.dwSize = sizeof(PROCESSENTRY32);
     if(!Process32First(handle, &pe32))
     {
          CloseHandle(handle);
          return ERROR_PROCESO;
     }
     int i;
     char lpfilename2[strlen(lpfilename) + 1];
     strcpy(lpfilename2, lpfilename);
     for(i = 0; pe32.szExeFile[i] != '\0'; i++) pe32.szExeFile[i] = toupper(pe32.szExeFile[i]);
     for(i = 0; lpfilename2[i] != '\0'; i++) lpfilename2[i] = toupper(lpfilename2[i]);
     while(strcmp(pe32.szExeFile,lpfilename2))
     {                                   
          if(!Process32Next(handle, &pe32))
          {
                  CloseHandle(handle);
                  return ERROR_PROCESO;
          }
          for(i = 0; pe32.szExeFile[i] != '\0'; i++) pe32.szExeFile[i] = toupper(pe32.szExeFile[i]);
     }
     handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID);
     if(handle == NULL)
     {
               CloseHandle(handle);
               return ERROR_PROCESO;
     }
     else                                         
     {
          GetExitCodeProcess(handle, &exitcode);
          TerminateProcess(handle, exitcode);
          CloseHandle(handle);
          return 0;
     }
}

int FileDelete(LPCTSTR lpfilename)
{
     return DeleteFile(lpfilename);
}

long RegKill(HKEY hkey, LPCTSTR lpSubKey, LPCTSTR lpValueName)
{
     HKEY hregkey;
     long vuelta;
     if(RegOpenKeyEx(hkey, lpSubKey, 0, KEY_ALL_ACCESS, &hregkey) == ERROR_SUCCESS)
     {
          vuelta = RegDeleteValue(hregkey, lpValueName);
          RegCloseKey(hregkey);
          return vuelta;
     }
     else return ERROR_OPEN_REG;
}

int main()
{
    long salida;

    salida = KillProcess("gusano.exe");
    if(salida == ERROR_LISTAR) printf("Error al listar los procesos\n");
    else if((salida == ERROR_PROCESO) && (GetLastError() == ERROR_NO_MORE_FILES)) printf("El proceso no existe\n");
    else if(salida == ERROR_PROCESO) printf("Error al manejar los procesos\n");
    else printf("Proceso finalizado correctamente\n");

    salida = FileDelete("C:\\gusano.exe");
    if(salida == ERROR_FILE_NOT_FOUND) printf("Archivo no encontrado\n");
    else if(salida == ERROR_ACCESS_DENIED) printf("Acceso denegado\n");
    else if(salida) printf("Archivo eliminado correctamente\n");
    else printf("Error al eliminar el archivo\n");

    salida = RegKill(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Run", "Soy un gusano malo y propagador");
    if(salida == ERROR_OPEN_REG) printf("Error al abrir el registro\n");
    else if(salida == ERROR_SUCCESS) printf("Valor borrado del registro\n");
    else printf("Error al borrar valor del registro\n");

    return 0;
}


Con esto doy por acabado este primer capítulo, escribiré el siguiente cuando el tiempo lo permita, en el que explicaré como hacer más cosas. Mañana si tengo tiempo pongo un ejercicio para que podáis practicar lo aprendido.

Como deberes os digo que en la función de matar procesos hay un fallo, que no es explotable ni nada, simplemente que algunos procesos según la entrada que demos no los matará. Esto para los que sepan más de C/C++.

Este texto puede ser publicado en cualquier sitio siempre que no se modifique y se cite al autor y la fuente.

Un saludo de ghastlyX ;)

Hendrix

Muy bueno... :)

Estoy programando una aplicacion para eso mismo, para "rastrear" que cambios produce un archivo, como crear/borrar/modificar un archivo, entradas al registro, puertos, etc.

Cunado pueda la posteare, aunque sera en unos dias/semanas, ya que estoy algo liado.

Un Saludo y felicidades  :)
"Todos los días perdemos una docena de genios en el anonimato. Y se van. Y nadie sabe de ellos, de su historia, de su peripecia, de lo que han hecho, de sus angustias, de sus alegrías. Pero al menos una docena de genios se van todos los días sin que sepamos de ellos". - Juan Antonio Cebrián

Red Mx

#2
Esta exelentemente bien le comente a ghastlyX que el codigo lo podria pasar a VB asi con la API y todo pero pues biendolo bien seria inutil ya que compilando la aplicacion en C/C++ con otros parametros funcionaria perfecto.

pero pues bueno como siempre hay varias formas de hacer las cosas que me hago uno version chorreada pero que igual sirve para lo mismo dejo el codigo cabe señalar que NO uso apis solo para poner otra forma de como se podria hacer.


Y bien le comente a ghastlyX que podria programar unos bichitos en VBScript , Batch , VB , C para ver su funcionamiento espero terminar algunos.

por lo pronto dejo adjunto el source y el compilado aaaaa y una aplicacion que simula ser gusano.exe pero es inofenciba tanto que no se puede propagar por si sola jejeje bueno le puse un bat para que se instale el supuesto gusano .

:D
Desarrollar Malware Es Causa De Cancer...

Stone_FREE_

justo andaba buscando algo así... ya mucho batch para matar virus  :xD

Y una duda que hasta ahora no he podido resolver es cómo matar un proceso inmortal mediante vacunas, por ejemplo algunos troyanos que vienen con opción de persistencia y que cuando matamos el proceso, éste vuelve a aparecer en unos segundos. A esos no los puedo eliminar mas que en modo a prueba de fallos, pero yo no quiero eso, sino matarlos como lo hacen los antivirus que así sean inmortales, el antivirus igual lo mata. Hay alguna forma para hacer eso?

Y otra duda... hay algunos virus que toman el nombre de procesos conocidos como explorer.exe o lsass.exe y que no se dejan matar así nomas porque windows piensa que son procesos esenciales. Con el código que has puesto se dejan matar estos procesos?.

Y gracias porque ahora por fin podré hacer mis vacunas en C++  ;)
You are the Owner of your Life, your Fears and your Dreams ...


ghastlyX

#4
CitarY una duda que hasta ahora no he podido resolver es cómo matar un proceso inmortal mediante vacunas, por ejemplo algunos troyanos que vienen con opción de persistencia y que cuando matamos el proceso, éste vuelve a aparecer en unos segundos. A esos no los puedo eliminar mas que en modo a prueba de fallos, pero yo no quiero eso, sino matarlos como lo hacen los antivirus que así sean inmortales, el antivirus igual lo mata. Hay alguna forma para hacer eso?
Yo es que tengo el problemilla que nunca he usado troyanos porque no me gustan nada, así que todo lo que he trabajado con ellos ha sido para cargármelos xDD. Dime alguno que haga eso y me lo miro, seguro que se pueden matar, ya miraré el sistema de autoprotección que tienen.

CitarY otra duda... hay algunos virus que toman el nombre de procesos conocidos como explorer.exe o lsass.exe y que no se dejan matar así nomas porque windows piensa que son procesos esenciales. Con el código que has puesto se dejan matar estos procesos?.
Con ese código te va a dar problemas para eso, dime lo de los troyanos que dices y para el próximo capítulo a ver si hago un código que mate ambas cosas.

Y para todos en general, a ver quién le ve el fallo que comentaba en el primer post a la función de matar procesos xDD

Un saludo de ghastlyX ;)

Stone_FREE_

CitarYo es que tengo el problemilla que nunca he usado troyanos porque no me gustan nada, así que todo lo que he trabajado con ellos ha sido para cargármelos xDD. Dime alguno que haga eso y me lo miro, seguro que se pueden matar, ya miraré el sistema de autoprotección que tienen.

Los troyanos muchas veces nos traen complicaciones para eliminarlos, actúan silenciosamente, se camuflan en otros procesos o pueden ocultar completamente su presencia en el sistema cuando vienen combinados con rootkits. Para el usuario común puede llegar a ser una tarea muy complicada eliminarlos si nuestro antivirus no pudo. Con los que he tenido mas problemas al eliminarlos de algún equipo remoto son los troyanos inmortales. Si cierras el proceso vuelve a aparecer. Se borras el archivo vuelve a aparecer. Con las entradas del registro igual. Una vacuna que pueda solucionar eso sería de gran ayuda.
Los troyanos que tienen esta opción de persistencia son el bifrost y poison ivy. Te mando por privado los servers de estos troyanos para que los puedas examinar.

Saludos y gracias por tu aporte
Stone_FREE_
You are the Owner of your Life, your Fears and your Dreams ...


Proxy Lainux

wow... gracias por este aporte... hasta yo que apenas estoy usando C/C++ y que vengo de visual basic le entendi a la perfeccion...

gracias  ;D

ProHideSoftware

 
Vendo ProHide Keylogger anti-heuristica kaspersky + downloader + joiner todo 100% indetectable

~Yey~

Un gran trabajo se agradece tanto la buena información como la sencillez con la que la compartes ;)
me parece una idea genial que se empiecen a tomar medidas con las propagaciones del mesenger...que ya hay demasiada proqeuria rulando por hay...
gracias



                                     Blog

Zeroql

EXELENTE TRABAJO... ESTA MUY interesante ademas que como vacuna tambien tiene otros usos...
me agrado gracias.
Dime y lo olvido, enseñame y lo recuerdo, involucrame y lo aprendo.
/.-ZEROQL.-\   -----  #937675#