Espameando a fotolog en C#

Si has creado algún documento interesante, este es su sitio

Moderador: Moderadores

Espameando a fotolog en C#

Notapor Nork » Vie Ago 22, 2008 3:05 pm

Imagen

  • Presentación
  • Conceptos básicos
  • Resumen de lo que haremos
  • Ver código por funciones
  • Despedida



Presentación

Hola a todos, bueno pues en este artículo os voy a intentar mostrar una de las maneras para crear un bot en C#. En este caso nuestra victima será la página fotolog ya que nos puede ser útil para hacer publicidad o cualquier cosa que os ocurra. No se pretende que ahora quede inservible la página o que este llena de bots ya que para eso os tendréis que saltar el captcha y es una cosa que no daremos aquí. Este artículo es, como siempre, de información para asegurar nuestras aplicaciones web contra estos programas. Dicho esto vamos a ver los conceptos básicos para luego entender todo lo que sigue.

Conceptos básicos

HTTPWEBREQUEST

Según Microsoft, la comenta de la siguiente manera:

La clase HttpWebRequest hace que se admitan las propiedades y los métodos definidos en WebRequest y que las propiedades y los métodos adicionales permitan al usuario interactuar directamente con servidores que utilicen HTTP.

Aquí dejo el enlace por si alguien quiere leerselo

Tengo que decir que esta clase sin su acompañante HTTPWebResponse no haría mucho en este artículo sólo que por comodidad y estética me referiré únicamente a HttpWebRequest [HWR].[/FONT]

[COLOR=black]Sistema de cookies en HWR


Un tema esencial para crear este tipo de bots es utilizar las cookies para navegar por los directorios del dominio logueado. En este punto puede crear confusiones de cómo realmente funcionan las cookies en esta clase por lo que intentaré explicarme lo mejor que pueda.

Primero de todo necesitamos declarar un “espacio” para guardar todas las cookies que necesitemos, en HWR es así:

Código: Seleccionar todo
CookieContainer misgalletas = new CookieContainer();


Ahora imaginemos que “misgalletas” es una jarra vacía, como esta:

Imagen
Ya tenemos nuestra jarra vacía preparada para llenarla. Ahora tenemos que hacer saber a la petición, que se comunicará con el servidor, que tiene a su disposición una jarra donde puede guardar todas las cookies. Es decir, así:

Código: Seleccionar todo
peticion.CookieContainer = miscookies;


Ahora ya sabe petición donde tiene que meter las cookies que le mande el servidor. La petición añadirá las cookies a la jarra de esta manera:

Código: Seleccionar todo
misgalletas.Add(peticion.Cookies);


Ahora ya tenemos en la jarra las cookies que nos mando el Server al loguarnos, un dibujo resumen:

Imagen

Espero que aunque sea “bastante” malo se pueda entender xD Ahora ya sabemos (o eso espero) como se puede trabajar con las cookies.

Argumentos que puedes necesitar en una petición POST

En una petición POST aparte del header de la petición donde se encuentra el user-agent, content-lenght y demás hay a veces que el servidor necesita de argumentos para rellenar las variables. Aunque es algo bastante fácil haré un breve resumen de cómo se pueden obtener dichos argumentos. Ya que la idea es aprender el concepto y en cada servidor te puede pedir a rellenar variables distintas.

En este caso yo usaré mozilla firefox y el addon Tamper Data. El tamper lo podéis descargar de aquí:

https://addons.mozilla.org/en-US/firefox/addon/966

Este programa trabaja como un Proxy, es decir, estará entre el cliente (tu) y el servidor (la página) analizando el trafico http que haya y dando la posibilidad de modificar las cabeceras y los parámetros.

Para activar la herramienta (estando ya delante de su interfaz) le daremos a comenzar modificación y a partir de ahí en cada petición saliente nos dará 3 opciones; modificar, podremos cambiar los parámetros de envío, enviar, se enviará la petición por defecto y abortar petición.

