Solution-LuCiFeR-First-CPP-Crackme

From aldeid
Jump to navigation Jump to search

Description

Objective

The objective of this crackme (http://crackmes.de/users/lucifer/first_c_crackme/) is to crack the serial generation algorithm and develop a keygen.

My keygen in action

Here is the output of my keygen in action (with debug information set to True):

$ ./keygen.py lucifer
[DEBUG] 0x40167E: edx=0x3b389b
[DEBUG] 0x401685: edx=0x12f364, eax=0xccdd61c5
[DEBUG] 0x40168A: eax=0x979b
[DEBUG] 0x401690: eax=0xfdf6db30
[INFO] Serial for lucifer: 1711276032-x019871

Code anlaysis

The code is relatively short. The interesting part is as below:

.text:00401668 lea     eax, [ebp+var_108]
.text:0040166E mov     [esp], eax          ; EAX = username
.text:00401671 call    _strlen             ; username's length
.text:00401676 mov     edx, eax            ; save username's length into EDX
.text:00401678 imul    edx, 875CDh         ; multiply EDX by 0x875CD
.text:0040167E mov     eax, 51EB851Fh      ; move 0x51EB851F into EAX
.text:00401683 mul     edx                 ; multiply EAX (0x51EB851F) by EDX (username's length)
.text:00401685 mov     eax, edx            ; save result into EAX
.text:00401687 shr     eax, 5              ; shift right result by 5
.text:0040168A imul    eax, 0FFFFFC90h     ; multiply result by 0xFFFFFC90
.text:00401690 mov     edx, 0
.text:00401695 push    edx
.text:00401696 push    eax
.text:00401697 fild    qword ptr [esp]     ; fetch the top of the stack (previously EAX) into a floating point value and stores it to ST(0)
.text:0040169A lea     esp, [esp+8]
.text:0040169E fstp    [ebp+var_410]       ; save ST(0) into EBP - 0x410
.text:004016A4 fld     [ebp+var_410]       ; push the operand back onto the FPU register stack
.text:004016AA fstp    qword ptr [esp+8]   ; save ST(0) onto the base stack as ESP+8
.text:004016AE mov     dword ptr [esp+4], offset aIX019871 ; "%i-x019871"

My keygen

#!/usr/bin/env python
import sys
import struct

def mul(reg, eax):
    """
    Return (EDX, EAX) tuple as result of multiplication
    """
    mulval = reg * eax
    return (mulval >> 32, mulval & 0xFFFFFFFF)

def double_to_hex(f):
    return struct.unpack('<Q', struct.pack('<d', f))[0]

def make_serial():
    eax = len(myusername)
    edx = eax * 0x875CD                             # 0x401673  imul edx, 8575CD
    if debug:
        print "[DEBUG] 0x40167E: edx=%s" % hex(edx)
    eax = 0x51EB851F                                # 0x40167E  mov eax, 51EB851F
    edx, eax = mul(edx, eax)                        # 0x401683  mul edx
    if debug:
        print "[DEBUG] 0x401685: edx=%s, eax=%s" % (hex(edx), hex(eax))
    eax = edx                                       # 0x401685  MOV EAX,EDX
    eax = eax >> 5                                  # 0x401687  SHR EAX,5
    if debug:
        print "[DEBUG] 0x40168A: eax=%s" % hex(eax)
    eax = (eax * 0xFFFFFC90) & 0xFFFFFFFF           # 0x40168A  imul eax, 0FFFFFC90h
    if debug:
        print "[DEBUG] 0x401690: eax=%s" % hex(eax)

    print "[INFO] Serial for %s: %s-x019871" % (myusername, str(double_to_hex(eax) & 0xFFFFFFFF))


if __name__ == '__main__':
    if len(sys.argv) < 2:
        print "Usage: %s <username>" % (sys.argv[0])
        sys.exit()
    
    debug = False
    myusername = sys.argv[1]
    make_serial()

Comments

Keywords: assembly x86 reverse-engineering crackme lucifer c++