C# [1.29] Gestion paquets longs

Inscrit
8 Septembre 2019
Messages
9
Reactions
3
#1
Bonjour à tous,

Je suis en train de développer un bot socket pour d retro et je me retrouve face à un soucis au niveau de la gestion des paquets longs tels que celui de l'inventaire (al).

paquet inventaire:
[01:15] --- al|270;0|49;1|319;0|98;0|147;0|466;1|245;0|515;2|294;0|73;1|122;1|171;1|220;0|490;0|269;0|48;1|318;0|97;0|146;0|465;0|244;0|514;1|23;2|293;0|72;2|121;1|170;2|440;0|219;0|268;0|538;0|47;1|317;0|96;0|145;0|464;1|243;0|513;1|22;2|292;0|71;0|120;2|169;1|218;0|488;1|267;0|537;0|46;1|316;2|95;0|144;0|463;0|512;1|21;0|291;0|70;0|119;1|168;1|217;0|487;0|266;0|536;0|45;1|315;2|94;0|143;1|462;0|511;2|20;0|290;0|69;0|339;0|118;1|167;2|216;0|486;1|44;1|314;2|93;2|461;2|510;2|19;0|289;0|68;1|338;0|117;1|166;0|215;0|485;0|43;1|313;0|92;0|141;0|460;0|509;2|18;0|288;0|67;1|337;0|116;1|165;1|214;0|484;0|42;0|312;0|91;0|140;0|459;0|508;2|17;0|287;0|66;1|336;0|115;2|164;2|213;0|483;0|41;0|311;0|139;0|507;2|16;0|286;0|65;1|335;0|114;1|163;2|212;0|482;2|261;0|40;0|310;0|89;0|138;0|457;0|236;0|506;2|15;0|285;0|64;1|334;0|113;1|162;2|211;0|481;2|260;0|39;0|309;0|88;0|137;0|23 --- Reçu

[01:15] --- 5;0|505;2|14;0|284;0|63;1|333;0|112;1|161;2|210;0|480;0|259;0|38;1|308;0|87;0|136;0|455;1|234;2|504;2|13;0|62;1|332;0|111;2|209;1|479;0|258;0|37;1|307;0|86;0|135;0|454;1|233;0|503;2|12;0|61;2|331;0|110;0|159;0|208;0|478;1|257;0|306;0|85;0|134;0|453;1|232;0|502;2|11;2|281;0|60;0|330;0|109;1|158;0|207;0|477;1|256;0|35;0|84;0|133;0|182;1|452;0|231;1|501;0|10;0|280;2|59;1|329;0|108;1|157;0|206;0|476;0|255;0|34;0|304;0|83;0|132;0|181;0|451;0|230;2|500;2|9;2|279;1|328;0|107;2|156;0|205;0|254;0|33;1|303;0|82;0|131;0|180;0|450;0|229;0|499;0|8;1|278;0|57;2|327;0|106;0|155;0|204;0|474;0|253;2|32;1|302;0|81;1|130;0|179;0|449;0|228;0|498;0|7;2|277;1|56;0|326;0|105;0|154;0|203;0|473;0|252;0|31;0|301;0|80;1|129;0|178;1|448;0|227;0|497;0|6;0|276;1|55;1|325;0|153;0|202;0|472;1|251;0|30;0|300;0|79;1|128;0|177;1|447;0|226;0|496;0|5;2|275;2|54;0|324;0|103;2|152;1|201;0|471;2|250;0|29;1|299;0|78;0|127;0|446;0|225;0|495;0|4;2|274;0|53;2|323;0|102;1|151;0|200;0|470;0|249;0|28;1|298;0|77;0|126;0|175;0|445;0|224;0|494;0|3;2|273;0|322;0|101;0|150;0|469;1|248;0|27;0|297;0|76;1|125;0|174;0|444;0|223;0|493;0|2;1|272;0|51;1|321;0|100;0|149;0|468;1|247;0|26;0|296;0|75;2|124;0|173;0|443;0|222;0|492;0|1;0|271;0|50;1|320;0|99;0|148;0|467;0|246;0|25;2|295;0|74;1|123;1|221;0|491;0|0;0 --- Reçu
Comme vous pouvez le voir, le paquet est reçu dans deux requêtes différentes. Comment est-ce que vous gérez ça ?

Merci d'avance,
Bonne journée
 
Inscrit
27 Septembre 2019
Messages
47
Reactions
250
#2
tu dois trouver le délimiteur et extraire chaque paquet, si tu trouves pas de délimiteur tu gardes dans un buffer le début du paquet et quand tu trouves le prochain délimiteur tu reconstitues le paquet. Tu n'as pas de garantie d'avoir un message complet avec TCP.
Donc ce que tu peux faire c'est juste avoir une string qui correspond au paquet actuel et concaténer jusqu'à ce que tu trouves un délimiteur, si tu trouves un délimiteur tu le remets à 0.
 
