POSTER 6.3

Reverse Engineering

By Alien & Christal

Outil : wdasm 8.9

la première partie recherche une soluce pour le code, la seconde va regarder la limitation du soft avant son enregistrement

le détournement de la protection était tellement simple que j'avais pensé laisser tomber mais Christal m'a conseillé d'aller plus loin. Une fois de plus il avait raison; Merci Chris.

Méthode classique :
Un code puis ok
On relève le message et on tombe dessus après une petite recherche dans les strings "invalid registration code". Double clic et le voila avec juste avant un joli petit je.
On change en jne via le debuger et que nous dit le joli message "thank you".
Oui mais est-ce bien réel ?
Ffermeture de wdasm et on lance poster.
Surprise c'est enregistré: magique !!!!

:0040C363 8B8D4CFFFFFF            mov ecx, dword ptr [ebp+FFFFFF4C]
:0040C369 3B8D48FFFFFF            cmp ecx, dword ptr [ebp+FFFFFF48]
:0040C36F 741B                    je 0040C38C.....................je devient jne

* Possible Reference to String Resource ID=00175: "Invalid Registration Code"
                                  |
:0040C371 68AF000000              push 000000AF
:0040C376 8B1548324800            mov edx, dword ptr [00483248]
:0040C37C 52                      push edx
:0040C37D E8CED10300              call 00449550
:0040C382 83C408                  add esp, 00000008

* Possible Ref to Menu: POSTER, Item: "New ... "
                                  |

* Possible Reference to String Resource ID=00001: "Create a new poster "
                                  |
:0040C385 B801000000              mov eax, 00000001
:0040C38A EB71                    jmp 0040C3FD

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040C36F(C)
|

* Possible StringData Ref from Data Obj ->"081349"
                                  |
:0040C38C 6890734700              push 00477390............vers code ok

pourquoi ? si on descend un peu dans le listing on va trouver une référence a poster.ini

* Possible StringData Ref from Data Obj ->"POSTER.INI"
                                  |
:0040C3A7 6898734700              push 00477398

via l'explorateur Windows, on cherche poster.ini et on le trouve dans le répertoire c:\windows
[POSTER]

start=081349........au départ cette valeur est a 1 car non enregistré
file0=......................garde les fichiers de travail sauvegardé 
file1=.........
file2=.........
file3=.........

Si on regarde ce qui se passe après le saut vers code ok, on voit que le soft ouvre le fichier poster.ini, se positionne sur la valeur start, vire le 1 et place 081349.
C'est tout ce qu'il fait, plus d'autre vérification par la suite afin de voir si le code est bon.

Trop simple donc on va regarder une autre façon de faire;
Retournons voir du coté de poster.ini dans le listing et on trouve ceci qui correspond a un code temporaire.
Allons bon c'est pas intéressant !
Mais si , parce que l'on va tirer profit du saut non pas en changeant le jne en je mais, en changeant la destination du saut, on l'expédie sur le code ok et ca marche aussi. Avec un avantage, on ne passe pas par toute les autres
vérifications qui suivent donc gain de vitesse d'exécution. Enfin si on veut…

* Possible StringData Ref from Data Obj ->"012248"
                                  |
:0040C1DA 681C734700              push 0047731C
:0040C1DF 8D8554FFFFFF            lea eax, dword ptr [ebp+FFFFFF54]
:0040C1E5 50                      push eax
:0040C1E6 E8B58E0500              call 004650A0
:0040C1EB 83C408                  add esp, 00000008
:0040C1EE 85C0                    test eax, eax
:0040C1F0 751B                    jne 0040C20D................devient jne 0040C38C

encore une autre possibilité

:0040C363 8B8D4CFFFFFF            mov ecx, dword ptr [ebp+FFFFFF4C]
:0040C369 3B8D48FFFFFF            cmp ecx, dword ptr [ebp+FFFFFF48]
:0040C36F 741B                    je 0040C38C
* Possible Reference to String Resource ID=00175: "Invalid Registration Code"

les deux lignes avant le saut sont très belles :
si mov..... dans la première pourquoi ne pas garder la même valeur pour le cmp dans la suivante nous allons donc changer celle ci et nous aurons donc :

:0040C369 3B8D48FFFFFF            cmp ecx, dword ptr [ebp+FFFFFF4C]

