Crackmes.de - The_thing by prout

This is a crackme level 2 (Easy) from https://crackmes.one/crackme/5ab77f5433c5d40ad448c1d6 )

Fast static analysis Link to heading

First, let’s see what type of file it is:

$ file thething
thething: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.4.1, dynamically linked, interpreter /lib/ld-linux.so.2, no section header

Ok, so 32 bits ELF and dynamically linked (this detail will be useful later). Not sure if stripped or not because of the “no section header”.

Let’s see what the ``strings’’ command says:

$ strings thething
read
ptrace
strcmp
sprintf
scanf
[TRUNCATED]
Serial: 
In fact, your serial have to be equal or bigger than 4 letters
[TRUNCATED]
__init_array_start
_IO_stdin_used
sprintf@@GLIBC_2.0
__data_start
_Jv_RegisterClasses
read@@GLIBC_2.0
__gmon_start__

A lot of symbols and function names, so it doesn’t seem to be stripped, good news. And also a lot of strings.

Dynamic analysis and cracking part Link to heading

Lets run the program :

$ ./thething 
Name: toto
Serial: ze32r1ze312r
Error ! I can't process this name/serial

Depending on the input, we can trigger an other error :

"In fact, your serial have to be equal or bigger than 4 letters"

We know that the string is at least 4 characters long. Lets keep digging with ltrace to see what sprintf or strcmp do:

$ ltrace ./thething
Couldn't find .dynsym or .dynstr in "/proc/6541/exe"

Not working, probably because of the “no section header”. Instead, I try to use the LD_PRELOAD trick with strcmp. I choosed strcmp because it’s often use to compare actual user input with expected input.

Prepare the file for the hook:

#include <stdio.h>

int strcmp(const char *s1, const char *s2){
	printf("cmp : <%s> <%s>", s1, s2);
	return 0;
}

(Always return 0, so strings will always match)

Compile to create the .so lib :

gcc -o strcmp.so -fPIC -shared strcmp.c -m32

note :

  • -fpic for position independant code)
  • -shared for shared library
  • -m32 to force x86 because my computer is x86_64 and the binary is x86

Try it :

$ LD_PRELOAD=$PWD/strcmp.so ./thething 
Name: Toto
Serial: EZRE
cmp : <'-160141484'> <EZRE>Well done :-)

The hook worked, we can see that the serial we entered is compared to a number (the expected serial). Let’s try it without LD_PRELOAD:

$ ./thething 
Name: Toto
Serial: -160141484
Well done :-)

No need to disassemble here, but by doing so we can see in IDA that the serial is the string representation of an integer (%d). This string is then compared to our input with strcmp.

GitHub Logo

Ok it works, next step, create a keygen for arbitraries names.

Keygen Link to heading

## Lazy way

Use the .so file can be used as a keygen.

#include <stdio.h>
int strcmp(const char *s1, const char *s2){
	printf("Serial found : <%s>", s1);
	return 0;
}

and …

LD_PRELOAD=$PWD/strcmp.so ./thething 
Name: AAAA
Serial: 339820865
Serial found : <339820865>Well done :-)

./thething 
Name: AAAA
Serial: 339820865
Well done :-)