Author:

  Potsmoke

Tools:

  Softice og MASM

Subject:

  Finne et serial ved å kode en bruteforcer i win32asm

Other:

  Minimum 1024x768 oppløsning, bruk Internet Explorer v5.x, sett på discovery (tv kanalen)



Denne teksten er dedikert til alle som på noen måte har støttet/hjulpet FHCF.
Noen ganger er man på jakt etter et spesielt tall, du vet ikke helt hvordan du skal finne dette tallet selv om du skjønner algoen, det er da man kan kode en bruteforcer for å slippe å prøve seg frem manuelt i softice/calc.exe, noe som kan ta en evighet.
Vi skal se på et helt tilfeldig program som du ikke trenger å vite navnet på, det er beskyttelsen som er interesang men hvis du ikke klarer deg uten et program navn kan vi godt kalle den Anna's strikkeoppskrift generator v3.4.
Jeg startet med å sette de vanlige breakpointene, kom meg inn i koden, tracet inn i et par calls og havnet i denne koden:

1. 0177:00423180  8B442404    MOV   EAX,[ESP+04]  <-- Flytter "fake" serial inn i EAX                    
2. 0177:00423184  33C9        XOR   ECX,ECX       <-- Setter ECX til 0                    
3. 0177:00423186  3D80969800  CMP   EAX,00989680  <-- Er "fake" serialen vår større enn 989680 (hex)?        
4. 0177:0042318B  7614        JBE   004231A1      <-- Hvis større fortsett nedover koden, ellers hopp til FAIL 
5. 0177:0042318D  56          PUSH  ESI           <-- Push verdien i ESI til stacken                  
6. 0177:0042318E  33D2        XOR   EDX,EDX       <-- Setter EDX til 0                  
7. 0177:00423190  BE33909700  MOV   ESI,00979033  <-- Flytter 979033 (hex) inn i ESI                   
8. 0177:00423195  F7F6        DIV   ESI           <-- Del EAX på ESI                     
9. 0177:00423197  5E          POP   ESI           <-- Siste verdi som ble lagt på stacken poppes inn i ESI
A. 0177:00423198  B801000000  MOV   EAX,00000001  <-- legg 1 i EAX                     
B. 0177:0042319D  85D2        TEST  EDX,EDX       <-- 0 i rest? (er EDX=0?)                    
C. 0177:0042319F  7402        JZ    004231A3      <-- Hvis 0 i rest, hopp og serial er OK                     
D. 0177:004231A1  8BC1        MOV   EAX,ECX       <-- legg 1 i EAX, serial INVALID                     
E. 0177:004231A3  C20400      RET   0004          <-- Returner fra subrutine (gå ut av callet)

Det vi nå vet er at "fake" serialen vi skal bruke må være større enn 989680 (hex) som vil si 10000000 (10 mill) i desimal for at vi skal komme oss forbi CMP'n i linje 3.
Hvis serialen vi skriver inn er 10000000 (dec) eller lavere vil vi i linje 4 hoppe og avbryte, invalid serial.
La oss skrive inn et "fake" serial som er større enn 10000000 (dec), da vil vi komme forbi CMP'n og dividere noen tall i linje 8, den deler EAX på ESI, EAX inneholder vårt "fake" serial mens ESI inneholder 979033 (hex) som er en fast verdi.
Resultatet av divisjonen lagres i EAX mens det som blir i rest havner i EDX.

Husk at EAX alltid er source (tallet i EAX deles på et annet tall/register og ikke motsatt), resultatet vil alltid havne i EAX og det som blir i rest alltid havner i EDX, slik er regelen for DIV/IDIV.
Når divisjonen er gjort vil vi som sagt stå igjen med resultatet i EAX mens det som ble i rest befinner seg i EDX, lenger ned i koden (linje B) vil du se at den tester om EDX=0, den sjekker altså om det ble noe i rest eller ikke.

