Menú

Mostrar Mensajes

Esta sección te permite ver todos los mensajes escritos por este usuario. Ten en cuenta que sólo puedes ver los mensajes escritos en zonas a las que tienes acceso en este momento.

Mostrar Mensajes Menú

Mensajes - s0d0ma

#1
Otros lenguajes / [C / C#] IRC a machetazos
Abril 01, 2018, 09:39:52 PM
Hola  He decidido solucionar algunos wargames para salir de la monotonia de la facultad, pero no simplemente hacerlo si no tratarme de empaparme lo que mas pueda para poder resolverlo (como realizar un "estado del arte" preliminar antes de sentarme a codear para resolver estos retos).

PostData[0] = No diré de donde saque los retos para no dañarle la experiencia a las demás personas que quieran realizarlos.

PostData[1] = Publicare el código del reto pero intentare hacer un énfasis "investigativo" y tratar de exponer un poco lo que aprendí y no solo subir la solución del reto.

PostData[2] = Cambiare algunos valores del planteamiento del reto para que no lleguen a este post si están buscando una solución de este reto.

Planteamiento del reto

El reto encontrado nos planteaba la siguiente situación, debíamos conectarnos a un servidor IRC (irc.server.com) con un puerto definido donde se estaba ejecutando el servicio IRC (6667), despues de esto debíamos enviar un mensaje privado a un bot que llamado Pepegrillo diciéndole !problema1. El bot nos contestara el mensaje con el siguiente formato.

Código: php
[numero_1] / [numero_2]


El siguiente procedimiento se debe realizar las siguientes operaciones con los números dados por el bot

1) calcular la raíz del numero_1
2) multiplicar el resultado anterior por el numero_2

Se debe enviar el bot Pepegrillo el resultado de la ultima operación redondeándolo a 2 cifras significativas para esto se tiene un tiempo de 2 segundos. Si el bot no responde es por que esta baneado el usuario y se debe esperar unos minutos antes de enviar una nueva respuesta.

