Roxog

BreizhCTF 2019 - Reverse (100 pts).

BreizhCTF 2019: Roxog

Challenge details

Event Challenge Category Points Solves
BreizhCTF 2019 Roxog Reverse 100 ?

Challenge: roxog md5sum : 25adcd4f3a2b281ec5b43e0f94236246

TL;DR

A Go binary, flag xored with static int

Methodology

Recon with r2

First we fire up r2 : r2 -A ./roxog It take quite a long time, we can first assume it’s staticly compiled

Then we search the main function (afl for listing function and ~main to make a grep on this list) :

The syntax look alike a Go binary, main.main is the main function in Go binaries.

Since it’s Go, I prefer IDA to reverse it. So let’s fire up IDA to make serious business :).

IDA Part

When looking at main_main, we don’t see any obvious comparison, except one that compare args, we can assume it’s the good way to follow since there is an os_Exit call in the box before.

When we have enough args and we jump below a strange function is called : runtime_text

Let’s see what’s hiding in this function.

In this function we can see some interesting things :


It seems that the initial name of this function was main.roxgo


The function is loading data that look like a cipher


And finally there is a loop with a xor by 0x7f

Hypothesis

At this point, I made the assumption that the data loaded by the function was xored by 0x7F. It cost almost no time to test this assumption and if it’s true, I will save a lot of time.

So let’s follow this hypothesis.

To have the data I go with radare again, data is at 0x4AFE80 we just have to tell the length and the address (here the length is totally random we just need a quick test) : ps 300 @0x4AFE80

Then let’s script it :

potential_cipher = open("out").read()

out = ""
for i in potential_cipher:
    out += chr((0x7f ^ ord(i)) & 0xff)

print(out)

Looks like we are on the right path :) The funny thing with Go, is that String are not like C char* so let’s find another way to dump this cipher.

GDB part

Let’s fire up GDB :



Now break at 0x40102F where we load the cipher



And step few instructions to see the loaded data in rax (n to step one instruction):

Now let’s dump rax data with dump memory out $rax $rax+30 where out is the output file, $rax the start and $rax+30 the stop address

And execute again our Python script since my out file is the same that I had before ;)

Ok we have the end o the flag … Let’s dump a little bit before :

And execute our script :

Conclusion

Try to make assumption when you’re reversing a CTF challenge, it can save you many time. And look for xor, many reverser likes to use xor in their challenges :)

Flag

BREIZHCTF{d0_y0u_Kn0w_7h47_m4nY_pr0j3kt5_4r3_wr1773n_in_GO?!_g0ph3r_rul35_t3h_w0r1d_0x7f}

@Areizen