Hallo e*pvpler,
heute möchte ich euch in einem Tutorial zeigen, wie ihr einen Browsergamebot erstellen könnt. Diese Methode wird nicht bei allen Browsergames klappen, jedoch wird sie bei vielen funktionieren. Als Beispiel nehme ich hier neopets.com.
•1. Start - Projekt erstellen/Vorbereitung
Ihr erstellt ein neues Projekt - ich nehme den Namen "BrowsergameTutorial" - und wählt eine normale Windowsanwendung. Natürlich könnte man es auch in einem Konsolenfenster realisieren, aber wir wollen eine nette GUI haben, mit der wir die Bot-User ansprechen. Nachdem ihr eure Form habt, stellt eure Eigenschaften so ein, wie ihr sie standardmäßig einstellt.
Um die Vorbereitungen abzuschließen sollten wir wissen, wie wir uns standardmäßig einloggen. Deshalb benutze ich das Browser-Plugin [Only registered and activated users can see links. Click Here To Register...].
Wir starten also Live HTTP Headers & stellen sicher, dass der Haken bei "Mitschneiden" sitzt. Wir öffnen einen neuen Tab von unserem Game - in meinem Fall neopets.com und loggen uns ein. Wir switchen wieder rüber auf unser LiveHTTPHeaders und haben folgenden Screen :
Uns interessieren diese Zeilen besonders :
•2. Die Klasse httpRequest
Wir wissen also, dass der obige Code gesendet wird. Das werden wir nun auch mit unserem Programm simulieren. Aber wie? Natürlich machen wir das mit einem HttpWebRequest, bzw. -response. Ich werde nicht genau erklären was welcher Code genau macht, darum bitte ich euch darum euch etwas in HttpWebRequest einzulesen. Falls es euch schon bekannt ist, dann könnt ihr gerne weiterlesen.
Wir erstellen also eine neue Klasse, ich nenne sie mal httpRequest. In dieser Klasse werden wir einige Funktionen erstellen, sodass es uns nachher leichter fällt weitere Aktionen auszuführen.
Wir importieren die bereits vorhandenen Namespaces System.IO,System.Text & System.Net. In der Klasse erstellen wir nun ein paar Variablen, um uns das Leben im späteren Verlauf einfacher zu machen. Wir brauchen eine Variable für den WebRequest, eine weitere Variable für den WebResponse um eine Antwort des Servers zu empfangen und eine letzte Variable für die Cookies, welche gesendet als auch empfangen werden. Somit sollte unsere Klasse bisher so aussehen :
Nun sollten wir eine Funktion schreiben, mit der wir eine Antwort, also Response, von dem Server bekommen. Diese Funktion soll im ganzen Projekt benutzt werden dürfen, also erstellen wir sie als Public. Der Parameter sollte die URL übergeben, die weiter benutzt wird.
Die vom request.CookieContainer empfangenen Cookies sollen in unserer Variable cookies gespeichert werden. Unsere request Variable erhält den Wert von CType. In der expression des CTypes erstellen wir einen neuen Webrequest mit dem Parameter - der URL. Der Typname des CTypes wird ein HttpWebRequest sein. Das gleiche erstellen wir nun auch für unsere response Variable, mit dem Unterschied, dass wir in der expression einen GetResponse haben & im Typnamen einen HttpWebResponse. Den Response wollen wir natürlich auch zurückgeben, also schreiben wir für den Return einen neuen Streamreader, der die empfangenen Daten ausliest und als String zurückgibt. Somit schaut unsere Funktion ungefähr so aus :
Nun haben wir das gleiche Spielchen nocheinmal, bloß dass wir noch ein Post als String hinterher hängen. Die Variablenzuweisung request = CType(HttpWebRequest.Create(url), HttpWebRequest) und request.CookieContainer = cookies können wir in unserer neuen Funktion oben stehen lassen. Um ein möglichst echten Post zu simulieren benötigen wir viele Infos aus unserem Live HTTP Headers. Oben im Bild seht ihr z.B Referer, User-Agents und Accepted-Language, welche wir alle simulieren wollen. Also fangen wir mit den UserAgents an. Einfach eine Zuweisung mit euren UserAgents als String für request.UserAgents erstellen. Falls ihr eure nicht nehmen wollt könnt ihr euch [Only registered and activated users can see links. Click Here To Register...] eine heraussuchen.
Die Methode ist in diesem Fall Post, also -> request.Method = "POST". Der Content-Typ ist bei fast (!) allen Games "application/x-www-form-urlencoded", also nehmen wir auch den mit. Nun brauchen wir die Accept-Language. Aber warte mal - es gibt keine Eigenschaft hierfür. Also müssen wir uns eben einen neuen Header erstellen. Um einen neuen Header hinzuzufügen erstellen wir eine neue Variable als WebHeaderCollection mit dem Wert der Header, also request.Headers. Dieser Variable fügen wir mit Add einen neuen Wert hinzu - in unserem Fall, wie man oben sieht - "Accept-Language: de-de,de;q=0.8,en-us;q=0.5,en;q=0.3".
Unsere bisherige Funktion sieht so aus :
Wir schauen wieder auf unseren Live Http Header und sehen Content-Lenght. Das sind die Bytes die gesendet werden, also brauchen wir ein ArrayByteals Byte. In das Array schreiben wir den Byte-Wert von unserem post, welchen wir mit der Encoding.Default.GetBytes ermitteln können. Das würde so aussehen :
Um den POST letztendlich zu verschicken brauchen wir einen Streamwriter, der es uns ermöglicht unsere Bytes zu versenden. Logisch, was?
In der Write-Funktion schreiben wir für den Buffer unseren ArrayByte, als Offset 0, da wir diesen in diesem Beispiel nicht brauchen & als Count geben wir die Länge unserer Bytes mit ArrayByte.Length an. Zuletzt übergeben wir der Responsevariable - wie oben auch - den Response wert und lesen es - wie oben auch - mit einem StreamReader aus.
Unsere komplette Klasse sieht also so aus :
•3. Der Login
Da wir nun unsere Klasse geschrieben haben können wir uns an den Login machen. Ich habe dafür einen Button & zwei Textboxen erstellt. Einmale eine userBox für den Namen & einmal eine passwortBox für - wer hätte es gedacht - das Passwort. kommen wir nun zum Code. Wie in der httpRequest-Klasse brauchen wir auch hier den Import von System.Text, System.IO & System.Net. Nun widmen wir uns der Sub des Buttons. Dieser soll, wenn die Textbox des Users und die des Passworts beide über 3 Zeichen haben versuchen sich anzumelden.
Um es einwenig übersichtlicher zu gestalten füge ich am Anfang eine Variable namens quell als String für den Quelltext ein. Über unserer Sub erstellen wir einen Objektverweis auf unsere Klasse. Ich habe ihn htrequest genannt. Diesen brauchen wir da der Member sonst nicht freigegeben wird.
Nun weisen wir der quell Variable die Funktion GetResponse von unserer Klasse HttpRequest zu. Als ersten Parameter benutzen wir die oberste Zeile unseres Live-HTTP-Headers - login.phtml - und als zweiten Paramter den String, den wir vorhin erforscht haben. Wo unser Name und Passwort steht, hauen wir einfach den Text unserer Textboxen hinein.
Mit dieser Funktion versucht er sich jetzt einzuloggen.
Danach ruft er nocheinmal die Hauptseite auf, da - wenn ich eingeloggt bin - dort etwas steht, was - wenn ich nicht eingeloggt bin - nicht da steht. Das nutzen wir aus und suchen nach dem Wert. Wenn er vorhanden ist sind wir drinnen, wenn nicht - eben nicht. So sieht dann unser Code in der LoginForm aus :
•4. Beispiel
Da wir jetzt wissen, wie es funktioniert kann man als Beispiel z.B die Neopunkte abrufen. Wir wechseln mit quell = htrequest.GetResponse("http://www.neopets.com/") auf die Hauptseite und sehen oben "Willkommen,NAME | NP: Neopuntke". Im Quelltext der Seite kann man erkennen, dass sich hinter Neopunkte ein Link ins Inventar verbirgt. Also nehmen wir uns jetzt RegEx zur Hand um den Abschnitt der Neopunkte zu suchen & herauszuschneiden. Ich werde RegEx nicht erklären, es gibt auf e*pvp, sowie auf anderen VB-Foren genug RegEx Tutorials.
Das folgende RegEx-Pattern sucht nach dem Link inventory.phtml und schneidet mit *.? die Neopunkte heraus. Mit sehr unsauberem Substring & Remove entfernen wir sind unnötigen Zeichen und haben unsere Neopunkte:
Mit diesem Bot kann man durch RegEx alles realisieren. Bei dem Spiel Kartoffelzähler können z.B die Bilder aus dem Quelltext gefiltert werden, diese gezählt werden und durch einen weiteren Post an den Server zurückgesendet werden. Dies ist eine Grundlage auf die man sehr viel aufbauen kann.
•5. Schlusswort
Ich bedanke mich erst einmal dafür, dass du dir die Mühe gemacht hast diesen Thread hier zu lesen & hoffe dass du etwas gelernt hast. Hast du Fragen oder Verbesserungsvorschläge bitte ich dich, diese in den Thread zu schreiben, sodass ich etwas ausbessern kann - oder die helfen kann.
Viel Spaß beim programmieren. (:
~Greetings
.Zeraki'
heute möchte ich euch in einem Tutorial zeigen, wie ihr einen Browsergamebot erstellen könnt. Diese Methode wird nicht bei allen Browsergames klappen, jedoch wird sie bei vielen funktionieren. Als Beispiel nehme ich hier neopets.com.
•1. Start - Projekt erstellen/Vorbereitung
Ihr erstellt ein neues Projekt - ich nehme den Namen "BrowsergameTutorial" - und wählt eine normale Windowsanwendung. Natürlich könnte man es auch in einem Konsolenfenster realisieren, aber wir wollen eine nette GUI haben, mit der wir die Bot-User ansprechen. Nachdem ihr eure Form habt, stellt eure Eigenschaften so ein, wie ihr sie standardmäßig einstellt.
Um die Vorbereitungen abzuschließen sollten wir wissen, wie wir uns standardmäßig einloggen. Deshalb benutze ich das Browser-Plugin [Only registered and activated users can see links. Click Here To Register...].
Wir starten also Live HTTP Headers & stellen sicher, dass der Haken bei "Mitschneiden" sitzt. Wir öffnen einen neuen Tab von unserem Game - in meinem Fall neopets.com und loggen uns ein. Wir switchen wieder rüber auf unser LiveHTTPHeaders und haben folgenden Screen :
Uns interessieren diese Zeilen besonders :
Code:
Content-Length: 68 destination=%252Findex.phtml&username=[I]NAME[/I]&password=[I]PASSWORT[/I]
Wir wissen also, dass der obige Code gesendet wird. Das werden wir nun auch mit unserem Programm simulieren. Aber wie? Natürlich machen wir das mit einem HttpWebRequest, bzw. -response. Ich werde nicht genau erklären was welcher Code genau macht, darum bitte ich euch darum euch etwas in HttpWebRequest einzulesen. Falls es euch schon bekannt ist, dann könnt ihr gerne weiterlesen.
Wir erstellen also eine neue Klasse, ich nenne sie mal httpRequest. In dieser Klasse werden wir einige Funktionen erstellen, sodass es uns nachher leichter fällt weitere Aktionen auszuführen.
Wir importieren die bereits vorhandenen Namespaces System.IO,System.Text & System.Net. In der Klasse erstellen wir nun ein paar Variablen, um uns das Leben im späteren Verlauf einfacher zu machen. Wir brauchen eine Variable für den WebRequest, eine weitere Variable für den WebResponse um eine Antwort des Servers zu empfangen und eine letzte Variable für die Cookies, welche gesendet als auch empfangen werden. Somit sollte unsere Klasse bisher so aussehen :
PHP Code:
Imports System.IO, System.Text, System.Net
Public Class HttpRequest
Dim request As HttpWebRequest
Dim cookies As New CookieContainer
Dim response As HttpWebResponse
End Class
Die vom request.CookieContainer empfangenen Cookies sollen in unserer Variable cookies gespeichert werden. Unsere request Variable erhält den Wert von CType. In der expression des CTypes erstellen wir einen neuen Webrequest mit dem Parameter - der URL. Der Typname des CTypes wird ein HttpWebRequest sein. Das gleiche erstellen wir nun auch für unsere response Variable, mit dem Unterschied, dass wir in der expression einen GetResponse haben & im Typnamen einen HttpWebResponse. Den Response wollen wir natürlich auch zurückgeben, also schreiben wir für den Return einen neuen Streamreader, der die empfangenen Daten ausliest und als String zurückgibt. Somit schaut unsere Funktion ungefähr so aus :
PHP Code:
Public Function ResponseWeb(ByVal url As String) As String
request = CType(HttpWebRequest.Create(url), HttpWebRequest)
response = CType(request.GetResponse(), HttpWebResponse)
request.CookieContainer = cookies
Return New StreamReader(response.GetResponseStream()).ReadToEnd()
End Function
Die Methode ist in diesem Fall Post, also -> request.Method = "POST". Der Content-Typ ist bei fast (!) allen Games "application/x-www-form-urlencoded", also nehmen wir auch den mit. Nun brauchen wir die Accept-Language. Aber warte mal - es gibt keine Eigenschaft hierfür. Also müssen wir uns eben einen neuen Header erstellen. Um einen neuen Header hinzuzufügen erstellen wir eine neue Variable als WebHeaderCollection mit dem Wert der Header, also request.Headers. Dieser Variable fügen wir mit Add einen neuen Wert hinzu - in unserem Fall, wie man oben sieht - "Accept-Language: de-de,de;q=0.8,en-us;q=0.5,en;q=0.3".
Unsere bisherige Funktion sieht so aus :
PHP Code:
Public Function GetResponse(ByVal url As String, ByVal post As String) As String
request = CType(HttpWebRequest.Create(url), HttpWebRequest)
request.CookieContainer = cookies
request.Method = "POST"
request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; rv:8.0) Gecko/20100101 Firefox/8.0"
request.ContentType = "application/x-www-form-urlencoded"
Dim NeueHeaderColl As WebHeaderCollection = request.Headers
NeueHeaderColl.Add("Accept-Language: de-de,de;q=0.8,en-us;q=0.5,en;q=0.3")
End Function
PHP Code:
Dim ArrayByte() As Byte = Encoding.Default.GetBytes(post)
request.ContentLength = ArrayByte.Length
In der Write-Funktion schreiben wir für den Buffer unseren ArrayByte, als Offset 0, da wir diesen in diesem Beispiel nicht brauchen & als Count geben wir die Länge unserer Bytes mit ArrayByte.Length an. Zuletzt übergeben wir der Responsevariable - wie oben auch - den Response wert und lesen es - wie oben auch - mit einem StreamReader aus.
Unsere komplette Klasse sieht also so aus :
PHP Code:
Imports System.IO, System.Text, System.Net
Public Class HttpRequest
Dim cookies As New CookieContainer
Dim request As HttpWebRequest
Dim response As HttpWebResponse
Public Function GetResponse(ByVal url As String) As String
request = CType(HttpWebRequest.Create(url), HttpWebRequest)
response = CType(request.GetResponse(), HttpWebResponse)
request.CookieContainer = cookies
Return New StreamReader(response.GetResponseStream()).ReadToEnd()
End Function
Public Function GetResponse(ByVal url As String, ByVal post As String) As String
request = CType(HttpWebRequest.Create(url), HttpWebRequest)
request.CookieContainer = cookies
request.Method = "POST"
request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; rv:8.0) Gecko/20100101 Firefox/8.0"
request.ContentType = "application/x-www-form-urlencoded"
Dim NeueHeaderColl As WebHeaderCollection = request.Headers
NeueHeaderColl.Add("Accept-Language: de-de,de;q=0.8,en-us;q=0.5,en;q=0.3")
Dim ArrayByte() As Byte = Encoding.Default.GetBytes(post)
request.ContentLength = ArrayByte.Length
Dim daten As Stream = request.GetRequestStream()
daten.Write(ArrayByte, 0, ArrayByte.Length)
response = CType(request.GetResponse(), HttpWebResponse)
Return New StreamReader(response.GetResponseStream()).ReadToEnd()
End Function
End Class
Da wir nun unsere Klasse geschrieben haben können wir uns an den Login machen. Ich habe dafür einen Button & zwei Textboxen erstellt. Einmale eine userBox für den Namen & einmal eine passwortBox für - wer hätte es gedacht - das Passwort. kommen wir nun zum Code. Wie in der httpRequest-Klasse brauchen wir auch hier den Import von System.Text, System.IO & System.Net. Nun widmen wir uns der Sub des Buttons. Dieser soll, wenn die Textbox des Users und die des Passworts beide über 3 Zeichen haben versuchen sich anzumelden.
PHP Code:
If loginBox.Text.Length < 3 Then
MsgBox("Du hast entweder kein oder zuwenige Zeichen beim Login eingegeben!")
Else
If pwBox.Text.Length < 3 Then
MsgBox("Du hast entweder kein oder zuwenige Zeichen beim Passwort eingegeben!")
Else
'hier einloggen
End If
End If
Nun weisen wir der quell Variable die Funktion GetResponse von unserer Klasse HttpRequest zu. Als ersten Parameter benutzen wir die oberste Zeile unseres Live-HTTP-Headers - login.phtml - und als zweiten Paramter den String, den wir vorhin erforscht haben. Wo unser Name und Passwort steht, hauen wir einfach den Text unserer Textboxen hinein.
Mit dieser Funktion versucht er sich jetzt einzuloggen.
Danach ruft er nocheinmal die Hauptseite auf, da - wenn ich eingeloggt bin - dort etwas steht, was - wenn ich nicht eingeloggt bin - nicht da steht. Das nutzen wir aus und suchen nach dem Wert. Wenn er vorhanden ist sind wir drinnen, wenn nicht - eben nicht. So sieht dann unser Code in der LoginForm aus :
PHP Code:
Public Class Form1
Dim htrequest As HttpRequest
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim quell As String
If userBox.Text.Length < 3 Then
MsgBox("Du hast entweder kein oder zuwenige Zeichen beim Login eingegeben!")
Else
If passwortBox.Text.Length < 3 Then
MsgBox("Du hast entweder kein oder zuwenige Zeichen beim Passwort eingegeben!")
Else
quell = htrequest.GetResponse("http://www.neopets.com/login.phtml", "destination=%252F&username=" & userBox.Text & "&password=" & passwortBox.Text)
quell = htrequest.GetResponse("http://www.neopets.com/")
If quell.Contains("Willkommen,") Then
MsgBox("Yeah wir sind drinnen!")
Else
MsgBox("lul no. :(")
End If
End If
End If
End Sub
End Class
Da wir jetzt wissen, wie es funktioniert kann man als Beispiel z.B die Neopunkte abrufen. Wir wechseln mit quell = htrequest.GetResponse("http://www.neopets.com/") auf die Hauptseite und sehen oben "Willkommen,NAME | NP: Neopuntke". Im Quelltext der Seite kann man erkennen, dass sich hinter Neopunkte ein Link ins Inventar verbirgt. Also nehmen wir uns jetzt RegEx zur Hand um den Abschnitt der Neopunkte zu suchen & herauszuschneiden. Ich werde RegEx nicht erklären, es gibt auf e*pvp, sowie auf anderen VB-Foren genug RegEx Tutorials.
Das folgende RegEx-Pattern sucht nach dem Link inventory.phtml und schneidet mit *.? die Neopunkte heraus. Mit sehr unsauberem Substring & Remove entfernen wir sind unnötigen Zeichen und haben unsere Neopunkte:
PHP Code:
Dim r As Regex = New Regex("<a\sid\=\'npanchor\'\shref\=\""\/inventory\.phtml\""\>.*?</a>")
Dim m As Match = r.Match(quell)
Dim cleantxt As String
If m.Success Then
Dim g = m.Groups(0)
cleantxt = g.ToString
cleantxt = cleantxt.Substring(41)
cleantxt = cleantxt.Remove(1, 4)
Label1.Text = cleantxt
End If
•5. Schlusswort
Ich bedanke mich erst einmal dafür, dass du dir die Mühe gemacht hast diesen Thread hier zu lesen & hoffe dass du etwas gelernt hast. Hast du Fragen oder Verbesserungsvorschläge bitte ich dich, diese in den Thread zu schreiben, sodass ich etwas ausbessern kann - oder die helfen kann.
Viel Spaß beim programmieren. (:
~Greetings
.Zeraki'