Argumentos para la petición POST de logueo

Ahora necesitamos ponernos en la página de logueo del fotolog, es decir, esta:
[url=http://account.fotolog.com/login]
http://account.fotolog.com/login[/url]

Una vez ahí activaremos nuestro tamper data “Comenzar modificación”. No cal poner ningún valor de momento. Ahora nos saldrán las 3 opciones y le damos a modificar. Dejo una screen para que veáis los datos que tenemos que tener en cuenta:

Imagen

En verde tenemos el header de la petición, ahí de momento no nos sirve nada. En rojo tenemos los parámetros que tenemos que rellenar y como podemos observar estos son; redirect, u_name y p_word. Esto no hay que olvidar que son variables y que cuando hagamos la petición lo que realmente haremos será:

Código: Seleccionar todo
account.fotolog.com/login?redirect=&u_name=TUUSUARIO&p_word=TUPASSWORD


Esto lo digo porque después, al comenzar a escribir en C# los argumentos se escribirán de esa manera y lo que tendremos que hacer será formar una string con todo esto, por lo que no hay que olvidar el carácter “&” a partir de la segunda variable.

Argumentos para la petición POST para dejar un mensaje

Vamos a ver que argumentos tenemos que enviar junto con la petición. Dejaré ya directamente la screen del Tamper Data y pasaré a comentar un valor un tanto peculiar.

Imagen

Vemos que aquí los parámetros son; ajax, t y message. Deducimos que message es el mensaje ya que he escrito “e” en el formulario :P, ajax tiene el valor de true por lo que podemos pensar que será algo así como una “variable boolean” (aunque ya te digo que siempre será true). El parámetro que nos puede resultar algo mas confuso es “t”.

Te explicaré como he hecho yo para sacar el valor y deducir que es así no perdemos tanto tiempo.
Lo primero que hay que hacer es mirar el código fuente de la página. Para eso vamos a mirar cualquier fotolog y observamos en el form de posteo lo siguiente:

Código: Seleccionar todo
<form id="gb_post_form" action="/gb.post" method="POST">
        <input type="hidden" name="t" value="vPhoYDt86DsIcXowvUvEja2GF+XP55ahtn0jBTqBcny6DkbhDZtEhSmrxVbXlhb6tILleUf4Ezr6LD5IdJ4G3K+0duMa5PaMUanZpRXNWhO25cn2qgW/WjCiMyQQtQGRhme6">
        <h3>Deja un mensaje en el libro de visitas:</h3>
        <div id="counter">&darr; <var>1500</var> caracteres restantes</div>
        <textarea name="message" rows="8" cols="40" id="guestbookMessage">   
        </textarea>       
        <div id="message_limit" class="limit">Límite de 1500 caracteres</div>       
       <div style="margin-top: .4em;">               
       <button class="btSubmit0" type="submit">Dejar tuMensaje</button>               
        <img src="http://si.fotolog.com/i67/images/icon_ajax_bar.gif" id="gbAjaxIndicator">       
</div></form> 


Como podemos observar hay un valor oculto en este form y precisamente se llama “t”. También vemos (yo ya lo he hecho) que si vamos a un fotolog distinto y miramos, tendremos otro valor de “t”, por lo que deducimos que este valor se asocia al fotolog a postear ya que si no el servidor no sabría en cual queremos postear. Cal decir que este valor cambia bastante rápido por lo que necesitaremos sacarlo en el momento del posteo mediante expresiones regulares.

Creo que habiendo leído esto ya entenderemos el código y como trabaja un poco el servidor.

Resumen de lo que haremos

Creo que antes de ponernos a ver código hay que pensar y estructurar un poco como vamos hacer las cosas.

La idea principal es que el programa sea autónomo y él solo vaya navegando por el fotolog sin que nosotros tengamos que interferir. Para eso vamos a partir de un fotolog cualquiera y a partir de ahí mediante expresiones regulares sacaremos los amigos de este y haremos esto todo el rato.

Sé que estaréis pensando “¿Y si alguien no tiene amigos agregados?” (Si no lo pensabais ahora tenéis esa duda así que xD) Bien, si alguien no tiene amigos nosotros daremos al programa unos cuantos fotologs de reserva que primeramente habremos mirado que tengan bastantes amigos agregados y en el caso que no encuentre en el fotolog que este mirando pasaremos a usar esos de “reserva”.

Teniendo mas o menos una idea ya creo que podemos pasar a ver el código.

Ver código por funciones:

Vamos a ver la función de logueo:

Código: Seleccionar todo
static CookieContainer sesion(string user, string pass)
          {
              //PASAMOS LAS PROPIEDADES A VARIABLES
              HttpWebRequest peticion;
              HttpWebResponse respuesta=null;
              CookieContainer misgalletas = new CookieContainer();
 
              string url = "http://account.fotolog.com/login"; //Sitio donde enviaremos la petición.
              string argumentos = string.Format("redirect=" + user + "&u_name=" + user + "&p_word=" + pass); //Los argumentos
              byte[] encodearg = Encoding.ASCII.GetBytes(argumentos);//pasamos a bytes los argumentos
              peticion = (HttpWebRequest)WebRequest.Create(url);//Creamos la petición a la url que indiquemos arriba            peticion.Referer = "http://www.fotolog.com"; //Ponemos un refer de fotolog por poner algo xd
              peticion.UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; es-ES; rv:1.8.1.13) Gecko/20080311 Firefox/2.0.0.13"; //Le decimos al server que navegamos con el explorador Mozilla
              peticion.AllowAutoRedirect = true; //Permitimos que nos redirecione ATENCIÓN aquí puede cambiar según el sistema de logueo pero en este caso si no lo permites no te loguea
              peticion.CookieContainer = misgalletas; //Explicado
              peticion.Method = "POST"; //El metodo sera POST y no GET
              peticion.ProtocolVersion = HttpVersion.Version10; //Usaremos la version10
              peticion.ContentType = "application/x-www-form-urlencoded"; //Códificamos los datos a enviar, aquí tener cuídado según el servidor tmb
              peticion.ContentLength = encodearg.Length; //Calculamos el tamaño de los argumentos
 
              Stream canal = peticion.GetRequestStream();//Creamos un canal para el envio y recibo de datos con el servidor
              canal.Write(encodearg, 0, encodearg.Length); //Enviamos datos
              canal.Flush();
              canal.Close(); //Limpiamos y cerramos
 
              try //INTENTAMOS OBTENER RESPUESTA
              {
                  respuesta = (HttpWebResponse)peticion.GetResponse(); //Cogemos lo que nos ha enviado el servidor
              }
              catch (Exception ex) //EN EL CASO DE NO SER POSIBLE...
              {
                  Console.WriteLine(ex.Message); //DEVOLVEMOS EL MENSAGE DE ERROR
              }
 
              misgalletas.Add(respuesta.Cookies); //AGREGAMOS A LA "JARRA" LAS COOKIES GENERADAS
 
              respuesta.Close(); //Cerramos
              return misgalletas; //Devolvemos las cookies generadas
          }


