C/C++ [RSA]cipherRSA

Inscrit
2 Juillet 2015
Messages
41
Reactions
0
#1
Bonjour, j'essaie maintenant de comprendre le code du client utilisé pour la création du paquet IdentificationMessage.
Cependant dans le fichier AuthentificationManager, la fonction cipherRSA me parait très étrange. La voici.
Code:
private function cipherRsa(param1:String, param2 : String, param3 : TrustCertificate) : Vector.<int>
{
	if (_loc7_)
	{
		var baOut : ByteArray = null;
		if (_loc7_)
		{
		}
		var debugOutput : ByteArray = null;
		if (_loc6_)
		{
		loop0:
			while (true)
			{
				var certificate : TrustCertificate = param3;
				if (_loc7_)
				{
					if (_loc6_)
					{
					addr49:
						while (true)
						{
							baIn.writeUTFBytes(this._salt);
							if (!_loc7_)
							{
							addr60:
								while (true)
								{
									var login : String = param1;
									if (_loc7_)
									{
									}
									var pwd : String = param2;
									if (_loc7_)
									{
										break;
									}
								}
								continue loop0;
							}
							break;
						}
						baIn.writeBytes(this._AESKey);
					}
					while (true)
					{
						var baIn : ByteArray = new ByteArray();
						if (!_loc6_)
						{
							§§goto(addr49);
						}
						§§goto(addr60);
					}
				}
				break;
			}
			if (_loc6_)
			{
			}
			try
			{
				§§push(File.applicationDirectory.resolvePath("debug-login.txt"));
				if (_loc7_)
				{
					if (!§§dup(§§pop()))
					{
						if (!_loc6_)
						{
							§§pop();
							if (_loc6_)
							{
							}
							§§push(File.applicationDirectory.resolvePath("debuglogin.txt"));
						}
					}
				}
				if (§§pop())
				{
					_log.debug("login with certificate");
					if (_loc7_)
					{
					}
					debugOutput = new ByteArray();
					if (_loc7_)
					{
						if (_loc7_)
						{
						}
						§§push(baIn);
						§§push(0);
						if (!_loc7_)
						{
							§§push((§§pop() - 18 - 24 + 1) * 3);
						}
						§§pop().position = §§pop();
						if (!_loc7_)
						{
						addr226:
							while (true)
							{
								debugOutput = RSA.publicEncrypt((new PUBLIC_KEY_V2() as ByteArray).readUTFBytes((new PUBLIC_KEY_V2() as ByteArray).length), baIn);
								if (_loc6_)
								{
								}
								§§push(_log);
								§§push("Login info (RSA Encrypted, ");
								if (!_loc6_)
								{
									§§push(§§pop() + debugOutput.length);
									if (!_loc6_)
									{
										§§push(§§pop() + " bytes) : ");
										if (_loc7_)
										{
										}
									}
									§§push(§§pop() + Base64.encodeByteArray(debugOutput));
								}
								§§pop().debug(§§pop());
								if (_loc6_)
								{
								}
								break;
							}
						}
						while (true)
						{
							§§push(debugOutput);
							§§push(0);
							if (_loc6_)
							{
								§§push((§§pop() - 1 + 1 - 1 + 61 - 1) * 12);
							}
							§§pop().position = §§pop();
						}
					}
					while (true)
					{
						if (!_loc6_)
						{
							§§goto(addr226);
						}
					}
				}
			}
			catch (e:Error)
			{
				if (_loc7_)
				{
					§§push(_log);
					§§push("Erreur lors du log des informations de login ");
					if (!_loc6_)
					{
						§§push(§§pop() + e.getStackTrace());
					}
					§§pop().error(§§pop());
				}
			}
			baOut = RSA.publicEncrypt(this._publicKey, baIn);
			if (_loc7_)
			{
				if (_loc6_)
				{
				loop4:
					while (true)
					{
						§§push(baOut);
						§§push(0);
						if (_loc6_)
						{
							§§push(§§pop() - 113 - 1 - 20 - 1 + 83 + 1);
						}
						§§pop().position = §§pop();
						if (!_loc6_)
						{
							if (!_loc6_)
							{
								if (_loc7_)
								{
								}
							addr381:
								§§push(_loc4_);
								§§push(0);
								if (_loc6_)
								{
									§§push((§§pop() * 100 + 1 - 1) * 14 + 1);
								}
								var /*UnknownSlot*/:*= §§pop();
							addr465:
								if (_loc7_)
								{
									break;
								}
								if (_loc6_)
								{
								}
								return ret;
							}
						addr376:
							while (true)
							{
								if (!_loc7_)
								{
									§§goto(addr381);
								}
								else
								{
									continue loop4;
								}
							}
						}
						break;
					}
				}
				while (true)
				{
					var ret : Vector.<int> = new Vector.<int>();
					§§goto(addr376);
				}
			}
			if (_loc6_)
			{
			}
			while (true)
			{
				§§push(baOut.bytesAvailable);
				§§push(0);
				if (!_loc7_)
				{
					§§push((§§pop() + 1 - 1) * 76 - 1 + 12);
				}
				if (§§pop() == §§pop())
				{
					break;
				}
				if (_loc6_)
				{
				loop8:
					while (true)
					{
						ret[i] = n;
						if (_loc7_)
						{
							if (!_loc6_)
							{
								if (_loc6_)
								{
								}
								§§push(i);
								if (!_loc6_)
								{
									§§push(§§pop() + 1);
								}
								var i : int = §§pop();
							}
						addr442:
							while (_loc7_)
							{
								continue loop8;
							}
							break;
						}
						if (_loc7_)
						{
							break;
						}
					}
					continue;
				}
				while (true)
				{
					var n : int = baOut.readByte();
					§§goto(addr442);
				}
			}
			§§goto(addr465);
		}
		while (true)
		{
			§§push(_loc4_);
			§§push(0);
			if (_loc6_)
			{
				§§push(-(§§pop() * 37 + 1 - 1 - 1));
			}
			var /*UnknownSlot*/:*= §§pop();
			if (!_loc6_)
			{
				§§goto(addr60);
			}
			§§goto(addr103);
		}
	}
	if (_loc6_)
	{
	}
	if (certificate)
	{
		baIn.writeUnsignedInt(certificate.id);
		if (_loc6_)
		{
		}
		baIn.writeUTFBytes(certificate.hash);
		if (_loc6_)
		{
		addr135:
			while (true)
			{
				baIn.writeUTFBytes(login);
				if (_loc6_)
				{
				}
				break;
			}
			baIn.writeUTFBytes(pwd);
			§§goto(addr162);
		}
	}
	while (true)
	{
		baIn.writeByte(login.length);
		if (_loc7_)
		{
			§§goto(addr135);
		}
		§§goto(addr157);
	}
}
Savez-vous comment fonctionnent les goto en as3? Auriez-vous une version de cette fonction dans laquelle les noms de variables seraient plus explicites?(2.29)J'ai bien regardé la fonction cipherRSA sur le dépot des sources, mais c'est pour la 2.26 ou encore la 2.18 alors ne sachant pas si la méthode a changée ou pas je ne m'en inspire pas.
Merci pour votre aide!
PS:voici la methode pour la 2.18, elle est bien plus claire:
Code:
var _loc9_:* = false;
         var _loc10_:* = true;
         var baOut:ByteArray = null;
         var n:* = 0;
         var baIn:ByteArray = new ByteArray();
         if(certificate)
         {
            baIn.writeUTFBytes(this._salt);
            baIn.writeUnsignedInt(certificate.id);
            baIn.writeUTFBytes(certificate.hash);
            baIn.writeByte(login.length);
            baIn.writeUTFBytes(login);
            baIn.writeUTFBytes(pwd);
         }
         else
         {
            baIn.writeUTFBytes(this._salt);
            baIn.writeByte(login.length);
            baIn.writeUTFBytes(login);
            baIn.writeUTFBytes(pwd);
         }
         baOut = RSA.publicEncrypt(this._publicKey,baIn);
         var ret:Vector.<int> = new Vector.<int>();
         baOut.position = 0;
         var i:int = 0;
         while(baOut.bytesAvailable != 0)
         {
            n = baOut.readByte();
            ret[i] = n;
            i++;
         }
         return ret;
      }
 

