Post

KnightCTF 2023- The Activator

KnightCTF 2023- The Activator

License Checker Bypass: A Classic Crackme

Essentially, it is classic crackme, where the main challenge was bypassing a series of checks embedded within the main() function. In this particular case, there was a complex set of checks performed on the input, and based on the result, a single boolean flag would be set, indicating whether the input was valid or not.

If the flag (checks_ok) was set to true, the program would display the CTF flag. Otherwise, it would simply output a message informing the user that the input was invalid:

1
2
3
4
5
if (checks_ok) {
  show_flag();
} else {
  std::cout << "Invalid Key." << std::endl;
}

Bypassing the Check

I used NOP instructions to bypass the check, this time I directly modified the program’s flow. Instead of altering the checks, I manually set the instruction pointer (RIP) to jump just before the show_flag() function call, effectively skipping all validation.

Here’s how I achieved this using GDB:

1
2
3
4
5
6
7
8
9
10
11
12
KnightOS License Checker.
Enter KnightOS Activation Key: ^C
Program received signal SIGINT, Interrupt.
0x00007ffff7b52992 in __GI___libc_read ...
(gdb) finish
Run till exit from #0  0x00007ffff7b52992 in __GI___libc_read ...
asdf
...
Value returned is $1 = 5
(gdb) set $rip=0x555555555bce
(gdb) c
Continuing.

By manually setting the RIP register to the address just before the show_flag() function, I was able to bypass all the checks and directly jump to the point where the flag is displayed.

Flag

After redirecting the instruction pointer, the program outputted the flag:

1
KCTF{Th47_License_ch3cker_w4S_similar_t0_Wind0ws_95_OSR_Activator_Right?}

Flagged

This post is licensed under CC BY 4.0 by the author.