El código esta comentado lo mejor que he podido, si hay alguna duda se pregunta y ya esta ;).

Ahora la función para sacar el valor de t:

Código: Seleccionar todo
static string t(string urls, CookieContainer miscookies)
          {
              HttpWebRequest hRequest = ((HttpWebRequest)WebRequest.Create("http://www.fotolog.com/"+urls));Creamos la petición al fotolog que nos pasaron como argumentos
              hRequest.CookieContainer = miscookies; //Utilizamos la misma jarra que cuando el logueo ;)
              hRequest.UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; es-ES; rv:1.8.1.13) Gecko/20080311 Firefox/2.0.0.13";
              StreamReader reader = new StreamReader(hRequest.GetResponse().GetResponseStream()); //El canal para mantener la comunicación con el servidor
              string devuelto = reader.ReadToEnd();//Aquí todo lo que nos ha respondido el servidor lo ponemos en un string
              reader.Close();
 
              try
              {
                  //Conseguimos el valor de t para saber donde postear y mantener la sessión
                  string str = devuelto;
                  int first = str.IndexOf("/gb.post");
                  first += 63;
                  int last = str.LastIndexOf("<h3>Leave a Guestbook Message:");
                  string str2 = str.Substring(first, last - first);
                  last = str2.LastIndexOf(">");
                  string td = str2.Substring(0, last - 1);
 
                  //Remplazar los caracteres especiales a hexadecimales
                  td = td.Replace("+", "%2B").ToString();
                  td = td.Replace("=", "%3D").ToString();
                  td = td.Replace("-", "%27").ToString();
                  td = td.Replace("/", "%2F").ToString();
 
                  return td;
              }catch{
                  return "NADA";
              }
          }