Conocimientos necesarios
Protocolo IRC
  • Introducción al protocolo
  • Aspectos del RFC
  • Análisis de cliente
  • Opiniones personales del irc a la fecha (2018)

    Sockets Linux
  • Introducción a sockets
  • Estructuras]
  • Uso del socket (Cliente)

    Planteamiento del codigo
  • Descripción de pasos genéricos
  • Código (C && C#)




    Protocolo IRC

  • Introducción al protocolo

    IRC (Internet Relay Chat) es un protocolo de comunicacion basado en texto para el intercambio de mensajes en tiempo real, incluyendo la tranferencia de archivos, mensajes privados entre usuarios que están en una misma sala de chat o en un mismo servidor.

    El modelo de conexion de software es CLIENTE-SERVIDOR, donde el servidor es donde se estará ejecutando el demonio que recibirá las conexiones de los clientes concurrentes (que se conectan por medio de un programa llamado CLIENTE IRC para consumir los recursos ofrecidos por el servidor).

    Para poder tener un servidor irc se debe tener instalado un demonio que nos deje operar nuestro servidor IRC. Existen varias alternativas de demonios para poder tener nuestro servidor IRC propio entre esos estan ircd-seven, InspIRCd, UnrealIRCd.

    (imagen: Banner Bahamut Deamon)

    (imagen: Banner UnrealIRCd)

    Existen varios clientes de irc, uno de los mas usados es el irssi. Ya que IRC esta basado en texto y como dicen en el propio RFC "siendo el cliente mas simple un programa capaz de conectarse a un servidor por medio de un socket" irssi es un cliente que permite conectarse por medio de un socket y poder interactuar con el servicio de IRC ( mas se realizara un análisis del protocolo con ngrep y irssi ).


  • Aspectos del RFC

    RFC: Es un escrito realizado por una o varias personas y contiene una propuesta para una nueva tecnología, donde se especifica la información técnica del uso. Las RFC en resumen es la documentación de protocolos y tecnologías de internet, son mantenidas y aprobadas por el IETF (No tienes permitido ver los links. Registrarse o Entrar a mi cuenta).

    Invitacion: Existen muchos RFC sin traducir al español aqui No tienes permitido ver los links. Registrarse o Entrar a mi cuenta podrán ser parte del grupo de traducción de las RFC. (Es bueno a veces encontrar un RFC en español), debo pulir mi ingles intentar ser parte del grupo de traducción.

    El RFC del protocolo IRC se puede encontrar aquí en español No tienes permitido ver los links. Registrarse o Entrar a mi cuenta y la versión mas actualizada No tienes permitido ver los links. Registrarse o Entrar a mi cuenta contiene todas las especificaciones tecnicas del protocolo. Solo comentare las que mas me llamaron la atencion :

    [-]IRC se ha desarrollado para trabajar sobre TCP/IP pero eso no implica que sea la unica forma que funcione.
    [-]Los servidores son la espina dorsal de la arquitectura para un servicio IRC, ya que un servidor puede estar a otros servidores irc para retro alimentar a un servidor principal.


    (imagen: arquitectura irc)


    (imagen: red pequeña de irc)

    [-]El final de un mensaje se toma por CRLF o "\r\n" o "\x0d\x0a"
    [-]El servidor envia el comando PING para verificar si un cliente sigue conectado, para que el cliente diga que esta vivo tiene que responder PONG
    [-]Commandos de uso basico terminados por CRLF

    Código: php
    CONNECT <target server> <port> [<remote server>]
    INFO [<target>]
    JOIN <channels> [<keys>]
    LIST [<channels> [<server>]]
    USER <username> * * :<username>
    PRIVMSG <user> :<message>
    QUIT : <message>


  • Analisis del cliente

    El plan aquí es literamente ver como se comporta el protocolo en caliente, ver como se inicia las comunicaciones y cual es el orden de esos comandos para poder ingresar a un server IRC. para ello se utilizara ngrep (full amor para esa herramienta) esta herramienta es un sniffer que puede matchear resultados por medio de "expresiones regulares".

    Iniciamos el ngrep con los siguentes parametros -x para visualizar el content del paquete en hexadecimal, -d para definir la interface de red que queremos monitorear, port definimos el puerto en el que se ejecuta el server irc y a despues de esto iniciar nuestra conexion con un servidor irc por medio del irssi (/connect No tienes permitido ver los links. Registrarse o Entrar a mi cuenta).


    El inicio de la comunicacion empezar seteando el NICK del cliente, luego sigue definirle al servidor el usuario con el que nos conectaremos, y luego viene 2 repuestas del server, podremos ver que cada mensaje termina con un "\r\n".


    Despues de esto vendran mas respuestas por parte del servidor con el banner de inicio y luego el mecanismo para mantener live la conexion entre el cliente y el servidor (PING).


    (imagen de conexion al server)


    (imagen mecanismo de verificacion de "live")

    Con esto ya se "toca madera" sentando un poco de lo antes leido en el RFC y con ello confirmamos que podemos interactuar mediante sockets con un server IRC (claro... para la interaccion cifrada de SSL cambia todo el asunto pero por ahora solo me preucupare por el text-plain... I need more skills dude).

  • Opiniones personales del irc a la fecha (2018).

    IRC estuvo muy movido una epoca, donde medio internet estaba por las redes de IRC, se usaba mucho para juegos, soporte, grupos de desarrolladores (aunque en esta fecha aun existen varios proyectos que intentan mantener live IRC como por ejemplo el grupo de telegram de radare, hicieron una integracion que los mensajes escritos en el irc se vean reflejados en el chat de telegram y asi mismo lo que se escriba en telegram se ve reflejado en el canal de IRC). Aun se veían botnets C&C administradas desde IRC... es una buena opcion pero hace poco tambien hicieron la implementacion de un RAT administrado por Telegram. 

    Montar un servidor IRC propio es bueno por que tu eres el que lo administra,  porque tu le configuras el tipo de cifrado vas a manejar por SSL, los clientes o las IP que vas a dejar conectarse al servidor , etc (O sea hardenning del hardcore y del pesado).

    IRC a la fecha sigue siendo una buena alternativa para la comunicacion de mensajes en tiempo real aunque existan muchas otras alternativas "mas seguras" que simplifican el uso y que traen ciertas opciones interesantes.

    "IRC no ha muerto...".




    Sockets Linux

  • Introducción sockets

    Los sockets son un abstraccion de software que permiten la intercomunicacion de datos y de informacion entre dos (o uno llegado el caso) por medio de la API del sistema operativo que se encargara de hacer interface con los protocolos de internet y de TPC/IP (o para intercomunicacion de procesos del sistema operativo).

    Para el uso de sockets se deberan tener en cuenta estas librerias del sistema.


  • Estructuras.

    Las estructura mostradas en esta seccion son muy importantes para trabajar con punteros, son estrucutras ya definidas dentro del archivo sys/socket.h. Estas estructuras se deberan llenarse adecuadamente por que luego se utilizaran por las funciones de sockets (creacion del handler y otros) y tiene informacion del socket.


    • hostent : informacion del host
    • sockaddr : sockaddr_in minimizada
    • in_addr : Contiene la ip del host
    • sockaddr_in : informaccion del socket


  • Uso de sockets (Cliente).
    Se puede resumir el uso de un socket a nivel de cliente en los siguentes pasos (a nivel de codigo).


    • Setear valores del socket (estructura sockaddr_in).
    • Creacion del handle del socket
    • Verificacion del handle
    • Conexion
    • Verificar conexion
    • Envio/recibo
    • Cerrar socket

    Dos cosas que se deben tener en cuenta: 1) si estamos programando un servidor o un cliente con multiples peticiones lo mejor es crear procesos para manejar cada caso de ejecucion 2) ya que la filosofia de linux es que todo es un archivo (hasta el mismo socket) en cierta manera lo que obtenemos de crear el handle del socket es un handle de un archivo asi que podremos usar ciertas funciones con las que se pueden interactuar con archivos "real" y usarlas con el handle del socket. En resumidas cuentas seria algo asi hasta el paso 5. (en la funcion socket, se le envia el tipo de familia del protocolo AF_INET (conexiones a red, si fuera AF_UNIX seria para intercomunicarse entre procesos internos de la maquina) , SOCK_STREAM (TCP o UDP), 0 = PROTOCOLO = TCP ).

    (en la funcion connect se le pasa por parametros, el handle del socket creado por la funcion socket, luego la estructura sockaddr_in con un cast necesario y por ultimo la cantidad de bytes)




  • Descripcion de programa

    Utilizare un diagrama de secuencia para describir la comunicacion entre el cliente y el servidor irc para la solucion del reto planteado (lo deje simple para solo enfocarme en comunicacion realizada, si encuentran algun error o alguna recomendacion la pueden escribir aqui. Gracias)

    Pasos:

    • Realizar conexion por sockets al servidor
    • Enviar comando "NICK s0d0ma\r\n"
    • Respuesta por parte del servidor "\x00\x00\x00\x00\x00\x00"
    • Enviar comando "USER s0d0ma * *:s0d0ma\r\n"
    • Respuesta del servidor (banner 1, banner 2, banner 3)
    • Enviar comando "PRIVMSG Pepegrillo:!problema1\r\n"
    • Respuesta del servidor "numero2 / numero2\r\n"
    • (procesar) Enviar respuesta "PRIVMSG Pepegrillo:!problema1 -rep%0.2f\r\n"
    • Respuesta del servidor con la flag
    • Cerrar conexion


  • Codigo

    C (GNU GCC)

    En la implementacion realizada en C se define antes de todo 1) un offset para encontrar la flag en el mensaje de respuesta 2) El puerto irc, se define una nueva estructura para almacenar los datos del servidor. y en el prototipo de funciones se encuentran nuestras  3 funciones a usar.



  • Recibir()

    Retornara un buffer donde esta almacenada la respuesta por parte del servidor y se debe pasar como parametro el handle del socket, crea un nuevo buffer de memoria de 2000 bytes. recibe información por medio de la función recv y queda almacenada en el buffer recién creado y al final se retorna el buffer.


  • Enviar()

    No retorna algún valor, solo se encargara de enviar datos por medio del socket, se tendrá que pasar como parámetro el handle del puntero, y el buffer de datos que se quiere enviar. Se crea primeramente un buffer de memoria del tamaño de la longitud del commando ingresado y se le suman 3 espacios mas para almacenar "\r\n". Luego envía la información por medio de la función send() y se libera el buffer temporal que habíamos creado para el comando+"\r\n".


  • Procesar()

    Retornara la respuesta al reto que es de tipo float, se tendrá que pasar como parametros le buffer donde se encuentran los números a operar y la longitud del username. Primeramente se define el buffer inicial donde estará la flag. en el primer ciclo se concatenaran todos los números de numero1 y en el segundo ciclo almacenamos todos los digitos del numero2, realizamos luego un atoi a ambos strings y los convertimos a int. Se realiza las operaciones indicadas y se retorna el float. (Nota mental : printf("%0.2f",float_mio);


    Dentro de la función main donde se puede visualizar los pasos efectuados para realizar este reto, se debe tener en cuenta que a la hora de generar los strings de los comandos se tenia que realizar una construcion de strings dinámico por medio de sprintf() que permite enviar un string dinámico a un buffer de memoria.  Se deben ir eliminando cada no de los buffers (entrada y de salida de datos) antes de usarlos para hacer un manejo de memoria adecuado.


    Codigo completo

    Código: c

    // Librerias basicas para

    #include <stdio.h> // I/O
    #include <stdlib.h> // Libreria standar para manejo de memoria, conversion numerica, etc
    #include <string.h> // manejo de strings (char * terminados en \0)
    #include <unistd.h> // Libreria que provee acceso a POSIX (api del sistema operativo)
    #include <math.h> // funciones matematicas

    // Librerias para sockets

    #include <sys/socket.h> // Provee funciones, estructuras usadas por el SOCKET API
    #include <arpa/inet.h> // Definiciones para operaciones de internet (htons, inet_addr,...)
    #include <netinet/in.h> // internet domain address estructuras y funciones
    #include <netdb.h> // dominio/DNS usada para el hostname lookup

    #define OFFSET_FLAG 32
    #define PUERTO 6667

    struct server_irc
    {
    const char * username;
    const char * canal;
    const char * IP;
    const int puerto;
    const char * botname;
    };


    char * recibir( int );
    void enviar( int , char * );
    float procesar( char * , int );

    int main()
    {
    // declaraciones
    struct server_irc server = {"s0d0maN", "", "211.88.163.14", 6667, "botco"};
    struct sockaddr_in irc_cliente;
    char * buffer;
    char * Commd;
    int handleSocket;
    float result;

    // Seteando valores del socket
    irc_cliente.sin_family = AF_INET; // Protocolo
    irc_cliente.sin_port = htons(server.puerto); // Puerto
    irc_cliente.sin_addr.s_addr = inet_addr(server.IP); // IP
    memset(irc_cliente.sin_zero,0,8); //rellenado de 0

    // iniciar socket
    handleSocket = socket(irc_cliente.sin_family, SOCK_STREAM, 0);

    // verificar el handle
    if(handleSocket == -1)
    {
    fprintf(stderr, "[ERROR] socket no creado\n");
    exit(-1);
    }

    // realizar conexion de socket
    if(connect(handleSocket, (struct sockaddr *) & irc_cliente, sizeof(irc_cliente)) == -1)
    {
    fprintf(stderr, "[ERROR] No conectado\n");
    exit(-1);
    }

    // recibir banner de conexion
    buffer  = recibir(handleSocket);
    free(buffer);
    buffer  = recibir(handleSocket);
    free(buffer);

    // enviar Nick y User
    Commd = ( char * ) calloc(strlen(server.username) + 6, sizeof(char));
    sprintf(Commd, "NICK %s", server.username);
    enviar(handleSocket, Commd);
    free(Commd);
    Commd = ( char * ) calloc(strlen(server.username)*2 + 13, sizeof(char));
    sprintf(Commd, "USER %s * * :%s", server.username, server.username);
    enviar(handleSocket, Commd);
    free(Commd);

    // recibir banner del inicio del servidor
    buffer  = recibir(handleSocket);
    free(buffer);
    buffer  = recibir(handleSocket);
    free(buffer);
    buffer  = recibir(handleSocket);
    free(buffer);

    // enviar mensaje privado al bot
    Commd = ( char * ) calloc(strlen(server.botname) + 14, sizeof(char));
    sprintf(Commd, "PRIVMSG %s :!problema1", server.botname);
    enviar(handleSocket, Commd);
    free(Commd);

    // recibir contenido del mensaje
    buffer  = recibir(handleSocket);
    printf(buffer);
    result = procesar(buffer, strlen(server.username));


    // enviar respuesta
    Commd = ( char * ) calloc(strlen(server.botname) + 40, sizeof(char));
    sprintf(Commd, "PRIVMSG %s :!problema1 -rep %0.2f", server.botname,result);
    enviar(handleSocket, Commd);
    free(Commd);

    // recibir flag
    buffer  = recibir(handleSocket);
    printf(buffer);
    free(buffer);

    // cerrar sesion
    enviar(handleSocket, "QUIT :IRC Cool");

    // cerrar socket
    close(handleSocket);

    return 0;
    }


    char * recibir(int handlesock)
    {
    char * bufferOut = (char *) calloc(2000, sizeof(char));
    recv(handlesock, bufferOut, 2000,0);
    return bufferOut;
    }

    void enviar(int handlesock,char * command)
    {
    char * tempCommand = (char *) calloc(strlen(command)+3, sizeof(char));
    sprintf(tempCommand,"%s\r\n",command);
    send(handlesock, tempCommand, strlen(tempCommand),0);
    free(tempCommand);
    }

    float procesar(char * buffer , int len_username)
    {
    int i = OFFSET_FLAG + len_username + 3;
    int k = 0;
    int numero_1 = 0, numero_2 = 0;
    char numero1[10], numero2[10];

    while( buffer[i] != ' ')
    {
    numero1[k] = buffer[i];
    k++;
    i++;

    }

    i = i + 2;
    k = 0;

    while( buffer[i] != '\r')
    {
    numero2[k] = buffer[i];
    k++;
    i++;

    }

    numero_1 = atoi(numero1);
    numero_2 = atoi(numero2);


    printf("\nnumero1 = %i\t", numero_1 );
    printf("numero2 = %i\t", numero_2 );
    printf("resultado = %0.2f\n\n", sqrt(numero_1) * (float) numero_2);

    return sqrt(numero_1) * (float) numero_2;
    }


    EJECUCION


    C# (Visual Studio 2017)

    La clase ClienteIrc se creara y utilizara en el código realizado en C#  para facilitarnos el manejo del protocolo IRC desde el código. Contiene los atributos :


    • dirección = se almacenara la ip del servidor irc donde nos vamos a conectar.
    • puerto = se almacenara el puerto (puerto de uso de irc 6667).
    • SockIrc = es nuestro objeto Socket en cual nos permitira hacer uso del api de red para realizar nuestro socket (System.Net.Socket y No tienes permitido ver los links. Registrarse o Entrar a mi cuenta).
    • username = Se almacenara el Nick para el ingreso de IRC
    • recvString = Se almacena el ultimo mensaje recibido por parte del servidor en un string.


    Contiene los metodos:

  • (constructor) ClienteIrc :

    Este método inicializa los atributos de la clase. recibe como parametros la ip, el puerto y el username.


    Se instancia el objeto socket, el constructor recibe los parametros de configuracion del socket, el parametro AddressFamaly es el valor de una enumeración que contiene como valores los esquemas de direcciones que puede usar la clase socket, en este caso se Usara el valor InterNetwork que especifica que es una dirección IP versión 4. Existen otros esquemas de direcciones.


    El parámetro SocketType, recibe el parámetro para el tipo de socket (en este caso STREAM), y el ultimo parámetro recibe el tipo de protocolo a usar (en este caso TCP). Luego se crea un objeto de tipo IPEndPoint el cual nos parseara la ip y el puerto del servidor para podérselo pasar al método de conexion, el constructor de este objeto recibe una una IP la cual se deberá parsear y el puerto. Por ultimo se inicia la conexion Con el método Connect() del socket. Si hay un error en la conexion el try-catch lo recibe.

  • Recibir :

    Este método recibirá los mensajes por parte del servidor. Primeramente de instancia un array de tipo byte (unsigned char) donde se almacenara la información que vamos a enviar por el socket.


    Luego se recibe la respuesta y se almacena la cantidad de bytes leídos, luego de esto debemos convertir el array de byte a un string, para esto se debe tomar el array de byte y Encodearlo (a ASCII) se le envía los parametros 1) array de respuesta byte, 2) el índice de de donde empezara a encodear y 3) es la cantidad de bytes seleccionados (como un offset final).

  • Command :

    Este método sera el encargado de enviar los datos por el socket. recibe como parámetro un string con los "comandos" que se le envia al servidor IRC. Se concatena un "\r\n" ya que en el RFC decía que los finales de un mensaje están marcados por "\r\n".


    Luego se hace lo mismo en el método recibir pero encodeando un string a un array de bytes (recordar ASCII) y se envía el array de bytes por el socket.

  • Close:

    Esta función, libera y setea los recursos del objeto para poder ser utilizado posteriormente. Se envía el comando al IRC para salir de nuestra sesión, se cierra el Socket y se setean los valores "by default"


    Aqui esta la implementacion de la clase y el codigo que soluciona el reto escrito en C#.

    Código: csharp

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Net;
    using System.Net.Sockets;

    namespace ircCtf
    {
        class Program
        {
            static void Main(string[] args)
            {
                string botInServer = "PepeGrillo";
                ClienteIrc ircclient = new ClienteIrc("213.56.152.135",6667,"s0d0maP");

                if(ircclient.SockIrc.Connected == true)
                {
                    Console.WriteLine(
                        "\nConectado {0} : {1} : {2}\n",
                        ircclient.direccion, 
                        ircclient.puerto,
                        ircclient.username
                    );

                    ircclient.Command(String.Format("NICK {0}",ircclient.username));
                    ircclient.Command(String.Format("USER {0} * * :{0}", ircclient.username));

                    for( int i = 0; i<5; i++)
                    {
                        ircclient.Recibir();
                    }

                    ircclient.Command(String.Format("PRIVMSG {0} :!ep1", botInServer));
                    ircclient.Recibir();
                    Console.Write("{0}",ircclient.recvString);

                    string[] segmentos = ircclient.recvString.Split(':');
                    string[] segmentos2 = segmentos[2].Split(':');
                    string[] tempNum = segmentos2[0].Split('/');

                    int num1 = int.Parse(tempNum[0]);
                    int num2 = int.Parse(tempNum[1]);
                    double result = Math.Sqrt(num1) * num2;

                    Console.WriteLine(String.Format("PRIVMSG {0} :!problema1 -rep {1}", botInServer, result.ToString("F").Replace(',', '.')));
                    ircclient.Command(String.Format("PRIVMSG {0} :!problema1 -rep {1}", botInServer, result.ToString("F").Replace(',', '.')));
                    ircclient.Recibir();
                    Console.Write("{0}", ircclient.recvString);

                    ircclient.SockIrc.Close();

                    Console.Read();
                }

            }
        }

        // clase ClienteIrc
        class ClienteIrc
        {
            public string direccion;
            public Int32 puerto;
            public Socket SockIrc;
            public string username;
            public string recvString;
            public string bot;

            public ClienteIrc(string ip, Int32 puerto, string username)
            {
                // inicializar datos
                this.direccion  = ip;
                this.puerto = puerto;
                this.username = username;

                try
                {
                    // inicializar socket
                    this.SockIrc = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    IPEndPoint dire_socket = new IPEndPoint(IPAddress.Parse(this.direccion), this.puerto);

                    // realizar conexion
                    this.SockIrc.Connect(dire_socket);
                }
                catch
                {
                    Console.WriteLine("ERROR de conexion");
                }
            }

            public void Recibir()
            {
                byte[] respuesta = new byte[2000];
                int ret = this.SockIrc.Receive(respuesta);

                this.recvString = Encoding.ASCII.GetString(respuesta,0,ret);
            }

            public void Command(string command)
            {
                command += "\r\n";
                byte[] datasend = Encoding.ASCII.GetBytes(command);
                this.SockIrc.Send(datasend);
            }

            public void Cerrar()
            {
                this.Command("QUIT : IRC Rulez");
                this.recvString = "";
                this.puerto = 0;
                this.username = "";
                this.direccion = "";
                this.SockIrc.Close();
            }
        }
    }


    Mucha gracias por tomarse el tiempo para leer esto.

    Saludos.

    REFERENCIAS:

    No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
    No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
    No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
    No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
    No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
    No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
    No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
    No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
    No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
    No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
    No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
    No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
    No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
    No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

    FUENTE:
    No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
#2
Hola foro.

Me presento, soy s0d0ma, me gusta el desarrollo (C/C++/C#) enfocado siempre a "weird stuff" o a temas que me llamen la atencion, espero poder aprender y compartir conocimientos en esta comunidad.

Saludos