Hvis EDX=X (et eller annet i rest) vil vi i linje C ikke hoppe og EAX vil bli lik 1 (linje D) noe som igjen vil si at serialen er invalid.
Det vi må gjøre her er å finne et tall større enn 10 mill (dec) som kan deles på 989680 (hex) og samtidig gi 0 i rest, hvis vi får til dette vil vi i linje C hoppe og serial er godkjent :) (fordi EAX alldri blir satt til 1).
Selve resultatet som havnet i EAX etter divisjonen kan vi bare kaste da det alldri blir brukt i denne algoen.

De som klarer å knekke algoen allerede her uten å bruteforce må bare late som de ikke skjønner den, vi kan jo late som den er noen hakk værre bare for moro skyld.
Hvor artig er det å prøve seg frem i softice eller med calc.exe for å finne dette tallet vi trenger? Ikke moro, for det prøvde jeg :)
Uansett hvor kjipt det måtte være så velger jeg å vise noen eksempler med calc.exe.

989680 (hex) <-- "fake" serial må være større enn dette tallet
10000000 (dec)

979033 (hex) <-- "fake" serial divideres på dette tallet
9932851 (dec)

Fyr opp calc.exe (start->run->calc) så kan vi prøve å dele noen tilfeldige tall, kryss av på Hex og Dword.

989681/979033=1 Resultatet av divisjonen er 1 og rest'n er?
Hvis man deler heksadesimale tall i calc.exe vil man ikke kunne se hva som blir i rest :(
Problemet løser vi enkelt og greit ved å konvertere de to heksadesimale tallene til desimal, i calc.exe skriver du inn 989681,
trykker Dec for å konvertere tallet til desimal og gjør samme med tallet vi skal dele på.

10000001/9932851=1,00676039537892997690189855863135
Her kan vi se at resultatet ble 1 og det som ble i rest er alt etter komma, altså 00676039537892997690189855863135.
For at vår serial skal bli godkjent kan det ikke være noen tall etter komma (0 i rest), hva selve resultatet blir er uvesentlig.
Hvis du tracer dette i softice vil du ikke se de samme tallene i EDX, grunnen er så enkel som at EDX er et 32-bits register og kun kan lagre 8 tegn/tall, det vil si de 8 første tallene etter komma --> 00676039 (men i hex og ikke desimal).

Vi har nå sett litt på tingene og du ser kanskje hvor vanskelig det er å finne et tall som som gir 0 i rest (en gyldig serial)?
Nå som jeg skjønner algoen (uten bruteforce) er det ikkeno problem men helt i starten lurte jeg litt på hvordan jeg skulle finne ut hvilket tall som ga 0 i rest, det endte med at jeg ringte rundt til noen folk, til og med en som går på høyskolen og vistnok har heavy matte, heavy my ass, gutten kunne jo ikke dividere engang :)
De fleste jeg snakket med sa at det ikke var mulig og jeg begynte neste å lure selv men heldigvis tok de feil.
Egentlig burde jeg vel ringt Elessar da han er matte freaker, han kunne sikkert løst denne lille saken i søvne, neste gang skal jeg plage han i steden :)

PANG!!! sa det i skallen min, hvorfor ikke mekke en liten bruteforcer, spør meg ikke hvor ideen kom fra for jeg har ikke peil på hvordan det egentlig gjøres.
Jeg fyrte opp IceDump og dumpet algoen til disken, satan jeg elsker screendump'n til IceDump.

0177:00423180  8B442404    MOV   EAX,[ESP+04]                      
0177:00423184  33C9        XOR   ECX,ECX                            
0177:00423186  3D80969800  CMP   EAX,00989680                       
0177:0042318B  7614        JBE   004231A1                           
0177:0042318D  56          PUSH  ESI                                
0177:0042318E  33D2        XOR   EDX,EDX                            
0177:00423190  BE33909700  MOV   ESI,00979033                       
0177:00423195  F7F6        DIV   ESI                                
0177:00423197  5E          POP   ESI                                
0177:00423198  B801000000  MOV   EAX,00000001                       
0177:0042319D  85D2        TEST  EDX,EDX                            
0177:0042319F  7402        JZ    004231A3                           
0177:004231A1  8BC1        MOV   EAX,ECX                            
0177:004231A3  C20400      RET   0004   

For at bruteforcern skulle fungere måtte jeg gjøre noen små endringer.

         mov eax, 989680h  ;legger 989680 (10000000 dec) i EAX
