Dossier n°8

Les CheckSums et les CRC


Il faut bien distinguer les checksum, des CRC.

Le premier va additioner le poids des bits qui composent le programme, et vérifier que la somme obtenue est bien égale à une valeur qu'il aura conservé quelque part en mémoire (et souvent HardCoded). Suivant les cas, il peut y avoir moyen de "réctifier" le décallage que pourrait avoir provoqué vos modifications en rééquilibrant la somme des octets à un autre endroit. Vous pouvez aussi trouver la routine de calcul et mettre la main sur la valeur d'origine du checksum (éventuellement modifiable par un hexéditeur) ainsi que sur la nouvelle somme qu'aura votre programme après le patchage. Une dernière solution, et de shunter le blocage lié au checksum au niveau du message "File Corrupted".

Pour les Code de Redondance Cyclique , l'idée principale est de voir le fichier comme une grande série de bits divisées par un nombre, et qui vous laissera un Reste, le CRC! Utilisant un algorythme de calcul, le CRC est beaucoup plus délicat à contourner...

Dans ce dossier, vous trouverez trois parties:

Les Checksums

Les CRC

Les programmes

Ce dossier a été créé à partir d'une compilation de textes du Groupe de Travail, et d'extraits de sites


CheckSum: Généralités


Cheksum: petite saloperie qui calcule le poids des octets composant les codes du programme.
Par exemple 5F en hexadécimal pèsera 95, et 5E pèsera 94. Donc si vous utilisez un éditeur héxa pour modifier l'exécutable, vous obtiendrez une boite "Intégrity Check Violation error" dès le lancement de celui-ci. Ceci dans le meilleur des cas, et dans le pire, le programme se contentera de cloturer l'application.


Comment cibler la routine de détection d'un Checksum corrompu