et ca marche aussi .
voila j'ai fait le tour du contournement du code, il y a peut être encore d'autres façons de faire, notamment dans le listing qui suit la référence "012248", mais ce n'est que de la répétition donc plus utile pour notre
recherche.

=========================================================================

pour attaquer cette seconde partie on va d'abord ouvrir le fichier poster.ini et remettre la valeur start a 1
donc un soft non enregistré.
il n'y a pas de limite dans le temps, mais il nous limite le nombre d'impressions a 12.
En fait ce n'est pas vrai, car il continue a imprimer au delà de la douzième impression, mais surprise !
Il imprime le bon de commande ( fallait quand même pas rêver !)
Lorsque l'on quitte le soft il y a une boite de rappel qui apparaît, et on peut voir que nous avons encore 12
fois le droit d'imprimer nous allons donc rechercher ce message dans les strings

* Possible StringData Ref from Data Obj ->"You have printed %d posters."
                                  |
:00440632 68E0BB4700              push 0047BBE0
:00440637 8D9530FFFFFF            lea edx, dword ptr [ebp+FFFFFF30]
:0044063D 52                      push edx

En partant de là, on remonte dans le listing jusqu' ici et on trouve des choses très intéressantes.
Par exemple si on regarde où nous envoie le jmp, on se retrouve en fin de procédure donc nous passons au dessus des contraintes liées au soft non enregistré et pour arriver là, juste un peu de curiosité.
Sous wdasm on regarde la valeur de eax en 00440498 : eax = 2 car pas enregistré.
On va donc changer ca pour arriver sur le jmp; c'est la façon la plus rapide pour être tranquille avec cette limitation

* Referenced by a CALL at Addresses:
|:0042B7D7   , :0042B8DF   , :0042B919   , :0043D4E0   
|
:00440488 55                      push ebp
:00440489 8BEC                    mov ebp, esp
:0044048B 81ECD4000000            sub esp, 000000D4
:00440491 0FBF054C244800          movsx eax, word ptr [0048244C]
:00440498 83F801                  cmp eax, 00000001.........devient cmp eax, 00000002
:0044049B 740C                    je 004404A9
:0044049D 0FBF0D4C244800          movsx ecx, word ptr [0048244C]
:004404A4 83F903                  cmp ecx, 00000003
:004404A7 7505                    jne 004404AE

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0044049B(C)
|
:004404A9 E9D3010000              jmp 00440681.............vers ret

une autre solution c'est de bloquer le compteur pour qu'il reste a 12

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00440583(C)
|
:0044058A 0FBF0D74314800     movsx ecx, word ptr[00483174]... nbre d'impressions effectuées
:00440591 83F90C             cmp ecx, 0000000C
:00440594 7F12               jg 004405A8
:00440596 668B1574314800     mov dx, word ptr [00483174]
:0044059D 6683C201           add dx, 0001....................incrémente le nbre d'impressions
:004405A1 66891574314800     mov word ptr [00483174], dx

il suffit donc de changer cette valeur en remplaçant le 0001 par 0000 comme ça le compteur ne compte plus rien et notre valeur restera a 12 impressions.
Et si par hasard, gros béta, j'ai joué trop longtemps et que je ne sais plus imprimer, comment remettre a zéro?
Facile il suffit de changer sa façon de calculer, s'il sait ajouter, il sait aussi soustraire, donc nous
allons changer de la façon suivante : par exemple on a imprimé 10 fois, on va faire le changement suivant :

:0044059D 6683C201                add dx, 0001      va devenir     sub dx,000A

donc 10 - 10 = 0 il nous reste 12 impressions c'est ti pas beau ?

En poussant plus loin l'examen du listing on peut voir que si on ne touche a rien. Il regarde si " enregistré ".
Si pas, à partir de la cinquième impressions on a un joli message qui nous avertit que nous avons fait x impressions.
Il va aussi aller ajouter une ligne dans le fichier poster.ini pc=x; x étant le nombre d'impressions effectuées.

Il y a aussi cette petite astuce qui dit que si on a fait 12 impressions, à partir de la 13eme, il continuera a imprimer mais uniquement le bon de commande.
Ca c'est marrant !
Enfin si on veut…

* Possible StringData Ref from Data Obj ->"%d"
                                  |
:004405B0 68A0BB4700              push 0047BBA0
:004405B5 8D8D30FFFFFF            lea ecx, dword ptr [ebp+FFFFFF30]
:004405BB 51                      push ecx

Conclusion
voila je crois que nous avons fait le tour de ce soft, une fois de plus il faut reconnaître que seule une vision profonde des choses nous permet d'approfondir nos connaissances.
Si on nous a mis des yeux et un cerveau ( le mien est petit ), c'est pour nous en servir, alors pourquoi faut il les laisser au placard ?
bonne question .
Précision finale, pour tester le soft même pas besoin d'entrer un code, on fait juste clic sur ok

A+
Alien


Lorsque Alien m'a envoyé le programme sur lequel il envisageait de plancher, j'ai eu le plaisir de le cracker en quelques minutes (mais alors toutes petites les minutes…).
Le genre de protection juste histoire de s'amuser 5 minutes! et de pouvoir se dire que tout auteur de Shareware devrait prendre des "cours" de cracking avant de chercher à monter une usine à gaz...

Pour autant, un programme peut encore receler des éléments intéressants, et Alien a eu raison de continuer.

Pour ma part, je me demandais bien ce que j'allais pouvoir faire de ce truc…

En plein dans ma période " DialogBox ", il m'a semblé qu'il pourrait être amusant de s'occuper un peu de celle qui s'occupait de l'enregistrement…

Et pour commencer, il fallait trouver l'adresse de cette DialogBoxParamA :

En cherchant " REGISTER " dans le Dead Listing:

* Reference To: USER32.MessageBoxA, Ord:0195h
                                  |
:0040594B FF15B4694800            Call dword ptr [004869B4]
:00405951 33C0                    xor eax, eax
:00405953 E9BE160000              jmp 00407016
:00405958 6A00                    push 00000000
:0040595A 682EBF4000              push 0040BF2E
:0040595F 8B4508                  mov eax, dword ptr [ebp+08]
:00405962 50                      push eax

* Possible StringData Ref from Data Obj ->"REGISTER"
                                  |
:00405963 6898684700              push 00476898
:00405968 8B0D50324800            mov ecx, dword ptr [00483250]
:0040596E 51                      push ecx

* Reference To: USER32.DialogBoxParamA, Ord:008Eh
                                  |
:0040596F FF1570694800            Call dword ptr [00486970]

Sachant que:

Les lignes qui précèdent ne laissent en rien supposer que le programme ait pu passer par la :

:0040594B FF15B4694800            Call USER32.MessageBoxA  > pas vu
:00405951 33C0                    xor eax, eax
:00405953 E9BE160000              jmp 00407016             > pas pris

Qu'il n'y a pas de références à un call, un saut conditionnel ou un jump avant l'appel à la Dialog Box, on en vient à se dire qu'il y a forcément eu un appel indirect sur cette boite...

Ce type de boite se paramètre de la manière suivante :

int DialogBoxParam(

    HINSTANCE hInstance,         // handle to application instance
    LPCTSTR lpTemplateName,     // identifies dialog box template
    HWND hWndParent,           // handle to owner window
    DLGPROC lpDialogFunc,     // pointer to dialog box procedure  
    LPARAM dwInitParam       // initialization value
   );	
push 00000000                   hInstance
push 0040BF2E                   lpTemplateName
mov eax, dword ptr [ebp+08]
push eax                        hWndParent
push 00476898  ->"REGISTER"     lpDialogFunc 
mov ecx, dword ptr [00483250]   
push ecx                        dwInitParam
Call USER32.DialogBoxParamA

Conclusion : l'appel se fait très certainement sur l'adresse 00405958 par je sais pas quoi...
Jetons un coup d'œil sur la pile :

Stack

KERNEL32!UTUnRegister+09DB at :BFF94407 (SS:EBP 0187:006DFC4C)
KERNEL32!ORD_0079+0757 at :BFF7363B (SS:EBP 0187:006DFC38)
POSTER!.text+0003B4FC at :0043C4FC (SS:EBP 0187:006DFC18)
ð POSTER!.text+072A at :0040172A (SS:EBP 0187:006DF3B4)

Bene ! l'appel vient de 0043C4FC. Allons voir :

Petit trace into le call sur lequel nous fait arriver cette adresse, et :

