Solution-DaXXoR-101-D-KeygenMe

From aldeid
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