1er troyano en Delphi By: Geek Lord Venezuela [R00t] Team

Iniciado por ANTRAX, Febrero 24, 2010, 04:34:48 PM

Tema anterior - Siguiente tema

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

Febrero 24, 2010, 04:34:48 PM Ultima modificación: Abril 15, 2013, 11:20:57 PM por Expermicid
Entre los Troyanos programados en Delphi encontramos:
Poison Ivy
Institution 2004
Beast
Sub7
NetBus
Optix Pro
Assasin 2
TequilaBandita
Bandook
Nuclear Rat
Coolvibes
Con esta lista (inconclusa) queda demostrado que es un lenguaje idóneo para nuestro propósito. Además se pueden hacer Binders y cualquier otro programa.
Formas de programar un Troyano en Delphi

A la hora de hacer un troyano o aplicación similar en Delphi básicamente podemos seguir 2 caminos:

1) Crear un form en el cual ponemos los componentes que trae Delphi.
Ventaja: Sencillez.
Desventaja: Utilizar un form repercute en el tamaño del server (aproximadamente 220 Kb comprimido con UPX).

2) Crear un Aplicacion de tipo consola (console aplication) y utilizar units livianas o directamente llamadas a la API de Windows.
Ventaja: Si no usamos units que engorden el proyecto podremos obtener aplicaciones mucho más pequeñas (de unos 30 Kb).
Desventaja: Mayor complejidad.

En un troyano de última generación, lo usual sería hacer el cliente con el primer método y el server con el segundo.
Como somos novatos tendremos que usar el primer método tanto para el cliente como para el servidor. Bueno... no se desilusionen, los servers de Optix, Sub7 y Theft están hechos con este método y nadie va a decir que sean malos. El único problema, como ya dije, es el tamaño pero dada la velocidad de las conexiones de hoy ya no es tan importante.

Aplicaciones cliente servidor usando componentes

Delphi trae distintos componentes para este fin, se destacan:
1) TServerSocket/TClientSocket los más usados para troyanos, simples y efectivos.
2) Los Componentes INDY más completos y de mayor tamaño. No he visto ningún troyano programado usando estos componentes aunque si vi que se usan mucho para otro tipo de aplicaciones cliente/servidor.

Entonces vamos a usar los TServerSocket/TClientSocket
(están en la "sección Internet" de la "Paleta de Componentes" en la IDE de Delphi, si no están hay que instalarlos).
Cuando trabajamos con sockets hay 2 aproximaciones posibles:
1) Leer datos del socket o escribir en él de forma asincrónica, así no se bloquea la ejecución de otro código en la aplicación mientras esto sucede. Esto es llamado "nonblocking connections".
2) La otra alternativa es usar "blocking connections" donde la aplicación espera que la lectura o escritura se complete antes de ejecutar la siguiente línea de código. Con "blocking connections" es necesario usar threads, lo que es más complicado, así que vamos a hacerlo de la primer forma (más común en troyanos).
Esto se elige en la propiedad "Server Type" de los componentes ClientSocket y ServerSocket.

Pasemos a los ejemplos, ambos están hechos con los componentes ClientSocket y ServerSocket usados en modo nonblocking.

PRIMER EJEMPLO (Client1.htm y Server1.htm)

Server

Ver las propiedades del componente ServerSocket1 (no necesita explicación).
Ver también los eventos de este componente.

Todo el código se relaciona con los eventos del socket ya que el programa no provee interacción con el usuario. Sin embargo el server tiene 3 espacios donde se loguea información.

Observen el evento "OnClientConnect", este indica el primer momento en el que el server se entera de la conexión con el cliente. Usando "TCustomWinSocket" el server puede ver quien está tratando de conectarse. Al final de este evento actualizamos la lista de conexiones usando la propiedad "ActiveConnections" del server.

Un código similar se ejecuta cuando el cliente se desconecta del server (OnClientDisconnect).

Vemos que el server puede leer los mensajes (que le envía el cliente) llamando a la función ReciveText. Esta operación se debe realizar solo cuando hay algún dato disponible para leer, o sea, cuando el evento OnClientRead es disparado.
Notar que esta es una lectura destructiva: la información que se extrae del (stream) es removida de ahí.

Cliente

Ver las propiedades del componente ClientSocket1 (no necesita explicación).
Ver también los eventos de este componente.

El cliente es más interactivo. Hay un EditBox donde se pone la dirección del server al que te queréis conectar. Con el CheckBox se activa y desactiva la conexión.
¿Se acuerdan del primer Remote Ziper? tenía un checkbox para conectar porque no sabía hacerlo de otra forma =).

Observen que se puede escribir un mensaje en el otro EditBox y presionando el botón se envía.

Tengan en cuenta que estos programas están lejos de ser perfectos porque no controlan ciertas cosas. Por ej. que el socket está activo antes de enviar el mensaje, por lo que pueden obtener errores si realizan determinadas acciones.