Voy a explicar la parte del código en la que se obtiene el valor:

Código: Seleccionar todo
                  string str = devuelto;
                  int first = str.IndexOf("/gb.post");
                  first += 63;
                  int last = str.LastIndexOf("<h3>Leave a Guestbook Message:");
                  string str2 = str.Substring(first, last - first);
                  last = str2.LastIndexOf(">");
                  string td = str2.Substring(0, last - 1);


Primero de todo en la variable int first conseguimos el número entero que se encuentra la cadena de caracteres “/gb.post”. Pongamos que se ha localizado en el número de carácter 200. Int last contiene tambien un valor de donde se encuentra la cadena <h3>Leave a Guestbook Message:
Pongamos en el ejemplo que se ha encontrado en el numero 100 ( ya que LastIndexOf indica que comience desde el último carácter).

Ahora en str2 lo que hacemos es pasar a string los caracteres que se encuentran entre el primer valor hasta el último. De esta manera obtenemos el valor de t. La otra comparación es para eliminar el carácter “>” que me salía, pero la idea es la misma.

Ahora la función de posteo:

Código: Seleccionar todo
static bool postear(string t, CookieContainer misgalletas, string msg, string name)
          {
              //PASAMOS LAS PROPIEDADES A VARIABLES
              HttpWebRequest peticion;
              HttpWebResponse respuesta;
 
              string url = "http://www.fotolog.com/gb.post"; //Sitio donde enviaremos la petición.
              string argumentos = string.Format("ajax=true&t="+t+"&message="+msg); //Los argumentos
              byte[] encodearg = Encoding.ASCII.GetBytes(argumentos);//pasamos a bytes los argumentos
              peticion = (HttpWebRequest)WebRequest.Create(url); //Creamos la petición a la url que indiquemos arriba
              peticion.Referer = "http://www.fotolog.com"; //Ponemos un refer de fotolog por poner algo xd
              peticion.UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; es-ES; rv:1.8.1.13) Gecko/20080311 Firefox/2.0.0.13"; //Le decimos al server que navegamos con el explorador Mozilla
              peticion.AllowAutoRedirect = true; //Permitimos que nos redirecione ATENCIÓN aquí puede cambiar según el sistema de logueo pero en este caso si no lo permites no te loguea
              peticion.CookieContainer = misgalletas; //Explicado
              peticion.Method = "POST"; //El metodo sera POST y no GET
              peticion.ProtocolVersion = HttpVersion.Version10; //Usaremos la version10
              peticion.ContentType = "application/x-www-form-urlencoded"; //Códificamos los datos a enviar, aquí tener cuídado según el servidor tmb
              peticion.ContentLength = encodearg.Length; //Calculamos el tamaño de los argumentos
 
              Stream canal = peticion.GetRequestStream(); //explicado
 
              canal.Write(encodearg, 0, encodearg.Length); //Enviamos datos
              canal.Flush();
              canal.Close(); //Limpiamos y cerramos
 
              try //INTENTAMOS OBTENER RESPUESTA
              {
                  respuesta = (HttpWebResponse)peticion.GetResponse(); //Explicado
                  string cojo = new StreamReader(respuesta.GetResponseStream()).ReadToEnd(); //Pasamos a la variable cojo la respuesta del servidor.
                  respuesta.Close(); //Cerramos
                  misgalletas.Add(respuesta.Cookies); //Aportamos las cookies en el caso que haya
                  return true;
              }
              catch
              {
                  return false;
              }
 
          }


