Sockets usando la red TOR C++

  • 2 Respuestas
  • 1382 Vistas

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

Desconectado d3adly

  • *
  • Underc0der
  • Mensajes: 90
  • Actividad:
    0%
  • Country: 00
  • Reputación 5
    • Ver Perfil
    • sh1tty c0d3
    • Email

Sockets usando la red TOR C++

  • en: Mayo 29, 2020, 09:34:07 pm
Hola a todos.
Hoy comparto con ustedes el manejo de sockets mediante la red TOR. Suponiendo que ya se tiene tor instalado y corriendo en el puerto por defecto 9050 proseguimos.
Primero debemos entender sobre la negociacion o Handshake que se lleva a cabo al conectar con un proxy. En el Request For Comment RFC 1982 You are not allowed to view links. Register or Login, pueden obtener mas información con respecto al proceso de conexión, en este post solo cubriremos conceptos basicos.
El Handshake basico se podria representar de la siguiente manera



Y sigue este flujo:
Primero el cliente en este caso PC A, envia una secuencia de tres bytes (5, 1, 0) al servidor proxy. El primer byte especifica la version de socks a usar en este caso 5, el segundo byte es para propositos de autenticación, especifica los metodos soportados por el cliente para autenticarse 1, y el tercer byte es el tipo de autenticación, en este caso 0 (sin autenticación), si la conexión se quiere realizar mediante usuario/contraseña entonces este ultimo byte seria 2.

Se envia la secuencia de bytes y el servidor responde con dos bytes, en esta caso (5, 0), siendo el primer byte la version de socks a utilizar 5, y el segundo el metodo de autenticación 0 (sin autenticación). Si el servidor requiere de autenticación responderia con 5,2, pero ya que utilizaremos un proxy local sin este metodo deberia de responder siempre con 5,0.

A continuación se envia la secuencia de bytes (5, 1, 0, 3, Host, Puerto), siendo el primer byte 5 como se menciona anteriormente la version de socks, el segundo byte 1 es el codigo de comando, que puede ser uno de los siguientes valores:

1 = Establecer conexión TCP/IP.
2 = Establece un enlace de puerto TCP/IP.
3  = Asocia un puerto UDP.

En este caso usaremos el primero 1 (Establecer conexión TCP/IP) , el tercer byte 0 es un byte reservado y debe ser 0, el cuarto byte 3 es el tipo de direccion del host que puede ser una de las siguientes:

1 = Dirección IPv4, seguida por la IP de 4 bytes
3 = Nombre de dominio, 1 byte para la longitud del nombre seguido del nombre del host.
4 = Dirección IPv6, seguida de la IP de 16 bytes.

Usaremos el byte 3 (Nombre de dominio, 1 byte para la longitud del nombre seguido del nombre del host), y el ultimo byte vendria siendo el numero de puerto en orden de red de 2 bytes You are not allowed to view links. Register or Login.

Si todo va bien el servidor proxy responde con la secuencia 5, 0, 0, 1, Host, Puerto , siendo el segundo byte 0 el estado de la negociación, en esta caso el 0 indica que todo ha salido bien, el tercer byte es reservado y es 0, y los ultimos tres vendrian siendo el tipo de dirección, dirección y puerto en orden de red.

Habiendo entrado en lo basico del proceso de comunicación con el servidor veamos como aplicarlo en código

Una vez realizada la conexión inicial con el servidor:
Código: (cpp) You are not allowed to view links. Register or Login
char buffer[3];
buffer[0] = 0x05;  //Version de socks
buffer[1] = 0x01; //Metodos de autenticacion soportados por el cliente
buffer[2] = 0x00; //Metodo de autenticacion a utilizar : Sin Autenticacion
send(Socket, buffer, 3, 0);
Enviamos la secuencia de tres bytes 0x05, 0x01, 0x00,  (0x05 - Version Socks    0x01 - Metodos soportados de autenticacion por el cliente    0x00 - No usar autenticacion).

Acto seguido recibimos la respuesta del servidor y verificamos si el estado del segundo byte es 0
Código: (cpp) You are not allowed to view links. Register or Login
char rbuffer[10];
recv(Socket, rbuffer, 10, 0);
if(rbuffer[1] == 0x00){
   //primera parte de negociacion correctamente
}

Ahora se procede a crear la ultima secuencia de bytes con los datos del destino al cual conectarnos
Código: (cpp) You are not allowed to view links. Register or Login
char fbuff[256];
memset(fbuff, 0, 256);
fbuff[0] = 0x05;  //version de socks
fbuff[1] = 0x01;  //Codigo de comando
fbuff[2] = 0x00;  //Byte reservado
fbuff[3] = 0x03; //Tipo de direccion del host

short host_port = htons(PORT);                  //convierte el numero de puerto a orden de bytes de red
char host_len = (char)strlen(HOSTNAME);        //Se obtiene la longitud del nombre host en un byte
memcpy(fbuff + 4, &host_len, 1);                //Luego se unen los datos junto con la secuencia anterior
memcpy(fbuff + 5, HOSTNAME, host_len);
memcpy(fbuff + 5 + host_len, &host_port, 2);

send(Socket, fbuff, 7 + host_len, 0);         //Se envia la secuencia de bytes

Y por ultimo recibimos la respuesta del servidor proxy, si el segundo byte es 0 significa que el proceso de negociación ha finalizado correctamente
Código: (cpp) You are not allowed to view links. Register or Login
recv(Socket, rbuffer, 10, 0);
if(rbuffer[1] == 0x00){
    //proceso de negociacion completo
    //Ahora se procede a intercambiar datos con el host de destino
}

Y sin mas mi código de una simple peticion HTTP usando TOR:

