Tags: xor re fst

Rating: 5.0

[pwn-re - 0pt.]

*That first flag was a dud, but I think using a similar trick to get the full binary file might be needed here. There is a least one password in there somewhere. Maybe reversing this will give you access to the authenticated area, then you can turn up the heat… literally.*

-----

### *Show me the mon^w code*

At this point, we must already have noticed that directory traversal is possible.

Since we can, let's use Linux's [process information pseudo-filesystem](http://lmgtfy.com/?q=man+5+proc) facility to grab an image of the executable.


% printf "2\n../../../proc/self/exe\n" | nc mngmnt-iface.ctfcompetition.com 1337 > main.elf
% file main.elf
main.elf: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=e78c178ffb1ddc700123dbda1a49a695fafd6c84, not stripped


Fine, the binary wasn't stripped... Let's search for a flag.


% nm main.elf | grep FLAG
0000000041414a40 r _ZL4FLAG
0000000041414a2c r _ZL9FLAG_FILE


The *_ZL4FLAG* symbol is a likely candidate. Let's grab its value.


% gdb -batch -ex 'file ./main.elf' -ex 'x/s _ZL4FLAG'
0x41414a40 <_ZL4FLAG>: "\204\223\201\274\223\260\250\230\227\246\264\224\260\250\265\203\275\230\205\242\263\263\242\265\230\263\257\363\251\230\366\230\254\370\272/bin/sh"


-----

### *await(ASCIIize(&_ZL4LFLAG[0]));*

Setting a watchpoint in gdb fucks up, and the binary wasn't stripped, so let's use a disassembler. It's straightforward enough.

In the *secondary_login* routine, we see how a *password* buffer is filled:
- A call to *scanf* attempts to extract up to 127 characters from the standard input, terminating at the first null.

- Right after this is a loop that XORs each of the previously extracted character with the value 0xFFFFFFC7, then stores the lowest byte back in-place.

- *_ZL4FLAG* and *password* are then compared; the *secondary login* succeeds iif they match.

Since the exclusive-or operation is reversible, we can recover the flag by xor'ing the contents _ZL4FLAG with a truncation of previous value (0xC7).


>>> "".join([chr(ord(x)^int("0xC7", 16)) for x in list('\204\223\201\274\223\260\250\230\227\246\264\224\260\250\265\203\275\230\205\242\263\263\242\265\230\263\257\363\251\230\366\230\254\370\272/bin/sh')]).split("}")[0]+'}'