Python Création de mon Bot MITM - Dofus Retro

Inscrit
24 Février 2024
Messages
8
Reactions
6
#1
Bonjour,


Depuis peu, je me suis lancé un défi : Me créer un BOT MITM en partant de 0 pour DOFUS RETRO.

Ce poste aura pour but de partager mes attentes, mes expériences, mes résultats et mes questions.

J'ai quelques bases en réseaux et en programmation avec le langage Python, c'est d'ailleurs ce langage que je compte utiliser principalement.

Ca fait quelques jours que je me suis lancé dans ce projet.
J'ai pas mal parcouru le forum Cadernis et il fallait bien commencé quelque part alors j'ai commencé mes toutes premières expériences avec Wireshark.


Objectif 1 : Installer et comprendre les bases de Wireshark - OK
Objectif 2 :
Trouver les échanges entre ma carte réseau et le serveur Allisteria - OK
Objectif 3 :
Récupérer les infos nécessaires pour passer sur la création de mon script avec pyshark (adresse IP du serveur, Port, etc...) - OK
Objectif 4 :
Créer un script Python (avec pyshark) pour récupérer et afficher dans mon terminal les paquets envoyés et reçus - OK
Objectif 5 :
Traduire les paquets bruts pour avoir un résultat compréhensible (héxadécimale -> chaîne de caractères en remplaçant les caractères non imprimables) - OK
Objectif 6:
Essayer de traduire un paquet en utilisant les infos trouvés sur le net - OK
(par exemple) grâce au Diagramme des packets Dofus : Lien Cadernis vers le Diagramme

Après quelques heures de tests, j'ai remarqué que certains paquets avaient bien évolués depuis l'époque du Diagramme des packets Dofus.

