PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Teamspeak Login per UDP-Client



Sirect
06.06.2009, 15:15
Hallo,
Ich habe vor mich bei einem Teamspeak2-Server per UDP einzuloggen.
Ich möchte nicht auf den Query-Port sondern als Player in einen Channel gehen können.
Nun habe ich mal den Traffic vom Teamspeak-Client mitgesnifft und versucht das Packet nachzubauen.

http://img3.imagebanana.com/img/l41y2jhd/teamspeak.PNG

Aber trotzdem sendet der Server keine Antwort.
Das Verbinden und Senden an sich klappt, aber danach scheint nichts mehr zu passieren.
Immerhin den Server-Intro sollte ich ja bekommen, denn bis dahin muss ich ja kein Reply mehr senden.
Habt ihr ne Idee woran es liegt?

Shadowstyle
06.06.2009, 15:20
Villeicht lässt der keine UDP verbindung zu?
Kann man das nicht einstellen?
Oder v. überprüft der das packet nach ob es iwi original is?
villeicht hilft dir das ja weiter =)

Sirect
06.06.2009, 15:23
Der ganze Traffic läuft über das UDP-Protokoll, also gehe ich mal davon aus dass ich das richtig gemacht habe :P
Hab mir den Traffic von einem TS-Flooder gerade mal angesehen, der sendet das gleiche und kommt rein.
Könnte mir vll mal jemand das Packet zusammenbauen? Ich glaub darin liegt der Fehler :S

blackberry
06.06.2009, 16:41
Ok... wenn's dich interessiert...
Zum Erklären der Pakete werde ich struct's verwenden (gibt's in VB ja auch - weiß aber nicht wie die da heißen -.-)

Nur zur Klarstellung:
BYTE = 1 Byte ;)
WORD = 2 Bytes
DWORD = 4 Bytes / 2 Words
X y[z] = Array vom Typ X mit z Elementen und dem Namen y.
Die Größe berechnet sich wie folgt:
GrößeVonY = GrößeVon( X ) * z

(Analysiert wurde das von Luigi Auriemma - ich fasse es jetzt nur zusammen)

Das Login-Paket:

typedef struct _TS2_LOGIN_PACKET
{
DWORD header;
DWORD ImmerNull1;
DWORD ImmerNull2;
DWORD ImmerNull3;
DWORD crc32;
BYTE clientlen;
BYTE client[29];
BYTE oslen;
BYTE os[29];
WORD major;
WORD minor;
WORD build;
WORD revision;
WORD options;
BYTE nicklen;
BYTE nick[29];
BYTE passlen;
BYTE pass[29];
BYTE userlen;
BYTE user[29];
}
TS2_LOGIN_PACKET;
Der Header wird mit 0x3BEF4 belegt (0xBLAH = hexadezimalzahl).
Die folgenden Werte müssen auf 0 gesetzt werden.
crc32 muss ebenfalls auf 0 gesetzt werden.
Dieser Wert wird mit der CRC32-Prüfsumme des Pakets gefüllt, sobald dieses _komplett_ ausgefüllt_ ist. (nicht vergessen)
Clientlen wird mit der Länge des Client-Strings gefüllt.
Der Client-String ist festgelegt auf: "TeamSpeak" (ohne Anführungszeichen). Damit ist clientlen auch fest auf den Wert 9 zu setzen.
Bei OS wird genauso verfahren, nur das der Wert hier variabel (dh. frei vom Programmierer wählbar) ist.
OS kann z.B. "Windows XYZ" sein. oslen wäre dann auf 11 (die Länge von "Windows XYZ") zu setzen.
Major, Minor, Build und Revision bilden die Version des Clients deines Bots ab.
Diese sind nur zu einem gewissen Grad frei wählbar, da der Server nur bestimmte Client-Versionen akzeptiert.
Ein Beispiel für eine korrekte Belegung wäre:
major = 2
minor = 0
build = 33
revision = 7
Also: 2.0.33.7

Options kann zwei Zustände annehmen:
0x0101 = unregistierter Benutzer
0x0201 = registierter Benutzer
Wird 0x0201 gewählt, so müssen die Felder user und pass einen korrekten Login (Loginname + Passwort) beschreiben.

Die verbleibenden Felder werden nach dem selben Prinzip wie bei client und os ausgefüllt.
nick ist der Name, der beim Bot im TS angezeigt werden soll
user ist der Loginname
pass ist das Passwort

Nun wird die CRC32-Prüfsumme des Pakets berechnet und in crc32 geschrieben!

Jetzt kann das Paket abgeschickt werden...

Der Server sendet jetzt folgendes Paket:

typedef struct _TS2_LOGIN_RESPONSE
{
DWORD header;
DWORD unknown1;
DWORD playerid;
DWORD seq;
DWORD crc32;
BYTE sname[30];
BYTE splat[30];
WORD server_major;
WORD server_minor;
WORD server_build;
WORD server_revision;
DWORD resp;
DWORD codecs;
DWORD unknown2;
WORD stype;
BYTE unknown3[66];
DWORD maxplayers;
DWORD challenge;
DWORD players;
BYTE swelcome[255];
}
TS2_LOGIN_RESPONSE;

Die Feldnamen sind ja eigentlich sehr Aussagekräftig, also beschreibe ich diese im Folgenden nicht.
Wichtig hierbei ist nur der Wert von "resp" und playerid und die "challenge".
Challenge und playerid speichern wir für spätere Pakete irgendwo ab...
resp gibt eventuelle Fehler beim Login an.
Mögliche Fehler sind z.B.
-2 = der Server ist voll
-1 = der Server ist Passwort-geschützt / es wurde kein (richtiges) PW für den Server angegeben
-5 = die Benutzte Clientversion wird nicht unterstützt
-4 = der gewählte Nickname enthält gesperrte Zeichen, oder ist Blacklistet
-7 = der Benutzeraccount ist bereits in Benutzung
-21 = Benutzername und/oder Passwort sind falsch
-6 = deine IP ist gebannt
Enthält resp keinen dieser Werte, so kann angenommen werden, dass der Benutzer akzeptiert wurde!

Das nächste Paket bewegt den Bot in einen Channel.

typedef struct _TS2_JOIN_CHANNEL
{
DWORD header;
DWORD challenge;
DWORD playerid;
DWORD seq;
DWORD unknown1;
DWORD crc32;
WORD unknown2;
BYTE channellen;
BYTE channel[29];
BYTE subchannellen;
BYTE subchannel[29];
BYTE channelpasslen;
BYTE chanpass[29];
DWORD bandwidth;
}
TS2_JOIN_CHANNEL;

Der header wird mit 0x5BEF0 belegt.
Challenge wird mit der vom Server gesendeten Challenge belegt.
Playerid wird auch mit der vom Server gesendeten playerid belegt.
seq wird auf 1 gesetzt. Wenn wir noch so ein Paket senden (um den Channel zu wechseln), setzen wird seq auf 2, auf 3, auf 4, usw. (also für jedes JOIN-Paket: seq = seq + 1)
Dieses Verfahren gilt auch für andere Pakete... (z.B. PING)
Unknown1 wird auf 0 gesetzt.
crc32 und unkown2 auch.
Nun folgt das bekannte Len-String-Verfahren:
channellen hält die Länge von channel usw.
Die Namen sind selbsterklärend.
Bandwidth setzen wir auf 0. (für mehr Informationen: einfach in den Sourcecode von tspeakfp schauen)

Nun wird die CRC32-Prüfsumme des Pakets berechnet und in crc32 geschrieben!

Wir senden das Paket.
Violà - der Bot ist in (s)einem Channel!

Als nächstes senden wir PING-Pakete, die dafür benutzt werden, um den Bot vor einem Timeout zu beschützen.
Diese sollten regelmäßig an den Server gesendet werden...

typedef struct _TS2_PING
{
DWORD header;
DWORD challenge;
DWORD playerid;
DWORD seq;
DWORD crc32;
}
TS2_PING;

Header wird mit 0x0001bef4 belegt.
challenge und playerid sind auch hier die Werte, die wir vom Server erhalten haben.
seq wird wie oben beschrieben nach jedem PING-Paket um 1 erhöht.
Zu Beginn fangen wir mit seq = 1 an.
crc32 wird auf 0 gesetzt.

Nun wird die CRC32-Prüfsumme des Pakets berechnet und in crc32 geschrieben!

Wir schicken das Paket ab.
Fertig!

_______________________________________

Ich denke das reicht fürs Erste.
Mehr Informationen findest du, wie gesagt, im Sourcecode von tspeakfp.


mfG. BlackBerry

Sirect
06.06.2009, 17:03
Hab mir mal den Source von tspeakfp angesehen und der leuchtet mir schon ein.
Die Frage ist wie ich den in VB portiere und ob es nicht viel zu kompliziert wäre einen Teamspeak-Bot zu schreiben, der auchnoch Musik abspielen soll.
In der Zeit hab ich ja mein einges VOIP-System geschrieben xD

blackberry
06.06.2009, 17:54
Wie's mit den Codecs aussieht weiß ich nicht.
Ich weiß nur, dass ein Bot auf diese Weise zum Server verbinden kann...

kInGoFcHaOs
08.06.2009, 20:33
In der Zeit hab ich ja mein einges VOIP-System geschrieben xD

des is garned so schwer ....