Certains programmes vérifient leur intégrité au démarrage et refusent de se lancer s'ils ont été "corrompus". Souvent cette protection est facile à retirer : bpx MessageBoxA si le soft affiche une messagebox pour signaler le problème ou tout simplement en traçant et en repérant le branchement qui fait quitter le programme. Néanmoins, il peut arriver que cette vérif soit bien faite et bien intégrée dans le programme (vérifs multiples et fonction de hachage pas évidente à repérer). C'est le cas des récentes versions de Windows Commander par exemple. Je me permets donc de vous fournir cette petite astuce : Il y a deux types de vérifs : celle qui vérifie l'intégrité en mémoire et celle qui vérifie l'intégrité du fichier exécutable. C'est pour cette dernière que l'astuce est utilisable : - Repérer dans le soft où celui-ci ouvre le fichier exécutable (bpx CreateFileA le permet très facilement). - Modifier le soft pour que celui-ci ouvre un autre fichier à la place (original.bak par exemple). - Et évidemment faite une copie du fichier exécutable non modifié (nommé original.bak dans l'exemple). Maintenant, le soft peut faire toutes les vérifs d'intégrité possible, aussi complexe soit-elle, vous ne serez plus embêté...
Remarque : cette astuce à l'avantage d'être applicable par un patch, puisqu'il suffit juste de copier l'original avant d'appliquer les modifications sur le fichier exécutable d'origine.
Brénuche


Rectification d'un Checksum par équilibrage des octets:

Le programme calculant la somme des octets le composant, toutes modifications de cette somme entrainera l'apprition d'un message d'erreur. L'idée consiste à trouver un endroit du programme non utilisé (routines shareware, messages d'erreur...) et d'y soustraire ou additionner à un octet l'equivalent de la différence que vous avez infliger à la cible en la patchant.

Généralités: HelpBldr by Christal

Extrait de Millénium by ACiD BuRN
CheckSum
Imaginez que vous venez de cracker un messagebox en memoire ou autres merdes et 
que après avoir modifiè le programme en hexa , le fichier ne se lance plus
de tout , mais quitte directe !! ou encore qu'il vous dise: "CRC ERROR blablablaa"
Et la vous dites!! merde!!!!! c quoi ce bordel! je peux meme pas patcher ;(
alors soit vous utilisez un mem patcher (patch qui ne patch qu'en memoire donc le programme
est tjs intacte, mais a besoin d'être lancé avec ca) sois vous reflechissez :)

Ca peut très bien etre plusieurs choses en fait !!

on va commencer par le checksum !
c quoi ? 
en fait , le programme fait une somme des valeurs ascii du programme et les compare
a une constante par exemple!
Et tant que c'est egale a cette constante, le programme se lance sans broncher!
Mais vous , vous venez de patcher avec des NOP , je , JMP ou autres !!
et ces instructions n'ont pas le même poids !

exemple à 2 francs:

il y avait un:

JE   XXXXXXXXXX

et vous l'avez remplacé par un JNE (BEURK , mais ca sera plus simple pour kicker le
checksum).

on dira que ca ressemblait à ca en hexa:

7428   (pour le "je")  == 74h + 28h = 9Ch = 156

donc 156 en decimal !! et vous avez patché en JNE:

7528 (pour le "jne") == 75h + 28 h = 9Dh = 157

157 est different de 156 donc en additionant tous les octets un a un , le programme trouvera
une difference et ne se lancera PAS :)
comment contourner ca ?

Ben , moi je modifierais ca en :

7527  = 75h + 27h = 9Ch = 156

on s'en fout de la valeur apres le jne car il ne sautera pas!!
et le resultat est donc egale à 156 et il croit que tout est OK :P
Bref c tout con mais ca marche tres bien !
Si par bonheur le programme vous annonce que le fichier avait ete modifié pas la peine
de jouer avec les octets comme ca mais desassemblez le fichier et regardez
dans les strings data references le message qu'il nous donnait et crackez moi ca siou plait ;p

Même motif, même punition:

JPEG optimizer 3.5 by D.LiriUm TrEs MinCe et Christal

Le Checksum

Jpeg Optimizer utilise des call indirects (du genre call [eax+40]) de façon très fréquente, si bien que le prog, depuis l'entry point, est une véritable horreur à tracer. Pour essayer de mettre la main sur le routine de calcul du poids des octets du programme, j'ai du tracer pendant plus d'une heure et demi avant de décider d'abandonner. On parle de la patience qu'il faut avoir, mais là…
Mon idée première avait été de partir de la String Data Ref "Abnormal Program Termination" en 00471B14, mais au premier call indirecte j'ai bien été obligé d'arrêter, après être remonté jusqu'en 004677E8. En partant de l'Entry Point, j'ai baissé les bras en 004312F2 alors que les 2 versions (enregistrée et non-enregistrée) passaient encore toutes deux par cette adresse. Le calcul du checksum se trouve donc obligatoirement entre 004312F2 et 004677E8.

La solution que tu as utilisée, à défaut d'être élégante, permet au moins de résoudre le problème posé par le checksum, et dans la mesure où tu sais à quel endroit tu disposes de place pour équilibrer le poids des octets modifiés, à défaut de mieux, c'est déjà ça…

Par contre, pour la modification que j'envisage de faire, il ne s'agit plus d'équilibrer 01 au poids des octets, mais 91d, soit 5Bh!
Reste à trouver 5B dans la routine code invalide qui acceptera de se faire modifier en 00…

Et

017F:004290C3  2BF9                SUB       EDI,ECX
017F:004290C5  8DB5BCFEFFFF        LEA       ESI,[EBP-0144]
017F:004290CB  87F7                XCHG      ESI,EDI
017F:004290CD  8BD1                MOV       EDX,ECX

va devenir:

017F:004290C3  2BF9                SUB       EDI,ECX
017F:004290C5  8DB00CFEFFFF        LEA       ESI,[EAX-01F4]
017F:004290CB  87F7                XCHG      ESI,EDI
017F:004290CD  8BD1                MOV       EDX,ECX


Rectification d'un Checksum par modification de sa somme:

Dans ce premier exemple, vous verrez un contrôle de l'intégrité du header, puis comment mettre la main sur la routine de contrôle, et enfin comment obtenir la valeur du checksum d'origine, et la nouvelle valeur liée aux bidouillages infligés à la cible.

DCeSS & PEShield by Pulsar et ChristalCh		

A l'initiative de Cmos, qui proposait un petit programme de 30 ko tout mouillé, DeCSS, mais protégé par PESHIELD version 0.2 d'ANAKIN [Da Vinci], j'ai voulu attaquer le programme à la loyale:
Lancement de DeCSS.exe via le Symbol Loader de SoftIce. No Break!
Premier coup bas!
Pas de problème, un p'tit uppercut signé ProcDump, et la first section de DeCSS passe de C0000040 à E0000020

PESHiELD RVA: 00001000 Offset: 00000400 Size: 00005600 Flags: C0000040
PESHiELD RVA: 0001D000 Offset: 00005A00 Size: 00000800 Flags: C0000040
ANAKIN98 RVA: 0003B000 Offset: 00006200 Size: 00001400 Flags: C0000040

Puis je suis reparti à la charge, toujours avec SoftIce.
Deuxième coup bas!
"Files was altered! Maybe it is infected by a virus".
Ca, c'est un message typique de checksum, mais comme en dehors du flags d'une section je n'ai encore rien fait, c'est que PESHIELD va contrôler l'état du PE Header, et les modifications qui lui ont été faite.

Ces modifications sont dans le header de l'exe qui commence en 400000 (pour plus d'infos documentez-vous la dessus)
On fait bpr 400000 401000 RW et on lance le prog....
Et là, on le fait breaker jusqu'à ce qu'on tombe sur un lodsd

:0043B400  AD                  LODSD            > là!
:0043B401  03D0                ADD     EDX,EAX
:0043B403  EB01                JMP     0043B406
:0043B405  68AD03D0EB          PUSH    EBD003AD
:0043B40A  01C8                ADD     EAX,ECX

on fait d edi et on doit trouver le nom de la première section...

:d edi
0003B000 00 29 47 3E 89 76 F8 B8-9E 07 BA 27 17 89 56 FE  .)G>.v.....'..V.
0003B010 89 46 FC 8B F0 EB 1B 26-8B 04 2B DB 8E C0 26 39  .F.....&..+...&9
0003B020 1E 00 00 74 18 8E 46 FE-26 8B 04 2B C9 8B F1 89  ...t..F.&..+....