Inscrit
8 Septembre 2019
Messages
9
Reactions
3
#3
tu dois trouver le délimiteur et extraire chaque paquet, si tu trouves pas de délimiteur tu gardes dans un buffer le début du paquet et quand tu trouves le prochain délimiteur tu reconstitues le paquet. Tu n'as pas de garantie d'avoir un message complet avec TCP.
Donc ce que tu peux faire c'est juste avoir une string qui correspond au paquet actuel et concaténer jusqu'à ce que tu trouves un délimiteur, si tu trouves un délimiteur tu le remets à 0.
Merci ça fonctionne bien, le délimiteur c’est « \0 » si jamais

J’ai une autre question concernant un nouveau paquet qui n’était pas présent avant. C’est le paquet HT, on reçoit un HT avec une clé et le client renvoie le HT avec une nouvelle clé. J’ai regardé dans les sources et ça concerne la télémétrie au vu du nom des méthodes, j’ai aucune idée de ce que ça signifie. T’as des pistes?
 
Inscrit
27 Septembre 2019
Messages
47
Reactions
250
#4
Merci ça fonctionne bien, le délimiteur c’est « \0 » si jamais

J’ai une autre question concernant un nouveau paquet qui n’était pas présent avant. C’est le paquet HT, on reçoit un HT avec une clé et le client renvoie le HT avec une nouvelle clé. J’ai regardé dans les sources et ça concerne la télémétrie au vu du nom des méthodes, j’ai aucune idée de ce que ça signifie. T’as des pistes?
Alors il me semble que le délimiteur c'est \n\0 y'a un truc du genre auquel il faut faire attention mais si ça marche tant mieux.
Pour les nouveaux paquets de télémétrie ils sont calculés par l'interface externe electron donc en javascript si je dis pas de connerie, si tu as un bot socket il faudra sûrement que tu émules le truc pour refaire l'algo sinon tu risques de te faire flagger j'imagine. C'est sûrement des infos qui sont encryptées et encodées en Base64. Quand tu regardes les sources tu as une idée de quelles infos ça envoie
 
Inscrit
8 Septembre 2019
Messages
9
Reactions
3
#5
Alors il me semble que le délimiteur c'est \n\0 y'a un truc du genre auquel il faut faire attention mais si ça marche tant mieux.
Pour les nouveaux paquets de télémétrie ils sont calculés par l'interface externe electron donc en javascript si je dis pas de connerie, si tu as un bot socket il faudra sûrement que tu émules le truc pour refaire l'algo sinon tu risques de te faire flagger j'imagine. C'est sûrement des infos qui sont encryptées et encodées en Base64. Quand tu regardes les sources tu as une idée de quelles infos ça envoie
Ok je vois, tu sais pourquoi ils se sont mis à utiliser Electron ? En tout cas si je réponds à HT avec la clé du HT reçu le bot continue de tourner, je ne sais pas si ça a une incidence et si ils font un check par rapport à ça

1662118007919.png

Les sources ne sont pas trop parlantes à ce propos
 
Dernière édition:
Inscrit
24 Février 2017
Messages
9
Reactions
9
#6
Ok je vois, tu sais pourquoi ils se sont mis à utiliser Electron ? En tout cas si je réponds à HT avec la clé du HT reçu le bot continue de tourner, je ne sais pas si ça a une incidence et si ils font un check par rapport à ça

Afficher la pièce jointe 851

Les sources ne sont pas trop parlantes à ce propos
Ils sont passés sur Electron pour pouvoir développer ce genre de "sécurité" et des features qu'il aurait été compliqué de faire autrement.
Tu risques effectivement de te faire flag et de passer dans la prochaine vague de ban en répondant mal à ces demandes.
Comme dit par AzureHaze, tu peux essayer de regarder ce qui est fait de ce côté (tout est obfu mais ça se fait)
 
Inscrit
30 Octobre 2019
Messages
76
Reactions
65
#7
Si tu veux botter hors de boune osef du paquet HT, il est pas utilisé sur la version legacy uniquement sur le client modern (obligatoire pour boune) avec electron sinon good luck pour déchiffrer tout ça.
 
