Friday, May 23, 2014

Kirjava KGM2 Crackme - PyDbg Self Keygen

Crackmes.de website had posted a simple crackme executable for creating a keygen. I quickly thought of putting PyDbg into action here. Manually debugging the executable lead me to a place where the decision making process takes place.


The EXE takes 8 characters as input for UserName and 12 characters as input for Serial. The EXE then applies an algorithm (not going into details as this blog post is for PyDbg) to the Inputted UserName and compares it with the Serial.

From the screenshot above there's a byte by byte comparison that takes place between the output of the algorithm (whose input was the UserName) and the Serial inputted.

We can take advantage of PyDbg here by hooking at the address 0x004010F4 and replacing content of BL register with contents of CH. Meanwhile we can print the content of CH register too (as the loop executes - we can print one character by character) - this will provide us with the valid serial for a given UserName.

Below Python code can help retrieve the Serial. Firstly execute the Crackme and then run the Python script.


from pydbg import *
from pydbg.defines import *

import utils
import sys
import os
from ctypes import *

global is_hooked

def tamper( dbg, args ):
 content_ecx = dbg.context.Ecx
 content_ecx = content_ecx >> 8
 dbg.set_register("Ebx", content_ecx)  #set the value for bl #CMP CH,BL - CH holds the correct key
 print "[*] %c" % content_ecx
 return DBG_CONTINUE

def hook_kgm2 (pydbg):
 is_hooked = 0
 hooks = utils.hook_container()
 hook_address  = 0x004010F4   #CMP CH,BL#JNZ.....
 if (is_hooked != 1):
  if hook_address:
   res = hooks.add(pydbg, hook_address, 0, tamper, None)
   is_hooked = 1
   if res:
    print "[*] Hooked at: 0x%08x" % hook_address
    print "[*] Give Username of size 8"
    print "[*] Give Password of size 12"
  else:
   print "[*] Error: Couldn't resolve hook address."
 return DBG_CONTINUE

dbg = pydbg()
dbg.set_callback(EXCEPTION_BREAKPOINT, hook_kgm2)
found_program = False

for (pid, name) in dbg.enumerate_processes():
 if name.lower() == "kgm2.exe":
  found_program = True
  dbg.attach(pid)

if found_program:
 dbg.run()
else:
 dbg.detach()
 

 When everything goes well you will see the below. Note the valid key printed vertically char by char on the command prompt.


Original key that's printed on the command prompt can be verified again.


No comments:

Post a Comment