BSidesSF CTF 2019 - dribbles (250pt)

blind reversing

March 4, 2019
reversing

dribbles (250pt)

Reversing

Description: You’ll have to “dribble” some information out for this one…

Location - dribbles-c4d3cee3.challenges.bsidessf.net:9999

Solution

This challenge does not include a file, so we need to first gather information from the remote server.

When we connect, we are able to enter a symbol that will be resolved:

[1/3] Resolve symbol> 

Typing in main for example gives us:

[1/3] Resolve symbol> main
main (buf@0x7ffd97ee7220) = 0x55ed193b43a9
[2/3] Resolve symbol>

From this we can tell that PIE is enabled. After we resolve three symbols, the program allows us to read chunks of memory:

Provide address and number of bytes to read>

At this point it would be useful to read the entire file so we have something to work with. Since this is a PIE binary, the base of the file is going to be aligned and equal to the PIE base. First I guessed that it would simply be main - 0x3a9 however this was incorrect. I guessed again main - 0x13a9 and this resulted in reading an ELF header as such:

Provide address and number of bytes to read> 0x55ed193b3000 20
0x55ed193b3000:  7f 45 4c 46 02 01 01 00  00 00 00 00 00 00 00 00 
0x55ed193b3010:  03 00 3e 00

The binary appeared to limit how large the chunk could be so I wrote a small program that read the entire file piece by piece and wrote the output to a file.

After opening the file in Hopper, we need to do a bit of cleaning up to make sure the procedures are loaded. Eventually, we obtain some useful assembly.

At the start of the main routine, we see a strange call that involves the string “flag.txt”. After some reversing, it essentially boils down to the following pseudocode:

FILE *f = open("flag.txt");
int64_t *buf = malloc(0x10);
buf[0] = 1;

// mmap will return a pointer to the new memory region
buf[1] = mmap(0, 0x1000, 1, 2, f, 0);
buf[1] ^= 0x5555555555555555;

So we know that the flag file is memory mapped to some region and we have a buffer (on the heap) that contains a pointer. We also know that there is a pointer to the buffer on the stack since this is a local variable in the main method. At this point we need a stack leak to start reading memory.

Luckly we can use the environ symbol in the libc library to leak a stack pointer.

[3/3] Resolve symbol> environ
environ (buf@0x7ffc36c61d50) = 0x7f37c4a0ef38
Provide address and number of bytes to read> 0x7f37c4a0ef38, 8
0x7f37c4a0ef38:  ffffff98 1f ffffffc6 36 fffffffc 7f 00 00

(the large looking values are just bytes being printed as 4-bit signed bytes, hence the leading 0xff’s)

Using this stack leak, I essentially wrote a program that would traverse the stack backwards and dereference each values as a buffer pointer. Then I tried to XOR the second buffer item and dereference it as another pointer. Eventually, I found the stack offset that corresponded with the buf pointer and I was able to read the flag from the memory mapped region.

comments powered by Disqus