:0040171C  0F87FE560000        JA      00406E20
:00401722  8B958CF4FFFF        MOV     EDX,[EBP+FFFFF48C]
:00401728  33C9                XOR     ECX,ECX
:0040172A  8A8AEE704000        MOV     CL,[EDX+004070EE]
:00401730  FF248D26704000      JMP     [ECX*4+00407026]  -> Oups !
:00401737  81BD8CF4FFFFBC020000CMP     DWORD PTR 

En arrivant en 00401730, ECX vaut 26h, et l'adresse "calculée" pour le jump donne 004070BE. Un petite intérrogation sur le contenue de cette adresse, et on trouve 00405958 (ou plus exactement 58 59 40 00).
Ca roule c't'affaire !

Maintenant un ch'tit coup d'éditeur hexa :

000064B0 4000 1C22 4000 A829 4000 A660 4000 5859 @.."@..)@..`@.
000064C0 4000 711B 4000 4966 4000 8B66 4000 8143  .q.@.If@..f@..C

Et valà notre adresse délicatement placée dans une table !.
Ce qui pourrait être fait, maintenant, c'est de remplacer cette valeur par l'adresse de la routine d'enregistrement de l'utilisateur validé que l'on va décortiquer un brin pour la partie la plus intéressante:

:0040C3A7  PUSH    00477398                      > Poster.ini
:0040C3AC  LEA     ECX,[EBP-00AC]                > bon sérial
:0040C3B2  PUSH    ECX                           > poussé sur la pile
:0040C3B3  PUSH    004773A4                      > start
:0040C3B8  PUSH    004773AC                      > POSTER
:0040C3BD  CALL    [WritePrivateProfileStringA]  > écrit

Et voici le résultat dans c:\Windows\Poster.ini

[POSTER]
start=081349

La suite est moins intéressante :

:0040C3C3  MOV     WORD PTR [0048244C],0001   > Flag Utilisateur Registered
:0040C3CC  PUSH    00                         > Bouton MB_OK
:0040C3CE  PUSH    004773B4                   > Registration (Titre)
:0040C3D3  PUSH    004773C4                   > Thank You (message)
:0040C3D8  MOV     EDX,[EBP+08]               > Handle de la fenêtre
:0040C3DB  PUSH    ECX                        > poussé sur la pile
:0040C3DC  CALL    [MessageBoxA]              > Message Box Glop ! Glop !

Puis le programme va fermer la boite d'enregistrement :

:0040C3E2  PUSH    00                         
:0040C3E4  MOV     EAX,[EBP+08]
:0040C3E7  PUSH    EAX
:0040C3E8  CALL    [EndDialog]

Ces quelques lignes vont nous casser le pied. Si le programme passe par elles alors que la DialogBox d'enregistrement n'a pas été ouverte, c'est l'application qui va se fermer partiellement, mais en restant en tache de fond sans possibilité de fermeture autre qu'un CTRL+ALT+SUPPR.
On vire en remplaçant Push 00 par JMP 0040C3EE

:0040C3EE  MOV     EAX,00000001   > Good Boy !
:0040C3F3  JMP     0040C3FD       > et on quitte...
:0040C3F5  XOR     EAX,EAX
:0040C3F7  JMP     0040C3FD
:0040C3F9  JMP     0040C4A0
:0040C3FB  JMP     0040C4A0
:0040C3FD  MOV     ESP,EBP        > en passant par ici.
:0040C3FF  POP     EBP
:0040C400  RET     0010

On pourrait faire bien plus simple en inversant le saut code valide/code invalide, mais vous allez voir que l'on va continuer à se faire mal aux cheveux :

Griser l'Item Registration :

Le programme permettant d'entrer différents codes (code : + 2 jours de rabe, code : serial temporaire et code : number définitif), l'auteur a laissé l'accès à la boite d'enregistrement, même avec le code définitif entré.
C'est pas BO !

On corrige...

Le principe est simple :

- il faut récupérer le Handle de la fenêtre (hWnd)
- il faut récupérer le handle des menus
- il faut trouver l'identificateur (ID) de l'item " register "
- et il faut la griser.

Un jeu d'enfant non ?

Et bien sur, il faut aussi trouver de la place !
On va commencer par ce petit problème.
Ce qui m'est venu à l'esprit en premier, a été de prendre la place de la routine " Code Invalide " :