Pasemos a obtener los fotologs amigos:

Código: Seleccionar todo
static string fotolog(string foto, string[] anterior)
{
              //CRAWLER
              HttpWebRequest hRequest = ((HttpWebRequest)WebRequest.Create("http://www.fotolog.com/"+foto+"/ff"));
              hRequest.UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; es-ES; rv:1.8.1.13) Gecko/20080311 Firefox/2.0.0.13";
              StreamReader reader = new StreamReader(hRequest.GetResponse().GetResponseStream());
              string devuelto = reader.ReadToEnd();
              reader.Close();
              string fotos="";
              bool existe=false;
              Regex r;
              //http://www.fotolog.com/
 
              r = new Regex(@"http://www.fotolog.com/\s*([^/]*)\s*>");
              //
              MatchCollection mc = r.Matches(devuelto);
              if (mc.Count > 0)
              {
                  foreach (Match m in mc)
                  {
                      //Console.WriteLine("{0}", m.Result("$1"));
                      string dato = m.Result("$1");
                      dato = dato.Replace("\"", "").ToString();
 
                      if (dato != foto&&dato!=foto+" class="+"goldcamera")
                      {
                          for (int i = 0; i<anterior.Length; i++)
                          {
                              if (dato != anterior[i])
                              {
                                  existe = false;
                              }
                              else
                              {
                                  existe = true;
                                  break;
                              }
                          }
                              if (!existe)
                              {
                                  fotos = dato;
                                  return dato;
                              }
                      }
                  }
              }
              return "hola";
          }


Aquí lo que hacemos es coger el código fuente de la página de amigos del fotolog que estemos viendo y mediante expresiones regulares buscamos coincidencias de las urls:
Código: Seleccionar todo
  r = new Regex(@"http://www.fotolog.com/\s*([^/]*)\s*>");
 
  MatchCollection mc = r.Matches(devuelto);


Luego observé que en los goldcamaras me cogía un valor que no era ningún fotolog por lo que hice una condición para que no cogiera ese valor ni tampoco los fotologs anteriores ( para no repetir):

Código: Seleccionar todo
if (dato != foto&&dato!=foto+" class="+"goldcamera")


Después devolvemos el valor que encontramos y listo.

Ahora pondré el código que nos dirá que nuestra fiesta de posteos se ha terminado :-(

Código: Seleccionar todo
static bool captcha(CookieContainer misgalletas, string name, string devuelto)
          {
              //AQUÍ NO HABRÁ NINGÚN PROBLEMA PARA ENTENDERLO...
              HttpWebRequest peticion = ((HttpWebRequest)WebRequest.Create("http://www.fotolog.com/" + name));
              peticion.CookieContainer = misgalletas;
              peticion.UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; es-ES; rv:1.8.1.13) Gecko/20080311 Firefox/2.0.0.13";
 
              try
              {
                  string str = devuelto;
                  int first = str.IndexOf("antibot");
                  first += 100;
                  int last = str.LastIndexOf("antibot_note");
                  last -= 279;
                  string td = str.Substring(first, last - first);
 
                  //Remplazar los caracteres especiales a hexadecimales
                  td = td.Replace("+", "%2B").ToString();
                  td = td.Replace("=", "%3D").ToString();
                  td = td.Replace("-", "%27").ToString();
                  td = td.Replace("/", "%2F").ToString();
                  return true;
              }
              catch
              {
                  return false;
 
              }
          }


