Solution-jockcranley-T0AD-K3YG3N

From aldeid
Jump to navigation Jump to search

Description

Objective

The objective of this challenge is to crack the serial generation algorithm from the username and write your own keygen.

My keygen in action

Below is the output of mykeygen in action, with debug set to True.

$ ./keygen.py myusername
[DEBUG] username=myuserna
[DEBUG] 0x4014ED EAX=0x28 EDX=0x28 EBX=0x28
--- index 0 ---
[DEBUG] 0x4014FF EAX=0x6d
[DEBUG] 0x401503 EAX=0x45
[DEBUG] 0x401506 EAX=0x4
[DEBUG] 0x401511 EAX=0x34
--- index 1 ---
[DEBUG] 0x4014FF EAX=0x79
[DEBUG] 0x401503 EAX=0x75
[DEBUG] 0x401506 EAX=0x34
[DEBUG] 0x401511 EAX=0x64
--- index 2 ---
[DEBUG] 0x4014FF EAX=0x75
[DEBUG] 0x401503 EAX=0xe9
[DEBUG] 0x401506 EAX=0x28
[DEBUG] 0x401511 EAX=0x58
--- index 3 ---
[DEBUG] 0x4014FF EAX=0x73
[DEBUG] 0x401503 EAX=0xb
[DEBUG] 0x401506 EAX=0x8
[DEBUG] 0x401511 EAX=0x38
--- index 4 ---
[DEBUG] 0x4014FF EAX=0x65
[DEBUG] 0x401503 EAX=0x7d
[DEBUG] 0x401506 EAX=0x3c
[DEBUG] 0x401511 EAX=0x6c
--- index 5 ---
[DEBUG] 0x4014FF EAX=0x72
[DEBUG] 0x401503 EAX=0xc6
[DEBUG] 0x401506 EAX=0x4
[DEBUG] 0x401511 EAX=0x34
--- index 6 ---
[DEBUG] 0x4014FF EAX=0x6e
[DEBUG] 0x401503 EAX=0x62
[DEBUG] 0x401506 EAX=0x20
[DEBUG] 0x401511 EAX=0x50
--- index 7 ---
[DEBUG] 0x4014FF EAX=0x61
[DEBUG] 0x401503 EAX=0x1
[DEBUG] 0x401506 EAX=0x0
[DEBUG] 0x401511 EAX=0x30
Serial: 4dX8l4P0

Code Analysis

Username length

The username should be at least 7 characters long. The following routine checks each character of the username and if a NULL character is met before the loop finishes, the program jumps to the end and fails.

If the provided username is longer than 8 characters, only the first 8 characters will be taken to generate the serial. As a consequence, 'myusername' will produce the same serial as 'myuserna'.

Serial

The rest of the code is commented in my keygen code.

My keygen

#!/usr/bin/env python
import sys

def make_serial(username):
    # if username is 6 characters, last character is a line feed
    if len(username) < 8:
        username += '\n'
    username = username[:8]     # Only 8 first characters of username are considered
                                # 00401530 cmp     [esp+44h+counter1], 8
    if debug:
        print "[DEBUG] username=%s" % username

    eax = ord(username[1])      # .text:004014C5 movzx   eax, [esp+44h+user_name+1] ; 2nd letter of username
    edx = eax                   # .text:004014CA movsx   dx, al          ; DX = 2nd letter of username
    edx *= 0x56                 # .text:004014CE imul    edx, 56h        ; EDX*=0x56
    edx = edx >> 0x8            # .text:004014D1 shr     dx, 8           ; EDX = EDX >> 0x8
    eax = eax >> 0x7            # .text:004014D5 sar     al, 7           ; AL = 2nd letter username >> 0x7
    ebx = edx                   # .text:004014D8 mov     ebx, edx        ; EBX = EDX
    ebx -= eax                  # .text:004014DA sub     ebx, eax        ; EBX = EBX - EAX
    eax = ebx                   # .text:004014DC mov     eax, ebx        ; EAX = EBX
                                # .text:004014DE movsx   eax, al
    var_8 = eax                 # .text:004014E1 mov     [esp+44h+var_8], eax ; username[1]
    var_33 = 0x20202020         # .text:00401419 mov     [esp+44h+var_33], 20202020h

    if debug:
        print "[DEBUG] 0x4014ED EAX=%s EDX=%s EBX=%s" % (hex(eax), hex(edx), hex(ebx))

    serial = []

    #for c, i in enumerate(username):
    for c in range(8):
        i = username[c]
        
        if debug:
            print "--- index %s ---" % c
        
        edx = username          # .text:004014EF lea     edx, [esp+44h+user_name]
        """
        # .text:004014F3 mov     eax, [esp+44h+counter1] ; EAX = username letter counter
        # .text:004014F7 add     eax, edx
        # .text:004014F9 movzx   eax, byte ptr [eax] ; EAX = letter of username
        # .text:004014FC movsx   eax, al
        """
        eax = ord(i)
        if debug:
            print "[DEBUG] 0x4014FF EAX=%s" % hex(eax)
    
        eax = eax ^ var_8       # .text:004014FF xor     eax, [esp+44h+var_8]
        if debug:
            print "[DEBUG] 0x401503 EAX=%s" % hex(eax)

        eax = eax & 0x3C        # .text:00401503 and     eax, 3Ch
        if debug:
            print "[DEBUG] 0x401506 EAX=%s" % hex(eax)

        var_18 = eax            # .text:00401506 mov     [esp+44h+var_18], eax
        eax = var_18            # .text:0040150A mov     eax, [esp+44h+var_18]
        eax += 0x30             # .text:0040150E add     eax, 30h
        if debug:
            print "[DEBUG] 0x401511 EAX=%s" % hex(eax)

        serial.append(eax)
        
        ecx = var_33            # .text:00401511 lea     ecx, [esp+44h+var_33]
        edx = c                 # .text:00401515 mov     edx, [esp+44h+counter1]
        edx += ecx              # .text:00401519 add     edx, ecx
        edx = eax               # .text:0040151B mov     [edx], al
        edx = var_18            # .text:0040151D mov     edx, [esp+44h+var_18]
        eax = edx               # .text:00401521 mov     eax, edx
        eax += eax              # .text:00401523 add     eax, eax
        eax += edx              # .text:00401525 add     eax, edx
        var_8 = eax             # .text:00401527 mov     [esp+44h+var_8], eax
        
    return serial
    
if __name__ == '__main__':
    debug = True
    
    if len(sys.argv) < 2:
        print "Usage: %s <username>" % sys.argv[0]
        sys.exit()
    
    username = sys.argv[1]
    
    # 0x401488 - 0x40147C
    if len(username) < 7:
        print "[ERROR] Username should be at least 7 characters"
        sys.exit()
    
    serial = make_serial(username)
    print "Serial: %s" % ''.join([chr(i) for i in serial])

Comments

Keywords: assembly x86 reverse-engineering crackme jockcranley toad keygen