017F:0040C35D  89854CFFFFFF        MOV     [EBP-00B4],EAX
017F:0040C363  8B8D4CFFFFFF        MOV     ECX,[EBP-00B4]
017F:0040C369  3B8D48FFFFFF        CMP     ECX,[EBP-00B8]
017F:0040C36F  741B                JZ      0040C38C        > Jump Good Boy
017F:0040C371  68AF000000          PUSH    000000AF        > début de Bad Boy
017F:0040C376  8B1548324800        MOV     EDX,[00483248]
017F:0040C37C  52                  PUSH    EDX

Dans cette routine, et avant d'arriver aux adresses " Good Boy ", il y a 29 octets à prendre. Si je décide de squatter là, mon patch ne devra pas être plus long !

Récupérer le handle de la fenêtre :

Le plus simple est de trouver une API qui en a également besoin, et où, habituellement, le programme va le mettre en mémoire :

* Reference To: USER32.CreateWindowExA, Ord:0055h
                                  |
:004372EF FF15586A4800            Call dword ptr [00486A58]
:004372F5 A348324800              mov dword ptr [00483248], eax

Bingo !
En [00483248] vous avez EAX qui vient se glisser dans une adresse mémoire (hWnd). Gut !

L'identificateur de l'Item de Menu :

Tutorial            [ID=0112h]
Examples            [ID=0100h]
About ...           [ID=0015h]
Registration        [ID=003Ah]

Danke Wdasm !
Mon ID est 0x003A

Au tour du handle des menus. Là encore, ce qui m'a paru le plus facile est d'utiliser l'API GetMenu, pour récupérer ce handle dans EAX.
Et sur la lancée, modification de l'item :

:0040C377  FF3548324800        PUSH    DWORD PTR [00483248]  > hWnd
:0040C37D  E89760B4BF          CALL    USER32!GetMenu        > EAX = hMenu
:0040C382  6A01                PUSH    01                    > grayed
:0040C384  6A3A                PUSH    3A                    > ID Item
:0040C386  50                  PUSH    EAX                   > hMenu
:0040C387  E8426AB4BF          CALL    USER32!EnableMenuItem > Done !
:0040C38C  6890734700          PUSH    00477390
:0040C391  8D8554FFFFFF        LEA     EAX,[EBP-00AC]

Et Une Item Grisée, Une !
Par contre, en relançant l'application, tout enregistré que vous soyez, vous avez droit au grand retour de notre Item tout ce qu'il y a de plus actif...

Une âme courageuse pourrait mettre un BPM sur le Flag Utilisateur ([0048244C]), attendre que la vérification du sérial lui ait été favorable, et s'occuper ensuite de modifier l'Item si l'Utilisateur est bel et bien enregistré. C'est tout à fait possible suite au passage à l'adresse 0040BC51 (bien sur après l'affichage de la fenêtre !). Puis envoyer le programme vers une routine identique à celle du dessus :

:0040BC51  8B4C85F0            MOV     ECX,[EAX*4+EBP-10] > Tout OK
:0040BC55  E919020000          JMP     0040BE73           > jump Patch
:0040BC5A  90                  NOP                        > équilibrage

Le patch :

Il est la réplique du précédent. D'ailleurs, il serait même possible d'envisager que le même patch puisse servir aussi bien à effacer l'Item Registration après enregistrement, qu'au lancement de l'application. Tout est histoire de condition. En tout état de cause, pour le moment je laisse en l'état, et je pars à la recherche d'un peu de place disponible. Quelques lignes en dessous de l'adresse 0040BC55, je trouve toute une famille de OR [ECX],ECX qui semble n'avoir rien à faire. Un petit BPR sur un bloc d'au moins une cinquantaine d'octets, et Zou ! C'est parti pour un patch...

:0040BE73  833D4C24480001      CMP     DWORD PTR [0048244C],01
:0040BE7A  7515                JNZ     0040BE91
:0040BE7C  FF3548324800        PUSH    DWORD PTR [00483248]
:0040BE82  E89265B4BF          CALL    USER32!GetMenu
:0040BE87  6A01                PUSH    01
:0040BE89  6A3A                PUSH    3A
:0040BE8B  50                  PUSH    EAX
:0040BE8C  E83D6FB4BF          CALL    USER32!EnableMenuItem
:0040BE91  51                  PUSH    ECX
:0040BE92  6859020000          PUSH    00000259
:0040BE97  E9BFFDFFFF          JMP     0040BC5B
:0040BE9C  0909                OR      [ECX],ECX
:0040BE9E  0909                OR      [ECX],ECX
:0040BEA0  0909                OR      [ECX],ECX

