Bypass Ankama launcher

Inscrit
25 Octobre 2022
Messages
6
Reactions
1
#1
Salut à tous
Je reprends le développement du MultiToolD2 qui était dispo sur Arkalys et Azote pour ceux qui se souviennent, le soft fonctionne pour le moment mais je voulais le faire fonctionner en emulant l’Ankama launcher pour pouvoir lancer ses compte directement depuis le tool, est-ce que quelqu’un a des infos à ce niveau le but serait de pouvoir faire fonctionner le multicompte sur serveur mono compte comme l’outil Frigost
Le soft sera entièrement open source et ouvert à la commu code en C#
Solution 1 emuler le launcher
Solution 2 retourner à l’ancien système de login
Toute info est bonne à prendre
 
Dernière édition:

AzureHaze

Contributeur
Inscrit
27 Septembre 2019
Messages
47
Reactions
250
#2
Salut, je connais pas le tool mais j'en ai créé un similaire qui te permet de bind ton client sur l'interface réseau que tu veux et ajouter un proxy. Si t'as besoin d'infos pour récupérer le token regarde ce thread. Pour créer un émulateur il faut juste écouter sur le port 26117 et renvoyer le paquet "auth_getGameToken {token}\0" après avoir récupéré le token, rien de très compliqué.

1666713104152.png
 
Inscrit
2 Mars 2022
Messages
4
Reactions
6
#3
Salut, je connais pas le tool mais j'en ai créé un similaire qui te permet de bind ton client sur l'interface réseau que tu veux et ajouter un proxy. Si t'as besoin d'infos pour récupérer le token regarde ce thread. Pour créer un émulateur il faut juste écouter sur le port 26117 et renvoyer le paquet "auth_getGameToken {token}\0" après avoir récupéré le token, rien de très compliqué.

Afficher la pièce jointe 867
As-tu plus d'information?
 
Inscrit
25 Octobre 2022
Messages
6
Reactions
1
#5
Salut, je connais pas le tool mais j'en ai créé un similaire qui te permet de bind ton client sur l'interface réseau que tu veux et ajouter un proxy. Si t'as besoin d'infos pour récupérer le token regarde ce thread. Pour créer un émulateur il faut juste écouter sur le port 26117 et renvoyer le paquet "auth_getGameToken {token}\0" après avoir récupéré le token, rien de très compliqué.

Afficher la pièce jointe 867
Woah j’adore ! Serait tu d’accord pour partager la source ? Ou au moins détailler complètement comment tu a fais pour l’adapter réseau etc ?
J’avoue ne ps avoir trop de connaissance en réseau et j’ai du mal à comprendre ton diagramme.m bien qu’il soit super détaillé
 
Inscrit
2 Mars 2022
Messages
4
Reactions
6
#6
Moi aussi j'ai envie d'apprendre :/ parce que j'aime pas le frigost
 

AzureHaze

Contributeur
Inscrit
27 Septembre 2019
Messages
47
Reactions
250
#7
Woah j’adore ! Serait tu d’accord pour partager la source ? Ou au moins détailler complètement comment tu a fais pour l’adapter réseau etc ?
J’avoue ne ps avoir trop de connaissance en réseau et j’ai du mal à comprendre ton diagramme.m bien qu’il soit super détaillé
Flemme de drop les sources mais fais ça par étape,

Pour binder ton client sur un adaptateur spécifique c'est simple, tu hook la fonction connect() (ws2_32.dll) et tu bind sur ton interface réseau avant de te connecter, tu peux même rajouter un proxy.

bind:
sockaddr_in adapterName{};
adapterName.sin_addr.s_addr = inet_addr("x.x.x.x"); // ip de l'adaptateur réseau
adapterName.sin_family = AF_INET;
adapterName.sin_port = 0;
bind(s, (sockaddr*)&adapterName, sizeof(adapterName));
Par contre un truc auquel il faut faire attention, sur le client electron il faut que ce soit le bon processus que tu hook (celui lancé avec --utility-sub-type=network.mojom.NetworkService en arguments)
 

AzureHaze

Contributeur
Inscrit
27 Septembre 2019
Messages
47
Reactions
250
#8
Pas encore released et pas forcément à vendre non plus (c'est pas l'idée du forum). Mais si je pouvais t'aider à dev le tien ce serait avec plaisir.

Si ça peut t'aider voilà ce que j'utilise pour émuler le launcher directement au niveau de mon client:

