C/C++ [Full Socket] RawDataMessage

Gohu

Membre Actif
Inscrit
16 Novembre 2013
Messages
222
J'aime
2
#1
Salut à tous,

Ca fait maintenant deux petites semaines que je me prends la tete avec le RawDataMessage. Je pense en avoir bien compris le début mais je bloque à un moment...
Je m'explique: j'ai décodé toutes les strings contenues dans les fichiers binaires. J'ai aussi compris qu'un byteArray était créé avec 16 bytes random. Dans les strings des fichiers binaires se trouvent un sorte de clef en base 64 (e.g: "ZNt7w9/VHucoJJdjSIMWzg==")

J'ai aussi compris le fait que un byteArray était créé contenant le gameServerTicket en writeUTF. La ou je bloque c'est au moment ou des opérations encore inconnues sont effectués avec le MAP_CELLS_COUNT, le byteArray de 16 bytes aléatoire et la clef en base 64 du fichier binaires. Le tout semble générer une clef utilisée pour le cipher en "simple-aes" (avec un objet PKCS5 avec comme blockSize 0 en troisième paramètre de la fonction getCipher) puis encodé en base64 puis envoyé par mp à GameServer.

Tout cela est à peu près mon état d'avancement mais comme je vous l'ai deja dis je bloque au niveau de ces opérations inconnues entrain les deux byteArrays et le MAP_CELLS_COUNT.

Un peu d'aide ne serait pas de refus, ou quelques indices pour me mettre sur une éventuelle piste
Merci d'avance pour votre aide!
 
A

Anonymous

Invité
#2
Salut,

J'ai le même problème que toi Gohu. Bot socket et impossible de rétablir la connexion depuis la dernière maj.
Je précise que mon bot est en as3 et que j'utilise FlashBuilder comme environnement de développement. Ca peut paraître simple (et en général ça l'est) du fait que je peux utiliser directement les sources en as3, mais la décompilation réserve parfois quelques surprises, en plus des subtilités plus liées à la logique et à l'algorithmique.

J'ai un peu avancé sur le décryptage et voici ce que ça donne :

- Le seul endroit où la classe RawDataMessage.as est instanciée est la classe d***s.logic.common.frames.ServerControlFrame.as.

- A ce moment, et à l'aide de la D***sPublicKey (contenue dans les binaries incorporés au D***sInvoker.swf), le contenu du RawDataMessage est converti à la volée en fichier swf qui se lance aussitôt en provoquant chez moi une erreur :

TypeError: Error #2007: Parameter value must be non-null.
at flash.utils::ByteArray/writeUTF()
at HumanCheck()



- En sauvegardant ce fichier swf en dur sur le disque (il peut avoir un poids variable aux alentours de 5ko), je le décompile et je trouve bien (entre autres) la classe HumanCheck.as. Le problème c'est que cette classe ne sort rien à la décompilation : elle fait planter le Sothink swf decomp et JPEXS me donne une erreur même en cochant la case de déobfuscation :

/*
* Erreur de décompilation
* Le code est probablement obsfusqué
* Type d'erreur: EmptyStackException
*/


donc bloqué à ce point sans encore connaître l'action de cette classe qui semble imortante.

- Le fichier swf contient aussi des binaries. mais là encore, impossible pour l'instant de savoir l'importance qu'ils ont.
Il me faudrait réussir à voir les sources de ce swf qui à mon avis détient les instructions d'envoi du mp au GameServer.

Gohu, je ne sais pas trop à quelle étape se trouve ce que tu décris/expliques dans ton post, mais peut-être qu'en associant nos idées on pourra trouver la solution.

Je joins le fameux fichier swf si ça peut intéresser qq1, ou si qq1 arrive à le décompiler correctement.

Atlantide
 
Inscrit
5 Mai 2012
Messages
368
J'aime
48
#3
Salut, j'avais entamé il y a quelques jours de mettre au propre les source de l'anti-bot, voici le code : https://github.com/LuaxY/Dofus-Anti-Bot
Il faudrais que je termine et n'oubliez pas que les bytes et base64 utilisé sont dynamique, ne prenez pas ceux que j'ai mis sur le dépot.

Pour ce qui est des source du client déobfusqué (intégralement), je maintiens a chaque mise à jour les source du client ici : https://github.com/Emudofus/Dofus/tree/master2

Enjoy ;)
 

Gohu

Membre Actif
Inscrit
16 Novembre 2013
Messages
222
J'aime
2
#4
Super merci sorrow!
Atlantide j'ai reussi a deobfu la classe a l'arrache le mieux serait que on
on discute sur skype
 
Dernière édition:
A

Anonymous