Código: (cpp) You are not allowed to view links. Register or Login
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<netdb.h>
#include<unistd.h>
#include<signal.h>

class TorSocket{
   private:
int SocketD;
   public:
int Connect(const char *cHostname, int iPort, const char *torhost = "127.0.0.1", const char *torport = "9050"){
struct sigaction act;
memset(&act, 0, sizeof(act));
act.sa_handler = SIG_IGN;
act.sa_flags = SA_RESTART;
sigaction(SIGPIPE, &act, 0);
struct addrinfo client, *addrs, *addr;
char rBuffer[10];
int iReceived = 0;
memset(&client, 0, sizeof(client));
client.ai_family = AF_UNSPEC;
client.ai_socktype = SOCK_STREAM;
client.ai_protocol = IPPROTO_TCP;
int iStatus = getaddrinfo(torhost, torport, &client, &addrs);
if(iStatus!=0){
std::cout<<"Error getaddrinfo\n";
return -1;
}
for(addr = addrs; addr != nullptr; addr = addr->ai_next){
if((this->SocketD = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol)) == -1){
continue;
}
if(connect(this->SocketD, addr->ai_addr, addr->ai_addrlen) == -1){
continue;
}
break;
}
freeaddrinfo(addrs);
if(this->SocketD == -1){
std::cout<<"No se pudo conectar al proxy\n";
return -1;
}
char cByteSequense1[3] = {0x05, 0x01, 0x00};
send(this->SocketD, cByteSequense1, 3, 0);
iReceived = recv(this->SocketD, rBuffer, 10, 0);
if(iReceived > 0){
if(rBuffer[0] != 0x05){   
std::cout<<"Version de socks invalida\n";
return -1;
}
if(rBuffer[1] == 0x00){
char cByteSequense2[256];
memset(cByteSequense2, 0, 256);
cByteSequense2[0] = 0x05;
cByteSequense2[1] = 0x01;
cByteSequense2[2] = 0x00;
cByteSequense2[3] = 0x03;
short sHost_Port = htons(iPort);
char cHost_Len = (char)strlen(cHostname);
memcpy(cByteSequense2 + 4, &cHost_Len, 1);
memcpy(cByteSequense2 + 5, cHostname, cHost_Len);
memcpy(cByteSequense2 + 5 + cHost_Len, &sHost_Port, 2);
send(this->SocketD, cByteSequense2, 7 + cHost_Len, 0);
memset(rBuffer, 0, sizeof(rBuffer));
iReceived = recv(this->SocketD, rBuffer, 10, 0);
if(rBuffer[1] == 0x00){
std::cout<<"Conexion satisfatoria\n";
//Ahora se puede enviar datos atraves de este socket
return this->SocketD;
} else {
return -1;
}
}
} else {
return -1;
}
return -1;
}

void CloseSocket(){
close(this->SocketD);
}

int SendData(const char *data, int size){
return send(this->SocketD, data, size, 0);
}

int ReadData(char*& buffer){
buffer = (char *)malloc(2048);
unsigned int so_far = 0;
char u_c[2];
while(recv(this->SocketD, u_c, 1, 0) > 0){
if(so_far >= 2048){
buffer = (char *)realloc(buffer, so_far + 1);
}
buffer[so_far++] = u_c[0];
}
buffer[so_far] = '\0';
return so_far;
}
};

//Simple ejemplo de peticion HTTP a url specificada
int main(int argc, char **argv){
if(argc < 2){
std::cout<<argv[0]<<" url\n";
return 0;
}
TorSocket tor;
char domain[128];
char *response;
strncpy(domain, argv[1], 128);
int stat = tor.Connect(domain, 80);
if(stat == -1){
std::cout<<"No se pudo conectar\n";
return -1;
}
std::cout<<"Conectado\n";
char packet[512];
snprintf(packet, 512, "GET / HTTP/1.1\r\nHost: %s\r\n\r\n", domain);
if(tor.SendData(packet, strlen(packet)) > 0){
unsigned int bytes = tor.ReadData(response);
if(bytes>0){
std::cout<<response<<"\n\n";
} else {
std::cout<<"No se recibio nada\n";
}
free(response);
} else {
std::cout<<"Error al enviar el paquete\n";
}
tor.CloseSocket();
return 0;
}


Una captura de pantalla
         

Espero les haya servido y le den un buen uso, cualquier correcion o duda dejenme saberla.

Saludos
Ph'nglui mglw'nafh Cthulhu R'lyeh wgah'nagl fhtagn

Conectado DtxdF

  • *
  • Moderador Global
  • Mensajes: 999
  • Actividad:
    100%
  • Country: 00
  • Reputación 22
  • Eres un auto y tienes dos opciones: Parar o Seguir
    • Ver Perfil
    • Mi repositorio de Github donde encontraras herramientas para tu trabajo.
    • Email

Re:Sockets usando la red TOR C++

  • en: Mayo 29, 2020, 09:55:41 pm
Respetos @You are not allowed to view links. Register or Login +1, un excelente aporte, sigue compartiendo estos conocimientos  ;D

~ DtxdF
Los seres humanos son robots, cuyo combustible es el afanado dinero.

Desconectado d3adly

  • *
  • Underc0der
  • Mensajes: 90
  • Actividad:
    0%
  • Country: 00
  • Reputación 5
    • Ver Perfil
    • sh1tty c0d3
    • Email

Re:Sockets usando la red TOR C++

  • en: Mayo 29, 2020, 11:41:25 pm
Gracias @You are not allowed to view links. Register or Login esa es la idea :)
Ph'nglui mglw'nafh Cthulhu R'lyeh wgah'nagl fhtagn