emulateur launcher:
std::optional<std::string> GetToken()
{
    CURL* curl;
    CURLcode res;
    curl = curl_easy_init();
    std::string token;

    try
    {
        const auto data = std::format("login={}&password={}&game_id=101", globals::login, globals::password);
        struct curl_slist* headers = nullptr;
        
        headers = curl_slist_append(headers, "Content-Type: application/json");
        curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
        curl_easy_setopt(curl, CURLOPT_URL, "https://haapi.ankama.com/json/Ankama/v5/Api/CreateApiKey");
        curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
        curl_easy_setopt(curl, CURLOPT_DEFAULT_PROTOCOL, "https");
        curl_easy_setopt(curl, CURLOPT_USERAGENT, "Zaap 3.7.4");
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data.data());
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, onResponseWrite);

        res = curl_easy_perform(curl);

        auto json = nlohmann::json::parse(buffer);
        const auto apiKey = json["key"].get<std::string>();

        buffer.clear();
        curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET");
        curl_easy_setopt(curl, CURLOPT_URL, "https://haapi.ankama.com/json/Ankama/v5/Account/CreateToken?game=101");
        headers = curl_slist_append(headers, std::format("apiKey: {}", apiKey.data()).data());
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
        res = curl_easy_perform(curl);

        json = nlohmann::json::parse(buffer);
        token = json["token"].get<std::string>();

        buffer.clear();
    }
    catch (...)
    {
        MessageBoxA(0, "Failed to get game token!", "error", 0);
    }

    curl_easy_cleanup(curl);

    return token;
}

DWORD WINAPI StartLauncherEmulator(LPVOID lpData)
{
    SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    std::array<char, 4086> buffer{ 0 };

    SOCKADDR_IN name;
    name.sin_addr.s_addr = inet_addr("127.0.0.1");
    name.sin_port = htons(globals::launcherPort);
    name.sin_family = AF_INET;

    bind(s, (SOCKADDR*)&name, sizeof(name));
    listen(s, 1);

    SOCKET client = accept(s, nullptr, nullptr);

    int bytesRead = recv(client, buffer.data(), std::size(buffer), 0);
    auto token = GetToken();
    auto response = std::format("auth_getGameToken {}", token->data()) + '\0';

    WSABUF buf;
    buf.buf = response.data();
    buf.len = response.size();
    DWORD bytesSent = 0;
    
    WSASend(client, &buf, 1, &bytesSent, 0, nullptr, nullptr);
  
    closesocket(s);
    closesocket(client);

    return 0u;
}
 
Dernière édition:
Inscrit
2 Mars 2022
Messages
4
Reactions
6
#9
Pas encore released et pas forcément à vendre non plus (c'est pas l'idée du forum). Mais si je pouvais t'aider à dev le tien ce serait avec plaisir
si quiero aprender pero no se nada de programacion :( estoy 0/0 aun asi puedes? y donde podria contactarte?
 
Inscrit
25 Octobre 2022
Messages
6
Reactions
1
#10
Pas encore released et pas forcément à vendre non plus (c'est pas l'idée du forum). Mais si je pouvais t'aider à dev le tien ce serait avec plaisir.

Si ça peut t'aider voilà ce que j'utilise pour émuler le launcher directement au niveau de mon client:

emulateur launcher:
std::optional<std::string> GetToken()
{
    CURL* curl;
    CURLcode res;
    curl = curl_easy_init();
    std::string token;

    try
    {
        const auto data = std::format("login={}&password={}&game_id=101", globals::login, globals::password);
        struct curl_slist* headers = nullptr;
       
        headers = curl_slist_append(headers, "Content-Type: application/json");
        curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
        curl_easy_setopt(curl, CURLOPT_URL, "https://haapi.ankama.com/json/Ankama/v5/Api/CreateApiKey");
        curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
        curl_easy_setopt(curl, CURLOPT_DEFAULT_PROTOCOL, "https");
        curl_easy_setopt(curl, CURLOPT_USERAGENT, "Zaap 3.7.4");
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data.data());
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, onResponseWrite);

        res = curl_easy_perform(curl);

        auto json = nlohmann::json::parse(buffer);
        const auto apiKey = json["key"].get<std::string>();

        buffer.clear();
        curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET");
        curl_easy_setopt(curl, CURLOPT_URL, "https://haapi.ankama.com/json/Ankama/v5/Account/CreateToken?game=101");
        headers = curl_slist_append(headers, std::format("apiKey: {}", apiKey.data()).data());
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
        res = curl_easy_perform(curl);

        json = nlohmann::json::parse(buffer);
        token = json["token"].get<std::string>();

        buffer.clear();
    }
    catch (...)
    {
        MessageBoxA(0, "Failed to get game token!", "error", 0);
    }

    curl_easy_cleanup(curl);

    return token;
}

DWORD WINAPI StartLauncherEmulator(LPVOID lpData)
{
    SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    std::array<char, 4086> buffer{ 0 };

    SOCKADDR_IN name;
    name.sin_addr.s_addr = inet_addr("127.0.0.1");
    name.sin_port = htons(globals::launcherPort);
    name.sin_family = AF_INET;

    bind(s, (SOCKADDR*)&name, sizeof(name));
    listen(s, 1);

    SOCKET client = accept(s, nullptr, nullptr);

    int bytesRead = recv(client, buffer.data(), std::size(buffer), 0);
    auto token = GetToken();
    auto response = std::format("auth_getGameToken {}", token->data()) + '\0';

    WSABUF buf;
    buf.buf = response.data();
    buf.len = response.size();
    DWORD bytesSent = 0;
   
    WSASend(client, &buf, 1, &bytesSent, 0, nullptr, nullptr);
 
    closesocket(s);
    closesocket(client);

    return 0u;
}
Est-ce que tu peux me contacter en priver qu’on puisse passer sur discord pour en discuter ?
 