nextsn:  inc eax           ;så øker vi EAX med 1 slik at fake serialen blir 10000001 og 2,3,4,5,6,7,8 osv
         push eax          ;pusher "fake" serialen til stacken slik at vi kan fortsette å bruke den senere
         mov esi, 979033h  ;legger 979033 (hex) inn i ESI 
         xor edx, edx      ;clearer EDX (setter EDX til 0)
         div esi           ;del verdien i EAX på verdien i ESI (del "fake" serial på 989680 hex)
         pop eax           ;popp'r verdien fra stacken og til EAX (verdien vi pushet lenger opp)
         test edx, edx     ;ga denne "fake" serialen 0 i rest?
         jnz nextsn        ;hvis ikke "fake" serialen ga 0 i rest prøv neste "fake" serial (øk 10000001 med 1)
         int 3             ;hvis "fake" serialen ga 0 i rest KRÆSJ bruteforcern :) (eller be softice poppe opp)

I denne koden vil den teste om 989681 hex (10000001) del på 989680 hex gir 0 i rest, hvis ikke prøv neste.
test om 989682 hex (10000002) del på 989680 hex gir 0 i rest, hvis ikke prøv neste.
test om 989683 hex (10000003) del på 989680 hex gir 0 i rest, hvis ikke prøv neste.
Slik vil den fortsette til vår "fake" serial gir 0 i rest :) koselig, den tester alle mulige kombinasjoner.
For de av dere som har lyst til å assemble/kompilere denne koden så har jeg lagt ved bruteforce.asm, bruk MASM.

Når du nå skal kjøre programmet (enten det som ligger med eller det du assemblet/kompilerte selv) så har du to valg.
Hvilke av de du velger har ingen betydning så du kan jo teste begge.
Fyr opp bruteforce.exe og programmet kræsjer etter ett sekund, du blir sikkert en smule skeptisk men det har du ingen grunn til :)
Klikk på "Details" knappen og du vil se dette:

-----------------------------------------------------------------------------
BRUTEFORCE caused an exception 03H in module BRUTEFORCE.EXE at 0177:0040101c.
Registers:
EAX=012f2066 CS=0177 EIP=0040101c EFLGS=00000246
EBX=00530000 SS=017f ESP=0063fe3c EBP=0063ff78
ECX=8173bb18 DS=017f ESI=00979033 FS=12af
EDX=00000000 ES=017f EDI=00000000 GS=0000
Bytes at CS:EIP:
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
Stack dump:
bff8b537 00000000 8173baf8 00530000 74757242 726f6665 45006563 00004558 
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
-----------------------------------------------------------------------------

En koselig feilmelding som egentlig ikke er noe annet enn resultatet av bruteforcern, rett før bruteforcern kræsjer (noe den gjør fordi jeg har brukt "int 3" interupt) popp'r den riktig serial inn i EAX, noter verdien i EAX fra feilmeldingen som er 12f2066.
Tallet i EAX er heksadesimalt slik som alle andre verdier i feilmeldingen, konverter tallet ved hjelp er calc.exe eller softice, jeg velger softice fordi det går 0,5 sekunder kjappere.
I softice skriver vi ? 12f2066 og softice svarer vennlig 19865702.

Riktige serialen for dette programmet er altså 19865702 :) det er jo veldig koselig spør du meg, dette er det første serialet som er gyldig hvis man starter på 10 mill og øker hele veien oppover, alt i alt er det i overkant av 400 gyldige serialer i dette tilfellet og vi kunne ha kodet en liten bruteforcer som la alle de gyldige serialene i en tekst fil feks.

Den andre måten som vi kan bruke er egentlig den samme som den forrige men før vi kjører programmet setter vi en liten breakpoint sak på int3 ved å skrive: i3here on.
Når vi nå kjører programmet vil softice poppe opp og vi kan bruke ? EAX for å få resultatet/serialen direkte fra softice, etter vi har gått ut av softice vil bruteforcern kræsje men det er helt ok.

