Solution-DaXXoR-101-D-KeygenMe
Jump to navigation
Jump to search
Description
Objective
The objective of this crackme (http://crackmes.de/users/daxxor_101/d_keygenme/) is to crack the serial algorithm from the provided username and to develop a keygen.
My keygen in action
Below is the output of my keygen with debug set to True.
$ ./keygen.py username [INFO] username length limited to 6 characters. Username truncated to 'userna' ----- index: 0 ----- [DEBUG] BP:0x40242A eax=0x17, ecx=0x5, edx=0x2 [DEBUG] BP:0x402431 eax=0x17, ecx=0x0, edx=0x2, ebx=0x17 [DEBUG] BP:0x40243A eax=0x23e, ecx=0x0, edx=0x0, ebx=0x17 [DEBUG] BP:0x40243F eax=0x23e, ecx=0x0, edx=0x0, ebx=0x17 [DEBUG] BP:0x402441 eax=0x3392, ecx=0x0, edx=0x0, ebx=0x17 [DEBUG] BP:0x402449 eax=0x3392, ecx=0x0, edx=0x0, ebx=0x17 ----- index: 1 ----- [DEBUG] BP:0x40242A eax=0x17, ecx=0x5, edx=0x0 [DEBUG] BP:0x402431 eax=0x17, ecx=0x0, edx=0x0, ebx=0x17 [DEBUG] BP:0x40243A eax=0x3407, ecx=0x0, edx=0x0, ebx=0x17 [DEBUG] BP:0x40243F eax=0x3407, ecx=0x0, edx=0x0, ebx=0x17 [DEBUG] BP:0x402441 eax=0x4aca1, ecx=0x0, edx=0x0, ebx=0x17 [DEBUG] BP:0x402449 eax=0x4aca1, ecx=0x0, edx=0x0, ebx=0x17 ----- index: 2 ----- [DEBUG] BP:0x40242A eax=0x14, ecx=0x5, edx=0x1 [DEBUG] BP:0x402431 eax=0x14, ecx=0x0, edx=0x1, ebx=0x14 [DEBUG] BP:0x40243A eax=0x4ad14, ecx=0x0, edx=0x0, ebx=0x14 [DEBUG] BP:0x40243F eax=0x4ad14, ecx=0x0, edx=0x0, ebx=0x14 [DEBUG] BP:0x402441 eax=0x5d8590, ecx=0x0, edx=0x0, ebx=0x14 [DEBUG] BP:0x402449 eax=0x5d8590, ecx=0x0, edx=0x0, ebx=0x14 ----- index: 3 ----- [DEBUG] BP:0x40242A eax=0x16, ecx=0x5, edx=0x4 [DEBUG] BP:0x402431 eax=0x16, ecx=0x0, edx=0x4, ebx=0x16 [DEBUG] BP:0x40243A eax=0x5d85f5, ecx=0x0, edx=0x0, ebx=0x16 [DEBUG] BP:0x40243F eax=0x5d85f5, ecx=0x0, edx=0x0, ebx=0x16 [DEBUG] BP:0x402441 eax=0x809830e, ecx=0x0, edx=0x0, ebx=0x16 [DEBUG] BP:0x402449 eax=0x809830e, ecx=0x0, edx=0x0, ebx=0x16 ----- index: 4 ----- [DEBUG] BP:0x40242A eax=0x16, ecx=0x5, edx=0x0 [DEBUG] BP:0x402431 eax=0x16, ecx=0x0, edx=0x0, ebx=0x16 [DEBUG] BP:0x40243A eax=0x8098380, ecx=0x0, edx=0x0, ebx=0x16 [DEBUG] BP:0x40243F eax=0x8098380, ecx=0x0, edx=0x0, ebx=0x16 [DEBUG] BP:0x402441 eax=0xb0d14d00, ecx=0x0, edx=0x0, ebx=0x16 [DEBUG] BP:0x402449 eax=0xb0d14d00, ecx=0x0, edx=0x0, ebx=0x16 ----- index: 5 ----- [DEBUG] BP:0x40242A eax=0x13, ecx=0x5, edx=0x2 [DEBUG] BP:0x402431 eax=0x13, ecx=0x0, edx=0x2, ebx=0x13 [DEBUG] BP:0x40243A eax=0xb0d14d6e, ecx=0x0, edx=0x0, ebx=0x13 [DEBUG] BP:0x40243F eax=0xb0d14d6e, ecx=0x0, edx=0x0, ebx=0x13 [DEBUG] BP:0x402441 eax=0xd1f88bf2a, ecx=0x0, edx=0x0, ebx=0x13 [DEBUG] BP:0x402449 eax=0xd1f88bf2a, ecx=0x0, edx=0x0, ebx=0x13 ===== [INFO] Serial for userna: 529055627
Code Analysis
Overview
Let's load the crackme into IDA-Pro and display strings. We immediately notice a string "Good, Now Make a Keygen!" which leads to 0x4022B0.
Username length
The username should be at least 4 characters and will be truncated to 6 characters if a longer username is provided.
_TEXT:0040234D lea eax, [ebp+lParam]
_TEXT:00402350 push eax ; lParam (username)
_TEXT:00402351 push 7 ; wParam
_TEXT:00402353 push WM_GETTEXT ; Msg (0xD)
_TEXT:00402355 push ds:hWnd ; hWnd
_TEXT:0040235B call SendMessageA
_TEXT:00402361 lea ecx, [ebp+lParam] ; result in username truncated to 6 characters
_TEXT:00402364 push ecx
_TEXT:00402365 call _strlen
_TEXT:0040236A add esp, 4
_TEXT:0040236D cmp eax, 4 ; \
_TEXT:00402370 jg short loc_40238E ; / check whether username length > 4
_TEXT:00402372 push 30h ; uType
_TEXT:00402374 push offset Caption ; "Error"
_TEXT:00402379 push offset Text ; "Name Too Short"
_TEXT:0040237E push 0 ; hWnd
_TEXT:00402380 call MessageBoxA
Serial encryption routine
_TEXT:0040238E loc_40238E:
_TEXT:0040238E mov dword ptr [ebp+var_10], 23Eh ;
_TEXT:0040238E ; var_10 = 0x23E
_TEXT:00402395 mov dword ptr [ebp+var_10+4], 0 ; var_10_4 = 0
_TEXT:0040239C mov [ebp+count_len_username], 0
_TEXT:004023A3
_TEXT:004023A3 loc_4023A3:
_TEXT:004023A3 lea edx, [ebp+lParam]
_TEXT:004023A6 push edx ; username[:6]
_TEXT:004023A7 call _strlen
_TEXT:004023AC add esp, 4
_TEXT:004023AF cmp eax, [ebp+count_len_username] ; counter1 <= len(username[:6])
_TEXT:004023B2 jl loc_40246F
_TEXT:004023B8 mov ebx, [ebp+count_len_username] ; var_8
_TEXT:004023BB cmp ebx, 8
_TEXT:004023BE mov esi, 1
_TEXT:004023C3 jb short loc_4023CA
_TEXT:004023C5 mov esi, 0
_TEXT:004023CA
_TEXT:004023CA loc_4023CA:
_TEXT:004023CA jb short loc_4023D6
_TEXT:004023CC mov eax, 0A1h
_TEXT:004023D1 call sub_402548
_TEXT:004023D6
_TEXT:004023D6 loc_4023D6:
_TEXT:004023D6 lea edi, [ebp+ebx+lParam] ;
_TEXT:004023D6 ; EDI = indexed letter of usename
_TEXT:004023DA cmp byte ptr [edi], 0 ; \ if last character (NULL char), go to the end
_TEXT:004023DD jz loc_402467 ; /
_TEXT:004023E3 test esi, esi
_TEXT:004023E5 jnz short loc_4023F1
_TEXT:004023E7 mov eax, 0A1h
_TEXT:004023EC call sub_402548
_TEXT:004023F1
_TEXT:004023F1 loc_4023F1:
_TEXT:004023F1 cmp byte ptr [edi], 0
_TEXT:004023F4 jz loc_402467
_TEXT:004023FA mov ecx, [ebp+count_len_username]
_TEXT:004023FD cmp ecx, 8
_TEXT:00402400 mov edx, 1
_TEXT:00402405 jb short loc_402409
_TEXT:00402407 mov dl, dh
_TEXT:00402409
_TEXT:00402409 loc_402409:
_TEXT:00402409 mov [ebp+var_4C], edx
_TEXT:0040240C jb short loc_402418
_TEXT:0040240E mov eax, 0A2h
_TEXT:00402413 call sub_402548
_TEXT:00402418
_TEXT:00402418 loc_402418:
_TEXT:00402418 mov ebx, [ebp+count_len_username]
_TEXT:0040241B lea esi, [ebp+ebx+lParam]
_TEXT:0040241F movzx eax, byte ptr [esi] ; indexed character of username[:6]
_TEXT:00402422 mov ecx, 5 ; ecx = 5
_TEXT:00402427 cdq
_TEXT:00402428 idiv ecx ; EDX:EAX = EDX:EAX / ECX
_TEXT:0040242A mov ebx, eax ; EBX = EAX
_TEXT:0040242C mov ecx, ebx ; ECX = EBX
_TEXT:0040242E sar ecx, 1Fh ; ECX >> 0x1F
_TEXT:00402431 mov eax, dword ptr [ebp+var_10] ; EAX = var_10
_TEXT:00402434 mov edx, dword ptr [ebp+var_10+4] ; EDX = var_10_4
_TEXT:00402437 imul ecx, eax ; ECX = ECX * var_10
_TEXT:0040243A imul edx, ebx ; EDX = EDX * EBX
_TEXT:0040243D add ecx, edx ; ECX+=EDX
_TEXT:0040243F mul ebx ; EAX*=EBX
_TEXT:00402441 add edx, ecx ; EDX+=ECX
_TEXT:00402443 mov dword ptr [ebp+var_10], eax ; var_10 = EAX
_TEXT:00402446 mov dword ptr [ebp+var_10+4], edx ; var_10_4 = EDX
_TEXT:00402449 cmp [ebp+var_4C], 0
_TEXT:0040244D jnz short loc_402459
_TEXT:0040244F mov eax, 0A3h
_TEXT:00402454 call sub_402548
_TEXT:00402459
_TEXT:00402459 loc_402459:
_TEXT:00402459 movzx edi, byte ptr [esi] ; EDI = current character of username
_TEXT:0040245C mov edx, edi ; EDX = EDI
_TEXT:0040245E sar edx, 1Fh ; EDX = EDX >> 0x1F
_TEXT:00402461 add dword ptr [ebp+var_10], edi ; var_10 += EDI (current character of username)
_TEXT:00402464 adc dword ptr [ebp+var_10+4], edx ; var_10_4 += EDX
_TEXT:00402467
_TEXT:00402467 loc_402467:
_TEXT:00402467 inc [ebp+count_len_username]
_TEXT:0040246A jmp loc_4023A3
My keygen
#!/usr/bin/env python
import sys
def make_serial():
var_10 = 0x23E # 0x40238E
var_10_4 = 0 # 0x402395
for c, i in enumerate(myusername):
eax = ord(i) # 0x40241F movzx eax, byte ptr [esi]
ecx = 5 # 0x402422 mov ecx, 5
(eax, edx) = divmod(eax, ecx) # 0x402428 idiv ecx
if debug:
print "----- index: %s -----" % c
print "[DEBUG] BP:0x40242A eax=%s, ecx=%s, edx=%s" % (hex(eax), hex(ecx), hex(edx))
ebx = eax # 0x40242A mov ebx, eax
ecx = ebx # 0x40242C mov ecx, ebx
ecx = ecx >> 0x1F # 0x40242E sar ecx, 1Fh
if debug:
print "[DEBUG] BP:0x402431 eax=%s, ecx=%s, edx=%s, ebx=%s" % (hex(eax), hex(ecx), hex(edx), hex(ebx))
eax = var_10 # 0x402431 mov eax, dword ptr [ebp+var_10]
edx = var_10_4 # 0x402434 mov edx, dword ptr [ebp+var_10+4]
ecx *= eax # 0x402437 imul ecx, eax
if debug:
print "[DEBUG] BP:0x40243A eax=%s, ecx=%s, edx=%s, ebx=%s" % (hex(eax), hex(ecx), hex(edx), hex(ebx))
edx *= ebx # 0x40243A imul edx, ebx
ecx += edx # 0x40243D add ecx, edx
if debug:
print "[DEBUG] BP:0x40243F eax=%s, ecx=%s, edx=%s, ebx=%s" % (hex(eax), hex(ecx), hex(edx), hex(ebx))
eax *= ebx # 0x40243F mul ebx
if debug:
print "[DEBUG] BP:0x402441 eax=%s, ecx=%s, edx=%s, ebx=%s" % (hex(eax), hex(ecx), hex(edx), hex(ebx))
edx += ecx # 0x402441 add edx, ecx
var_10 = eax # 0x402443 mov dword ptr [ebp+var_10], eax
var_10_4 = edx # 0x402446 mov dword ptr [ebp+var_10+4], edx
if debug:
print "[DEBUG] BP:0x402449 eax=%s, ecx=%s, edx=%s, ebx=%s" % (hex(eax), hex(ecx), hex(edx), hex(ebx))
edx = edx >> 0x1F # 0x40245E sar edx, 1Fh
var_10 = (var_10 + ord(i)) & 0xFFFFFFFF # 0x402461 add dword ptr [ebp+var_10], edi
var_10_4 = (var_10_4 + edx) & 0xFFFFFFFF # 0x402464 adc dword ptr [ebp+var_10+4], edx
print "====="
print "[INFO] Serial for %s: %s" % (myusername, var_10)
if __name__ == '__main__':
if len(sys.argv) < 2:
print "Usage: %s <username>" % sys.argv[0]
sys.exit()
myusername = sys.argv[1]
if len(myusername) < 4: # 0x40236D
print "[ERROR] username should be at least 4 characters"
sys.exit()
if len(myusername) > 6: # 0x402361
print "[INFO] username length limited to 6 characters. Username truncated to '%s'" % myusername[:6]
myusername = myusername[:6]
debug = True
make_serial()
Comments
Keywords: assembly x86 reverse-engineering crackme daxxor keygenme