Bon on est bien la!
On commence à tracer jusqu'à tomber sur:
dec ecx
jnz XXX
jmp XXX

0043B41D  EB02                 JMP     0043B421
0043B41F  C78B03D0C1C202EB01C7 MOV     DWORD PTR [EBX+C2C1D003],C701EB02
0043B429  49                   DEC     ECX
0043B42A  75D1                 JNZ     0043B3FD
0043B42C  EB01                 JMP     0043B42F
0043B42E  CA3B95               RETF    953B
0043B431  6D                   INSD    > hep, un coup d'œil ici!

On met un bpx sur le jmp ,on enlève le bpr précèdent, et on lance...
Au break, il est préférable d'enlever le bpx, car si Peshield regarde, il pourrait ne pas aimer trouver un 0CCh!
Et on trace un peu jusqu'à tomber sur cmp edx,[ebp+xxx]

0043B429  49                  DEC     ECX
0043B42A  75D1                JNZ     0043B3FD
0043B42C  EB01                JMP     0043B42F
0043B42E  CA3B95              RETF    953B
0043B42F  3B956D110000        CMP     EDX,[EBP+0000116D] le code a changé!
0043B435  EB01                JMP     0043B438
0043B437  C80F855D            ENTER   850F,5D
0043B43B  0200                ADD     AL,[EAX]

et deux F10 plus tard:

0043B437  C80F855D            ENTER     850F,5D
0043B438  0F855D020000        JNZ       0043B69B (NO JUMP si PE Header intègre)
0043B43E  8B85C9110000        MOV       EAX,[EBP+000011C9]
0043B444  EB03                JMP       0043B449

Checksum pas Glop

:d edx
013F:00845904 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? 
013F:00845914 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? 
013F:00845924 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? 

On met un bpm X sur l'offset de cette instruction, on ferme le prog, et on enlève les modifs des sections
Puis on relance le prog et il breake sur le bpm x.
Là, on a le bon checksum dans edx car on a rien modifié...

Checksum Glop Glop

:d edx
013F:0084610D ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? 
013F:0084611D ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? 
013F:0084612D ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? 

C'est pas nécessaire de faire ça mais je vous montre un peu les protections que Peshield utilise....

Danc cet exemple, vous aurez deux cas de figure: Commen forcer le programme à reconnaître le nouveau checksum, et comment modifier le programme en fonction de ce nouveau checksum:

Teleport pro 1.29 by Christal

This program has been altered, possibly by a virus; program execution will stop now

On a un petit Checksum sur le programme...
Possibilité d'un CRC32 ? Peut être, mais facile à contourner :

:0040B482     mov eax, dword ptr [0047B6EC] -> EAX = good value
:0040B487     cmp esi, dword ptr [eax]      -> ESI = Value réelle calculée
:0040B489     je 0040B49E                   -> bad boy, don't touch my program
:0040B48B     push ebx
:0040B48C     push ebx

* Possible StringData Ref from Data 0bj ->"This program has been altered, "
->"possibly by a virus; program execution will stop now."

qu'il est facile de shunter en faisant un

:0040B482  MOV       ESI,[0047B6EC]  -> good value in ESI
:0040B488  NOP
:0040B489  JMP       0040B49E        -> et on saute le message Pas Glop ! 
Mais il y a une manière plus élégante de se débarrasser du Checksum :

:0040B482     mov eax, dword ptr [0047B6EC] -> EAX = good value
:0040B487     cmp esi, dword ptr [eax]      -> ESI = Value réelle calculée

La bonne valeur du Checksum est placée dans [0047B6EC]. Une rapide recherche dans le Dead Listing semble montrer qu'il n'y aurait pas de mov [0047B6EC], et que par conséquent il est fort probable que la valeur attendue se trouve dans les codes du programme en clair. Une interrogation D *EAX va donner E01928E3, valeur que l'on va retrouver facilement avec un éditeur hexa :

0007B6EC F0B6 4700 E019 28E3 F0B6 0700 0000 0000 5468 6973 ..G... .........This
0007B700 2070 726F 6772 616D 2068 6173 2062 6565 6E20 616C  program has been al

Et placée juste avant le message d'erreur...

Après les différentes modifications apportées au programme, il n'y aurait plus qu'à poser un BPM X sur 0040B482, relever la valeur contenue dans ESI, et aller l'inscrire à la place de l'autre ?
Et bien oui !
Ca marche, la valeur du Checksum n'étant pas Hard Coded, le programme va maintenant vérifier l'intégrité de ses codes en utilisant la nouvelle valeur mise en place. Glop ! Glop !


Détourner la routine "File Corrupted":

Un checksum n'infecte pas obligatoirement la totalité des codes de l'exécutable. Parfois seul le header de celui ci est contrôlé. Quand le programme à la gentillesse de vous alerter qu'il se juge contaminé par un quelconque Virus (ou toute autre modification), il s'empresse de vous en prévenir. Suivant les cas un BPX sur MessageBoxA peut faire l'affaire, sinon, il faudra tracer le programme dès son EntryPoint.

Shunter la routine en placant un RET au début de celle ci:

Extrait 3D exploration 1.2.54 (ASPack 2000) by Christal

En avançant pas à pas, (infirmière, passez-moi F10) :

3D Exploration File corrupted !

Ouch !
Tension les gars, va nous faire un arrêt cardiaque !

Le prog à un CRC.
Méchante chose ça.
Très contagieux en ce moment qui plus est !

En va enlever la tumeur, mais pour commencer, voyons si l'infection est généralisée :

BPX GetProcAddress :
Glop !

Droit dessus

:BFF70000 4D 5A 90 00 03 00 00 00-04 00 00 00 FF FF 00 00  MZ..............
:BFF70010 B8 00 00 00 00 00 00 00-40 00 00 00 00 00 00 00  ........@.......
:BFF70020 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
:BFF70030 00 00 00 00 00 00 00 00-00 00 00 00 80 00 00 00  ................
:BFF70040 0E 1F BA 0E 00 B4 09 CD-21 B8 01 4C CD 21 54 68  ........!..L.!Th
:BFF70050 69 73 20 70 72 6F 67 72-61 6D 20 63 61 6E 6E 6F  is program canno
:BFF70060 74 20 62 65 20 72 75 6E-20 69 6E 20 44 4F 53 20  t be run in DOS
:BFF70070 6D 6F 64 65 2E 0D 0D 0A-24 00 00 00 00 00 00 00  mode....$.......

L'infection part de l'entête du Header (l'adresse 00400000 du programme dont le contenu a été chargé en BFF70000)
En cherchant quelques lignes plus bas, on repère vite la section
.text dont les caractéristiques ont été modifiées :

:BFF701A0 2E 74 65 78 74 00 00 00-05 C9 04 00 00 90 00 00 .text...........
:BFF701B0 00 D0 04 00 00 90 00 00-00 00 00 00 00 00 00 00 ................
:BFF701C0 00 00 00 00 20 00 00 60-5F 49 4E 49 54 00 00 00 .... ..`_INIT...
:BFF701C0 00 00 00 00 20 00 00 60-5F 49 4E 49 54 00 00 00 .... ..`_INIT...

Histoire de voir si le CRC a infecté l'ensemble des tissus, une petite modification dans les codes du programme (une version "saine"), va démontrer que seul le header est atteint.
C'est un moindre mal.

En sortant de l'API GetProcAddress, un " d edx " va donner :

:004E5B9E 56 69 72 74 75 61 6C 46-72 65 65 00 56 69 72 74 VirtualFree.Virt
:004E5BAE 75 61 6C 50 72 6F 74 65-63 74 00 45 78 69 74 50 ualProtect.ExitP
:004E5BBE 72 6F 63 65 73 73 00 00-00 00 00 75 73 65 72 33 rocess.....user3
:004E5BCE 32 2E 64 6C 6C 00 4D 65-73 73 61 67 65 42 6F 78 2.dll.MessageBox
:004E5BDE 41 00 77 73 70 72 69 6E-74 66 41 00 4C 4F 41 44 A.wsprintfA.LOAD
:004E5BEE 45 52 20 45 52 52 4F 52-00 54 68 65 20 70 72 6F ER ERROR.The pro
:004E5BFE 63 65 64 75 72 65 20 65-6E 74 72 79 20 70 6F 69 cedure entry poi
:004E5C0E 6E 74 20 25 73 20 63 6F-75 6C 64 20 6E 6F 74 20 nt %s could not

Gasp !
Serait ce l'obscure éventualité d'une autre tumeur au niveau de l'Import table ?

Il va falloir opérer dans le vif, et pour commencer trouver le call gérant le CRC et affichant la MessageBoxA "
3D Exploration File corrupted ! ", puis envoyant vers un ExitProcess.
Mieux vaut prévenir la famille que le malade est entre la vie et la mort…

Berck !
Du CCA...
Saleté de code polymorphe !
Infirmière, passez-moi F8, il va falloir tracer dans tous les call, hormis les call [registre+adresse]

Le premier relais est passé en EntryPoint+4DC

:004E54DF  6801F0BF00          PUSH    00BFF001
:004E54E4  C3                  RET

Et là, brusque changement.
Le virus s'installe ailleurs...
Bye bye les adresses 004EXXXX, on descend en 00BFF001.
Et bien baptisons ce 00BFF001, ce sera l'EP2

Le relais suivant est en 00BFF5D0 (EP2+5D4)

:00BFF5C5  61                  POPAD
:00BFF5C6  7508                JNZ     00BFF5D0
:00BFF5C8  B801000000          MOV     EAX,00000001
:00BFF5CD  C20C00              RET     000C
:00BFF5D0  680814BF00          PUSH    00BF1408
:00BFF5D5  C3                  RET

En cherchant un peu à partir de cette adresse, le call MessageBoxA/ExitProcess est en :

:00BF06B5 E816F9FFFF     CALL 00BEFFD0      > cochonnerie here !
:00BF06BA 8B45F8         MOV  EAX,[EBP-08]
:00BF06BD E85A22FFFF     CALL 00BE291C0 

Petite ablation discrète, on place un RET à l'entrée du call en question.
Le CRC est OUT !

Glop ! Glop !

Shunter la routine en inversant un saut conditionnel:

Genius 2.7 (ASPack) by Christal

Le Checksum :

Au lancement de votre copie décompressée, le programme va immédiatement détecter qu’il y a un peu plus d’octets que dans la version d’origine.

La " punition " est infligé par une boite de message " The file has been modified ". Eh oui !
De 131,8%, une paille !
Bpx MessageBoxA pour le localiser : Rien DialogBoxParamA : Pareil. Task/Hwnd/Bmsg : Break

Attaquons de l'entry point…
Un checksun étant rarement à la sortie d'un programme, on devrait tomber dessus assez vite en utilisant F 10 dans SoftIce.

Une fois la routine s'occupant de l'affichage de ce NagScreen localisée, vous allez remonter à la recherche d'un Branchement qui pourrait l'éviter :

:00559DA4 E80F37F0FF              call 0045D4B8
:00559DA9 8BD8                    mov ebx, eax
:00559DAB 8BC6                    mov eax, esi
:00559DAD E8DE91EAFF              call 00402F90
:00559DB2 84DB                    test bl , bl 
:00559DB4 7511                    jne 00559DC7

Et le voilà ! C'est le premier qui se présente, et qui évite la procédure du NagScreen.
Posez un breakpoint dessus, au passage suivant (après être sortie de SoftIce, et avoir relancé Genius 2), un simple inversion de Flag va nous débarrasser du Checksum, qui n'était pas bien méchant.

A ce niveau, le plus simple est de passer cet exécutable dans votre Hexéditeur préféré, et de remplacer le JNE 00559DC7 par un JMP 00559DC7, pour ne plus être embêté.

Le même, le pareil:

Sales Agent by christal


Toutes les versions de salesAgent n'en sont pas équipées, mais c'est le cas pour Image Styler, Image Ready, et Director (probablement la version 2 de salesAgent)
Si vous modifiez le loader Director.exe, par exemple, le checksum s'activera en affichant une boite de message "Important application files are missing or corrupted ...". Un breakpoint sur MessageBoxA va permettre de localiser les lignes suivantes:

 * Possible StringData Ref from Data Obj ->"^^L;dIZ8"
 
 :0040AB7E E86D980000              call 004143F0
 :0040AB83 83C408                  add esp, 00000008
 :0040AB86 83F801                  cmp eax, 00000001
 :0040AB89 7458                    je 0040ABE3              > no jump
 :0040AB8B 6869010000              push 00000169
 :0040AB90 E8BB9B0000              call 00414750
 :0040AB95 83C404                  add esp, 00000004
 :0040AB98 6810200000              push 00002010
 :0040AB9D 6A00                    push 00000000
 :0040AB9F 68A4584500              push 004558A4
 :0040ABA4 6A00                    push 00000000
 :0040ABA6 FF1598224300            Call USER32.MessageBoxA  >nag 
Et un petit dernier...

ZVolume 3.1 (ASProtect) by LutiN NoIR

Je m'attendais à trouver un antisoftice comme dans d'autres progs protégés avec asprotect mais là on dirait bien que l'on a droit à un cheksum. Pour en être certain je suis aller sur le site d'asprotect et voilà ce qu'il disent :
compression of the application
encryption of the application
counteraction to dumping application memory with the tool like ProcDump.
application integrity check
counteraction to debuggers and disassemblers
counteraction to memory patching
API for interaction between application and protection routines
Ca fait pas mal de truc. En tout cas une chose est sur il y a bien un checksum. Donc il faut le virer. Pour cela le checksum doit surement utilisé la fonction CreateFileA pour vérifier le fichier où en créer un autre. J'ai donc mis sous softice un pnt d'arrêt : bpx createfilea. et on lance le prog. Softice break et on remonte le code avec F12 et on trace un peu pour trouver cela :

:0049C2BB  5E                  POP       ESI 
:0049C2BC  5B                  POP       EBX 
:0049C2BD  C3                  RET 
:0049F9E0  894304              MOV       [EBX+04],EAX 
:0049F9E3  837B0400            CMP       DWORD PTR [EBX+04],00 
:0049F9E7  7D23                JGE       0049FA0C                (JUMP ) 
:0049FA0C  807DFF00            CMP       BYTE PTR [EBP-01],00 
:0049FA10  740A                JZ        0049FA1C                (NO JUMP) 
:0049FA12  648F0500000000      POP       DWORD PTR FS:[00000000] 
---------------------------- coupé --------------------------------
:004A94F2  8B45EC              MOV       EAX,[EBP-14] 
:004A94F5  3B45F0              CMP       EAX,[EBP-10] 
:004A94F8  7443                JZ        004A953D          <-- on inverse 
:004A94FA  8A154CEA4A00        MOV       DL,[004AEA4C] 
:004A9500  8B45F8              MOV       EAX,[EBP-08] 
:004A9503  E858EBFFFF          CALL      004A8060 
:004A9508  8945F4              MOV       [EBP-0C],EAX 
:004A950B  837DF400            CMP       DWORD PTR [EBP-0C],00 
:004A950F  742C                JZ        004A953D                (NO JUMP) 
:004A9511  8D85E4FEFFFF        LEA       EAX,[EBP-011C] 
:004A9517  8D95E9FEFFFF        LEA       EDX,[EBP-0117] 
:004A951D  B9FF000000          MOV       ECX,000000FF 
:004A9522  E8ED11FFFF          CALL      0049A714 
:004A9527  8B85E4FEFFFF        MOV       EAX,[EBP-011C] 
:004A952D  E83A14FFFF          CALL      0049A96C 
:004A9532  8B55F4              MOV       EDX,[EBP-0C] 
:004A9535  8B5205              MOV       EDX,[EDX+05] 
:004A9538  E8CBF7FFFF          CALL      004A8D08  

Donc il y a un saut en 4A94F8 qui ne s'effectue pas. Ensuite il y a le même en 4A950F, et après un fonction affiche le message d'erreur. Mais si on force le saut en 4A94F8 le prog se lance :). Donc voilà où se vérifient l'intégrité du programme.

