Come costruire un bot?

martedì 02 dicembre 2008 - 14.04

kduhcm Profilo | Junior Member

Ciao ragazzi,
dovrei interfacciarmi a un sito web di cui conosco login e password, effettuare la login, entrare in una pagina per la ricerca, effettuare la ricerca e 'rubare' i risultati che dovrei utilizzare per un'altra elaborazione. Il problema e' che non ho mai fatto una cosa del genere e non so da dove cominciare. Ho liberta' di azione, potrei farla in asp.net oppure con una applicazione win32 in c sharp. Cosa mi consigliate? E come faccio a farla?

-----------------------------------------------------------------------------------------------------------------------
Sviluppo siti web Roma www.actasoftware.com

Anonimo Profilo | Senior Member

Fondamentalmente devi fare solo delle richieste HTTP e di parsarne la risposta. Puoi provare a sniffare il traffico tra il browser e il server (un' utility carina per farlo è Live HTTP Heaaders, un estensione di Firefox: https://addons.mozilla.org/en-US/firefox/addon/3829) e successivamente a ricreare le richieste attraverso la classe HttpWebRequest: http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.aspx.
Una volta che sei arrivato a scaricare la pagina che ti serve si tratta solo di parsarla per ottenere i dati.
Riccardo

kduhcm Profilo | Junior Member

Non ho capito molto... innanzitutto:

- Conviene fare un applicazione asp.net o win32 ?

- con quali comandi si possono catturare le pagine ?

- avresti qualche esempio di codice?

-----------------------------------------------------------------------------------------------------------------------
Sviluppo siti web Roma www.actasoftware.com

Anonimo Profilo | Senior Member

Non sò quali siano le tue esigenze, dal punto di vista implementativo è equivalente realizzare un applicazione winform o asp.net

Per il codice di esempio un po' specifico ci sarebbe da valutare un pochino come funziona il sito.
In generale per effettuare il login immagino tu debba mandare dei dati con il metodo post, trovi un esempio qui:
http://www.netomatix.com/httppostdata.aspx
mentre per fare una generica richiesta http e salvarne la risposta in un file il codice dovrebbe essere una cosa del genere:

HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://tuourl"); request.UserAgent = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)"; request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"; request.Headers.Add("Accept-Language", "it-it,it;q=0.8,en-us;q=0.5,en;q=0.3"); request.KeepAlive = true; request.Timeout = 2000; saveResponse(request.GetResponse().GetResponseStream(), "nomefile.ext"); private void saveResponse(Stream source, String filename) { FileStream target = new FileStream(filename, FileMode.Create); byte[] buffer = new byte[0x10000]; int bytes; try { while ((bytes = source.Read(buffer, 0, buffer.Length)) > 0) { target.Write(buffer, 0, bytes); } } finally { target.Flush(); target.Close(); } }
Riccardo

kduhcm Profilo | Junior Member

Ok, ho scelto un applicazione win32 cosi' non ho problemi di timeout. Riesco a catturare l'html ma non riesco a loggarmi in automatico mi dice che la user e la password sono errati. Da cosa dipende secondo te? (li ho omessi in questo codice)

private void btnGetPagina_Click(object sender, EventArgs e)
{
Uri url = new Uri("https://www.epc.bnl.it/login.asp");
WebRequest r = WebRequest.Create(url);
r.Method = "POST";
string postData = "nomeutente=xxxxxxxx&password=xxxxxxxxx";
byte[] data = Encoding.UTF8.GetBytes(postData);
r.ContentLength = data.Length;
r.ContentType = "application/x-www-form-urlencoded";
using (System.IO.Stream s = r.GetRequestStream())
{
s.Write(data, 0, data.Length);
}
string html = string.Empty;
using (WebResponse response = r.GetResponse())
{
using (Stream stream = response.GetResponseStream())
{
using (StreamReader sr = new StreamReader(stream))
{
html = sr.ReadToEnd();
txtHtml.Text = html;
}
}
}
}


-----------------------------------------------------------------------------------------------------------------------
Sviluppo siti web Roma www.actasoftware.com

Anonimo Profilo | Senior Member

Hai visto che la password la invia già criptata con SHA256?

Riccardo

kduhcm Profilo | Junior Member

Si, ho visto la pagina e lui cripta la password con SHA256 in questo modo con javascript prima di fare il post. Posso emulare la cosa dal bot ?
Esiste un comando del genere in c sharp?

...
<form method="post" action="login.asp" id="formpwd" name="formpwd"
onsubmit="javascript:calchash()">
<h3>Nome utente</h3>
<input type = "text" size="35" maxlength="35" name="nomeutente" />
<h3>Password</h3>
<input type="password" name="password" id="password" />
<input type="submit" value="Invia" id="submit1" name="submit1" /><input type="reset" value="Annulla" id="reset1" name="reset1" />
</form>
...
function calchash(){
var pwd = document.getElementById("password");
var h = -1;
var s = pwd.value;

if (s.length== 64) {
var v = new RegExp("[A-F0-9]");
var r= s.match(v);
h = r.index;
}
if (h!=0) {
pwd.value=SHA256(s.toUpperCase());
}
return true;
}
...

-----------------------------------------------------------------------------------------------------------------------
Sviluppo siti web Roma www.actasoftware.com

Anonimo Profilo | Senior Member

Ecco a te:

using System.Text; using System.Security.Cryptography; public static class PasswordHasher { private static SHA256Managed hasher = new SHA256Managed(); public static string Hash(string password) { UTF8Encoding utf8 = new UTF8Encoding(); byte[] passwordBytes = utf8.GetBytes(password.ToUpper()); byte[] passwordHash = hasher.ComputeHash(passwordBytes); return toHexString(passwordHash); } public static string toHexString(byte[] a) { StringBuilder sb = new StringBuilder(a.Length * 2); foreach (byte b in a) { sb.AppendFormat("{0:X2}", b); } return sb.ToString(); } }

Ti basta fare

String passwordCriptata = PasswordHasher.Hash("password");
Riccardo

kduhcm Profilo | Junior Member

ok, grazie :-)))
Pero' ho un altro problema. Una volta effettuato il login il mio bot dovrebbe navigare per il sito per prendere delle informazioni. La pagina di login
pero' ha impostato delle variabili session. A questo punto come faccio a navigare per il sito senza venir reindirizzato alla maschera di login?

