DNX.INC Crackme #2.0
(Crackme MMX 1.0)
by themoon

Tutorial by Lucifer48
(July 19th, 2001)



Introduction

I don't use very often MMX instructions. It is why, i've choosen to solve this crackme. It's written strangly (badly!) (Visual C++ i think) but it's funny.

A first look

You can change the mmx section characteristics to C0000020. Now have a look with Soft-ICE. The crackme checks if you have some mmx registers (see ismmx.asm). A funny thing, all Win32 API calls are made like that :

  push argN
  ...
  push arg1
  push (offset retaddress)
  push dword ptr [XXX32!TheWin32ApiA]
  ret
retaddress:

The author declares two atoms (see API : GlobalAddAtom and GlobalGetAtomName).

"Good boy :)"  in XXXX:004014B9
"Bad boy :("   in XXXX:004014C0

A part of the crackme is decrypted with a encrytion routine (CALL 0040158A). The rest is very classical, a wndproc ... Let's find some serials..

Protection scheme

Here is the beginning :


XXXX:004012CB  CMP   EAX, 04		; fours chars min for our serial
XXXX:004012CE  JB    004014BF		; "Bad boy :("
XXXX:004012D4  EMMS			; empties the MMX state
XXXX:004012D6  MOVD  MM0, EAX
XXXX:004012D9  BTS   EAX, 1F		; change CF
XXXX:004012DD  CDQ
XXXX:004012DE  MOVD  MM1, EDX
XXXX:004012E1  DEC   EDX
XXXX:004012E2  NOT   EDX
XXXX:004012E4  MOVD  MM2, EDX
XXXX:004012E7  PSLLQ MM2, 05		;MM2*32d
XXXX:004012EB  PAND  MM2, MM1
XXXX:004012EE  PXOR  MM2, MM0
XXXX:004012F1  PSUBD MM3, MM3		;MM3=0 (doubleword)
XXXX:004012F4  PCMPEQD MM3, MM2		; if (MM3==MM2) then MM3=-1 else MM3=0
XXXX:004012F7  MOVD  EAX, MM3
XXXX:004012FA  INC   EAX
XXXX:004012FB  JNZ   004014BF		; "Bad boy :("

So our serial will be 32 chars long. Then, the serial rewritten. Example:


the entered dummy serial is : "3615780015985347156456361736ABC8".
-----CRACKME!bss----------------------------------byte--------------PROT---(0)--
XXXX:00402000 36 15 78 00 15 98 53 47-15 64 56 36 17 36 15 78  6.x...SG.dV6.6.x
--------------------------------------------------------------------------------
(let's assume that our 128 bit serial is divided in 4 parts : p1, p2, p3, p4)

Remark: You should also enter letters..

We are in XXXX:00401353. After lots of garbage code.. this the following first check :


XXXX:004013BB  MOVD EAX, MM1
XXXX:004013BE  NEG  EAX				; the only acceptable value is 0
XXXX:004013C0  SBB  EAX, EAX			; Carry flag must be cleared
XXXX:004013C2  INC  EAX
XXXX:004013C3  PUSH DWORD PTR [EAX*4+00401500]	; [004014BF ; 004013CB]
XXXX:004013CA  RET

I have (just before XXXX:4013B5):

MM0 = 00000000 506E7F42		;cpuid eax=0 : mm0=xor(eax,ebx,ecx,edx)
MM1 = 00000000 15985347		;p2
MM2 = 00000000 ADFFFFCE
MM3 = 00000000 24FF6D46

So the second part of my serial (p2) is : MM0 XOR ADFFFFCE = FD91808C.
The second check is even more simple : the first dword of my serial should not be XX XX XX XX (i mean: p1 XOR (BSWAP p1) != 0).
The third check, primary like the second check (it's a SUB not a XOR), but there are aften another condition : (p1 SHR 8) = p3.


XXXX:00401441  MOVD    EAX, MM1
XXXX:00401444  CMPXCHG EDX, EDX		;make eax=edx
XXXX:00401447  LAHF			;load flags in AX
XXXX:00401448  AND     EAX, 00004000
XXXX:0040144D  SHR     EAX, 0E
XXXX:00401450  JMP     [EAX*4+00401508]	; [004014BF ; 0040145A]

The last part (p4) is the most interesting :


XXXX:00401480  MOV  EDI, 00402100	;little 8 bytes buffer
XXXX:00401485  MOVQ [EDI], MM1		;MM1=FFxxFFyy FFzzFFtt	(where xxyyzztt = p4)
XXXX:00401488  PUSH EDI
XXXX:00401489  PUSH 0040171C		;"[[ master&slave proj"
XXXX:0040148E  CALL 0040151E		;nice routine !
XXXX:00401493  MOVQ MM0, [EDI]		;we should obtain one of these values :
					;2DFFC7DC A26A64C2
					;2DFFC7DD A26A64C1
					;2DFFC7DD A26A64C2

See brute/mmx.asm for more details. I don't know which (known) algo is used in the CALL 0040151E.. Finally p4 equals 6D6D7821 (unique solution).

Conclusion

Even if using MMX instructions is a good idea. This final product is not very good. All this garbage code is boring (PAND MM0, MM0, ...) and MMX instructions are here used as extra 32 bits registers only; the saturation operations are not used. It could have been a very good crackme, however the operations are limited to XOR, OR, AND, ADD, SUB. It's too linear. I'd like to watch the source by curiosity.

Greetings: Only youuuu ;).



(c) Lucifer48. All rights reserved & reversed