Inscrit
8 Septembre 2019
Messages
9
Reactions
3
#8
Ils sont passés sur Electron pour pouvoir développer ce genre de "sécurité" et des features qu'il aurait été compliqué de faire autrement.
Tu risques effectivement de te faire flag et de passer dans la prochaine vague de ban en répondant mal à ces demandes.
Comme dit par AzureHaze, tu peux essayer de regarder ce qui est fait de ce côté (tout est obfu mais ça se fait)
Il faut regarder dans D1ElectronLauncher.js ?
C’est minifié et obfu


Si tu veux botter hors de boune osef du paquet HT, il est pas utilisé sur la version legacy uniquement sur le client modern (obligatoire pour boune) avec electron sinon good luck pour déchiffrer tout ça.
Ils risquent de le déployer sur la legacy un jour j’imagine
 
Inscrit
30 Octobre 2019
Messages
76
Reactions
65
#9
Ils risquent de le déployer sur la legacy un jour j’imagine
Non, electron c'est basé sur chromium donc un navigateur qui permet d'exécuter du JS, ça sera pas deploy sur le legacy, par contre ces fdp veulent supprimer (source interview de logan avec pro team à la japan expo) le legacy, à voir s'ils le font étant donné les problèmes de perf du client modern https://www.dofus.com/fr/forum/1751-dofus-retro/2377461-ameliorer-performances-client-modern
 
Inscrit
27 Septembre 2019
Messages
47
Reactions
250
#10
Alors il me semble que le délimiteur c'est \n\0 y'a un truc du genre auquel il faut faire attention mais si ça marche tant mieux.
Pour les nouveaux paquets de télémétrie ils sont calculés par l'interface externe electron donc en javascript si je dis pas de connerie, si tu as un bot socket il faudra sûrement que tu émules le truc pour refaire l'algo sinon tu risques de te faire flagger j'imagine. Ça a l
Il faut regarder dans D1ElectronLauncher.js ?
C’est minifié et obfu




Ils risquent de le déployer sur la legacy un jour j’imagine
Je pense pas, ça voudrait dire qu'on aurait accès à l'algo en décompilant le .swf
 
Inscrit
8 Septembre 2019
Messages
9
Reactions
3
#11
Je pense pas, ça voudrait dire qu'on aurait accès à l'algo en décompilant le .swf
Dans tous les cas on a accès à l’algo dans les fichiers js liés à électron ?

L’algo qui fait un traitement sur la valeur reçue par le premier HT il est forcément en local au niveau du client non?
 
Inscrit
24 Février 2017
Messages
9
Reactions
9
#12
Inscrit
8 Septembre 2019
Messages
9
Reactions
3
#13
Il utilise https://github.com/javascript-obfuscator/javascript-obfuscator pour obfu le client Electron
Cet obfu n'est visiblement plus maintenu depuis peu, il a fort à parier que des projets pour le reverse ne vont pas tarder à apparaître, sinon ça se fait plutôt bien quand on sait où chercher
J'ai déminifié le fichier et je suis en train de remonter le fil, on voit qu'ils ont fait ça pour brouiller les pistes c'est imbuvable, si t'as des infos, une méthodologie ou quoi je suis preneur
 
Inscrit
27 Septembre 2019
Messages
47
Reactions
250
#14
J'ai déminifié le fichier et je suis en train de remonter le fil, on voit qu'ils ont fait ça pour brouiller les pistes c'est imbuvable, si t'as des infos, une méthodologie ou quoi je suis preneur
Un début de piste avec de4js:
1662150323084.png
 
Inscrit
8 Septembre 2019
Messages
9
Reactions
3
#15
Yes j'ai tenté plusieurs deobfuscateur ça reste très illisible

Code:
a0_0x1232b3 = {_0xd0469c: 2639, _0x521f7b: "x!2z"};

_0x2e0b7c = _0x8a9bab[_0x3e0f24(1809, 678, a0_0x1232b3._0x521f7b, a0_0x1232b3._0x521f7b - 279)]("|");
typiquement ce genre de syntaxe, le " _0x521f7b: "x!2z"" puis dans son tableau il le soustrait je comprends pas

La valeur "x!2z" est utilisée 279 fois dans le document, c'est pas un code ASCII, ni du Base64 j'ai pas de correspondance

Code:
J16uz+HP6kPvE4fneEPg5BJPLcio0ULFsuDpcI7e9XU6jeN5fLX2kku+mUWYPY0FpLF4hS9TIRnWAne0UrT2HSqT63j8a+hJev4JSW93mEZcXxUle6S4tFNxg6wn8WERApunTNWz0SwYNmuRlyDV38aptCv1WJ+a9Wi+WmD+3KfFV02DgFQkjofW4T40yTAV6aFYcopTn4MUInplV6c99H8wmVu0eUS8dZOp1I0D0Q+5BW+KkOUsZgBPLE4mVkwXn1wisxFmcGV3ly1bL838jHFm182LvdR7MHF4VPK+mTzf2zXOgXMiGzTtOVWsOO8BLPDcuxnNrU6+ywzLt9iF2g==
Le HT reçu ça semble être du Base64
 