La condition en 0040BE73 permet de tester si l'utilisateur est enregistré ou non, auquel cas le programme saute le patch, et l'Item reste intact pour permettre d'accéder à celui ci. Si l'utilisateur est enregistré (bonnes informations dans le fichier Poster.ini), l'Item est Grayed.
Et pour ne pas flanquer le souque dans le programme, les 2 push ECX et 00000259 restaurent les octets que le jmp en 0040BC55 avait écrasé.

Mais il a moyen de faire autrement, bien que de façon assez définitive:

Griser l'item directement dans le fichier sur DD :

Avant modification, le texte de l'Item (en Wide Char Format) et de ses caractéristiques est ainsi :

00090420 1500 2600 4100 6200 6F00 7500 7400 2000 ..&.A.b.o.u.t. .
00090430 2E00 2E00 2E00 0000 8000 3A00 2600 5200 ..........:.&.R.
00090440 6500 6700 6900 7300 7400 7200 6100 7400 e.g.i.s.t.r.a.t.
00090450 6900 6F00 6E00 0000 0000 0000 1000 7800 i.o.n.........x.

Pour qu'il apparaisse grisé, il faut remplacer 80 par 81 :

00090420 1500 2600 4100 6200 6F00 7500 7400 2000 ..&.A.b.o.u.t. .
00090430 2E00 2E00 2E00 0000 8100 3A00 2600 5200 ..........:.&.R.
00090440 6500 6700 6900 7300 7400 7200 6100 7400 e.g.i.s.t.r.a.t.
00090450 6900 6F00 6E00 0000 0000 0000 1000 7800 i.o.n.........x.

Et basta !

Par contre, plus moyen d'accéder à cet Item, et donc de provoquer un enregistrement par un clic sur celui ci à la première fois ou l'utilisateur voudra s'enregistrer...
Un peu trop radical, non ?

On peut continuer à faire mumuse...

Virer la DialogBox de départ:

Je n'en vois pas l'utilité. Elle n'apporte rien, que ce soit dans la version Shareware (style : Enregistrez-vous) soit dans la version Enregistrée. Pour la supprimer, il y a différentes méthodes, mais une de celles qui est la plus simple à mettre en œuvre, et de la réduire à la taille d'un pixel. ExeEscope est parfait pour ce genre de travail :

X  9        Y   39        Width  1      Height   1

On pourrait continuer encore longtemps à apporter des modifications à l'originale, mais il faudra rapidement trouver de l'espace pour structurer toutes ces patchs, et ne pas continuer à jouer sur l'empirisme...

Trouver de la place :

Regardons ce que le padding a pu nous laisser comme place à la fin de la dernière section de Poster.exe :

Name   Virt Size   Virt Offset  Raw Size   Raw Offset  Characteristics
.text   00072ED3    00001000    00073000    00000400    60000020
.rdata  00001BB0    00074000    00001C00    00073400    40000040
.data   0000F5E4    00076000    00009A00    00075000    C0000040
.idata  00002008    00086000    00002200    0007EA00    C0000040
.rsrc   000252EC    00089000    00025400    00080C00    40000040

La section .rsrc étant la dernière, jetons un œil bienveillant sur celle-ci.

Adresse de début de la section :
Ad Image Base 00400000 + Virtual Offset 00089000 = 00489000

Le code de la section .rsrc commence à l'offset 0x80C00 pour finir à l'offset 0x80C00 + 0x25400 = 0xA6000, mais la taille du code étant de 0x252EC, il doit être possible de squatter quelques octets à partir de l'offset 0xA5EF0.

Confirmation en Image :

000A5EC0 0900 4200 6100 6400 2000 5600 6100 6C00 ..B.a.d. .V.a.l.
000A5ED0 7500 6500 0000 0000 0000 0000 0000 0000 u.e.............
000A5EE0 0000 0000 0000 0000 0000 0000 0000 0000 ................
000A5EF0 0000 0000 0000 0000 0000 0000 0000 0000 ................

Soit A6000 - A5EF0 = 110h, ou encore 272 octets de disponibles à partir de l'adresse 0x00489000 + 0x252EC = 0x004A52EC.

Espérons que ce sera suffisant...

Bonne Journée

Christal