Protokół GG. Problem z zalogowaniem się.

Odpowiedz Nowy wątek
2010-05-04 10:53
0

Witam,

na razie mam taki kod

#include <iostream>
#include <winsock2.h>
#include <windows.h>
 
using namespace std;
 
struct gg_header {
    int type;       /* typ pakietu */
    int length;     /* dlugosc reszty */
}header;
 
#define GG_WELCOME 0x0001
 
struct gg_welcome {
    int seed;       /* klucz szyfrowania hasla */
}welcome;
 
#define GG_LOGIN60 0x0015
 
struct gg_login60 {
    int uin;                /* numer */
    int hash;               /* hash hasla */
    int status;             /* status na wjazd */
    int version;            /* wersja klienta */
    char unknown1;          /* 0x00 */
    int local_ip;           /* moje ip */
    short local_port;       /* port na ktorym slucham */
    int external_ip;        /* zew. ip */
    short external_port;    /* zew. port */
    char image_size;        /* maks. rozm. grafiki z kb */
    char unknown2;          /* 0xbe */
    char description[];     /* opis / nie musi byc */
    int time;               /* czas / nie musi byc */
}login;
 
#define GG_NEW_STATUS 0x0002
 
struct gg_new_status {
    int status;             /* na jaki zmienic */
    char description[];     /* opis / nie musi byc */
    int time;               /* czas / nie musi byc */
}nstatus;
 
int gg_login_hash(char *password, unsigned int seed)
{
    unsigned int x, y, z;
 
    y = seed;
 
    for (x = 0; *password; password++) {
        x = (x & 0xffffff00) | *password;
        y ^= x;
        y += x;
        x <<= 8;
        y ^= x;
        x <<= 8;
        y -= x;
        x <<= 8;
        y ^= x;
 
        z = y & 0x1f;
        y = (y << z) | (y >> (32 - z));
    }
 
    return y;
}
 
void clear(struct gg_header *header)
{
 
    header->type = 0;
    header->length = 0;
 
}
 
int main(int argc, char **argv[])
{
 
    WSADATA wsd;
    SOCKET sock;
    struct sockaddr_in server;
 
    int numer = 12345;
    char *password = "jakies haslo";
 
    if(WSAStartup(MAKEWORD(2,2), &wsd) != 0)
    {
 
        cout<<"Nie mozna utworzyc WinSocka\r\n";
        cout.flush();
        return 1;
 
    }
 
    sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if(sock == INVALID_SOCKET)
    {
 
        cout<<"Nie mozna utworzyc gniazda ( "<<WSAGetLastError()<<" )\r\n";
        cout.flush();
        return 2;
 
    }
 
    server.sin_family = AF_INET;
    server.sin_port = htons((u_short)8074);
    server.sin_addr.s_addr = inet_addr("91.214.237.11");
 
    cout<<"ip: "<<inet_addr("91.214.237.11")<<"\r\n";
    cout<<"port: "<<htons((u_short)8074)<<"\r\n";
    cout.flush();
 
    if(connect(sock, (sockaddr *)&server, sizeof(server)) == SOCKET_ERROR)
    {
 
        cout<<"Nie mozna sie polaczyc ( "<<WSAGetLastError()<<" )\r\n";
        cout.flush();
        return 3;
 
    }
 
    clear(&header);
 
    /******* pobieranie seeda *******/
 
    if(recv(sock, (char *)&header, sizeof(header), 0) > 0)
    {
 
        if(recv(sock, (char *)&welcome, header.length, 0) > 0)
        {
 
            cout<<"seed: "<<welcome.seed<<"\r\n";
            cout.flush();
 
        } else {
 
            cout<<"seed failed\r\n";
            cout.flush();
 
        }
 
    }
 
    login.uin = numer;
    login.hash = gg_login_hash(password, welcome.seed);
    login.status = 0x0002;
    login.version = 0x20;
    login.unknown1 = 0x00;
    login.local_ip = 0x00;
    login.local_port = 1550;
    login.external_ip = 0x00;
    login.external_port = 1550;
    login.unknown2 = 0xbe;
    login.image_size = 256;
    //login.description[]
    //login.time
 
    /****** logowanie *****/
 
    #define GG_LOGIN_OK 0x0003
    #define GG_LOGIN_FAILED 0x0009
 
    clear(&header);
 
    header.type = GG_LOGIN60;
    header.length = sizeof(login);
 
    if(send(sock, (char *)&header, sizeof(header), 0) > 0)
    {
 
        if(send(sock, (char *)&login, sizeof(login), 0) > 0)
        {
 
            clear(&header);
 
            //if(recv(sock, (char *)&header, sizeof(header), 0) > 0)
            //{
 
                recv(sock, (char *)&header, sizeof(header), 0);
                if(header.type == GG_LOGIN_OK)
                {
 
                    cout<<"login ok\r\n";
                    cout.flush();
 
                } else if (header.type == GG_LOGIN_FAILED)
                {
 
                    cout<<"login failed\r\n";
                    cout.flush();
 
                } else {
 
                    cout<<"wtf?!\r\n";
 
                }
 
                cout<<header.length<<"\r\n";
                cout.flush();
                printf("0x%x\r\n", header.type);
 
            //}
 
        }
 
    }
 
    closesocket(sock);
    WSACleanup();
 
    getchar();
 
    return 0;
 
}