SEGUNDO EJEMPLO (Client2.htm y Server2.htm)

Server

Acá ya vamos viendo la implementación de un protocolo (como los que usan los troyanos).
Un protocolo es un conjunto de reglas (comandos). Básicamente el server puede recibir distintos pedidos y según el pedido ejecutar distintas acciones.

En este ejemplo el server acepta 4 tipos de pedidos:
Listar un directorio.
Enviar un BMP.
Enviar un txt.
Ejecutar un programa.

A su vez, cuando el server contesta debe indicar que tipo de información va a enviar además de la información.

Lo esencial es ver que hace el server cuando lee del socket (OnClientRead).
Primero extrae los primeros 5 caracteres del texto recibido por que estos contienen el comando.
Luego, se ejecuta un código dependiendo del texto (comando) contenido en estos 5 primeros caracteres. Los comandos son:
EXEC!, TEXT!, BITM!, LIST!
En las fuentes pueden ver el código que se ejecuta según el comando.

Cliente

Vimos que el server también manda 5 caracteres que le permiten saber al cliente que tipo de información va a recibir.
En el ejemplo del cliente se ve otra forma de proceder ante la lectura del encabezado. (yo siempre usé la anterior tanto para el cliente como para el servidor).
Acá cuando el cliente lee, fija un estado para saber que tipo de información viene a continuación.

Eso es todo por ahora, Si quieren ver más sobre este tema pueden bajarse el libro de Marcos Cantú "Mastering Delphi 6" en PDF de alguna red P2P (está en inglés). El tema está tratado en el capítulo 21.

------------------------------------------------------------------------------------------

Nuestro Primer Troyano

En este ejemplo vamos a ver 2 cosas nuevas: Como activar el ClienteSocket usando un botón en vez de un checkBox y como prevenir que salten errores.

Abre un nuevo proyecto en Delphi y coloca un componente ServerSocket en el Form.
En las propiedades del componente pon Active en True, ServerType en stNonBlocking y elige un puerto (ej. 800) en el cual el server escuchará.

Ahora debemos escribir el evento OnRead.
En el ejemplo cuando se recibe el comando '01' el server hace beep, cuando se recibe el '02' muestra un mensaje del cliente y devuelve una confirmación, esto les va a servir de base para más adelante asociar funciones más divertidas a los comandos.

Código: delphi
procedure TForm1.ServerSocket1ClientRead 
   (Sender:TObject;Socket:TCustomWinSocket);
var Command:integer;
    FullCommand,st:string;
begin
  FullCommand:=Socket.ReceiveText;
  st:=copy(FullCommand,1,2);
  Command:=StrToInt(st);
  case Command of
  01:beep;
  02:
    begin
   ShowMessage(st);
   st:='The message '''+st+''' has been received';
   Socket.SendText(st);
    end;
//etc.
end;
end;


Ahora pasemos al cliente.

Abre otro nuevo proyecto en Delphi y colócale un componente ClientSocket, tres botones y dos EditBoxes.
En las propiedades del ClientSocket pon Active en False, ClientType en stNonBlocking y pon el mismo puerto que en el server (ej. 800).

A continuación está el código de los eventos OnCreate, OnRead y OnError del ClientSocket1 y los eventos OnClick de los botones Button1, Button2 y Button3:

Código: delphi
procedure TForm1.FormCreate(Sender: TObject); 
begin
    Button1.Caption:='Connect';
    Button2.Caption:='Send Beep';
    Button3.Caption:='Send Message';
    Edit1.Text:='127.0.0.1';
    Edit2.Text:='Hi from client!';
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
    if ClientSocket1.Active=False then
        try
            ClientSocket1.Host:=Edit1.Text;
            ClientSocket1.Active:=True;
            Button1.Caption:='Disconnect';
        except
            ClientSocket1.Active:=False;
        end
    else
    begin
        ClientSocket1.Close;
        Button1.Caption := 'Connect';
    end;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
    ClientSocket1.Socket.SendText('01');
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
    ClientSocket1.Socket.SendText('02'+Edit2.Text);
end;

procedure TForm1.ClientSocket1Read
   (Sender:TObject;Socket:TCustomWinSocket);
var s:string;
begin
    s:=Socket.ReceiveText;
    ShowMessage(s);
end;

procedure TForm1.ClientSocket1Error
   (Sender: TObject;Socket: TCustomWinSocket;
   ErrorEvent: TErrorEvent;var ErrorCode: Integer);
begin
    ErrorCode:=0;
    Button1.Caption:='Connect';
end;


El código casi se explica solo salvo por el evento OnError. Con este evento manejamos los errores que ocurren en el socket, y escribiendo "ErrorCode:=0;" prevenimos de que salte un ESocketError.
By Sr_Sombrero and Geek Lord.