<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="fr">
	<id>https://t4ctech.hyperion-roleplay.com/index.php?action=history&amp;feed=atom&amp;title=Reverse-engineering_LGC</id>
	<title>Reverse-engineering LGC - Historique des versions</title>
	<link rel="self" type="application/atom+xml" href="https://t4ctech.hyperion-roleplay.com/index.php?action=history&amp;feed=atom&amp;title=Reverse-engineering_LGC"/>
	<link rel="alternate" type="text/html" href="https://t4ctech.hyperion-roleplay.com/index.php?title=Reverse-engineering_LGC&amp;action=history"/>
	<updated>2026-07-10T05:44:58Z</updated>
	<subtitle>Historique des versions pour cette page sur le wiki</subtitle>
	<generator>MediaWiki 1.40.1</generator>
	<entry>
		<id>https://t4ctech.hyperion-roleplay.com/index.php?title=Reverse-engineering_LGC&amp;diff=43&amp;oldid=prev</id>
		<title>FunJp : Page créée avec « == Généralités == L&#039;algorithme classique de génération de nombres pseudo-aléatoires est de la forme :  X(n+1)=(aX(n)+C) mod M  C&#039;est un formule très simple : un &quot;... »</title>
		<link rel="alternate" type="text/html" href="https://t4ctech.hyperion-roleplay.com/index.php?title=Reverse-engineering_LGC&amp;diff=43&amp;oldid=prev"/>
		<updated>2017-04-23T19:41:35Z</updated>

		<summary type="html">&lt;p&gt;Page créée avec « == Généralités == L&amp;#039;algorithme classique de génération de nombres pseudo-aléatoires est de la forme :  X(n+1)=(aX(n)+C) mod M  C&amp;#039;est un formule très simple : un &amp;quot;... »&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Nouvelle page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;== Généralités ==&lt;br /&gt;
L&amp;#039;algorithme classique de génération de nombres pseudo-aléatoires est de la forme :&lt;br /&gt;
&lt;br /&gt;
X(n+1)=(aX(n)+C) mod M&lt;br /&gt;
&lt;br /&gt;
C&amp;#039;est un formule très simple : un &amp;quot;générateur congruentiel linéaire&amp;quot; ou &amp;quot;Linear Congruential Generator&amp;quot; (LGC) en anglais.&lt;br /&gt;
&lt;br /&gt;
Il va de soit, qu&amp;#039;a la vue de la formule, il existe un moyen de retrouver les paramètres à partir des données.&lt;br /&gt;
&lt;br /&gt;
Ce que je propose : Remplacons les vilaines tables de t4c par leur formules respectives ont y gagnera en taille de code et en clarté (quoi que ca soit discutable)&lt;br /&gt;
&lt;br /&gt;
== Méthode 1 (BruteForce) ==&lt;br /&gt;
&lt;br /&gt;
== Méthode 2 (Mathématique) ==&lt;br /&gt;
Tout d&amp;#039;abord voyons comment faire pour une suite simple et courte que j&amp;#039;ai concocté pour l&amp;#039;occasion:&lt;br /&gt;
&lt;br /&gt;
225022651 2758271555 3694341235 2360776595 1568339 3917311699&lt;br /&gt;
&lt;br /&gt;
//on va considerer que le seed est stocké sur 32 bits ce qui nous donne M = 2147483647&lt;br /&gt;
&lt;br /&gt;
(en cours)&lt;br /&gt;
&lt;br /&gt;
== Méthode 3 (Reversing) ==&lt;br /&gt;
La recherche du code: Le decryptage des ELNG à surement un minimum de verification d&amp;#039;erreurs voyons ce qu&amp;#039;on peut trouver au niveau des chaines&lt;br /&gt;
&lt;br /&gt;
j&amp;#039;ai tapé &amp;quot;language&amp;quot; pour ma recherche : &amp;#039;An unkown language file error occured on line %u.&amp;#039;&lt;br /&gt;
&lt;br /&gt;
mmm fabuleux&lt;br /&gt;
&lt;br /&gt;
et un peu plus bas &amp;#039;Loading language file %s .&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Parfait ! voyons le code qui y fait référence en remontant en haut de la fonction je tombe sur :&lt;br /&gt;
 0043BDDB                 call    esi ; fopen&lt;br /&gt;
 0043BDDD                 mov     edi, eax&lt;br /&gt;
 0043BDDF                 add     esp, 8&lt;br /&gt;
 0043BDE2                 test    edi, edi&lt;br /&gt;
 0043BDE4                 mov     [ebp+var_28], edi&lt;br /&gt;
 0043BDE7                 jnz     short loc_43BE27&lt;br /&gt;
 0043BDE9                 mov     ecx, dword ptr [ebp+arg_0]&lt;br /&gt;
 0043BDEC                 push    ecx             ; char&lt;br /&gt;
 0043BDED                 push    offset aCouldNotLoadLa ; &amp;quot;Could not load language file %s.&amp;quot;&lt;br /&gt;