Mam problem z zalogowaniem się. Dostaję ciągle status 0 zamiast 3 (prawidłowe zalogowanie się) czy nawet 9 (nieprawidłowe zalogowanie). Czy ktoś wie gdzie jest problem ?

Pozostało 580 znaków

2010-05-04 11:27
0

Masz błędy w definicji struktur, ich pola powinny być upakowane bajt po bajcie.
To znaczy że pole INT po CHAR powinno być pod adresem pola CHAR plus jeden. Domyślne 'pakowanie' jest 8, czyli typy ośmiobajtowe i większe zawsze będą pod adresem podzielnym przez 8, a mniejsze (int, short) pod adresem podzielnym przez ich wielkość (4,2).

GCC:

struct s1{}PACKED;

MSVC:

#pragma pack(push)
#pragma pack(1)
struct s1{};
struct s2{};
#pragma pack(pop)

sizeof(struct {char,int}) będzie domyślnie 8, a z pakowaniem 1 spadnie do pięciu bajtów.

Pozostało 580 znaków

2010-05-04 11:50
0

Poprawiłem, cały kod wygląda teraz tak

#include <iostream>
#include <winsock2.h>
#include <windows.h>
 
using namespace std;
 
struct gg_header {
    int type;       /* typ pakietu */
    int length;     /* dlugosc reszty */
}PACKED;
 
#define GG_WELCOME 0x0001
 
struct gg_welcome {
    int seed;       /* klucz szyfrowania hasla */
}PACKED;
 
#define GG_LOGIN60 0x0015
 
struct gg_login60 {
    int uin;                /* numer */
    int hash;               /* hash hasla */
    int status;             /* status na wjazd */
    int version;            /* wersja klienta */
    char unknown1;          /* 0x00 */
    int local_ip;           /* moje ip */
    short local_port;       /* port na ktorym slucham */
    int external_ip;        /* zew. ip */
    short external_port;    /* zew. port */
    char image_size;        /* maks. rozm. grafiki z kb */
    char unknown2;          /* 0xbe */
    char description[];     /* opis / nie musi byc */
    int time;               /* czas / nie musi byc */
}PACKED;
 
#define GG_NEW_STATUS 0x0002
 
struct gg_new_status {
    int status;             /* na jaki zmienic */
    char description[];     /* opis / nie musi byc */
    int time;               /* czas / nie musi byc */
}PACKED;
 
int gg_login_hash(char *password, unsigned int seed)
{
    unsigned int x, y, z;
 
    y = seed;
 
    for (x = 0; *password; password++) {
        x = (x & 0xffffff00) | *password;
        y ^= x;
        y += x;
        x <<= 8;
        y ^= x;
        x <<= 8;
        y -= x;
        x <<= 8;
        y ^= x;
 
        z = y & 0x1f;
        y = (y << z) | (y >> (32 - z));
    }
 
    return y;
}
 
/*void clear(struct gg_header *header)
{
 
    header->type = 0;
    header->length = 0;
 
}*/
 