Dans l'exemple proposé par TaMaMBoLo, il s'agit de supprimer un Call pour que le Checsum vous soit toujours favorable:

Harmony Assistant by TaMaMBoLo

Step 3

Bon on panique poa..Quand le prog détecte que son code a été patché, il vous affiche un beau message et le prog se ferme . Comme je l'ai dit plus haut, pas la peine d'essayer de mettre un breakpoint sur MessageBoxA,ça marchera pas ... Par contre dans le step 1, on avait remarqué quelque chose de très interressant : le call qui fermait le prog . CALL 00554120 à l'addresse 4D5142 (voir dernier desassemblage du step 1) .Bon,et ben on va mettre un breakpoint la dessus ... On reprend symbol loader et on rouvre Harmony . Sous softice on tape :BPX 554120.Et on relance avec F5 . De nouveau le message à la con s'affiche, et on click sur 'ok' et softice se déclenche.On a ceci sous les yeux :

:00554120  PUSH      ESI
:00554121  PUSH      EDI
:00554122  SUB       ESP,18
:00554125  LEA       EDI,[ESP+08]
:00554129  MOV       ESI,006077F8
:0055412E  MOVSD
:0055412F  MOVSD
:00554130  MOVSD

La routine n'est pas interressante en elle-meme ...Ce qui est interressant,c'est de savoir d'ou elle vient cette routine...Pour ça,c'est très simple.Quand vous êtes à l'addresse 554120, Vous tapez A sous softice pour etre dans l'éditeur Asm . Et on entre RET à la place du push esi . Et on quitte l'éditeur ASm avec escape . Le RET va nous faire sortir de la routine et on va tomber juste derrière le Call 554120 .
De cette façon, on va voir où dans le programme cette routine est appellée . Donc on appuie sur F10 pour exécuter le RET et on arrive à ceci :