Voici ce que j'ai pu décrypter d'un paquet GM.
Pas certain que tout soit exacte mais c'est ce que j'ai déduis lors de mes tests, si vous connaissez les "Infos Inconnues", ou si vous voyez des informations erronés, je suis preneur.
(Informations récupérés sur le paquet d'un joueur au hasard.)

PACKET GM TRADUCTION BRUT
info_packet_gm.png

PACKET GM TRADUCTION AVEC MON SCRIPT PYTHON
packet_gm_traduit.png

On peut voir dans ACCESSOIRES, qu'il n'arrive pas a me donner le nom des items avec l'ID 12958 et l'ID 12809, c'est simplement parce que j'utilise un ancien fichier txt de Maxoubot, Objets.txt pour chercher les infos.

Ce sont simplement des items qui ont été rajoutés par la suite et mon fichier Objets.txt n'est pas à jour.

Il y a aussi quelques différences lorsque le joueur porte des items Obvijevan, des items Polykrome, une dinde Caméléone, etc...
Pour le moment, j'ai juste gérer les erreurs du script, j'ai pas réussi a traduire toutes ces informations, pareil pour les emblèmes, mais ça viendra, ça me passionne vraiment et je suis motivé.

Globalement, la plus part des paquets GM qui ont des informations associés à une entité se ressemblent plus ou moins.
J'ai pu remarqué qu'il y a quelques différences entre les paquets GM hors combat, en combat et aussi si les joueurs sont connectés ou en mode marchand, si c'est une autre entité (comme par exemple un PNJ, un Percepteur, etc...).


Objectif 7: Trouver la fameuse signature des paquets - OK

Pendant mes expériences, j'ai pu remarqué la présence d'une signature des paquets sur version modern qu'on ne retrouve pas sur la version legacy.

Pour le moment, j'ai aucune idée de comment décrypter cette signature pour, plus tard, pouvoir reproduire cette signature lors de mes envoies de paquets via mes scripts pour effectuer des actions via les scripts.
Chaque chose en son temps, je suis encore loin de cette étape.

EXEMPLE D'UN PAQUET EN MODERN (censuré)
paquet_crypte_modern_censure.png

EXEMPLE D'UN PAQUET EN LEGACY (censuré)
paquet_legacy_censure.png



Objectif 8: Récupérer les infos venant du launcher DOFUS (globalement refaisant les objectifs 2 a 5 mais pour le launcher) - OK

Première chose, j'ai remarqué que le launcher pouvait avoir deux IP suivant le moment de connexion.
Ensuite, je suis tombé sur des informations qui me semblaient importantes (dans un Layer HTTP2), j'ai adapté mon script pour enlever tous les paquets superflus, viser uniquement ce Layer HTTP2 spécifique et y récupérer uniquement ce que je voulais.

Quand j'ouvrais le launcher, j'avais des centaines de paquets, il a fallu faire un tri pour garder uniquement ce que je voulais garder, et ce n'était pas si simple, mes compétences en programmation sont très basique, heureusement avec des bons prompt, chatGPT m'a solutionné le tout !


Voici a quoi ça ressemble (pour le moment je ne sais pas si j'aurai besoin de ces données mais je trouvais ça intéressant xD)
1er paquet : OUVERTURE DU LAUNCHER
2eme paquet : LANCEMENT DU COMPTE POUR SE CONNECTER EN JEU

paquet_launcher_censure.png

Pour le moment, mes découvertes s'arrêtent là.

Pour la suite, j'aimerai :
- Comprendre les données se trouvant dans les fichiers .swf décompilés via la décompilation des fichiers avec JPEXS
Pour le moment je comprends rien, je ne sais pas quel fichier .swf spécifique je dois décompiler et comment comprendre et extraire les données nécessaires pour avancer.

- Réussir a me placer entre ma carte réseau et le serveur pour pouvoir récupérer, interpréter et renvoyer des paquets au serveur de jeu (MITM)
A ce niveau là, je connais rien, je dois découvrir le fonctionnement de base et comment je peux mettre cela en place.

Voici quelques infos que certains voudront surement récupérer et que je peux partager :
A date du 24/02/2024
server_ip_allisteria =
'172.65.210.126'
port : 443


Je rappel que je débute de 0, je n'avais aucunes connaissances du fonctionnement avant mon démarrage dans ce projet.
Assez d'infos pour commencer, merci de m'avoir lu, n'hésitez pas a participer si le sujet vous intéresse et/ou si vous souhaitez m'aider.
 
Dernière édition:
Inscrit
24 Février 2024
Messages
8
Reactions
6
#2
Objectif 9 : Comprendre, décompiler, extraire, formater les données se trouvant dans les fichiers .swf - OK

J'ai fais quelques recherches pour réussir a avoir les dernières données du jeu.

Pour cela je suis tombé sur : https://github.com/Dysta/PyLangGetter

Grâce à cela, j'ai récupéré le dossier lang où se trouve tous les .swf qui m'intéressent.

J'ai utilisé JPEXS pour décompiler les DoAction qui se trouvent dans "scripts" et j'ai tout exporter sous format .as (ActionScript)

J'ai ensuite créer un script Python pour récupérer les données dans le fichier, les formatés dans le même genre que l'ancien fichier Objets.txt que j'utilisais dans mon script pour le formatage des paquets GM.

ID|NOM DE L'OBJET|DESCRIPTION DE L'OBJET

J'ai commencé par remettre mon fichier Objets.txt à jour grâce aux données récupérés et formattés du fichier item_fr.swf

Et voilà ce que ça me donne.
AVANT
accessoires_nok.png

APRES
accessoires_ok.png


:inlove:

Pour résumer, j'arrive maintenant a récupérer les dernières versions des fichiers du jeu nécessaire pour mon projet.
Décompilation OK
Exportation OK
Formatage OK
Utilisation des données OK


Hier je n'y comprenais que dalle, j'étais bloqué la dessus, bien content d'avoir pu avancer grâce au forum Cadernis et a mes recherches !

Plus tard je pense mettre toutes ces informations dans des bases de données type sqlite plutôt que de passer par un fichier.txt

Je vais continuer de fouiller un peu dans les fichiers du jeu pour voir ce que je peux y trouver d'intéressant et ensuite je me lance dans l'objectif 10 : Réussir a me placer entre ma carte réseau et le serveur pour pouvoir récupérer, interpréter et renvoyer des paquets au serveur de jeu (MITM)

Ca sera une autre paire de manche, mais comme pour tout, on va fouiller et expérimenter =).
 
Dernière édition:
Inscrit
24 Février 2024
Messages
8
Reactions
6
#3
Aujourd'hui, je me suis attaqué à l'objectif 10 et je sens que ça va être bien compliqué cette histoire...

Je me suis basé sur d'ancien fichier vb (Connexion_Token.vb) puis j'ai reproduis ça en Python.

J'ai donc fais un script pour essayer de récupérer la clé API en envoyant une requête POST à https://haapi.ankama.com/json/Ankama/v5/Api/CreateApiKey

Et pour le token :

url = "https://haapi.ankama.com/json/Ankama/v5/Account/CreateToken?game=101"
headers = {
'apiKey': api_key,
'user-agent': 'Zaap 3.12.8'
}

Cependant, je me retrouve avec l'erreur suivante : {"status":422,"message":"Guest account only for game 102"}
Message qui me signifie que je n'ai pas les droits nécessaires pour récupérer ce que je veux via cet API.

Alors peut-être qu'a l'époque il n'y avait pas de sécurité a ce niveau, mais aujourd'hui, c'est le cas.

Je suis un peu bloqué…

Si quelqu'un sait comment récupérer d'une autre façon la clé API, j'aimerai bien avoir cette information.

Merci d'avance pour votre aide !
 
Inscrit
24 Février 2024
Messages
8
Reactions
6
#4
Toujours dans mes tests, j'ai vraiment beaucoup de mal a mettre en place la connexion avec le proxy pour pouvoir ensuite envoyer des paquets perso au serveur.

Pour récapituler, je sais que lors du lancement du launcher (que le launcher peut communiquer avec différentes adresses IPs), je récupère un LAYER HTTP2 dans un HEADER avec plusieurs informations (apikey, certificat_id, certificat_hash)

Lors du lancement du launcher, le path est avec un game=99, a ce moment là, le certificat_id et le certificat_hash sont vides.
(path: /json/Ankama/v5/Account/CreateToken?game=99&certificate_id=&certificate_hash=)

Lors de la connexion de mon compte Dofus Retro, j'ai un path avec un game=101 et a ce moment là, j'ai un certificat_id et un certificat_hash qui vont être générés/récupérés ?.
(les valeurs ci-dessous ont été modifiés pour éviter que je me fasse taper sur les doigts par Ankama directement :'(
(path: /json/Ankama/v5/Account/CreateToken?game=101&certificate_id=365984859&certificate_hash=5123654f8549a333g256d95958974b54ve365b154c19f9c3d12535a3658595489)

Mais je ne sais pas si j'vais avoir besoin de cette apikey ou des certificats_id et hash...

Maintenant, je ne sais pas comment mettre en place mon proxy, comment le setup, comment faire pour que je puisse enfin envoyé des paquets au serveur pour par exemple faire bouger mon personnage...

J'ai parcouru le forum dans tous les sens, mais j'avance pas...Le dernier poste que j'ai lu est celui-ci : https://cadernis.fr/index.php?threads/mitm-d-fus.2722/

Il m'a permit de comprendre certaines choses, mais j'ai quand même l'impression de faire du surplace.

Ce que je voudrai faire actuellement (j'utilise Python), c'est :
- Setup un proxy au milieu (entre le serveur et mon client (j'ai pensé a utiliser fritm)
- Connecter mon compte Dofus Retro
- Lancer mon MITM (pour avoir le proxy qui s'active entre le serveur et mon client)
- Pouvoir visualiser les paquets entrants et sortants sur mon interface Tkinter (ou autre)
- Pouvoir envoyer un paquet via un send_packet, par exemple, un packet de déplacement pour faire bouger mon personnage.

Pour le moment je vois personne qui n'a répondu a mes posts, le forum est-il mort ?
Merci d'avance à ceux qui essayeront de m'aider.
 
Dernière édition:
Inscrit
7 Octobre 2019
Messages
18
Reactions
5
#5
Salut,
je ne sais pas si le forum est mort mais je vais essayer de t'aider un (un copain python ça fait plaisir).
Setup un proxy au milieu=> pour ce cas je pense que Fritm est une bonne alternative tu peux hook le PID de ton client, le 3ème plus précisément.
Connecter mon compte Dofus Retro=> moi j'ai utiliser postman pour vraiment voir comment récupérer l'apikey et j'ai traduit en python directement sur l'application ( !!je crois qu'il faut faire uniquement les requêtes en http non avec requests)
Lancer mon MITM + visualiser les paquets => je pense qu'une fois hook ton client tu pourras rediriger dans proxy et voir les paquets.

En tout cas , bon courage pour la suite :)
 
Inscrit
24 Février 2024
Messages
8
Reactions
6
#6
Salut,
je ne sais pas si le forum est mort mais je vais essayer de t'aider un (un copain python ça fait plaisir).
Setup un proxy au milieu=> pour ce cas je pense que Fritm est une bonne alternative tu peux hook le PID de ton client, le 3ème plus précisément.
Connecter mon compte Dofus Retro=> moi j'ai utiliser postman pour vraiment voir comment récupérer l'apikey et j'ai traduit en python directement sur l'application ( !!je crois qu'il faut faire uniquement les requêtes en http non avec requests)
Lancer mon MITM + visualiser les paquets => je pense qu'une fois hook ton client tu pourras rediriger dans proxy et voir les paquets.

En tout cas , bon courage pour la suite :)
Salut, je te remercie pour ton aide !

Quand tu dis pour setup le proxy : "le 3ème plus précisément.", tu parles de quoi ?
Ce que j'ai fais c'est :
- Ouvrir le gestionnaire de tâche (affiché les PID)
- Lancer le launcher
- Lancer le compte Dofus Retro

Mais dans mon gestionnaire de tâche, je n'ai qu'un seul Dofus Retro avec un seul PID de visible, du coup je ne comprends pas le "le 3ème plus précisément"

Autre chose, si je coupe et relance le jeu, le PID change a nouveau.

J'ai regardé dans la doc de fritm, et via mon terminal avec help(fritm) je vois que deux packages.

Du coup je comprends pas ce que tu entends par "le 3ème plus précisément."

Si tu peux m'éclairer, je te remercie d'avance :) !

Et désolé encore, je débute !

EDIT 1 :

Hmmm tu parles surement du 3 ème processus de l'ankama launcher, je me trompe ?

Capture d'écran 2024-02-29 165020.png


EDIT 2 :

En attendant une réponse, j'ai regardé rapidement postman, j'ai réussi a récupérer mon token via requests finalement, mais j'ai plusieurs questions.

Dans mon script j'ai rentré l'api, le certificat id et le certificat hash en dur, j'imagine que c'est pas la meilleure solution ?
Après, franchement, je dois tout mélanger et pas trop comprendre ce que je fais, mais je continue a chercher et a avancer :p

Capture d'écran 2024-02-29 134949.png

1) l'apikey, le certificat id et le certificat hash restent toujours les mêmes ? ils sont associés au compte ?
2) pareil pour le token ? il reste toujours le même ou il change ?



Maintenant faut que je vois comment je peux utiliser tout ça, je vais réfléchir a tête reposé mais si tu as des pistes de réflexions pour moi, je suis preneur.
 
Dernière édition:
Inscrit
7 Octobre 2019
Messages
18
Reactions
5
#7
"le 3ème plus précisément.", tu parles de quoi ? => je parle du 3ème PID de dofus rétro.C'est celui là qu'il te faudra pour voir le trafic entre le ton serveur et ton client.
Mais avant il faut bypass le launcher.
Passe en Mp ça sera plus simple

EDIT: De plus je crois que c'est mieux de passer en http plutôt qu'avec request
 
Dernière édition:
Inscrit
24 Février 2024
Messages
8
Reactions
6
#8
Grâce à Janembam, j'avance un petit peu (merci).

Je suis actuellement sur le bypass du launcher et j'ai remarqué plusieurs choses (vous me dîtes si j'ai tort).

Pour pouvoir bypass le launcher il faut :
- login
- password
- apikey
- certificat_id (sinon il nous dit qu'il manque des paramètres de sécurités)
- certificat_hash (sinon il nous dit qu'il manque des paramètres de sécurités)

A l'heure actuelle, j'ai énormément de mal a récupérer les informations via l'API, il me retourne toujours des erreurs du genre :

Erreur API: Statut 422, Réponse: {"status":422,"message":"Missing required parameters 'login'"}

Puis..

Erreur API: Statut 422, Réponse: {"status":422,"message":"Invalid conditions parameters 'game_id' with value '101' for condition 'in : 18;22;102'"}

Du coup, je ne sais pas comment bien paramétrer mon script pour récupérer les informations nécessaires via l'API (apikey, certificat_id et certificat_hash)

En rentrant les informations nécessaires en dur (que j'ai sniffé auparavant avec pyshark), ça fonctionne j'arrive a me connecter sans le launcher :

Capture d'écran 2024-03-02 190339.png

Du coup, je ne suis plus très loin, si quelqu'un sait comment récupérer correctement les données via l'api car le script ci-dessous me retourne des erreurs :

Python:
import http.client
import json
import socket
import ssl

# Informations de connexion chargées depuis des variables ou un fichier de configuration
login = "monnomdecompte"
password = "monmotdepasse"
launcherPort = 26117

def get_api_key(login, password):
    context = ssl._create_unverified_context()
    conn = http.client.HTTPSConnection("haapi.ankama.com", context=context)
  
    payload = f"login={login}&password={password}&game_id=101"
    headers = {"Content-Type": "application/json", "User-Agent": "Zaap 3.12.9"}
  
    conn.request("POST", "/json/Ankama/v5/Api/CreateApiKey", body=payload, headers=headers)
    response = conn.getresponse()
    response_data = response.read().decode()
  
    if response.status != 200:
        print(f"Erreur lors de l'obtention de l'API Key: Statut {response.status}, Réponse: {response_data}")
        conn.close()
        return None
  
    api_key = json.loads(response_data).get("key")
    conn.close()
    return api_key

def get_token():
    api_key = get_api_key(login, password)
    if not api_key:
        print("Impossible d'obtenir l'API Key.")
        return None
  
    context = ssl._create_unverified_context()
    conn = http.client.HTTPSConnection("haapi.ankama.com", context=context)
  
    headers = {"Content-Type": "application/json", "User-Agent": "Zaap 3.12.9", "apikey": api_key}
    conn.request("GET", "/json/Ankama/v5/Account/CreateToken?game=101", headers=headers)
    response = conn.getresponse()
    token = json.loads(response.read().decode()).get("token")
  
    conn.close()
    return token

def start_launcher_emulator():
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.bind(('127.0.0.1', launcherPort))
    server_socket.listen(1)
    print(f"Listening on port {launcherPort}...")
  
    client_socket, addr = server_socket.accept()
    print(f"Connection from {addr} has been established.")
  
    token = get_token()
    if token:
        response = f"auth_getGameToken {token}\0"
        client_socket.sendall(response.encode('utf-8'))
    else:
        print("Échec de l'obtention du token.")
  
    client_socket.close()
    server_socket.close()

if __name__ == "__main__":
    start_launcher_emulator()
Résultat :
Listening on port 26117...
Connection from ('127.0.0.1', XXXXX) has been established.
Erreur lors de l'obtention de l'API Key: Statut 422, Réponse: {"status":422,"message":"Invalid conditions parameters 'game_id' with value '101' for condition 'in : 18;22;102'"}
Impossible d'obtenir l'API Key.
Échec de l'obtention du token.



Merci d'avance pour votre aide, bon week-end ! :)
 
Inscrit
11 Mars 2024
Messages
3
Reactions
0
#9
Pourquoi cherches-tu à bypass le launcher pour faire ton MITM ? Tu n'en as pas besoin ! Si c'est du bonus, pourquoi pas mais sinon ne t’embête pas avec cela.
Tu as avoir un problème bien plus pénible, avec le "packet" `ù` !

Courage à toi !
 
Inscrit
24 Février 2024
Messages
8
Reactions
6
#10
Projet en pause pour le moment, je n'ai pas trop le temps, quand j'aurai le temps, je compte aussi me renseigner aussi sur les possibilités d'optimisation des bots pixels.

Je reviendrai faire un update si j'avance, pour le moment je suis sur autre chose.

Quand tu parles du packet 'ù', tu parles des paquets signés qui se trouvent sur la version "Modern" qui est obligatoire sur Boune ?

Ou c'est autre chose ? (je suis un peu sorti du truc ces dernières semaines.)
 
Inscrit
11 Mars 2024
Messages
3
Reactions
0
#11
Projet en pause pour le moment, je n'ai pas trop le temps, quand j'aurai le temps, je compte aussi me renseigner aussi sur les possibilités d'optimisation des bots pixels.

Je reviendrai faire un update si j'avance, pour le moment je suis sur autre chose.

Quand tu parles du packet 'ù', tu parles des paquets signés qui se trouvent sur la version "Modern" qui est obligatoire sur Boune ?

Ou c'est autre chose ? (je suis un peu sorti du truc ces dernières semaines.)
Oui exactement celui-ci !
 
Haut Bas