zahid98

Membre Actif
Inscrit
13 Decembre 2014
Messages
352
Reactions
2
#2
Salut , c'est pas que la fonction est étrange mais c'est ton décompilateur qui ne fait pas son boulot comme il le faut , voici une version de cipherRSA plus lisible .
Code:
private function cipherRsa(param1:String, param2:String, param3:TrustCertificate) : Vector.<int>
      {
         var _loc9_:* = false;
         var _loc10_:* = true;
         var _loc5_:ByteArray = null;
         _loc10_;
         var _loc8_:* = 0;
         var _loc4_:ByteArray = new ByteArray();
         if(param3)
         {
            _loc4_.writeUTFBytes(this._salt);
            _loc10_;
            _loc4_.writeUnsignedInt(param3.id);
            !_loc10_;
            _loc9_;
            _loc4_.writeUTFBytes(param3.hash);
            _loc10_;
            _loc4_.writeByte(param1.length);
            _loc9_;
            _loc10_;
            _loc4_.writeUTFBytes(param1);
            !_loc9_;
            _loc9_;
            _loc4_.writeUTFBytes(param2);
            _loc9_;
         }
         else
         {
            _loc4_.writeUTFBytes(this._salt);
            _loc10_;
            _loc4_.writeByte(param1.length);
            _loc9_;
            _loc4_.writeUTFBytes(param1);
            _loc9_;
            _loc4_.writeUTFBytes(param2);
            _loc9_;
         }
         _loc5_ = RSA.publicEncrypt(this._publicKey,_loc4_);
         _loc9_;
         var _loc6_:Vector.<int> = new Vector.<int>();
         _loc10_;
         _loc9_;
         _loc5_.position = 0;
         _loc9_;
         var _loc7_:* = 0;
         !_loc10_;
         while(true)
         {
            _loc9_;
            if(_loc5_.bytesAvailable == 0)
            {
               break;
            }
            _loc9_;
            _loc8_ = _loc5_.readByte();
            !_loc10_;
            _loc9_;
            _loc6_[_loc7_] = _loc8_;
            _loc9_;
            _loc7_++;
            _loc10_;
            _loc10_;
         }
         _loc9_;
         return _loc6_;
      }
