Solution-profdraculare-keygenme228
Jump to navigation
Jump to search
Introduction
Description
This crackme is avilable here. It is a 32-bit ELF with following properties:
File | ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.26, BuildID[sha1]=da7362dd421162cfa9675f61b5cfda8def545213, not stripped |
---|---|
MD5 | acbd0dc7f847cc1cf5cec36a95976873 |
SHA1 | e0eb5754c4f246426e0c989e071b948c128e6731 |
SHA256 | 8eeeeecd966bf18d4ac72c201714f355e81decf2e301e00bdf1c52fa9400111c |
Overview
Code analysis
Initialization
This part of the code is asking for a serial that will be stored at [ESP+0x15], computes the length of the serial (saved to [ESP+0x114]) and checks that it is greater than 2 characters.
.text:0804850C ; int __cdecl main(int argc, const char **argv, const char **envp)
.text:0804850C public main
.text:0804850C main proc near
.text:0804850C
.text:0804850C argc = dword ptr 8
.text:0804850C argv = dword ptr 0Ch
.text:0804850C envp = dword ptr 10h
.text:0804850C
.text:0804850C push ebp
.text:0804850D mov ebp, esp
.text:0804850F and esp, 0FFFFFFF0h
.text:08048512 sub esp, 120h
.text:08048518 mov dword ptr [esp+114h], 0
.text:08048523 mov dword ptr [esp], offset format ; "Enter serial:"
.text:0804852A call _printf
.text:0804852F lea eax, [esp+15h] ; my_serial stored at [ESP+0x15]
.text:08048533 mov [esp+4], eax
.text:08048537 mov dword ptr [esp], offset aS ; "%s"
.text:0804853E call ___isoc99_scanf
.text:08048543 lea eax, [esp+15h]
.text:08048547 mov [esp], eax ; s
.text:0804854A call _strlen
.text:0804854F mov [esp+114h], eax ; len(my_serial) at [ESP+0x114]
.text:08048556 cmp dword ptr [esp+114h], 2 ; len(my_serial) should be > 2
.text:0804855E jg short loc_804856C
.text:08048560 mov dword ptr [esp], 1 ; status
.text:08048567 call _exit
Monotonic ascending
This code is comparing each character of the serial by groups of 2 (serial[i] and serial[i+1]) and ensures that each following character is equal or greater than the previous one:
┌─────┬─────┬─────┬─────┬─────┐ │ a │ d │ d │ g │ c │ └─────┴─────┴─────┴─────┴─────┘ │ ▲ │ ▲ │ ▲ │ ▲ └───┘ └───┘ └───┘ └───┘ +3 +0 +3 -4
.text:0804856C loc_804856C:
.text:0804856C mov dword ptr [esp+118h], 1 ; j = 1
.text:08048577 mov dword ptr [esp+11Ch], 0 ; i = 0
.text:08048582 jmp short loc_80485C8
.text:08048584 ; ---------------------------------------------------------------------------
.text:08048584
.text:08048584 loc_8048584:
.text:08048584 lea edx, [esp+15h] ; edx = my_serial
.text:08048588 mov eax, [esp+11Ch] ; eax = i
.text:0804858F add eax, edx
.text:08048591 movzx eax, byte ptr [eax] ; eax = my_serial[i]
.text:08048594 movsx edx, al ; edx = my_username[i]
.text:08048597 mov eax, [esp+11Ch] ; eax = i
.text:0804859E add eax, 1 ; i += 1
.text:080485A1 movzx eax, byte ptr [esp+eax+15h] ; eax = my_serial[i]
.text:080485A1 ; (i has been incremented before. Now points to my_serial[i+1]
.text:080485A6 movsx eax, al
.text:080485A9 mov ecx, edx ; ecx = my_username[i-1]
.text:080485AB sub ecx, eax
.text:080485AD mov eax, ecx ; eax = username[i] - username[i+1]
.text:080485AF test eax, eax
.text:080485B1 jle short loc_80485C0 ; jump to 0x80485C0 if myserial[i] <= my_serial[i+1]
.text:080485B3 mov dword ptr [esp+118h], 0 ; // Branch if my_serial[i+1] < my_serial[i]
.text:080485B3 ; j = 0
.text:080485BE jmp short loc_80485DB
.text:080485C0 ; ---------------------------------------------------------------------------
.text:080485C0
.text:080485C0 loc_80485C0:
.text:080485C0 add dword ptr [esp+11Ch], 1 ; // Branch if my_serial[i+1] >= my_serial[i]
.text:080485C0 ; // (monotonic increasing)
.text:080485C0 ; i += 1
.text:080485C8
.text:080485C8 loc_80485C8:
.text:080485C8 mov eax, [esp+114h] ; eax = len(my_serial)
.text:080485CF sub eax, 1 ; eax = len(my_serial)-1
.text:080485D2 cmp eax, [esp+11Ch]
.text:080485D9 jg short loc_8048584 ; loop until all characters of my_serial are read
Monotonic descending
This code is comparing each character of the serial by groups of 2 and ensures that serial[i] is greater than or equal to serial[i+1] by starting at the end of the serial. It ignores the first character:
i = 4 3 2 1 0 ┌─────┬─────┬─────┬─────┬─────┐ │ a │ m │ h │ f │ c │ └─────┴─────┴─────┴─────┴─────┘ ▲ │ ▲ │ ▲ │ └───┘ └───┘ └───┘ +5 +2 +3
.text:080485E5 mov dword ptr [esp+118h], 0FFFFFFFFh
.text:080485F0 mov eax, [esp+114h] ; eax = len(my_serial)
.text:080485F7 sub eax, 1 ; eax = len(my_serial) - 1
.text:080485FA mov [esp+11Ch], eax ; i = len(my_serial) - 1
.text:080485FA ; (1st char won't be tested)
.text:08048601 jmp short loc_8048647
.text:08048603 ; ---------------------------------------------------------------------------
.text:08048603
.text:08048603 loc_8048603:
.text:08048603 lea edx, [esp+15h]
.text:08048607 mov eax, [esp+11Ch] ; eax = i
.text:0804860E add eax, edx
.text:08048610 movzx eax, byte ptr [eax] ; eax = my_serial[i]
.text:08048610 ; (i starting at the end of string)
.text:08048613 movsx edx, al ; edx = my_serial[i]
.text:08048616 mov eax, [esp+11Ch] ; eax = i
.text:0804861D add eax, 1 ; i+=1
.text:08048620 movzx eax, byte ptr [esp+eax+15h]
.text:08048625 movsx eax, al ; eax = my_serial[i+1]
.text:08048628 mov ecx, edx ; ecx = my_serial[i]
.text:0804862A sub ecx, eax ; \
.text:0804862C mov eax, ecx ; / eax = my_serial[i] - my_serial[i+1]
.text:0804862E test eax, eax
.text:08048630 jns short loc_804863F ; jump to loc_804863F if my_serial[i] > my_serial[i+1]
.text:08048632 mov dword ptr [esp+118h], 0 ; j = 0
.text:0804863D jmp short loc_8048651
.text:0804863F ; ---------------------------------------------------------------------------
.text:0804863F
.text:0804863F loc_804863F:
.text:0804863F sub dword ptr [esp+11Ch], 1 ; // Branch if my_serial[i+1] < my_serial[i]
.text:0804863F ; i -= 1
.text:08048647
.text:08048647 loc_8048647:
.text:08048647 cmp dword ptr [esp+11Ch], 0
.text:0804864F jg short loc_8048603 ; while (i>0)
Keygen
Code
#!/usr/bin/env python
from random import randint
# Serial length generated randomly
SERIAL_LEN = randint(3,10)
DEBUG = True # False
def make_serial():
if DEBUG:
print "[INFO] Length: %d" % SERIAL_LEN
serial = []
# randomly choose branch
choice = randint(0,1)
### monotonic ascending
if choice == 0:
if DEBUG:
print "[INFO] Monotonic ascending"
# feed serial with 1 item
# max_rand based on a minimal space of 1 between chars
# to ensure that serial will reach its length
c = randint(33, 126 - SERIAL_LEN + 1)
serial.append(c)
i = 1 # 1 item already in serial
while i < SERIAL_LEN:
max_rand = 126 - SERIAL_LEN + i + 1
# serial[i+1] should be >= serial[i]
# implies that serial[i+1] can be equal to serial[i]
c = randint(serial[-1], max_rand)
while c < serial[-1]:
c = randint(serial[-1], max_rand)
serial.append(c)
i += 1
### monotonic descending
else:
if DEBUG:
print "[INFO] Monotonic descending"
# feed serial with 1 item (can be whatever printable)
serial.append(randint(33, 126))
# feed serial with a 2nd character
c = randint(33 + SERIAL_LEN - 2, 126)
serial.append(c)
i = 2 # 2 items already in serial
while i < SERIAL_LEN:
min_rand = 33 + SERIAL_LEN - i - 1
# serial[i+1] should be <= serial[i]
# implies that serial[i+1] can be equal to serial[i]
c = randint(min_rand, serial[-1])
while c > serial[-1]:
c = randint(min_rand, serial[-1])
serial.append(c)
i += 1
return ''.join([chr(i) for i in serial])
if __name__ == '__main__':
print "Serial: %s" % make_serial()
Tests
Keygen | Check |
---|---|
$ ./keygen.py [INFO] Length: 9 [INFO] Monotonic descending Serial: cT9922### |
$ ./keygenme228 Enter serial:cT9922### Greetings from Penguinland! |
$ ./keygen.py [INFO] Length: 5 [INFO] Monotonic descending Serial: sK5'$ |
$ ./keygenme228 Enter serial:sK5'$ Greetings from Penguinland! |
$ ./keygen.py [INFO] Length: 6 [INFO] Monotonic descending Serial: :P-%$! |
$ ./keygenme228 Enter serial::P-%$! Greetings from Penguinland! |
$ ./keygen.py [INFO] Length: 8 [INFO] Monotonic ascending Serial: Bbmoprs{ |
$ ./keygenme228 Enter serial:Bbmoprs{ Greetings from Penguinland! |
$ ./keygen.py [INFO] Length: 9 [INFO] Monotonic ascending Serial: ]fjpwy||~ |
$ ./keygenme228 Enter serial:]fjpwy||~ Greetings from Penguinland! |
$ ./keygen.py [INFO] Length: 5 [INFO] Monotonic descending Serial: U3'$" |
$ ./keygenme228 Enter serial:U3'$" Greetings from Penguinland! |
$ ./keygen.py [INFO] Length: 10 [INFO] Monotonic ascending Serial: *+3Soxz||} |
$ ./keygenme228 Enter serial:*+3Soxz||} Greetings from Penguinland! |
Comments
Keywords: assembly x86 reverse-engineering crackme profdraculare keygenme228 crackmes.de