Problem z protokołem GG

0

Hello!
W ramach nauki C# postanowiłem napisać sobie prosty program, który
zaloguje się i wyśle wiadomość.
Odbieram wiadomość powitalną, seed, etc., ale mam problem z samym
zalogowaniem się.
Stworzyłem taką strukturę:

[StructLayout(LayoutKind.Sequential, Pack = 1)]
private struct ggPacketLogin
{
   public uint Type;
   public uint Size;
   public uint Uin;
   public uint Hash;
   public uint Status;
   public uint Version;
   public byte dunno1;
   public uint local_ip;
   public UInt16 local_port;
   public uint external_ip;
   public UInt16 external_port;
   public byte image_size;
   public byte dunno2;
}

i tak ją zapełniłem:

pckLogin.Type = 0x0015;
pckLogin.Size = GetStructureSize(pckLogin);
pckLogin.Uin = 9999999;
pckLogin.Hash = Convert.ToUInt32(gg_login_hash("haslo",
   pckWelcome.Seed));
pckLogin.Status = 0x0003;
pckLogin.Version = 0x24;
pckLogin.dunno1 = 0x00;
pckLogin.local_ip = 1401964399;
pckLogin.local_port = 8074;
pckLogin.external_ip = 3641780572;
pckLogin.external_port = 8074;
pckLogin.image_size = 30;
pckLogin.dunno2 = 0xbe;

GetStructureSize liczy wieklość struktury bez Type oraz Size (czyli
wychodzi 35).

Funkcja gg_login_hash:

public long gg_login_hash(string password, uint seed)
{
   uint x, y, z;

   y = seed;

   for (int i = 0; i < password.Length; i++)
   {
       x = 0;

       x = (x & 0xffffff00) | password[i];
       y ^= x;
       y += x;
       x <<= 8;
       y ^= x;
       x <<= 8;
       y -= x;
       x <<= 8;
       y ^= x;

       z = y & 0x1f;
       y = (y << Convert.ToInt32(z)) | (y >> Convert.ToInt32((32 - z)));
   }

   return y;
}

I na koniec, tak wysyłam pakiet:

IntPtr pIP = Marshal.AllocHGlobal(1024);
Marshal.StructureToPtr(pckLogin, pIP, false);
Marshal.Copy(pIP, byBufor, 0, 1024);
this.scGniazdo.Send(this.byBufor);

W odpowiedzi zawsze otrzymuję 0x09, czyli błąd logowania.
Na tym się zatrzymuję, siedzę nad tym już trzeci dzień i nic nie
przychodzi mi do głowy. Prosiłbym o delikatne nakierowanie ;).
Pozdrawiam,
Rev.

0

jako wersa klienta gg podaj 0x21 i polacz sie z serwerem m1.gadu-gadu.pl powinno pÓjsc :> oczywiscie jezeli wczesniej poprawnie wysylasz pakiety czyli: naglowek a pozniej glowna czesc pakietu :> u mnie problem z logowaniem byl taki ze nie na kazdej wersji gg w tej stukturze chcialo sie logowac nie wiem czemu, jak wpisalem u siebie 0x21 to mi smiga bez problemu...

0

przeanalizuj kod komponentu thgg lub gglite. Na C# przenieść powinno pójśc łatwo :)

0

Duh. Problem okazał się banalny - błąd znajdował się w metodzie liczącej hash hasła. "X" musiało być resetowane tylko na początku, a ja to robiłem z każdą iteracją pętli ;).

0

przy opkazji tematu GG w C# pozwole sobie zadać pytanie :]

czy wysyłć pakiety za pomocą TcpClient ?

czy w ten sposób mozna wysyłać ?

Int32 port = 443;
TcpClient client = new TcpClient("217.17.41.92", port);
ASCIIEncoding zm = new ASCIIEncoding();

Byte[] data = zm.GetBytes(Convert.ToString(header));

NetworkStream stream = client.GetStream();
stream.Write(data, 0, data.Length);
listBox1.Items.Add("Wyslano: "+header);
data = new Byte[256];
String responseData = String.Empty;

Int32 bytes = stream.Read(data, 0, data.Length);
responseData = zm.GetString(data, 0, bytes);
listBox1.Items.Add("Odebrano: "+responseData);
client.Close();  
0

Nie do końca. Klasa Convert nie przekonwertuje Ci struktury.
Na przykład: mamy wypełnioną już strukturę pckLogin:

IntPtr pIP = Marshal.AllocHGlobal(1024);
Marshal.StructureToPtr(pckLogin, pIP, false);
Marshal.Copy(pIP, byBufor, 0, 1024);

W ten sposób kopiujemy ją do tablicy byte[] byBufor (trochę zabawy z kopiowaniem struktur jest, można to zrobić tą metodą - kopiując ją napierw do pamięci unmanaged, potem kopiując ją znowu, używając BinaryReader albo wskaźników z C). Potem możemy już wysłać byBufor korzystając np. z wcześniej stworzonego socketa:

private Socket scGniazdo = new Socket(AddressFamily.InterNetwork,
    SocketType.Stream, ProtocolType.IP);

Dane do struktury kopiujesz analogicznie:

IntPtr pIP = Marshal.AllocHGlobal(1024);
Marshal.Copy(this.byBufor, 0, pIP, 1024);
this.pckWelcome = (ggPacketWelcome)Marshal.PtrToStructure(pIP, typeof(
    ggPacketWelcome));

Pzdr.

ps. klasa Marshal znajduje się w System.Runtime.InteropServices.

0

aaa super, dzięki ;P

a kiedy wyslać gg_welcome na samym początku, jeszcze przed nagłówkiem ?

0

gg_welcome jest przecież normalnym, pełnym pakietem odbieranym zaraz na początku po połączeniu zawierający seed do hashowania hasła.
Strukturę wszystkich pakietów masz na stronei protokołu ekg (pamiętaj, żeby wysyłać albo dodawać do każdego pakietu nagłówek pakietu gg - czyli typ oraz wielkość wysyłanej struktury).

http://www.phpfi.com/110458 - tutaj masz pierwszą klasę na której metodą prób i błędów próbowałem się pomyślnie zalogować.
do tego musisz na formie dać textboxa i buttona. wtedy wszystko odpalasz tak:
http://www.phpfi.com/110460
Powineneś dostać w odpowiedzi pakiet 0x03 (ustawiając wcześniej sobie numer gg i swoje haslo w gg.cs). Nie próbuj za często się reconnectować, bo dostaniesz bana na ip na każdy numer na jakieś pół godziny.

0

Hmm. A ja dalej mam problem. Niby protokół odbiera pakiet "3" ale gdy próbuje zmienic status to status sie nie zmienia. nie moge tez wyslac wiadomosci. Udostępniłbyś może źródła całej klasy ? Z może dysponujecie komponentem obsługującym GG pod pplatforme .net ?

Albo przynajmniej czy ktos mógłby dopisać funkcje wysyłającą wiadomość. I oczywiscie zdefiniować odpowiedni pakiet?

0

Przepraszam, ze odkopuje ten temat, ale wciążmam problemy z tym GG. W odpowiedzi na pakiet logowania dostej pakiet 0x003 (czyli jest dobrze i jestem zalogowany). Natomiast, gdy chce zmienić status na dostępny to nic sie nie dzieje. Robie to tak:

      pakiet.pckStatus.Type = 0x0002;
                  pakiet.pckStatus.status = 0x0003;
                  pakiet.pckStatus.Size = Convert.ToUInt32((Marshal.SizeOf(pakiet.pckStatus) - Marshal.SizeOf(pakiet.pckStatus.Type) - Marshal.SizeOf(pakiet.pckStatus.Size)));
                  IntPtr pIP = Marshal.AllocHGlobal(1024);
                  Marshal.StructureToPtr(pakiet.pckStatus, pIP, false);
                  Marshal.Copy(pIP, byBuffor, 0, 1024);
                  
                  
                  this.scGniazdo.Send(this.byBuffor);

Nie zwraca zadnego błędu, ale opis pozostaje niezmieniony. Czemu tak jest ?

0

no to i ja odkopię

otóż zmogły mnie wiadomości konferencyjne oraz wiadomości z dodatkowymi atrybutami tekstu. o ile na odebrani etego mam jeszcze jakiś pomysł, to z wysłaniem sonie nie radzę. dotychczas wszystko mi szło jak po maśle, a teraz utknąłem. od początku jadę po opisie protokołu.

jakiś pomysł?

0

czy mozna kogos prosic o wrzucenie gdzies zrodelek zwiazanych z inicjacja polaczenia tj. generowanie hasha wysylanie powitalnego odbieranie i laczenie sie z serwerem ?
z góry dzieki

0

co trzeba zrobic, żeby odebrac pakiet powitalny/seed (albo cos w tym stylu)? Łącze sie z serwerem m1.gadu-gadu.pl.
przez
gniazdo.Connect("m1.gadu-gadu.pl",443)
gniazdo ma właściwośc Connected=True, czyli się połączyło i jest ok. Muszę coś wysyłac (jakiś specyficzny pakiet czy coś) żeby dostac seed do tworzenia pakietu gg_login?

edit: dobra, juz doszedłem do tego sam, natomiast mam pytanie o dalsza częśc. Jak wypełniam pakiet gg_welcome, to które ip mam gdzie wpisywac? Rozumiem, ze ip zewnetrzne, to jest to, które mam w sieci publicznej, a wewnętrzne to jest to w sici wewnetrznej czyli 192.168.x.x czy jeszcze jakoś inaczej? Czy port który wysyłam w tym pakiecie to jest ten sam, z którym sie łaczę do serwera gg? (w moim przypadku 443)

1 użytkowników online, w tym zalogowanych: 0, gości: 1