int main(int argc, char **argv[])
{
 
    WSADATA wsd;
    SOCKET sock;
    struct sockaddr_in server;
    struct gg_welcome welcome;
    struct gg_login60 login;
    struct gg_new_status nstatus;
    struct gg_header header;
 
    int numer = twoj_nr;
    char *password = "haslo";
 
    if(WSAStartup(MAKEWORD(2,2), &wsd) != 0)
    {
 
        cout<<"Nie mozna utworzyc WinSocka\r\n";
        cout.flush();
        return 1;
 
    }
 
    sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if(sock == INVALID_SOCKET)
    {
 
        cout<<"Nie mozna utworzyc gniazda ( "<<WSAGetLastError()<<" )\r\n";
        cout.flush();
        return 2;
 
    }
 
    server.sin_family = AF_INET;
    server.sin_port = htons((u_short)8074);
    server.sin_addr.s_addr = inet_addr("91.214.237.11");
 
    cout<<"ip: "<<inet_addr("91.214.237.11")<<"\r\n";
    cout<<"port: "<<htons((u_short)8074)<<"\r\n";
    cout.flush();
 
    if(connect(sock, (sockaddr *)&server, sizeof(server)) == SOCKET_ERROR)
    {
 
        cout<<"Nie mozna sie polaczyc ( "<<WSAGetLastError()<<" )\r\n";
        cout.flush();
        return 3;
 
    }
 
    header.type = 0;
    header.length = 0;
 
    /******* pobieranie seeda *******/
 
    if(recv(sock, (char *)&header, sizeof(header), 0) > 0)
    {
 
        if(recv(sock, (char *)&welcome, header.length, 0) > 0)
        {
 
            cout<<"seed: "<<welcome.seed<<"\r\n";
            cout<<"header type: "<<header.type<<"\r\n";
            cout.flush();
 
        } else {
 
            cout<<"seed failed\r\n";
            cout.flush();
            return 4;
 
        }
 
    }
 
    login.uin = numer;
    login.hash = gg_login_hash(password, welcome.seed);
    login.status = 0x0002;
    login.version = 0x20;
    login.unknown1 = 0x00;
    login.local_ip = 0x00;
    login.local_port = 1550;
    login.external_ip = 0x00;
    login.external_port = 1550;
    login.unknown2 = 0xbe;
    login.image_size = 256;
    //login.description[]
    //login.time
 
    /****** logowanie *****/
 
    #define GG_LOGIN_OK 0x0003
    #define GG_LOGIN_FAILED 0x0009
 
    header.type = 0;
    header.length = 0;
 
    header.type = GG_LOGIN60;
    header.length = sizeof(login);
 
    if(send(sock, (char *)&header, sizeof(header), 0) > 0)
    {
 
        if(send(sock, (char *)&login, sizeof(login), 0) > 0)
        {
 
            header.type = 0;
            header.length = 0;
 
            //if(recv(sock, (char *)&header, sizeof(header), 0) > 0)
            //{
 
                recv(sock, (char *)&header, sizeof(header), 0);
                if(header.type == GG_LOGIN_OK)
                {
 
                    cout<<"login ok\r\n";
                    cout.flush();
 
                } else if (header.type == GG_LOGIN_FAILED)
                {
 
                    cout<<"login failed\r\n";
                    cout.flush();
 
                } else {
 
                    cout<<"wtf?!\r\n";
 
                }
 
                cout<<header.length<<"\r\n";
                cout.flush();
                printf("0x%x\r\n", header.type);
 
            //}
 
        }
 
    }
 
    closesocket(sock);
    WSACleanup();
 
    getchar();
 
    return 0;
 
}

I dalej nie otrzymuję ani 3 ani 9, tylko zero.

Pozostało 580 znaków

2010-05-04 15:14
0

login.image_size = 256; // 9 bitów zmieści się w 8?

Zastanów się nad dwoma ostatnimi polami w gg_login60. Pierwsze z nich (description) jest opcjonalne, tzn może być, ale nie musi. Jeżeli jest, to musi kończyć się zerem.
Drugie (time) też jest opcjonalne, ale może być tylko wtedy, gdy pierwsze istnieje, a ponieważ time nie ma stałej pozycji w strukturze, nie może istnieć w definicji struktury.

Pozostało 580 znaków

2010-05-04 15:41
hck
0

Miałem taki sam wątek założyć :D
Też mam z tym problem, tyle że używam protokołu w wersji 8.

//main.cpp:
#include <iostream>
#include <WinSock2.h>
#include <Windows.h>
#include <string>
#include "declars.h"
#include "SHA1.h"
using namespace std;
 
