Now moving onto level 4, for the challenges on Chapter 5 from the Practical Binary Analysis book from Dennis Andriesse. Let’s start, as we did for the previous 2 levels.

In this post we’ll walk through lvl4.

Let’s see what hint we get first:

binary@binary-VirtualBox:~/code/chapter5$ ./oracle 3a5c381e40d2fffd95ba4452a0fb4a40 -h

Watch closely while I run

We definitely need to execute this binary to figure out what it does, let’s fire this one up:

binary@binary-VirtualBox:~/code/chapter5/level4$ ./lvl4

binary@binary-VirtualBox:~/code/chapter5/level4$

Apparently it might do nothing, so let’s start looking at the binary information first. We’ll start with readelf and nm to gather a general idea of it:

binary@binary-VirtualBox:~/code/chapter5/level4$ readelf -h -n lvl4

ELF Header:

Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00

Class: ELF64

Data: 2's complement, little endian

Version: 1 (current)

OS/ABI: UNIX - System V

ABI Version: 0

Type: EXEC (Executable file)

Machine: Advanced Micro Devices X86-64

Version: 0x1

Entry point address: 0x400550

Start of program headers: 64 (bytes into file)

Start of section headers: 4464 (bytes into file)

Flags: 0x0

Size of this header: 64 (bytes)

Size of program headers: 56 (bytes)

Number of program headers: 9

Size of section headers: 64 (bytes)

Number of section headers: 29

Section header string table index: 28 Displaying notes found at file offset 0x00000254 with length 0x00000020:

Owner Data size Description

GNU 0x00000010 NT_GNU_ABI_TAG (ABI version tag)

OS: Linux, ABI: 2.6.32 Displaying notes found at file offset 0x00000274 with length 0x00000024:

Owner Data size Description

GNU 0x00000014 NT_GNU_BUILD_ID (unique build ID bitstring)

Build ID: f8785d89a1f11e7b413c08c6176ad1ed7b95ca08

binary@binary-VirtualBox:~/code/chapter5/level4$ nm -D lvl4

w __gmon_start__

U __libc_start_main

U setenv

U __stack_chk_fail

The first piece of data we got, is that apparently this binary will use setenv to do something, that’s one hint. Let’s follow up by taking a look at the strings (I removed a part for readability):

binary@binary-VirtualBox:~/code/chapter5/level4$ strings lvl4

/lib64/ld-linux-x86-64.so.2

libc.so.6

__stack_chk_fail

__libc_start_main

setenv

__gmon_start__

GLIBC_2.4

GLIBC_2.2.5

D$(1

P@UH

TTQ\\]TH

L$(dH3

UH-@

AWAVA

AUATL

[]A\A]A^A_

XaDht-+1432=/as4?0129mklqt!@cnz^

FLAG

;*3$"

GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609

.shstrtab

...

.comment

The two pieces of information here are the FLAG and a random string XaDht-+1432=/as4?0129mklqt!@cnz^ . Curiously, that string with random characters seems have a length of 32 characters. Similarly to the other flags we’ve found.

So we have 3 useful pieces of information:

We know it might call setenv() We found a FLAG string (probably used by setenv()) We found a 32 char string that resembles the flag

Next steps would be to trace what the binary does, for this, we can use strace and/or ltrace to find out more. In this particular case, strace did not produced any particularly useful hint, but this is the output of ltrace:

binary@binary-VirtualBox:~/code/chapter5/level4$ ltrace -i ./lvl4

[0x400579] __libc_start_main(0x4004a0, 1, 0x7ffc86ed9f28, 0x400650 <unfinished ...>

[0x400529] setenv("FLAG", "656cf8aecb76113a4dece1688c61d0e7"..., 1) = 0

[0xffffffffffffffff] +++ exited (status 0) +++

So now looks like we found the flag. That seemed a little straightforward by using the right tools but how did that random string became the flag?

We can disassemble the binary and look close to 0x400529:

400500: 0f b6 14 04 movzx edx,BYTE PTR [rsp+rax*1]

400504: 32 90 d8 06 40 00 xor dl,BYTE PTR [rax+0x4006d8]

40050a: 88 14 04 mov BYTE PTR [rsp+rax*1],dl

40050d: 48 83 c0 01 add rax,0x1

400511: 48 83 f8 20 cmp rax,0x20

400515: 75 e9 jne 400500 <__libc_start_main@plt+0x80>

400517: ba 01 00 00 00 mov edx,0x1

40051c: 48 89 e6 mov rsi,rsp

40051f: bf 00 07 40 00 mov edi,0x400700

400524: e8 37 ff ff ff call 400460 <setenv@plt>

Here were can see that it’s a rolling xor between the string we’ve identified before and the value that [rsp+rax*1] points to in 0x400500. We can see that this will loop until rax == 0x20.

Now that we’ve taken a look into how that random string becomes the flag we can validate if we’re correct:

binary@binary-VirtualBox:~/code/chapter5$ ./oracle 656cf8aecb76113a4dece1688c61d0e7

+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+

| Level 4 completed, unlocked lvl5 |

+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+

Run oracle with -h to show a hint

With the correct flag, and the binary for level 5, now we can move to the next one.