Et si tu veux des variables plus parlantes , je pense qu'il serait plus judicieux de décompiler le client Bêta avec JPEX Décompiler .
 
Dernière édition par un modérateur:
Inscrit
2 Juillet 2015
Messages
41
Reactions
0
#3
Bonsoir et merci beaucup pour ta réponse!
Sais tu où je peux trouver le client beta?
J'ai un peu cherché sur le forum et je n'ai trouvé personne à avoir essayé de générer des couples de clef publique et clef privé compatible avec dofus?(ce que fait le serveur)
 

BlueDream

Administrateur
Membre du personnel
Inscrit
8 Decembre 2012
Messages
2 010
Reactions
149
#4
Bonsoir,

Voici ou trouver le client bêta de Dofus 2.29:

http://www.dofus.com/fr/mmorpg/actualit ... maintenant

En ce qui concerne le système de clés, le serveur possède une clé privé, la clé publique contenue dans le client permet de vérifier si la clé que t'envoi le serveur provient bien de cette clé privé.
 
Inscrit
2 Juillet 2015
Messages
41
Reactions
0
#5
Merci beaucoup Alexandre.
Justement, le soucis c'est que j'essaye de développer un émulateur. Alors j'ai sniffer la clef publique que le serveur envoit au client et je l'ai envoyé au client. Donc le client reconnait bien la clef et m'envoit le paquet IdentificationMessage. Mais je suis coincé car je ne peux pas retrouvé la clef privée (normal c'est du rsa^^) et déchiffrer les credentials.
Il faut donc que je comprennes comment le client vérifie les clefs RSA pour pouvoir générer les miennes et envoyer une clef publique perso que le client reconnaitrait.
 

BlueDream

Administrateur
Membre du personnel
Inscrit
8 Decembre 2012
Messages
2 010
Reactions
149
#6
Le mieux serait de procéder comme Stump c'est à dire envoyer un RawDataMessage permettant le renvoi des identifiants en clair.
 
Inscrit
2 Juillet 2015
Messages
41
Reactions
0
#7
Alors effectivement c'est une possibilité, mais je trouve ça un peu sale^^
Je vais essayer de trouver l'algo qu'utilise dofus pour faire passer la pair de valeur de la clef publique en une seule trame de int et comment celle-ci est vérifiée...
Ca promet du travail :)
 
Inscrit
2 Juillet 2015
Messages
41
Reactions
0
#9
Merci beaucoup pour ces sources, si je trouve une technique je la partagerai!
Sinon j'utiliserais le RDM :lol:
 
Inscrit
2 Juillet 2015
Messages
41
Reactions
0
#10
Bonjour,
Du coup je suis en train d'essayer de générer des clefs rsa côté serveur avec openssl.
Mais je ne trouve pas beaucoup d'informations sur le format utilisé pour l'envoi des clefs.
Dans AuthentificationManager, la chaine reçu (la "clef" que le serveur envoi dans le paquet HelloConnectMessage) est encodé en format PEM (base64+ suffixe et prefixe correspondant). Ensuite dans le fichier PEM, je vois que DER est utilisé pour récupérer la clef (dependance de la bibliotheque hurlant qui gère la crypto).

