Localisation du code QR en mémoire
Le code QR est stocké sous forme d'image PNG, identifiable par son en-tête fichier. L'en-tête PNG standard commence par la séquence hexadécimale : 89 50 4E 47 0D 0A 1A 0A, suivie de sections comme IHDR. En utilisant Cheat Engine (CE) pour attacher le processus WeChat, on recherche la chaîne "IHDR" pour locailser les adresses mémoire susceptibles de contenir l'image. Les adresses vertes (dynamiques) sont généralement à exclure.
La structure de données du code QR comprend un pointeur vers les données de l'image et sa longueur. Pour isoler l'adresse principale, on effectue une recherche pointeur sur les adresses trouvées, en ajustant l'adresse cible en soustrayant 0x12 (car l'en-tête complet précède IHDR). Après filtrage par taille (typiquement autour de 4 Ko), on identifie l'adresse pertinente, par exemple 0x05FD3CC4.
En plaçant un point d'arrêt mémoire en écriture sur cette adresse via OllyDbg (OD), on intercepte le code qui modifie le code QR lors du rafraîchissement. L'extrait de code suivant illustre la réinitialisation et la mise à jour des données :
mov dword ptr [reg_struct], 0x0 ; Réinitialisation du pointeur image
mov dword ptr [reg_struct+0x4], 0x0 ; Réinitialisation de la longueur
push 0x1
push reg_buffer
call update_image_pointer
add esp, 0x8
mov dword ptr [reg_struct], eax ; Nouveau pointeur (initialement nul)
test eax, eax
cmovne ecx, reg_size
mov dword ptr [reg_struct+0x4], ecx ; Affectation de la longueur
Le code ci-dessus fait partie d'une fonction qui prépare l'espace pour le nouveau code QR. Les données réelles sont remplies ultérieurement par une autre routine, identifiable en poursuivant l'exécution après l'appel.
Détermination du décalage de l'adresse
Pour obtenir un décalage stable, on utilise la fonction "pointer scan" de CE sur l'adresse identifiée. Après deux scans successifs (en redémarrant WeChat entre chaque), les résultats se réduisent à quelques adresses candidates. En comparant avec le code assembleur dans OD, on repère des décalages comme 0x654 correspondant à la structure dans le registre esi. Par exemple :
lea ecx, [esi+0x654] ; Pointeur vers la structure code QR
call allocate_image_data
push edi
push ebx
push [esi+0x654]
call fill_image_content
Le décalage final, tel que WeChatWin.dll+0x1635C58, peut varier selon la version de WeChat. Ce décalage permet de lire directement le code QR sans hook.
Sauvegarde du code QR avec un script
En utilisant un script, comme avec aardio, on peut lire les données à partir de l'adresse calculée et les sauvegarder en fichier PNG. Voici un exemple adapté :
import process
import string
proc = process.find("WeChat.exe")
qr_struct_addr = 0x05FD3CC4 ; À remplacer par l'adresse calculée via décalage
img_ptr = proc.readNumber(qr_struct_addr)
img_len = proc.readNumber(qr_struct_addr + 0x4)
qr_data = proc.readString(img_ptr, img_len)
string.save("C:\\temp\\qr_code.png", qr_data)
Le script extrait les octets bruts de l'image et les enregistre directement, sans conversion supplémentaire.
Accès à la chaîne de caractères du code QR
Pour obtenir la chaîne de caractères du code QR (utilisée pour générer le lien de connexion), on recherche dans CE la chaîne correspondante après rafraîchissement. En identifiant l'adresse de base via un pointeur statique, comme WeChatWin.dll+0x1635C58, on peut lire directement la chaîne. Cette approche simplifie le processus en évitant la manipulation d'images, car la chaîne peut être convertie en code QR via une API externe.