Invité
#5
Merci Sorrow, super utile :)

Sinon Gohu, là je suis 2 semaines en vacances au bord de la mer, alors je passe un temps minimum sur l'ordi, quelques minutes tout au plus par jour. Donc pour le skype, il faudra attendre que je rentre et que je me créé un compte... eh oui... pas encore "in touch" :(
Mais si tu veux, en attendant, on peut continuer le dialogue à vitesse réduite ici sur le forum.

En tout cas, je vois que vous avez déjà une bonne longueur d'avance sur moi en ce qui concerne le système anti-bot. Il faut aussi que j'étudie les sources de Sorrow à ce sujet, car la partie de récupération et de traitement automatique des binaires dynamiques me semble un peu ... balèze ;)

J'ai déjà une question qui me vient à l'esprit : je ne retrouve nulle part dans le code original du jeu, la partie qui gère automatiquement le remplissage des data1 et data2, codés en dur dans le code de Sorrow (dans la classe HumanCheck) ?

Mais bon, je n'ai pas vraiment encore eu le temps de chercher...

Alors merci encore à vous deux et à plus.

Atlantide
 
Inscrit
5 Mai 2012
Messages
368
J'aime
48
#6
Il ya a des données random dans le HumanCheck mais également dans les binaryData, c'est là que tu trouvera les strings, dont le base64, mais pour les obtenir c'est à coup d'opération XOR, j'ai pas encore mis le code au claire sur cette partie.
 
A

Anonymous

Invité
#8
Salut à tous

Quelqu'un pourrait-il m'envoyer la classe HumanCheck.as dans sa forme brute, désobfusquée de préférence, mais même obfusquée c'est pas grave. Celle de Sorrow donnée en lien un peu plus haut me semble retouchée de manière à ce qu'elle soit fonctionnelle, mais j'aimerais pouvoir analyser le code brut de décoffrage :)

Sinon, quel outil avez-vous utilisé pour extraire cette classe ? Quel décompileur ou désobfusqueur ? Moi j'ai essayé avec les classiques Sothink et JPEXS, mais ça n'a pas marché :(

Merci d'avance à vous

Atlantide
 
A

Anonymous

Invité
#11
Voila c'est ok. J'ai réussi à relancer ma connexion.
Mais je n'ai eu aucun souci de traitement des datas dynamiques puisque je laisse le HumanCheck dynamique original s'exécuter comme un grand. Il fallait juste que je synchronise correctement les autres classes du DI.swf qu'il utilise. C'est à cela que m'a servi le code brut de la classe HumanCheck.as.
Malheureusement, je n'ai pas grand chose à vous apporter étant donné que je n'ai pas (trop) eu à mettre les mains dans le cambouis ;)
Merci encore pour votre aide, et si je peux vous être d'une quelconque utilité, n'hésitez pas à me demander (je ne sais d'ailleurs même pas si de votre côté, vous avez terminé de recoder votre connexion).

Atlantide
 

Gohu

Membre Actif
Inscrit
16 Novembre 2013
Messages
222
J'aime
2
#12
Pour ma part je suis entrain de mettre en place la gestion du paquet de maniere dynamique.
Ma connection ne devrait plus trop tarder
 

Gohu

Membre Actif
Inscrit
16 Novembre 2013
Messages
222
J'aime
2
#13
Bon je reviens car ca dois faire 2 jours que je tourne en rond.
J'envoie le MP a GameServer mais a chaques fois je me fais recaler et il semblerait que cela vienne de ma clef d'encryption qui n'es pas bonne car en sniffant juste apres je recupère le mp envoyé par le client mais je n'arrive pas a décrypter le message or cela devrait etre le cas car le raw change toutes les 90 donc la clef utilisée par le client devrait etre la meme

donc voici mon code de génération de la clef:
Code:
    RpnParser p(path + "/RDM/Assets/HumanCheck.as");
    QList<int> result = p.parseFile(); //list des entiers des 16 writeBytes
    m_decryptKey = m_binariesStrings[p.getDecryptKeyPos(decryptInt)]; //byteArray avec la key en b64 random --> vérifié plusieurs fois et contients les bonnes valeurs pour sur!

    Writer w1;
    foreach (int i, result)
        w1.writeByte(i); //16 bytes random --> vérifiés plusieurs fois et contients les bonnes valeurs pour sur!

    QByteArray data1 = w1.getBuffer();    
    for (int i = 0; i < data1.size(); i++)
        m_key[i] = (data1[i] ^ (m_decryptKey[i % m_decryptKey.size()] * 2));
 
A

Anonymous

Invité
#15
j'ai bien vu ton message gohu, mais c'est au-dessus de mes compétences.
D'une part je n'ai pas eu pour moi-même à entrer dans le code de cryptage et à l'analyser.
D'autre part le C/C++ n'est pas le langage que j'utilise.

Mais c'est bien de la connexion initiale au gameserver que tu parles ?
Parce que 2 à 3 min après s'être connecté, le serveur renvoie un second RawDataMessage 2x moins lourd, et qui contient un HumanCheck différent et qui donc se traite différemment. Il se solde par l'envoi au serveur d'un CheckIntegrityMessage : nouvelle classe fournie par le HumanCheck.

Désolé de ne pas pouvoir en faire davantage. Peut-être qq1 d'autre reprendra-t-il le flambeau ?
Atlantide
 
Inscrit
5 Mai 2012
Messages
368
J'aime
48
#16
Le CheckIntegrityMessage de mémoire c'est juste un random quelconque (négatif me semble). C'est l'ancien anti-bot.
 
A

Anonymous

Invité
#17
Bonjour à tous...

Désolé de UP, mais à nouvelle maj, nouveaux problèmes...
Il semble que AG ait relevé d'un cran la complexité de son système anti-bot :(

La méthode sendTicket() de la classe HumanCheck me cause de méchants ennuis, par le biais d'une drôle de méthode nommée "MethodInfo-6()":

ArgumentError: Error #2004: One of the parameters is invalid.
at Error$/throwError()
at flash.filesystem::File/set nativePath()
at flash.filesystem::File()
at HumanCheck/sendTicket()
at MethodInfo-6()

Mais vu le code que me sort le decompiler pour la classe HumanCheck.as, difficile de débugger quoi que ce soit.
Quelqu'un aurait-il déjà rendu cette classe lisible ou du moins la méthode "sendTicket()" ?
Et dans le cas contraire, pourrait-on m'expliquer comment on déchiffre les portions de code du type :

Code:
_SafeStr_2._SafeStr_7(-1820302788)
Voilà, pour l'instant je cale ! Et ça commence à me faire peur... 2 maj coup sur coup qui me terrassent... ou peut-être devrais-je me remettre en question et retourner à l'école ? Il existe des écoles pour ça ??? :)