Inscrit
25 Octobre 2022
Messages
6
Reactions
1
#13

AzureHaze

Contributeur
Inscrit
27 Septembre 2019
Messages
47
Reactions
250
#14
Salut merci pour les sources ça pourrait être utile mais je ne comprends pas pourquoi le hash est code en dur, je n’ai pas essayé de lancer le jeu avec ta valeur, on a un code fonctionnel pour rétro mais pas sur la version 2 :/
Ca semble pas poser de problème sur retro que le client n'ait pas défini le hash id mais sur d2 il tente pas de se connecter au launcher si on lui passe pas en argument ^-^
 
Inscrit
11 Mai 2016
Messages
1
Reactions
0
#16
Pas encore released et pas forcément à vendre non plus (c'est pas l'idée du forum). Mais si je pouvais t'aider à dev le tien ce serait avec plaisir.

Si ça peut t'aider voilà ce que j'utilise pour émuler le launcher directement au niveau de mon client:

emulateur launcher:
std::optional<std::string> GetToken()
{
    CURL* curl;
    CURLcode res;
    curl = curl_easy_init();
    std::string token;

    try
    {
        const auto data = std::format("login={}&password={}&game_id=101", globals::login, globals::password);
        struct curl_slist* headers = nullptr;
       
        headers = curl_slist_append(headers, "Content-Type: application/json");
        curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
        curl_easy_setopt(curl, CURLOPT_URL, "https://haapi.ankama.com/json/Ankama/v5/Api/CreateApiKey");
        curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
        curl_easy_setopt(curl, CURLOPT_DEFAULT_PROTOCOL, "https");
        curl_easy_setopt(curl, CURLOPT_USERAGENT, "Zaap 3.7.4");
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data.data());
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, onResponseWrite);

        res = curl_easy_perform(curl);

        auto json = nlohmann::json::parse(buffer);
        const auto apiKey = json["key"].get<std::string>();

        buffer.clear();
        curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET");
        curl_easy_setopt(curl, CURLOPT_URL, "https://haapi.ankama.com/json/Ankama/v5/Account/CreateToken?game=101");
        headers = curl_slist_append(headers, std::format("apiKey: {}", apiKey.data()).data());
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
        res = curl_easy_perform(curl);

        json = nlohmann::json::parse(buffer);
        token = json["token"].get<std::string>();

        buffer.clear();
    }
    catch (...)
    {
        MessageBoxA(0, "Failed to get game token!", "error", 0);
    }

    curl_easy_cleanup(curl);

    return token;
}

DWORD WINAPI StartLauncherEmulator(LPVOID lpData)
{
    SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    std::array<char, 4086> buffer{ 0 };

    SOCKADDR_IN name;
    name.sin_addr.s_addr = inet_addr("127.0.0.1");
    name.sin_port = htons(globals::launcherPort);
    name.sin_family = AF_INET;

    bind(s, (SOCKADDR*)&name, sizeof(name));
    listen(s, 1);

    SOCKET client = accept(s, nullptr, nullptr);

    int bytesRead = recv(client, buffer.data(), std::size(buffer), 0);
    auto token = GetToken();
    auto response = std::format("auth_getGameToken {}", token->data()) + '\0';

    WSABUF buf;
    buf.buf = response.data();
    buf.len = response.size();
    DWORD bytesSent = 0;
   
    WSASend(client, &buf, 1, &bytesSent, 0, nullptr, nullptr);
 
    closesocket(s);
    closesocket(client);

    return 0u;
}
Lorsque j'utilise ce code, j'ai un code d'erreur 1020 quelqu'un sait à quoi ça correspond ?
 
Inscrit
17 Mai 2021
Messages
15
Reactions
12
#17
Lorsque j'utilise ce code, j'ai un code d'erreur 1020 quelqu'un sait à quoi ça correspond ?
Oui c'est le code retour de cloudflare qui est un WAF (wab application firewall), il détecte les requêtes douteuses. Pour contourner ça tente de forcer le tls 3, fait des test avec postman pour voir déjà si la requête fonctionne avant de l'implémenter dans du code.
Fait attention aux entêtes et aux paramètres de ta requêtes.

Le tout c'est de tester et re tester jusqu'à ce que ta requête passe avec certains paramètres. C'est pas une science exacte les protections cloudflare car personne sait vraiment comment elles fonctionnent.
 
Haut Bas