:0054BC68 PUSH 00
:0054BC6A CALL 00554120
:0054BC6F POP  ECX----- on tombe ici en exécutant le RET
:0054BC70 RET

On continue la trace avec la touche F10 pour finalement arriver la :

:0049CD10  PUSH      EBX
:0049CD11  PUSH      ESI
:0049CD12  PUSH      EBP
:0049CD13  SUB       ESP,10
:0049CD16  MOV       EBP,[ESP+20]
:0049CD1A  CALL      004A85F2
:0049CD1F  MOV       EBX,EAX
:0049CD21  MOV       EAX,[005E0044]------ On met dans Eax le checksum 1 
:0049CD26  CMP       EAX,[005E009C]------ On compare le checksum 1 avec le checksum calculé
:0049CD2C  JNZ       0049CD3B------------ c bon,on saute...
:0049CD2E  MOV       EAX,[005E0130]------ met dans Eax le checksum 2(2ème vérif)
:0049CD33  CMP       EAX,[005E06C8]------ On compare le checksum 2 avec le checksum calculé
:0049CD39  JZ        0049CD4B------------ c bon,on saute...
:0049CD3B  PUSH      000000D4
:0049CD40  CALL      004A36BD------------ sinon...
:0049CD45  POP       ECX
:0049CD46  CALL      0054BC68------------ le call qui ferme le proggy
:0049CD4B  PUSH      EBX----------------- on est arrivé ici .
:0049CD4C  CALL      004A5E43
:0049CD51  TEST      AL,AL

Bon finalement on a attérit en 49CD4B . Juste en remontant légérement dans le code on voit plein de trucs cools ...En 49CD21 on met le contenu de 5e0044 dans eax .
Ensuite on compare eax avec le contenu d'une autre addresse memoire : 5E009C .
Cherchez poa plus loin, il est là votre checksum ... On remarque aussi le meme type de routine en 49CD2E : MOV EAX,[005E0130], suivit de CMP EAX,[005E06C8] .
Deux routines similaires avec des addresses différentes, donc deux checksums ...

Step 4

Pour trouver ou sont calculés les checksum , j'ai utilisé Windasm . On sait que les deux checksums calculés sont stockés en 5E009C et 5E06C8 . Et bien on va cherchez avec Windasm tous les endroits du code où sont appelées ces deux addresses . On va dans l'option 'Search' et on rentre notre chaine hexa A L'ENVERS ! Je rappelle qu'en hexa on met le bit de poids faible devant . Donc 5E009C = 9C005E . On trouve plusieurs références à cette addresse mais une a retenue mon attention :

:004D527E 6A04                    push 00000004
:004D5280 6A01                    push 00000001
:004D5282 689C005E00              push 005E009C---- le premier checksum
:004D5287 E894D90600              call 00542C20---- le call qui le calcul
:004D528C 83C410                  add esp, 00000010
:004D528F 53                      push ebx
:004D5290 6A04                    push 00000004
:004D5292 6A01                    push 00000001
:004D5294 68C8065E00              push 005E06C8---- le second checksum
:004D5299 E882D90600              call 00542C20---- et le meme call 
:004D529E 83C410                  add esp, 00000010
:004D52A1 6A00                    push 00000000