Devuelve true si se ha detectado el captcha. Podría decir que sale aproximadamente cada 32 post luego si lo validas desde tu Explorer te da para unos 60 post más… aunque esto me ha variado ligeramente así que puedes activar vuestra imaginación para saltar esto, introducir el captcha cada vez que se detecte, ejecutar el programa con diferentes cuentas y poner un sleep mas grande entre cada post… no sé apañárosla ;)

El main quedaría de esta manera:

Código: Seleccionar todo
using System;
  using System.Collections.Generic;
  using System.Text;
  using System.IO;
  using System.Net;
  using System.Web;
  using System.Text.RegularExpressions;
  using System.Threading;
 
  namespace Fotolog
  {
      class Program
      {
          static void Main(string[] args)
          {
              string blog = args[3];
              bool stat;
              string td;
              string[] anterior;
              anterior = new string[30];
              int post = 0;
              CookieContainer cokies;
              string msg = args[2].Replace("-", " ").ToString();
 
              do
              {
                  Console.WriteLine("Logueando...");
                  cokies = sesion(args[0], args[1]);
              } while (cokies.Count <= 1);
              Console.WriteLine("Logueo exitoso... comenzando el proceso.");
              do
              {
                  Console.WriteLine();
                  Console.WriteLine("------------------------------------------------------------------");
                  Console.WriteLine("Buscando amigos en {0}.", blog);
 
                  if (blog == "")
                  {
                      td = t(args[2], cokies);
                      blog = td;
                  }
                  else
                  {
                      blog = fotolog(blog, anterior);
                      td = t(blog, cokies);
                  }
                  Console.WriteLine("Posteando en {0}.", blog);
 
                  if (postear(td, cokies, msg, args[0]))
                  {
                      post += 1;
                      Console.WriteLine("Post número {1}.Se ha posteado correctamente en {0}.", blog, post);
                      stat = true;
                      Thread.Sleep(20000);
                  }
                  else
                  {
                      Console.WriteLine("No se ha podido postear.");
                      stat = false;
                  }
              } while (stat);
 
              Console.WriteLine("Error en el programa, pusla cualquier tecla para salir.");
              Console.ReadLine();
          }


Bueno pues este es el código entero así que a partir de aquí os dejo solos en el camino entre tú y la imaginación.

Despedida:

Espero que os haya gustado el artículo tanto como a mí escribirlo :D y que almenos hayáis aprendido algo nuevo que de eso se trata. Un saludo y cualquier duda sobre el artículo podéis hacermela.

S4ludos!!!

Nork [NullBytes]
Última edición por Nork el Vie Ago 22, 2008 10:27 pm, editado 1 vez en total
La televisión me ha culturizado porque cada vez que la encienden en casa me voy a leer a mi cuarto.
Avatar de Usuario
Nork
<|:-)
<|:-)
 
Mensajes: 476
Registrado: Dom Feb 11, 2007 1:00 am
Ubicación: 2348,8574,7

Notapor deibix » Vie Ago 22, 2008 8:52 pm

Gracias Nork, me lo he leido y esta muy bien!!!

gracias por el aporte. A ver si encuentro tiempo y le meto mano :roll:
No hay laberinto del que no pueda escapar
deibix
:-D
:-D
 
Mensajes: 184
Registrado: Lun Ene 29, 2007 9:38 pm

Notapor Nork » Vie Ago 22, 2008 10:30 pm

deibix escribió:Gracias Nork, me lo he leido y esta muy bien!!!

gracias por el aporte. A ver si encuentro tiempo y le meto mano :roll:


Muchas gracias ;) He corregido las imágenes que no enlazaban con imageshack para verlas mas grandes :D
La televisión me ha culturizado porque cada vez que la encienden en casa me voy a leer a mi cuarto.
Avatar de Usuario
Nork
<|:-)
<|:-)
 
Mensajes: 476
Registrado: Dom Feb 11, 2007 1:00 am
Ubicación: 2348,8574,7


Volver a Faq

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 1 invitado

cron