Description: You’ll have to “dribble” some information out for this one…
Location - dribbles-c4d3cee3.challenges.bsidessf.net:9999
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>
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 = 1; // mmap will return a pointer to the new memory region buf = mmap(0, 0x1000, 1, 2, f, 0); buf ^= 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
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.