Bon, c'est pas très dur à comprendre : En 4d5280 on sauvegarde le premier checksum. A cet instant 5e009c=0000000000. Une fois le call 542C20, la case mémoire 5e009c calcul du deuxième checksum , c'est le meme call 542C20 ... Et si on vire ces deux calls,les valeurs dans 5e009c et 5e06c8 seront toujours égales à 0, non ? Il ne nous reste plus qu'a trouver l'autre endroit où sont recalculés les checksums ...
On fait comme prédemment,on recherche avec windasm 5E0044 (A L'ENVERS !)et on tombe sur ceci :


:004D51AE E8EB5CFFFF call 004CAE9E
:004D51B3 E8C65DFFFF call 004CAF7E
:004D51B8 6830015E00 push 005E0130------le premier checksum
:004D51BD 6844005E00 push 005E0044------Et le second ...
:004D51C2 E8632AFDFF call 004A7C2A------le call qui crée les checksums

Et ben voilà!on y est...Cette fois c'est le call 4a7c2a qui génère les checksums...
Il suffit de virer ce call 4a7c2a pour que 5e0130 et 5e0044 soient égals à 0,nan?
De cette façon, le prog aura beau comparer les addresses mémoires entre elles, elles seront toujours égales à 0,donc le checksum sera bon...Faites les modifs avec votre éditeur hexa et lancez Harmony ...BiNGo! Y work ...

WinDelete et Splash (VBOX protected) by Christal

Le checksum

Il est calculé ici:

:070066EA 8BC3                    mov eax, ebx
:070066EC 33FB                    xor edi, ebx
:070066EE F7D0                    not eax
:070066F0 3145B0                  xor dword ptr [ebp-50], eax
:070066F3 8D85F0FDFFFF            lea eax, dword ptr [ebp-210]
:070066F9 50                      push eax
:070066FA 8D8520FFFFFF            lea eax, dword ptr [ebp-E0]
:07006700 81F7494C0000            xor edi, 00004C49
:07006706 50                      push eax
:07006707 57                      push edi <- longueur du code
:07006708 33F3                    xor esi, ebx
:0700670A FF75B0                  push [ebp-50]
:0700670D 81F64A570000            xor esi, 0000574A
:07006713 8975C4                  mov dword ptr [ebp-3C], esi
:07006716 89BD0CFFFFFF            mov dword ptr [ebp+FFFFFF0C], edi
:0700671C 56                      push esi <- Code RVA
:0700671D FF7584                  push [ebp-7C]
:07006720 E843120000              call 07007968

et ici. Les paramètres sont les mêmes:

:070071B2 8D8514FEFFFF            lea eax, dword ptr [ebp+FFFFFE14]
:070071B8 C645FC23                mov [ebp-04], 23
:070071BC 50                      push eax
:070071BD 8D8520FFFFFF            lea eax, dword ptr [ebp+FFFFFF20]
:070071C3 50                      push eax
:070071C4 FFB50CFFFFFF            push dword ptr [ebp+FFFFFF0C]
:070071CA FF75B0                  push [ebp-50]
:070071CD FF75C4                  push [ebp-3C]
:070071D0 FF7584                  push [ebp-7C]
:070071D3 E890070000              call 07007968

Rappelez vous que les BPX actifs changent les paramètres, aussi, effacez tous les breakpoints avant ces calls

Le checksum de Vboxt410.dll est calculé ici

:07006F62 8D458C                  lea eax, dword ptr [ebp-74]
:07006F65 50                      push eax
:07006F66 8D8504FFFFFF            lea eax, dword ptr [ebp+FFFFFF04]
:07006F6C 50                      push eax
:07006F6D A138FE0407              mov eax, dword ptr [0704FE38]
:07006F72 FF7028                  push [eax+28]
:07006F75 E836DF0000              call 07014EB0

Un autre contrôle est réalisé à l'intérieur de Vboxb410.dll, et envoi le résultat qu'il à trouvé à PreviewParadise sous la formes d'une combinaison à 2 paramètres:

:070072D8 8B450C                  mov eax, dword ptr [ebp+0C]
:070072DB 8B4D2C                  mov ecx, dword ptr [ebp+2C]
:070072DE F7D0                    not eax
:070072E0 33C8                    xor ecx, eax <- 1=OK 
:070072E2 7510                    jne 070072F4

Quand vous aurez réussi ces modifications en mémoires, il ne vous restera plus qu'à utiliser votre éditeur hexadécimal.