-----------------------------------------------------------------------------------------------------------------------
Sviluppo siti web Roma www.actasoftware.com

Anonimo Profilo | Senior Member

Probabilmente è un problema di cookie, dai un occhio a questo link, c'è un esempio di codice che li gestisce:
http://blog.strikefish.com/blog/index.cfm?mode=entry&entry=FE7C55D8-1422-201A-559B1E6213899E41

Ciao ciao!
Riccardo

kduhcm Profilo | Junior Member

Bello questo tips che mi hai segnalato, sei gentilissimo... Ora sono riuscito fare la login col mio bot.

dimmi solo un'ultima cosa:

Il sito non utilizza i cookie per tener traccia di user e password di login (ho messo sotto debug la pagina c sharp e non ne trova), quindi tiene traccia della
user di login con delle variabili session. Che tu sappia, e' possibile continuare la navigazione tra le pagine se la pagina si aspetta una variabile session
impostata?
Posso simulare la variabile session in qualche modo o la cosa o e' impossibile?

-----------------------------------------------------------------------------------------------------------------------
Sviluppo siti web Roma www.actasoftware.com

Anonimo Profilo | Senior Member

Ti consiglio di provare a navigare il sito con Mozilla e di attivare l'addon live http headers, scoprirai sicuramente qualche cosa di interessante
Se la sessione viene tenuta su server non dovresti avere problemi ma di soltio vengono usati anche cookies.
Sul quel sito, pur sbagliando password mi ha settato un cookie: ASPSESSIONIDSQBQCCSB=LMNLLFBDMLIMJPLKJOJJKIMB percui presumo che li setti anche a login effettuato.

Riccardo

kduhcm Profilo | Junior Member

Installato! Hai ragione, si vedono cose interessanti. Mi sono loggato ed ecco qui: come immaginavo usa una variabile SESSION
di nome codutente. Per andare alla pagina elenprat.aspx credo che dovrei impostargliela in qualche modo... Se ci provo mi rispedisce alla login.asp

https://www.epc.bnl.it/elenprat.asp

