TCP-/HTTP- Pakete NUR empfangen

03/06/2012 16:41 BotofWar#1
Hi zusammen,

also wie oben angedeutet versuche ich ein kleines Proggi zu schreiben was den Datenverkehr protokolliert, bzw bestimmte Werte erkennt wenn ich manuell ein Browsergame spiele. Mein Problem ist im Moment das ich nicht weiss wie ich einen bereits bestehenden Socket erkennen und "anzapfen" kann. Irgendwie muss das ja gehn, sonst würden z.b. Wireshark oder so proggis das ja auch nicht lesen können.
Soll hinterher etwa so aussehen:

Hotkey blabla (Start);
"abhören" solange bis ein Paket mit gesuchtem Wert von bestimmter IP empfangen wird;
bestimmten wert erkennen;
wert irgendwo hin übergeben;
exit

bin für jeden Gedankenansatz dankbar.
03/07/2012 17:39 Crack-wtf#2
Naja für gewöhnlich macht man bei solchen sachen folgendes.
Man schreibt in die Hosts datei den host, und leitet ihn auf 127.0.0.1 um.

Dabei werden aber eingehende UND ausgehende packete umgeleitet.

Für deine zwecke solltest du mal nach "autoit sniffer" oder so googeln.
Dann bekommst du zwar alle packete, die über deine Leitung laufen, aber mit einem anständigen filter sollte das kein Problem sein.
(z.B. immer den entsprechenden host filtern.)
03/07/2012 17:54 Lawliet#3
Mit "Winpcap" sollte das ziemlich einfach gehen ;)
03/08/2012 11:20 BotofWar#4
Puh... ich merk grad das ich mich hier scheinbar in ein Thema begebe an dem sich schon viele andere die Zähne ausgebissen haben.
Hostsdatei? Umleiten? Verbinden von Winpcap mit AI????
Oh mann... ich bin zwar mittlerweile echt gut mit Pixel- und Memory-Bots, aber das hängt mir alles noch n bissel zu hoch.
Ich glaube ich gebe das Thema vorläufig erstmal auf.
Aber falls doch irgend jemand vielleicht irgendwelche Codeschnipsel oder sowas zum klauen und rumprobieren hat würden ich und viele andere uns sehr freuen.
Danke schonmal für die erhaltenen Antworten.

Edit: Ah... so langsam komme ich hinter die Geschichte mit Winpcap... Ich bleib dran.
03/08/2012 15:25 Lawliet#5
Such mal über Google dieses Tutorial:
"[TUT]Paket Bot Teil 1: Packet Sniffing"
03/08/2012 18:11 BotofWar#6
Ja, hatte ich auch schon gefunden, allerdings ist das grössten teils für Gäste unsichtbar. Meinst Du der Beitrag ist so ausführlich und informativ dass es sich lohnt sich anzumelden?
03/08/2012 19:52 Lawliet#7
Klar, anmelden kostet ja nichts ;)
03/09/2012 18:36 BotofWar#8
Huhu...
Also erstmal ein dickes THX für die Winpcap-Sache....
Wenn man sich da erstmal eingelesen hat ist es ja doch schon recht simpel.
Habe soweit auch schon die ersten Erfolge erzielen können.
Allerdings hänge ich jetzt an der sache das empfangene Paket ordentlich zu splitten.
Problem ist hier:
Code:
  $sniff = sniff($packet[3])
  
  $Hauptinfo=StringMid($sniff, StringInStr($sniff, "{"))
  $HauptinfoCut=StringReplace($Hauptinfo, '"', "")
  $Itemarray=StringSplit($HauptinfoCut,",")
  
  $Speed= StringMid($Itemarray[3], StringInStr($Itemarray[3], ':'))	

  If $sniff <> False Then MsgBox(16,"Paket",$sniff & @CRLF & @CRLF & $Itemarray[0]& @CRLF & $Itemarray[1]& @CRLF & $Itemarray[2]& @CRLF & $Itemarray[3]& @CRLF & $Itemarray[$Itemarray[0]-1] & @CRLF & $Speed )
Ich will lediglich den in $Itemarray[3] enthaltenen Text am Doppelpunkt trennen und dadurch ein eigenes Array erstellen.
Einen Gültigen Wert hat das erste Array nachweislich erstellt da dieser Wert in der MSGBox (noch ungesplittet) dargestellt wird.

Was mache ich hier falsch?

Fehlermeldung:
Sniffer.au3 (59) : ==> Array variable has incorrect number of subscripts or subscript dimension range exceeded.:
$Speed= StringMid($Itemarray[3], StringInStr($Itemarray[3], ':'))
$Speed= StringMid(^ ERROR
03/09/2012 22:57 Lawliet#9
StringSplit gibt ein Array mit 3 Feldern zurück, also [0], [1] und [2]. Das ist dein Fehler.
Außerdem solltest du mit "If isArray" arbeiten, damit bei Fehlern nicht dein Script abstürzt.
03/10/2012 00:39 BotofWar#10
Wie kommst Du darauf?
Eigentlich müssten es wesentlich mehr sein. [0] hat mir z.B. 49 ausgegeben.
Und in der MsgBox funzt [3] auch.
03/10/2012 12:45 Lawliet#11
Achso, da hab ich was verwechselt. Kannst du mich mal in Skype oder Icq adden. Wenn ich das ganze Script hab, finde ich sicher schnell den Fehler.
03/18/2012 15:40 BotofWar#12
Hi zusammen,

nach den vorangegangenen hilfreichen Antworten hab ich mir die entsprechenden Schnipsel zusammengesucht und ein halbwegs brauchbares Skript erstellt.
Allerdings gibt es noch ein Problem mit dem ich absolut nicht zurecht komme.
In dem Skript wird ein TCP-Paket empfangen und ausgewertet.
Das funktioniert soweit perfekt.
Problematisch wird es jetzt wenn die HTTP-Sequenz aus mehreren TCP-Paketen besteht.
Manchmal funktioniert es durch Zufall das der Skript mir dann das komplette und vor allem korrekte Paket zusammen stückelt. Aber das funktioniert nur gefühlte 1 von 10 mal.
Was mache ich hier falsch?

Hier der komplette Code:
Code:
#include <Winpcap.au3> 
#include <String.au3>
#include <Array.au3>


HotKeySet("^q", "verlassen")

$dll = DllOpen("user32.dll")

$Server="XYServer.net"

$ServerIP="000.00.000.00"

local $PaketType


$filter = "tcp port 80"
$filter = "src host "&$ServerIP

$winpcap=_PcapSetup()
If ($winpcap=-1) Then 
	MsgBox(16,"Pcap error !","WinPcap not found !") 
	exit 
EndIf 

$pcap_devices=_PcapGetDeviceList()
If ($pcap_devices=-1) Then 
	MsgBox(16,"Pcap error !",_PcapGetLastError()) 
	exit 
EndIf 

$int = $pcap_devices[0][0]

$pcap = _PcapStartCapture($int, $filter, 0)
If ($pcap = -1) Then
	MsgBox(16, "Pcap error !", _PcapGetLastError())
EndIf
$Endcheck=0
$PaketType=""
while $PaketType<>"Etwas bestimmtes"
	If IsPtr($pcap) Then
		$time0 = TimerInit()
		While (TimerDiff($time0) < 5000)
			$packet = _PcapGetPacket($pcap)
			If IsInt($packet) Then ExitLoop
				
			$sniff = sniff($packet[3])
			
			if StringInStr($sniff, "Etwas bestimmtes") then ;Ich suche nur nach Paketen die "Etwas bestimmtes" enthalten
				
				$PaketType="Etwas bestimmtes"
				
				$Hauptinfo=StringMid($sniff, StringInStr($sniff, "{"))
				
				$ContentLen1=_StringBetween($sniff, 'Content-Length: ', @CRLF)
				$ContentLen=$ContentLen1[0]
				$infoLen=stringlen($Hauptinfo)
				
;------------------------------------AB HIER.....
				while $infoLen<$ContentLen
					$packet = _PcapGetPacket($pcap)
					If IsInt($packet) Then ExitLoop
					$sniff = sniff($packet[3])
					$Hauptinfo=$Hauptinfo & $sniff
					$infoLen=stringlen($Hauptinfo)
				WEnd
;------------------------------------....BIS HIER funktioniert es nicht immer genau wie ich es will

				MsgBox(16,"Paket", $Hauptinfo & @CRLF _;$Hauptinfo & @CRLF _
				& @CRLF _
				& $ContentLen _
				& @CRLF _
				& $infoLen)
				
				;hier käme noch die eigentliche Auswertung / Zersplittung von $Hauptinfo ist aber jetzt zu lang und hierfür nicht relevant

			EndIf
		WEnd
	EndIf
WEnd

_PcapFree()


Func sniff($data)

Local $ipheaderlen = BitAND(_PcapBinaryGetVal($data, 15, 1), 0xF) * 4
Local $tcpoffset = $ipheaderlen + 14
Local $tcplen = _PcapBinaryGetVal($data, 17, 2) - $ipheaderlen ; ip total len - ip header len
Local $tcpheaderlen = BitShift(_PcapBinaryGetVal($data, $tcpoffset + 13, 1), 4) * 4
Local $tcpsrcport = _PcapBinaryGetVal($data, $tcpoffset + 1, 2)
Local $tcpdstport = _PcapBinaryGetVal($data, $tcpoffset + 3, 2)
Global $tcpsequence = _PcapBinaryGetVal($data, $tcpoffset + 5, 4)
Global $tcpflags = _PcapBinaryGetVal($data, $tcpoffset + 14, 1)
Local $httpoffset = $tcpoffset + $tcpheaderlen + 1
Global $httplen = $tcplen - $tcpheaderlen
$sniff_packet = BinaryMid($data, $httpoffset) 

If $httplen = 0 Then Return False ; empty tcp packet
If $tcpsrcport = 80 Then
	$String = _HexToString($sniff_packet)
	Return $String;$sniff_packet ; server ==> client
EndIf
If $tcpdstport = 80 Then
	$String = _HexToString($sniff_packet)
	Return $String;$sniff_packet ; server ==> client
EndIf

EndFunc

Func verlassen() 
	
	_PcapFree() ; close winpcap 
	DllClose($dll)		
	exit

EndFunc
03/18/2012 22:37 Lawliet#13
$packet[2] müsste die Packet länge enthalten. Lass mal $infoLen=stringlen($Hauptinfo) weg und Arbeite mit dem $packet Array. Klappt denn das auslesen von "Content-Length" immer? Und wenn ich das richtig sehe, könnte bei denem Loop auch schon das nächste Packet empfangen werden? Schau mal was immer vor dem nächsten HTTP Header kommt? Wenn ein Umbruch kommt, Empfang einfach so lang, bis ein @CRLF kommt und splitte das Packet dann gleich an der Stelle auf.
03/19/2012 21:25 BotofWar#14
$packet[2] gibt die länge vom gesamten Paket wieder. Also inclusive "HTTP/1.1 200 OK blablabla".
Ich brauche ja nur die Länge vom eigentlichen Content. Deswegen das Extrahieren und Auslesen von "Content-Length". Das funzt auch immer einwandfrei.
Aber jetzt kommt das böse Bubu wenn (ich vermute mal) irgend ein fremdes Paket was nicht direkt an das bereits ausgelesene gehört ankommt und somit einen falschen String in meine $Hauptinfo einpflanzt.
Das muss ich irgendwie in den Griff bekommen das NUR das auch wirklich dazugehörige Folgepaket empfangen wird.
Irgendwie muss das doch gehen, Immerhin kann jeder Browser das ja auch anständig zusammenstückeln.
Irgendwie ist auch im ganzen Netz nichts darüber zu erfahren. Rächen sich hier jetzt meine Wissenslücken auf dem Gebiet TCP/HTTP das ich nichtmal weiss wonach ich wirklich suchen muss oder ist das letztendlich so banal das sich keiner der sich damit auskennt n Kopf darum macht?
03/19/2012 21:55 Lawliet#15
Normal empfängt man eben auch nur die Packete, die über den eigenen Socket empfangen werden ;)