Reverse Engineering

Challenge
Topic

FCaaS (0 solve)

Staged ELF, Runtime Modification, Input Validation

FCaaS

Description

Like usual flag checker. Nothing new, but now running as a service

Solution

Given ELF bit file, then open it using IDA

From the main function we can see that the program receive user input using scanf and store it on v13.

v13 values are processed with xor operation and stored in dest variable. Function sub_14bb use dest variable as argument and when we dive on the function we can see that the function actually RC4 algorithm

Since we know the key we can reimplement it on our main programming language, in this case i reimplement it on python.

The last function called on main function is executing file located on memory, we can check the syscall on link below https://github.com/torvalds/linux/blob/master/arch/x86/entry/syscalls/syscall_64.tblarrow-up-right

So actually the RC4 algorithm used to decrypt the actual binary that validate the flag. Here is script i use to decrypt the binary

Running the new elf we can see that there is no output but we can confirm that it is valid elf

Now the question is how can the binary validate the flag? and where is our input stored?

When we decompile the new binary we can see that there are some values that looks like our input which is gemastik2023{AA...AA}. Take a look on assembly code we can see that 0x67 or g stored on address 0x12c9

On initial binary, we found the same value (0x12c9 or 4809)

and we can confirm that v8[45] value is 0, so line 330 with j = 45 produce dest[3809] = v9[0] ^ v13[0]. Line 331 do the same thing but with different value which is dest[16176] = v13[10]^v12[9]. Checking value on address 16176 or 0x3f30 on new binary we found that it also store constant (0x41)

Now we know how is our input stored in second binary. So the next step is understanding how the second binary validate our input.

So actually there are 3 functions that process our input, so take a look on each function.

From the constant stored on each function we can confirm that those 3 function generate md5 hash. After knowing all functions we can rewrite flow like below

We know all the variable values except the input. So basically we can bruteforce each byte by validating with md5 result stored in check variable (each input can be validated with 3 bytes hash). After getting valid input on index x1 we can recover another value on index x2 and so on. Here is final script to recover the flag by bruteforcing

Flag : gemastik{you_know_the_pattern_you_got_the_flag}

Last updated