int main()
{
 
    gg_welcome welcome;
    gg_login80 login;
 
    SOCKET      sock;
    sockaddr_in addr;
    WSAData     data;
 
    WSAStartup(MAKEWORD(2,2), &data);
    sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
 
    addr.sin_addr.S_un.S_addr = inet_addr("91.214.237.17");
    addr.sin_family = AF_INET;
    addr.sin_port = htons(8074);
 
    if(connect(sock, (sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR)
    {
        cerr << "could not connect\n";
        cin.get();
        return -1;
    }
 
    cout << "connected\n";
 
    recv(sock, (char*)&welcome, sizeof(welcome), 0);
    cout << "seed: " << welcome.seed << endl;
 
    string result;
    CSHA1 sha1;
    sha1.Update((const unsigned char*)&pass, strlen(pass));
    sha1.Update((const unsigned char*)&welcome.seed, sizeof(welcome.seed));
    sha1.Final();
    sha1.ReportHashStl(result, CSHA1::REPORT_HEX_SHORT);
    strcpy(login.hash, result.c_str());
    for(int i = 40; i < 64; i++)
    {
        login.hash[i] = '\0';
    }
 
    login.uin = 13039737;
    strcpy(login.language, "pl");
    login.hash_type = 0x02;
    login.status =  0x0002;
    login.flags = 0;
    login.features = 0x00000007;
    login.local_ip = 0;
    login.local_port = 0;
    login.external_ip = 0;
    login.external_port = 0;
    login.image_size = 255;
    login.unknown1 = 0x64;
    login.version_len = 0x23;
    strcpy(login.version, "Gadu-Gadu Client build 10.0.0.10450");
    login.type = 0x0031;
    login.size = sizeof(login) - 8;
 
    send(sock, (char*)&login, sizeof(login), 0);
    int buf = 0;
    recv(sock, (char*)&buf, 4, 0);
    cout << buf;
 
    cin.get();
    return 0;
};
 
//declars.h:
#pragma pack(push)
#pragma pack(1)
 
struct gg_welcome {
    int type, size;
    int seed;   
};
 
struct gg_login80 {
        int type, size;
        int uin;              /* numer Gadu-Gadu */
        char language[2];     /* język: "pl" */
        char hash_type;       /* rodzaj funkcji skrótu hasła */
        char hash[64];        /* skrót hasła dopełniony \0 */
        int status;           /* początkowy status połączenia */
        int flags;            /* początkowe flagi połączenia */
        int features;         /* opcje protokołu (0x00000367)*/
        int local_ip;         /* lokalny adres połączeń bezpośrednich (nieużywany) */
        short local_port;     /* lokalny port połączeń bezpośrednich (nieużywany) */
        int external_ip;      /* zewnętrzny adres (nieużywany) */
        short external_port;  /* zewnętrzny port (nieużywany) */
        char image_size;      /* maksymalny rozmiar grafiki w KB */
        char unknown1;        /* 0x64 */
        int version_len;      /* długość ciągu z wersją (0x23) */
        char version[];       /* "Gadu-Gadu Client build 10.0.0.10450" (bez \0) */
};
 
#pragma pack(pop)

Też cały czas dostaję 0.


joł joł ****!

Pozostało 580 znaków

2010-05-05 10:12
0
sapero napisał(a)

login.image_size = 256; // 9 bitów zmieści się w 8?

Zastanów się nad dwoma ostatnimi polami w gg_login60. Pierwsze z nich (description) jest opcjonalne, tzn może być, ale nie musi. Jeżeli jest, to musi kończyć się zerem.
Drugie (time) też jest opcjonalne, ale może być tylko wtedy, gdy pierwsze istnieje, a ponieważ time nie ma stałej pozycji w strukturze, nie może istnieć w definicji struktury.

To z image_size już poprawione, ale nie rozumiem o co Ci chodzi z tymi 2 polami. Z tego co ja zrozumiałem to time musi być jeżeli jest description, ale skoro go nie ma to i time też nie ma :D Czyli co, mam wywalić time z definicji ?

Pozostało 580 znaków

2010-05-05 11:20
0

Musisz wywalić time ze struktury bo i tak nie użyjesz go bezpośrednio. Jedyny sposób na użycie go to

char *pszOpis = "będę o";
size_t opisLen = strlen(pszOpis)+1;
gg_login60 *login = (gg_login60*)new char[sizeof(gg_login60)/*31*/ + opisLen + sizeof(int)/*4*/];
login->... = ...;
memcpy(login->description, pszOpis, opisLen);
 
int *pTime = (int*)(&login->description[opisLen]);
*pTime = ...;

Musisz też się upewnić że "char description[]" ma rozmiar ZERO, o ile chcesz używać sizeof(gg_login60) jako wzorca (=31). W przeciwnym wypadku musisz sobie pododawać rozmiary zmiennych i wstawić sumę do jakiegoś #define, albo użyj makra FIELD_OFFSET(gg_login60, description).

char description[0] jest akceptowane przynajniej w gcc, i jasno widać że nie zajmuje pamięci.

Poza tym dobrze by było gdyby wszystkie struktury wysyłane miały na początku header, by jednym send() załatwić sprawę.

struct gg_login60
{
   gg_header hdr;
   //tutaj pola gg_login60, ale bez time
}

W tym przypadku pobierając sizeof(gg_login60) musisz odjąc sizeof(gg_header).

HCK

login.size = sizeof(login) - 8;

Taki rozmiar wycina login.version z pakietu, astrcpy(login.version, "Gadu-Gadu Client build 10.0.0.10450");

nadpisuje Ci jakieś zmienne, bo gg_login80.version[] jest zbyt małe by pomieścić ten string. Zaalokuj strukturę przez NEW, malloc,alloca, albo na stałe ustaw X w char version[X] (w gg_login80) na rozmiar tego stringa +1.

Ewentualnie użyj jakiegoś bufora char[sizeof(gg_login80)+max_text_size] i castuj go na gg_login80*. Pola version i size zainicjuj wtedy tak:
```cpp
strcpy(login->version, "Gadu-Gadu Client build 10.0.0.10450");
login->size = sizeof(gg_login80) - 8/*header*/ + strlen(login->version) /* + 1 jeśli trzeba*/;

Pozostało 580 znaków

2010-05-05 12:18
0

Zrobiłem jak napisałeś, ale bez dodawania headera, na razie wygląda to tak

struct gg_login60 {
    int uin;                /* numer */
    int hash;               /* hash hasla */
    int status;             /* status na wjazd */
    int version;            /* wersja klienta */
    char unknown1;          /* 0x00 */
    int local_ip;           /* moje ip */
    short local_port;       /* port na ktorym slucham */
    int external_ip;        /* zew. ip */
    short external_port;    /* zew. port */
    char image_size;        /* maks. rozm. grafiki z kb */
    char unknown2;          /* 0xbe */
    char description[0];    /* opis / nie musi byc */
    //int time;             /* czas / nie musi byc */
}PACKED;
    login.uin = numer;
    login.hash = gg_login_hash(password, welcome.seed);
    login.status = 0x0002;
    login.version = 0x20;
    login.unknown1 = 0x00;
    login.local_ip = 0x00;
    login.local_port = 1550;
    login.external_ip = 0x00;
    login.external_port = 1550;
    login.unknown2 = 0xbe;
    login.image_size = 128;
    //login.description[]
    //login.time

i nadal dostaję 0 ;/

Pozostało 580 znaków

2010-05-05 15:08
hck
0
        type    49  int
        size    137 int
        uin 13039737    int
        language    0x003dfe4c "pl" char [3]
        hash_type   2 ''   char
        hash    0x003dfe50 "tutaj hasz" char [64]
        status  2   int
        flags   0   int
        features    7   int
        local_ip    0   int
        local_port  0   short
        external_ip 0   int
        external_port   0   short
        image_size  -1 'ÿ'  char
        unknown1    100 'd' char
        version_len 35  int
        version 0x003dfeae "Gadu-Gadu Client build 10.0.0.10450"    char [35]

Taką tę strukturę mam kiedy ją wysyłam, dalej 0 dostaję.


joł joł ****!

Pozostało 580 znaków

2010-05-05 19:40
0

login.features = 0x00000007;

hck, wg. opisu protokolu 8 tam powinno być wartość 0x00000367 a nie taka jak ty wpisałeś :)

int features; / opcje protokołu (0x00000367)/

edit

sory, niedoczytałem :p

edit2

taką prośbę mam, jakby ktoś posiadał działający kodzik (łączy z serwerem, powiedzmy zmienia status i rozłącza) bo ja już serio nie iwem o co chodzi z tym moim kodem, to prosiłbym o wrzucenie chociaż kawałka :P

Pozostało 580 znaków

2010-05-05 22:52
0

http://www.sendspace.com/file/zpt3dz
To klient 6.0, pisałem go przed wojną w devcpp, a dzisiaj przeniosłem pod CB.
Ma dwa proste boty odpowiadające i częściowo obsługuje listę userów pobraną z serwera.

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

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