callsite

CSAW CTF Qualifiers 2019

Call me maybe? nc rev.chal.csaw.io 1001

A rev with a nasty binary. There are so many functions. I do not like this binary.

Screenshot of IDA Pro on the callsite binary, with a lot of code and functions.

Static Analysis

After staring at the sea of functions in IDA for a little bit, I gave up and tried dumb things instead.

$ strings callsite | grep flag
flag.txt
WARNING: Unsupported flag value(s) of 0x%x in DT_FLAGS_1.
s->_flags2 & _IO_FLAGS2_FORTIFY
version == NULL || (flags & ~(DL_LOOKUP_ADD_DEPENDENCY | DL_LOOKUP_GSCOPE_LOCK)) == 0
imap->l_type == lt_loaded && (imap->l_flags_1 & DF_1_NODELETE) == 0

Oh neat, flag.txt is a lead. It’s not hard to find the string in IDA, and then follow cross-references to reach the code referencing it.

Screenshot of IDA Pro of part of the callsite binary using flag.txt.

Purely circumstantially, this looks a lot like code we’d like to call to print the flag. Phew! We’ve found the most important lines of assembly from among the hundreds of functions. It appears that there is a comparison between some string and the suspiciously alphanumeric string “aaGr6xly5gT42” before the code to print the flag.

Dynamic Analysis

After trying a bunch of things in gdb I basically just learned that callsite 1234 5678 segfaults while trying to execute the address 0x1234. In addition, there were some suspicious strings to be found in the registers when that segfault happens. (This output is from voltron show reg.)

[ o d I t s z a P c ]
[                   ]
RIP 0000000000001234 | 4....... |
RAX 0000000000000001 | ........ |
RBX 0000000000715580 | .Uq..... | => "aaaj23.Ahui1k"
RBP 00007FFFFFFFDE68 | h....... | => 0x7FFFFFFFE217 => "/home/fidget/portal/callsite"
RSP 00007FFFFFFFDC78 | x....... | => 0x400693 => "1"
RDI 0000000000715580 | .Uq..... | => "aaaj23.Ahui1k"
RSI 0000000000000000 | ........ |
RDX 00007FFFFFFFDC88 | ........ | => "40x200
RCX 0000000000000000 | ........ |
R8  0000000000000000 | ........ |
R9  0000000000000000 | ........ |
R10 0000000000000000 | ........ |
R11 00000000004BA260 | `.K..... |
R12 0000000000407AD0 | .z@..... | => "UH"
R13 0000000000000000 | ........ |
R14 00000000006E4018 | .@n..... | => 0x450830 => "H"
R15 0000000000000000 | ........ |
CS  0033  DS  0000
ES  0000  FS  0000
GS  0000  SS  002B

More in-depth interactive stepping allowed me to determine that the segfaulting instruction was 0x40068f, although this wasn’t actually that useful:

.text:000000000040068F                 call    [rsp+0C8h+var_C0]

However, the function in which this instruction resides disassembles moderately well, and it has a few clues in the form of string literals:

Screenshot of IDA Pro on the subroutine

There’s some "%lx" energy floating around, corroborating how our first argument was interpreted as hexadecimal to obtain an address. As for "aa", which suspiciously appears at the start of the string we saw pointed to by our registers as well as the string literal being compared against, fortenforge figured out that the C crypt function was being called on the second argument we passed to callsite, and the result was this suspicious string. crypt is an ancient DES-based hash function with a salt of exactly two characters, which happened to be aa in this case. So it seems like we should reverse the hash aaGr6xly5gT42 to figure out what the second argument should be.

We fed the hash to hashcat for maybe an hour before fortenforge also realized we could probably just cut the Gordian knot by jumping to the code after the check at 0x400cbb. I did so, and:

$ nc rev.chal.csaw.io 1001
Give me two args, space separated:
400cbb whatever
flag{you_got_the_call_site}
Wrong!

“Wrong” is a social construct, as they say.

(note: the commenting setup here is experimental and I may not check my comments often; if you want to tell me something instead of the world, email me!)