Dernière édition:
Inscrit
27 Septembre 2019
Messages
47
Reactions
250
#16
Yes j'ai tenté plusieurs deobfuscateur ça reste très illisible

Code:
a0_0x1232b3 = {_0xd0469c: 2639, _0x521f7b: "x!2z"};

_0x2e0b7c = _0x8a9bab[_0x3e0f24(1809, 678, a0_0x1232b3._0x521f7b, a0_0x1232b3._0x521f7b - 279)]("|");
typiquement ce genre de syntaxe, le " _0x521f7b: "x!2z"" puis dans son tableau il le soustrait je comprends pas

La valeur "x!2z" est utilisée 279 fois dans le document, c'est pas un code ASCII, ni du Base64 j'ai pas de correspondance

Code:
J16uz+HP6kPvE4fneEPg5BJPLcio0ULFsuDpcI7e9XU6jeN5fLX2kku+mUWYPY0FpLF4hS9TIRnWAne0UrT2HSqT63j8a+hJev4JSW93mEZcXxUle6S4tFNxg6wn8WERApunTNWz0SwYNmuRlyDV38aptCv1WJ+a9Wi+WmD+3KfFV02DgFQkjofW4T40yTAV6aFYcopTn4MUInplV6c99H8wmVu0eUS8dZOp1I0D0Q+5BW+KkOUsZgBPLE4mVkwXn1wisxFmcGV3ly1bL838jHFm182LvdR7MHF4VPK+mTzf2zXOgXMiGzTtOVWsOO8BLPDcuxnNrU6+ywzLt9iF2g==
Le HT reçu ça semble être du Base64
Oui c'est encodé en Base64 mais la data semble être encryptée. Je pense que tu perdrais moins de temps à faire un MITM si tu comptes cibler des serveurs qui requierent le client electron
 
Inscrit
24 Février 2017
Messages
9
Reactions
9
#17
Yes j'ai tenté plusieurs deobfuscateur ça reste très illisible
Le HT reçu ça semble être du Base64
J'ai juste traduit la fonction à la main, un peu à l'arrache mais ça donne une bonne idée de ce qui est fait.
Curieux de voir ce qui peut en sortir ;)
getTelemetry:
      _0x5289db.exports.getTelemetry = async function (key, _0x3fcd92) {
        var _0x22bea2;
        var _0x4c8ae2 = key.split("|");

        try {
          _0x22bea2 = _0xb105b4.decrypt(_0x4c8ae2[0], 'utf8');
        } catch (err) {
          return void console.error(err);
        }

        if (null == _0x22bea2) {
          return 'err';
        }

        var decodedString;
        var _0x517feb = _0x22bea2.split("|");
        try {
          decodedString = crypto.enc.Base64.parse(_0x517feb[0]);
        } catch (err) {
          return void console.error(err);
        }

        var _0x4543b4 = _0x517feb[1] != _0x3fcd92.basics[33]; // basics[33] = dofusPseudo
        var _0x22b578 = _0x517feb[2];
        var _0x5c8a0a = _0x22b578 ? _0x22b578.split(",") : [];
        var _0x48a990 = _0x517feb[3];

        const iv = crypto.lib.WordArray.random(16);
        var encodedResult = await async function (_0x801f02, _0x23ee79, _0x5481f0, _0x59a6b1) {
          var _0x28e9f5 = new Function("contextData", _0x23ee79)(_0x5481f0);
          var _0x2aac5d = [];
          await _0x3a6a89();
          var _0x2b4cbd = _0x564f06.cfData.hash;

          _0x2aac5d.push(_0x2b4cbd);
          _0x2aac5d.push(_0x28e9f5);
          _0x2aac5d.push(_0x59a6b1 ? 1 : 0);

          var _0x49c9b5 = 0;
          if (_0x801f02.length > 0) try {
            var _0x5b6ae7 = await _0x381c3d.processLoad(_0x801f02.join(","))
            for (var i = 0; i < _0x5b6ae7.length; i++) {
              var _0x1d5589 = _0x5b6ae7[i];
              if (_0x1d5589.pid) {
                for (var _0x384f8e = -1, _0x4daac8 = _0x1d5589.proc, j = 0; j < _0x801f02.length; j++) {
                  if (_0x801f02[j] == _0x4daac8) {
                    _0x384f8e = j;
                    break;
                  }
                }
                if (-1 != _0x384f8e) {
                  _0x49c9b5 |= 2 ** _0x384f8e;
                }
              }
            }
          } catch (err) {
            _0x49c9b5 = -1;
          }
          _0x2aac5d.push(String(_0x49c9b5));
          _0x2aac5d.push(getRandomNetworkKey());
          return _0x2aac5d.join("|");
        }(_0x5c8a0a, _0x48a990, _0x3fcd92, _0x4543b4);

        try {
          encodedResult = function (passphrase, _0x1ab429, iv) {
            var message = crypto.enc.Utf8.parse(_0x1ab429);
            return crypto.AES.encrypt(message, passphrase, {
              iv: iv,
              mode: crypto.mode.CBC,
              padding: crypto.pad.Pkcs7,
            });
          }(decodedString, encodedResult, iv);
        } catch (err) {
          return void console.error(err);
        }
        encodedResult += "|" + iv;
        document.getElementById("flashGame").onTelemetryCallback({ answer: encodedResult });
      };
 
