rezk2ll's KeygenmeNasm Tutorial
Target: rezk2ll’s KeygenmeNasm
URL: http://www.crackmes.de/users/rezk2ll/keygenmenasm/
Protection: Serial.
Description: Crackme with a serial protection.
Tools: objdump / x86 assembly knowledge.
First disassemble the keygenme and take a look at what it does.
objdump -d -M intel keygenme
keygenme: file format elf32-i386
Disassembly of section .text:
08048080 <_start>:
; print out headers
8048080: b8 04 00 00 00 mov eax,0x4
8048085: bb 01 00 00 00 mov ebx,0x1
804808a: b9 d0 91 04 08 mov ecx,0x80491d0
804808f: ba 2f 00 00 00 mov edx,0x2f
8048094: cd 80 int 0x80
8048096: b8 04 00 00 00 mov eax,0x4
804809b: bb 01 00 00 00 mov ebx,0x1
80480a0: b9 ff 91 04 08 mov ecx,0x80491ff
80480a5: ba 0c 00 00 00 mov edx,0xc
80480aa: cd 80 int 0x80
; read name
80480ac: b8 03 00 00 00 mov eax,0x3 ; sys_read
80480b1: bb 00 00 00 00 mov ebx,0x0 ; stdin
80480b6: b9 84 92 04 08 mov ecx,0x8049284 ; variable to use
80480bb: ba 0f 00 00 00 mov edx,0xf ; length 0xf
80480c0: cd 80 int 0x80 ; syscall
80480c2: 83 f8 03 cmp eax,0x3 ; if len(name) <= 3
80480c5: 0f 8e df 00 00 00 jle 80481aa ; jump to invalid name message
80480cb: 50 push eax ; push len(name) on to the stack
80480cc: 83 f8 0e cmp eax,0xe ; if len(name) > 0xe
80480cf: 0f 8f d5 00 00 00 jg 80481aa ; jump to invalid name message
; print out serial input request
80480d5: b8 04 00 00 00 mov eax,0x4
80480da: bb 01 00 00 00 mov ebx,0x1
80480df: b9 0b 92 04 08 mov ecx,0x804920b
80480e4: ba 0c 00 00 00 mov edx,0xc
80480e9: cd 80 int 0x80
; read serial
80480eb: b8 03 00 00 00 mov eax,0x3 ; sys_read
80480f0: bb 00 00 00 00 mov ebx,0x0 ; stdin
80480f5: b9 93 92 04 08 mov ecx,0x8049293 ; variable to use
80480fa: ba 0f 00 00 00 mov edx,0xf ; length 0xf
80480ff: cd 80 int 0x80 ; syscall
8048101: 5b pop ebx ; ebx = len(name)
8048102: 39 d8 cmp eax,ebx ; if len(name) != len(serial)
8048104: 89 c7 mov edi,eax
8048106: 75 5c jne 8048164 ; jump to invalid serial message
8048108: 50 push eax ; push len(serial) to the stack
8048109: 31 c0 xor eax,eax
804810b: 31 db xor ebx,ebx
804810d: 31 c9 xor ecx,ecx
804810f: 31 d2 xor edx,edx
8048111: 5a pop edx ; edx = len(serial)
8048112: 4a dec edx ; len(serial)--
8048113: be 84 92 04 08 mov esi,0x8049284 ; move our entered name to esi
8048118: b0 05 mov al,0x5 ; init value for the OR operation
0804811a :
804811a: 8a 1c 0e mov bl,BYTE PTR [esi+ecx1] ; bl = name[i]
804811d: 88 df mov bh,bl ; bh = name[i]
804811f: 08 c3 or bl,al ; bl = name[i] OR value
8048121: 88 f8 mov al,bh ; value = name[i]
8048123: 88 1c 0e mov BYTE PTR [esi+ecx1],bl ; name[i] = bl
8048126: 41 inc ecx ; i++
8048127: 39 d1 cmp ecx,edx ; if i < len(serial)
8048129: 7c ef jl 804811a ; loop
804812b: 31 db xor ebx,ebx
804812d: bb 93 92 04 08 mov ebx,0x8049293 ; ebx = our entered serial
8048132: 31 c0 xor eax,eax
08048134 :
8048134: 8a 04 0e mov al,BYTE PTR [esi+ecx1] ; al = name[i]
8048137: 8a 24 0b mov ah,BYTE PTR [ebx+ecx1] ; ah = serial[i]
804813a: 38 c4 cmp ah,al ; if name[i] != serial[i]
804813c: 75 26 jne 8048164 ; jump to fail
804813e: 49 dec ecx ; i--
804813f: 83 f9 00 cmp ecx,0x0 ; if i >= 0
8048142: 7d f0 jge 8048134 ; loop
8048144: eb 45 jmp 804818b ; if all characters match, jump to success message
08048146 :
8048146: ba 01 00 00 00 mov edx,0x1
804814b: b9 a2 92 04 08 mov ecx,0x80492a2
8048150: bb 00 00 00 00 mov ebx,0x0
8048155: b8 03 00 00 00 mov eax,0x3
804815a: cd 80 int 0x80
804815c: 80 7c 11 ff 0a cmp BYTE PTR [ecx+edx*1-0x1],0xa
8048161: 75 e3 jne 8048146
8048163: c3 ret
; wrong serial message
08048164 :
8048164: 83 ff 0f cmp edi,0xf
8048167: b8 04 00 00 00 mov eax,0x4
804816c: bb 01 00 00 00 mov ebx,0x1
8048171: b9 3f 92 04 08 mov ecx,0x804923f
8048176: ba 14 00 00 00 mov edx,0x14
804817b: cd 80 int 0x80
804817d: e8 c4 ff ff ff call 8048146
8048182: b8 01 00 00 00 mov eax,0x1
8048187: 31 db xor ebx,ebx
8048189: cd 80 int 0x80
; correct serial message
0804818b :
804818b: b8 04 00 00 00 mov eax,0x4
8048190: bb 01 00 00 00 mov ebx,0x1
8048195: b9 17 92 04 08 mov ecx,0x8049217
804819a: ba 28 00 00 00 mov edx,0x28
804819f: cd 80 int 0x80
80481a1: b8 01 00 00 00 mov eax,0x1
80481a6: 31 db xor ebx,ebx
80481a8: cd 80 int 0x80
; invalid name message
080481aa :
80481aa: b8 04 00 00 00 mov eax,0x4
80481af: bb 01 00 00 00 mov ebx,0x1
80481b4: b9 53 92 04 08 mov ecx,0x8049253
80481b9: ba 2e 00 00 00 mov edx,0x2e
80481be: cd 80 int 0x80
80481c0: e8 81 ff ff ff call 8048146
80481c5: b8 01 00 00 00 mov eax,0x1
80481ca: 31 db xor ebx,ebx
80481cc: cd 80 int 0x80
So a basic OR operation is made on each character of the name to generate the serial. The first value is 0x05 and the subsequent values are the previous character value of the name. So lets write a keygen.
# keygen.py by Klefz
print("rezk2ll's KeygenmeNasm keygen by Klefz")
name = input("Name: ")
serial = ""
value = 0x5
if len(name) < 3 or len(name) > 13:
print("Name has to be 3-13 characters.")
raise SystemExit
for c in name:
charValue = value | ord(c)
value = ord(c)
serial += chr(charValue)
print("Serial: " + serial)