Observations
Let’s take a look at the binary.
$ file main32
main32: ELF 32-bit LSB executable, Intel 80386, version 1 (GNU/Linux), statically linked, stripped
Nothing special here. Let’s try our previous strategy by taking a look at the strings. But unfortunately it’s not that simple as we see from the truncated output below.
$ strings main32
;;pa
\ A}a
`'<p
$< N
yB88p
6 zN
-99
O```
^l*O
UPX!
UPX!
But wait there’s something at the end “UPX!”. This is a hint in itself for someone with previous experience. Now let’s assume we don’t know anything.
Taking a look at the hint, we see another usefull tool calle binwalk
. Examining the binary again using binwalk
, which is a really great tool to keep around for CTFs.
We come across some interesting stuff…
$ binwalk main32
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
0 0x0 ELF, 32-bit LSB executable, Intel 80386, version 1 (GNU/Linux)
249200 0x3CD70 Copyright string: "Copyright (C) 1996-2017 the UPX Team. All Rights Reserved. $"
Besides the ELF binary we see that we have some ‘UPX’ stuff. So what’s this? A quick google and you will find that UPX is a free packer for executables. What the hell is a packer? It’s kind of a fancy word for a compressor. But it’s a special kind. The packed executable is capable of unpacking itself into memory. That’s why if you try to run the executable, it runs perfectly fine. What this means is that when we try running strings on the executable it shows us the strings from the packed file. So let’s unpack this executable. You can get the utility to unpack from here.
Let’s unpack the file.
$ upx -d main32
Ultimate Packer for eXecutables
Copyright (C) 1996 - 2017
UPX 3.94 Markus Oberhumer, Laszlo Molnar & John Reiser May 12th 2017
File size Ratio Format Name
-------------------- ------ ----------- -----------
657636 <- 275636 41.91% linux/i386 main32
Unpacked 1 file.
Now lets run “strings”
$ strings main32 | grep 'flag'
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
<flag_here>
_dl_x86_hwcap_flags
_dl_stack_flags
_dl_x86_cap_flags
And that’s how we solve this level.