Int 3 er genialt og kan brukes til mye rart, tenk deg at du koder en patch, keygen, bruteforcer eller noe annet og et eller annet sted i koden er det noe galt.
Det du kan gjøre er å legge til en int 3 i assembly koden din, reassemble/kompilere, sette i3here on i softice og neste gang du kjører programmet vil du havne akkurat der du la til int 3 i koden din.
Uten int 3 ville jeg alldri ha fått kodet noen keygens som fungerte :)

Vil du vite en heftig ting? Det tok bruteforcern ca. ett sekund å finne serialen, 19865702-10000001=9865701, den greide å teste 9865701 (i underkant av 10 millioner) fokkings serialer på dette ene sekundet og da snakker vi om på min heftige power AMD 400 :)
Hvis ikke dette er imponerenes så kan du grave deg ned, den kjørte altså koden nesten 10 millioner ganger på denne tiden, det er 8 linjer ASM pr runde, 80 millioner linjer assembly, men man kan egentlig ikke regne slik da noen linjer tar 1 byte mens andre 6 (opcodes).

Jeg trodde egentlig ikke noe på resultatet så jeg laget meg en teller ved å øke ECX med en pr runde, men det stemte vist fant jeg ut så da kan man egentlig begynne å lure på hva fasan prosessoren egentlig driver med ellers når det går så satans tregt, kanskje den har tatt seg juleferie og feter seg med ribbe/kalkun bytes.
En annen heftig ting er at denne bruteforcern er på 1Kb, hadde den vært kodet i noe annet (feks. C) ville den vært på 20-30Kb, det er jo nesten ikke forskjell det :) Bare 19-29Kb.

Nå som vi har funnet en serial som fungerer kan vi teste den ut på calc.exe, husk å sett kalkulatoren til Dec slik at vi har muligheten til å se hva som blir i rest.
19865702/9932851=2 Resultatet blir 2 og det er ikkeno etter komma, altså 0 i rest, dette stemmer bra.

Å bruteforce noe vil ikke si at du kan keygenne noe, releaser du en bruteforcer så er dette ikke en keygen, hvis du lager bruteforceren din slik at den samler opp alle gyldige serials i en tekst fil, koder en "keygen" og ber den spytte ut serialer i tilfeldig rekkefølge så er dette ikke en keygen men en serializer.
Gir du ut feks. en bruteforcer og kaller det en keygen så er det lureri, fy fy.
Bruteforce er siste utvei og skal helst ikke brukes men kan faktisk brukes slik at du etterhvert skjønner algoen og får til å mekke en keygen.
For å mekke en bruteforcer trenger du å vite en del så jeg ser ikke på det som helt på jordet, man må tross alt finne algoen, skjønne algoen mer eller mindre og kunne kode en bruteforcer.

Litt komisk det som skjedde nå, jeg greide å få potetgull i musa mi, dumt :) dakar logitech'n. Verdens fineste tastatur/mus går best på naturlig potetgullfett.
Tro det eller ei men jeg spiser faktisk potetgull (spesielt ostepopp) med skje, det har jeg lært av skakke Arachno.


Greets/Takk til: (i tetrahydrocannabinolsk rekkefølge Xor 4, Shl 13)

Trevil, Elessar, Alx, Juice, Melk, Glassius, Dominate, Snak3, Arachno, Blitzer, Charles Manson, Mr. Green, CptCrk, Noen, pDriLl, Physiker, SpiritMaster, Sprinder, Stormgren, The Viper, KeHaven, Fuzzbox, Infinity, Padi, Dawai, MisterE, tE, tKC, Tck, Da Diablo, FastCode, Sheep, CDK, Jony, Elwolfie, Bishop og alle jeg ikke husker i hue akkurat nå :(

Alle som henger på #Cracking.no og støtter det lille sletne norske cracke miljøet.
Noen få på #Cracking4newbies, flesteparten er jo horer.
Alle som har besøkt FHCF web'n, lest FHCF tekster, brukt releasene våre osv.
Alle som på noen måte har hjulpet FHCF, takk takk
Alle X FHCF members

Cream og Dread, mine helter :) men begge grupper er jo døde :(
Paradox, Fairlight, leet :)

FHCF finner du på #Cracking.no (IRC EFNet)
www.fhcf.net, der er det fett :)
team_fhcf@hotmail.com