Pwnable.kr - flag


In order to keep this challenge streak alive, I decide to play with another one from pwnable.kr called flag. This time our task is purely reverse enginnering, since we’re only given a binary, with no source code, no listening applications or ssh connections.

Papa brought me a packed present! let's open it.

I started analyzing by running a file command on the binary.

[email protected] ~/programming/pwnable.kr % file flag
flag: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, stripped
[email protected] ~/programming/pwnable.kr % ./flag
I will malloc() and strcpy the flag there. take it.

It shows us that it’s a stripped binary. Running it only prints a message for us, telling how the code works using high level interpretation.

[email protected] ~ % strings flag
$Info: This file is packed with the UPX executable packer http://upx.sf.net $
$Id: UPX 3.08 Copyright (C) 1996-2011 the UPX Team. All Rights Reserved. $

After running strings tool, I’ve noticed these lines - it’s packed with UPX packer. We can use upx tool to unpack the binary into a more readable one. Let’s take a look.

1 [email protected] ~/programming/pwnable.kr % upx -d flag -o flag_               :(
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
-------------------- ------ ----------- -----------
883745 <- 335288 37.94% linux/amd64 flag_

Unpacked 1 file.

Great, now we’re ready to analyze it with gdb.

[email protected] ~/programming/pwnable.kr % gdb flag_
GNU gdb (GDB) 8.0.1
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from flag_...(no debugging symbols found)...done.
(gdb) set disassembly-flavor intel
(gdb) disass main
Dump of assembler code for function main:
0x0000000000401164 <+0>: push rbp
0x0000000000401165 <+1>: mov rbp,rsp
0x0000000000401168 <+4>: sub rsp,0x10
0x000000000040116c <+8>: mov edi,0x496658
0x0000000000401171 <+13>: call 0x402080 <puts>
0x0000000000401176 <+18>: mov edi,0x64
0x000000000040117b <+23>: call 0x4099d0 <malloc>
0x0000000000401180 <+28>: mov QWORD PTR [rbp-0x8],rax
0x0000000000401184 <+32>: mov rdx,QWORD PTR [rip+0x2c0ee5] # 0x6c2070 <flag>
0x000000000040118b <+39>: mov rax,QWORD PTR [rbp-0x8]
0x000000000040118f <+43>: mov rsi,rdx
0x0000000000401192 <+46>: mov rdi,rax
0x0000000000401195 <+49>: call 0x400320
0x000000000040119a <+54>: mov eax,0x0
0x000000000040119f <+59>: leave
0x00000000004011a0 <+60>: ret
End of assembler dump.

Here we have an assembly code of main function. One particular thing that brought my notice is at main+32, where something is passed into rdx. Let’s set a breakpoint line after, at mov+39 and check what rdx is storing.

(gdb) break *0x000000000040118b
Breakpoint 1 at 0x40118b
(gdb) run
Starting program: /home/w3ndige/programming/pwnable.kr/flag_
I will malloc() and strcpy the flag there. take it.

Breakpoint 1, 0x000000000040118b in main ()
(gdb) x/s $rdx
0x496628: "UPX...? sounds like a delivery service :)"

Great, a flag! But after a little bit of playing with it, I’ve found another place where it’s possible to find a flag. Take a look at main+49 and see what’s in eax.

(gdb) break *0x000000000040119a
Breakpoint 1 at 0x40119a
(gdb) run
Starting program: /home/w3ndige/programming/pwnable.kr/flag_
I will malloc() and strcpy the flag there. take it.

Breakpoint 1, 0x000000000040119a in main ()
(gdb) x/s $eax
0x6c96b0: "UPX...? sounds like a delivery service :)"

And here we have the flag, once again.

Keep learning and stay safe! ~ W3ndige