Merci d'avance

Atlantide
 
A

Anonymous

Invité
#18
ooops... j'oubliais de joindre le fichier dynamique issu du RawDataMessage... Sa taille a aussi sérieusement augmenté depuis la 2.21 ; de 5 à 48 ko !
On ne soucie plus de la bande passante des clients chez AG ;)
 

Gohu

Membre Actif
Inscrit
16 Novembre 2013
Messages
222
J'aime
2
#19
Salut atlantide!
J'ai EXACTEMENT le meme probleme sur la methode-6 qui appelle la fonction nativePath (c'est elle qui bug) et le path que elle lui donne n'est autre que... DofusInvoker.swf! Et oui...
Je ne sais pas pourquoi mais quand j'execute en as3 j'ai exactement le meme probleme. Peut etre que le raw detecte un debugger et redirige sur un code qui crash ?
 
Dernière édition:
Inscrit
9 Novembre 2017
Messages
21
J'aime
1
#20
  • [21:37:00:185] [Worker] Adding frame: [object SocialDataFrame]
  • [21:37:00:185] [Worker] Adding frame: [object DareFrame]
  • [21:37:00:186] [ServerConnection] [server_game] [SND] > FriendsGetListMessage @50
  • [21:37:00:187] [ServerConnection] [server_game] [SND] > AcquaintancesGetListMessage @51
  • [21:37:00:188] [ServerConnection] [server_game] [SND] > IgnoredGetListMessage @52
  • [21:37:00:189] [ServerConnection] [server_game] [SND] > SpouseGetInformationsMessage @53

  • [21:37:00:217] [ErrorManager] Error : 'TypeError: Error #1010: A term is undefined and has no properties.'(how to solve this error?)

  • [21:37:00:814] [Worker] Adding frame: [object SocialDataFrame]
  • [21:37:00:815] [Worker] Adding frame: [object DareFrame]
  • [21:37:00:815] [ServerConnection] [server_game] [SND] > FriendsGetListMessage @54
  • [21:37:00:815] [ServerConnection] [server_game] [SND] > AcquaintancesGetListMessage @55
  • [21:37:00:816] [ServerConnection] [server_game] [SND] > IgnoredGetListMessage @56
  • [21:37:00:816] [ServerConnection] [server_game] [SND] > SpouseGetInformationsMessage @57
  • [21:37:00:825] [ErrorManager] Error : 'Error: chat is already used by an other option manager.'
 
Haut Bas