l&amp;#039;ouverture étant ici , le décryptage ne devrait pas être loin... on suit le saut qui génère l&amp;#039;erreur ou non et on descend de quelques lignes :&lt;br /&gt;
 0043BE48                 push    edi&lt;br /&gt;
 0043BE49                 lea     ecx, [ebp+var_40]&lt;br /&gt;
 0043BE4C                 mov     byte ptr [ebp+var_4], 4&lt;br /&gt;
 0043BE50                 mov     [ebp+var_D], 0&lt;br /&gt;
 0043BE54                 call    sub_43B640&lt;br /&gt;
 0043BE59                 lea     ecx, [ebp+var_40]&lt;br /&gt;
 0043BE5C                 call    sub_43B670&lt;br /&gt;
 0043BE61                 cmp     al, 0FFh&lt;br /&gt;
 0043BE63                 mov     ebx, ds:isalpha&lt;br /&gt;
Partiellement gagné le premier call fait en effet un appel à une fonction qui fixe le seed à 0x2d9d&lt;br /&gt;
&lt;br /&gt;
Le deuxieme quand à lui lit un caractère grace a fgetc et decrypte l&amp;#039;octet recupéré grace à une table et un bête xor&lt;br /&gt;
 0043B6A3                 movsx   eax, byte_507E58[edx]&lt;br /&gt;
 0043B6AA                 movsx   edx, bl&lt;br /&gt;
 0043B6AD                 xor     eax, edx&lt;br /&gt;
Les références croisées nous amenerons directement au remplissage de la table:&lt;br /&gt;
 0043B600 loc_43B600:&lt;br /&gt;
 0043B612                 push    0FFh&lt;br /&gt;
 0043B617                 push    0&lt;br /&gt;
 0043B619                 mov     ecx, offset unk_50D81C&lt;br /&gt;
 0043B61E                 call    ??RRandom@@QAEHHH@Z ; Random::operator()(int,int)&lt;br /&gt;
 0043B623                 mov     byte_507E58[esi], al&lt;br /&gt;
 0043B629                 inc     esi&lt;br /&gt;
 0043B62A                 cmp     esi, 1E8Fh&lt;br /&gt;
 0043B630                 jl      short loc_43B612&lt;br /&gt;
La fonction random prend 2 arguments , bien evidement ici la valeur min et max voyant les chiffres, en suivant les appels on se retrouve au coeur du générateur:&lt;br /&gt;
 0045517C                 mov     eax, dword_50A7DC&lt;br /&gt;
 00455181                 mov     ecx, ?Seed@Random@@0_KA ; unsigned __int64 Random::Seed&lt;br /&gt;
 00455187                 push    0&lt;br /&gt;
 00455189                 push    2B3DD441h&lt;br /&gt;
 0045518E                 push    eax&lt;br /&gt;
 0045518F                 push    ecx&lt;br /&gt;
 00455190                 call    __allmul&lt;br /&gt;
 00455195                 add     eax, 1&lt;br /&gt;
 00455198                 adc     edx, 0&lt;br /&gt;
 0045519B                 cmp     esi, edi&lt;br /&gt;
 0045519D                 mov     ebx, eax&lt;br /&gt;
 0045519F                 mov     ?Seed@Random@@0_KA, ebx ; unsigned __int64 Random::Seed&lt;br /&gt;
 004551A5                 mov     dword_50A7DC, edx&lt;br /&gt;
l&amp;#039;algorithme est donc ici seed=seed*0x2b3dd441+1; (les opérations sont en 64 bits)&lt;br /&gt;
&lt;br /&gt;
mais ce n&amp;#039;est pas la valeur renvoyée par la fonction:&lt;br /&gt;
 004551C6                 mov     edx, dword_50A7DC&lt;br /&gt;
 004551CC                 mov     ecx, 16&lt;br /&gt;
 004551D1                 mov     eax, ebx&lt;br /&gt;
 004551D3                 call    unknown_libname_253 ; Microsoft VisualC 2-8/net runtime&lt;br /&gt;
ici un appel non reconnu à une fonction de librairie qui effectue un bit shift à droite de 16 bit sur l&amp;#039;entier de poids faible de l&amp;#039;int64 donc : ((seed &amp;amp; 0xFFFFFFFF)&amp;gt;&amp;gt;16)&lt;br /&gt;
&lt;br /&gt;
ce à quoi je rajoute :&lt;br /&gt;
&lt;br /&gt;
(result%((max+1)-min))+min&lt;br /&gt;
&lt;br /&gt;
(calculé avec __aullrem)&lt;br /&gt;
&lt;br /&gt;
La fonction résultante simplifiée :&lt;br /&gt;
 __int64 Seed; &lt;br /&gt;
 &lt;br /&gt;
 unsigned char Random(void)&lt;br /&gt;
 {&lt;br /&gt;
     Seed=Seed*0x2b3dd441+1;&lt;br /&gt;
     return ((Seed &amp;amp; 0xFFFFFFFF)&amp;gt;&amp;gt;16)%0x100;&lt;br /&gt;
 };&lt;br /&gt;
Découvrir les paramètres du générateur d&amp;#039;après les valeurs de sortie etait ici plus ou moins voué a l&amp;#039;échec du fait de la destruction des octets de poids faible.&lt;br /&gt;
&lt;br /&gt;
--Chaotikmind&lt;/div&gt;</summary>
		<author><name>FunJp</name></author>
	</entry>
</feed>