GET /elenprat.asp HTTP/1.1
Host: www.epc.bnl.it
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; it; rv:1.8.1.14) Gecko/20080404 Firefox/2.0.0.14
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language: it-it,it;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Referer: https://www.epc.bnl.it/menu.asp
Cookie: ASPSESSIONIDSQBQCCSB=ANNLLFBDIMOIGFLHFCJCMADK; ASPSESSION=codutente=939

HTTP/1.x 200 OK
Connection: Keep-Alive
Content-Length: 5613
Expires: Wed, 03 Dec 2008 21:43:15 GMT
Date: Wed, 03 Dec 2008 21:43:15 GMT
Content-Type: text/html
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
Cache-Control: private


-----------------------------------------------------------------------------------------------------------------------
Sviluppo siti web Roma www.actasoftware.com

Anonimo Profilo | Senior Member

Ti conviene ricreare perfettamente l'header come lo vedi, compreso il referrer, io una volta sono diventato pazzo per quello.
Per i cookie prova questo codice:

Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra

la classe netutils invece è una cosa del genere:

class NetUtils { [DllImport("wininet.dll", SetLastError = true)] public static extern bool InternetGetCookie( string url, string cookieName, StringBuilder cookieData, ref int size); public static CookieContainer GetUriCookieContainer(Uri uri) { CookieContainer cookies = null; int datasize = 256; StringBuilder cookieData = new StringBuilder(datasize); if (!InternetGetCookie(uri.ToString(), null, cookieData, ref datasize)) { if (datasize < 0) return null; cookieData = new StringBuilder(datasize); if (!InternetGetCookie(uri.ToString(), null, cookieData, ref datasize)) return null; } if (cookieData.Length > 0) { cookies = new CookieContainer(); cookies.SetCookies(uri, cookieData.ToString().Replace(';', ',')); } return cookies; } }
Riccardo

kduhcm Profilo | Junior Member

Io utilizzo questo (vedi codice)... mi fa la login e mi entra... Mi propone l'html della pagina successiva che e' divisa in 3 frame (mi propone quella del frame principale). Dopo di che rifaccio la stessa richiesta cambiando solo l'url della pagina richiesta ma mi re-indirizza nella pagina di login... come devo fare la seconda richiesta? I cookie li gestisco con la foreach... ma poi? Dici che devo riproporre lo stesso http header visualizzato con l'addons live http che ti ho mostrato nel post precedente, ma come si fa?

String url = "https://www.epc.bnl.it/login.asp";
//String strPost = ConfigurationSettings.AppSettings["LoginPassword"];
string pwd = "8B54B05E87446E386D2069B47DB6DAF9F1B600C0FFA0AD7841635F213D64D91C";

string strPost = "nomeutente=xxxxxxxxxxx&password=" + pwd;

StreamWriter myWriter = null;
CookieContainer myContainer = new CookieContainer();

//Request #1 (the login)
HttpWebRequest objRequest = (HttpWebRequest)WebRequest.Create(url);
objRequest.Method = "POST";
objRequest.ContentLength = strPost.Length;
objRequest.ContentType = "application/x-www-form-urlencoded";
objRequest.CookieContainer = new CookieContainer();

try
{
myWriter = new StreamWriter(objRequest.GetRequestStream());
myWriter.Write(strPost);
}
catch (Exception ee)
{
Console.WriteLine(ee.Message);
}
finally
{
myWriter.Close();
}

HttpWebResponse objResponse = (HttpWebResponse)objRequest.GetResponse();
//retain the cookies
foreach (Cookie cook in objResponse.Cookies)
{
myContainer.Add(cook);
}

//Check out the html.
using (StreamReader sr =
new StreamReader(objResponse.GetResponseStream()))
{
String test = sr.ReadToEnd();
txtHtml.Text = test;
// Close and clean up the StreamReader
sr.Close();
}

-----------------------------------------------------------------------------------------------------------------------
Sviluppo siti web Roma www.actasoftware.com

Giuseppe75 Profilo | Newbie

Ciao Anonimo, per prima cosa mi sento in obbligo di ringraziarvi per le informazini tratte da questo sito.
Ora ho letto i post di kduhcm, e vorrei un aiuto anche per me.
Ho bisogno di prendere delle informazioni da diversi siti, sempre con autorizzazione da parte del richiedente, e duplicale le info anche nel mio sito.
Potresti darmi una mano?
Grazie 1000
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2024
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5