Inscrit
8 Septembre 2019
Messages
9
Reactions
3
#18
J'ai juste traduit la fonction à la main, un peu à l'arrache mais ça donne une bonne idée de ce qui est fait.
Curieux de voir ce qui peut en sortir ;)
getTelemetry:
      _0x5289db.exports.getTelemetry = async function (key, _0x3fcd92) {
        var _0x22bea2;
        var _0x4c8ae2 = key.split("|");

        try {
          _0x22bea2 = _0xb105b4.decrypt(_0x4c8ae2[0], 'utf8');
        } catch (err) {
          return void console.error(err);
        }

        if (null == _0x22bea2) {
          return 'err';
        }

        var decodedString;
        var _0x517feb = _0x22bea2.split("|");
        try {
          decodedString = crypto.enc.Base64.parse(_0x517feb[0]);
        } catch (err) {
          return void console.error(err);
        }

        var _0x4543b4 = _0x517feb[1] != _0x3fcd92.basics[33]; // basics[33] = dofusPseudo
        var _0x22b578 = _0x517feb[2];
        var _0x5c8a0a = _0x22b578 ? _0x22b578.split(",") : [];
        var _0x48a990 = _0x517feb[3];

        const iv = crypto.lib.WordArray.random(16);
        var encodedResult = await async function (_0x801f02, _0x23ee79, _0x5481f0, _0x59a6b1) {
          var _0x28e9f5 = new Function("contextData", _0x23ee79)(_0x5481f0);
          var _0x2aac5d = [];
          await _0x3a6a89();
          var _0x2b4cbd = _0x564f06.cfData.hash;

          _0x2aac5d.push(_0x2b4cbd);
          _0x2aac5d.push(_0x28e9f5);
          _0x2aac5d.push(_0x59a6b1 ? 1 : 0);

          var _0x49c9b5 = 0;
          if (_0x801f02.length > 0) try {
            var _0x5b6ae7 = await _0x381c3d.processLoad(_0x801f02.join(","))
            for (var i = 0; i < _0x5b6ae7.length; i++) {
              var _0x1d5589 = _0x5b6ae7[i];
              if (_0x1d5589.pid) {
                for (var _0x384f8e = -1, _0x4daac8 = _0x1d5589.proc, j = 0; j < _0x801f02.length; j++) {
                  if (_0x801f02[j] == _0x4daac8) {
                    _0x384f8e = j;
                    break;
                  }
                }
                if (-1 != _0x384f8e) {
                  _0x49c9b5 |= 2 ** _0x384f8e;
                }
              }
            }
          } catch (err) {
            _0x49c9b5 = -1;
          }
          _0x2aac5d.push(String(_0x49c9b5));
          _0x2aac5d.push(getRandomNetworkKey());
          return _0x2aac5d.join("|");
        }(_0x5c8a0a, _0x48a990, _0x3fcd92, _0x4543b4);

        try {
          encodedResult = function (passphrase, _0x1ab429, iv) {
            var message = crypto.enc.Utf8.parse(_0x1ab429);
            return crypto.AES.encrypt(message, passphrase, {
              iv: iv,
              mode: crypto.mode.CBC,
              padding: crypto.pad.Pkcs7,
            });
          }(decodedString, encodedResult, iv);
        } catch (err) {
          return void console.error(err);
        }
        encodedResult += "|" + iv;
        document.getElementById("flashGame").onTelemetryCallback({ answer: encodedResult });
      };
Merci ça m'a donné des infos dont j'ai pu me servir, du coup j'ai émulé une app electron j'ai abandonné l'idée de désobfusquer ce js
 
Haut Bas