D'après mes recherches, les clefs dofus sont encodées en X509, d'après les infos de sorrow et les miennes, je pense que l'on a:
le serveur charge une paire de clefs rsa déja générée (grandes) : clef publique /clef privée
le serveur génère une paire de clefs rsa (plus petites) :clef publique/clef privé
le serveur encode la clef publique en X509, puis la chiffre avec clef privé selon le scheme PKCS.
Il envoie cette chaine sous le nom "key", dans le paquet HelloConnectmessage.
Le client possède clef publique, il dechiffre "key" et en extrait clef publique en DER (le meme format que les certificats x509 mais ce n'est pas un certificat).
Il prend clef publique la passe en base64 et rajoute les suffixes et prefixes pour la stocker en PEM.
Ensuite il l'utilise!! ;)
Vous en pensez quoi? Est ce que j'ai bien raison quand je dis que le format PEM contient la clef en X509?

Merci pour vos réponses!!
 
Inscrit
2 Juillet 2015
Messages
41
Reactions
0
#12
Ouep je viens de voir ça^^
Merci pour ta réponse :)
Bon bah je vais implementer ça coté serveur puis faudra que j'insere ma clef publique dans le client....
 
Inscrit
2 Juillet 2015
Messages
41
Reactions
0
#13
Quelques petites précisions ont été rajoutées à mon premier post.
EDIT: j'ai réussi à implémenter le RSA sur mon émulateur avec la bibliotheque Crypto++.
Il me reste à développer un launcher pour modifier la clef du client.
Mais je n'ai aucune connaissance en modification de memoire à la volée :o
Je vais aller voir chez google si ils savent :)
 

Labo

Membre Actif
Inscrit
16 Aout 2013
Messages
799
Reactions
15
#14
Pas besoin, tu décompiles avec JPEXS, tu modifies et tu recompiles. Ensuite tu lances directement Dofus sans launcher et c'est bon.
 
Inscrit
2 Juillet 2015
Messages
41
Reactions
0
#15
Bonsoir Lago je te remercie pour ta réponse, avec quel logiciel puis-je recompiler le client?
 
Inscrit
16 Mars 2014
Messages
214
Reactions
30
#16
Si tu fait tes modifications / rajouts avec Jpexs ta juste à faire save et sa sera bon :)

Modération: Merci de ne pas citer les derniers messages
 
Inscrit
2 Juillet 2015
Messages
41
Reactions
0
#17
Merci!! je vais tester mon rsa j'ai trop hâte de savoir si ça passe ou ça casse^^
EDIT:ça ne marche pas car je n'envoie pas le certificat X509 de la clef publique.
 
Inscrit
2 Juillet 2015
Messages
41
Reactions
0
#18
J'essaie de finir l’implémentation du rsa coté serveur et je me heurte à la difficulté de la bibliothèque openSSL...C'est assez rageant il n'y a pas trop de documentation :evil:
Avez-vous déja utilisé du RSA en c++ quelle bibliothèque utilisez-vous?

EDIT: j'ai téléchargé flex pour développer en flash avec la bibliotheque hurlant crypto pour essayer de comprendre comment ça fonctionne et de développer un truc semblable en c++.
 
Inscrit
2 Juillet 2015
Messages
41
Reactions
0
#19
Bonsoir,
J'ai fini d'implementer le systeme de gestion de clefs RSA sur mon emulateur.
OpenSSL est assez dur à prendre en main^^
J'ai ajouté à mon projet un générateur de clef maison.
J'ai modifié la clef publique du client (se référer à mon premier post).
Cependant lorsque le client reçoit le paquet HelloConnectMessage il jette une exception.
voici la pile des appels
  • AuthentificationManager->cipherRSA
    RSA->publicEncrypt
    PEM->readRSAPublicKey
    DER->extractBinary

Du coup je sais pas trop d'où viens l'erreur sachant que la clef chiffrée est bien envoyée etc...(visiblement bien acceptée par le client)
La question c'est pourquoi le client lance une exception en enlevant les bornes du format PEM alors que c'est lui qui les ajoute lorsqu'il reçoit la clef?
Si vous vous y connaissez un peu n'hésitez pas à aller faire un tour sur la branche RSA de mon depot
https://github.com/noilir/Trilogy/tree/RSA-wolfssl
 
Haut Bas