Description

SEPC is a “medium” linux kernel based reversing challege. SEPC stands for “Secure Enclave Password Checker”, with the challenge being featured in the 2023 HTB Business CTF.

Players are given three files:

bzImage             (kernel image)
initramfs.cpio.gz   (file system)
run.sh              (a helper script to run the program)

Flag

Initially I was under the impression that I was going to need to debug the kernel of the virtual machine to better understand what was happening under the hood. But simply reversing and dumping some data from the kernel module was all that was needed!

We can extract the file system from the provided gzip with the following command:

$ gunzip -c initramfs.cpio.gz | cpio -id

After extracting the file system we can:

  1. Test the “checker” binary for system calls
  2. Reverse engineer the usermode application and the kernel module “checker.ko”

Exectuing strace against the usermode application we see that it reads in a password from the user, tries to open a fd to the kernel module, tries to write each letter of the password to the opened fd and then read the response. For me, this is enough to start reverse engineering the kernel module.

Ghidra does not automatically find all of the kernel functions on its own, so we begin to manually search. Eventually we come across the following function:

If we look closely, we see that this function is mimicing the exact behavior that the user mode application is adhering to. I’ve left out the _copy_from_user call, but the user input is being populated in DAT_00100c40.

The user input is then being compared to the result of a simple xor operation between data in the .rodata section.. To copy out the .rodata we can use objcopy:

$ objcopy checker.ko --dump-section .rodata=rodata

Then we can manually write out the xor operation against the data:

#!/usr/bin/env python3

with open("rodata", "rb") as f:
    data = f.read()
    f.close()

s1 = data[0x20:0x60]
s2 = data[0x60:]

for i in range(len(s2)):
    print(chr(s1[i]^s2[i]), end="")

print()

Running the script we get the flag: