Thumbnail: BoilersCTF

BoilersCTF 2022 - crackme

on under writeups
2 minute read

Initial Analysis

The first step in reversing a binary is to check its file type. We can do this with the file command:

$ file crackme
crackme: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically
linked, interpreter /lib64/ld-linux-x86-64.so.2,
BuildID[sha1]=62f2a0ce4eb1f676d6731a914cfc190a2450111c, for GNU/Linux 3.2.0,
not stripped

We can see from this output that the file is an ELF 64-bit binary. The next step is to try running the binary and see what happens.

$ ./crackme
Product Key> test
Key incorrect, not activating.

This indicates that the binary is asking for some kind of product key.

The next step is to run the binary in a debugger (such as GDB) or a tracer (such as ltrace) to see what kind of output it gives. Unfortunately, in this case, running the binary in a debugger or tracer yields no useful information.

Decompiling with Ghidra

With no useful information from running the binary in a debugger or tracer, the next step is to open the binary in a disassembler. I chose to use Ghidra for this task.

The decompiled main function looks like this:

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char s[60]; // [rsp+10h] [rbp-40h] BYREF
  int v5; // [rsp+4Ch] [rbp-4h]

  v5 = 0;
  printf("Product Key> ");
  fgets(s, 47, stdin);
  if ( (unsigned int)check(s) )
  {
    printf("Key correct, activating.\n");
    return 0;
  }
  else
  {
    printf("Key incorrect, not activating.\n");
    return 1;
  }
}

We can see that the program is asking for a product key and then passing it to a function called check(). If check() returns a non-zero value, the program prints “Key correct, activating.” and returns 0. Otherwise, it prints “Key incorrect, not activating.” and returns 1.

Reversing the check() Function

The next step is to reverse the check() function. After looking at the code, it appears to be a bunch of nested if statements. There are several ways to attack this. We can set breakpoints at each if statement, use angr, or count the instructions between each if. I decided to simply convert each if comparison into characters and manually find the flag.

The flag was bctf{133&_letmein_123}.

Conclusion

This post walked through the process of reversing a binary called “crackme” in order to find the flag. We started by checking the file type and running it to see what happened. We then used Ghidra to decompile the main function and saw that it was passing a product key to a function called check(). Finally, we reversed the check() function and manually found the flag.

2022, writeup, reverse, ghidra, BoilersCTF