Published in

A bit off

# Practical Binary Analysis: Ch 05 Challenge lvl5

Continuing with the challenges in Chapter 5, Practical Binary Analysis from Dennis Andriesse. Goal is to find a flag that would let us to open the next challenge while techniques being explained so far into the book are applied.

All levels start with a file, and in this case it’s another executable file that we have for level file. Execute the challenge:

`binary@binary-VirtualBox:~/code/chapter5/level5\$ ./lvl5nothing to see here`

That was not that useful no? Using previous level flag and getting some hints this is what we see:

`binary@binary-VirtualBox:~/code/chapter5\$ ./oracle 656cf8aecb76113a4dece1688c61d0e7 -h   Secrets hidden in code unusedThe method of redirection is the key   Static rather than dynamically`

Now we know that most of the binary analysis we’ll have to make is static, and that some how we’ll have to change program execution to give us the flag. Let’s see what else can we find.

`binary@binary-VirtualBox:~/code/chapter5/level5\$ strings lvl5 | more/lib64/ld-linux-x86-64.so.2libc.so.6__printf_chkputs__stack_chk_fail__libc_start_main__gmon_start__GLIBC_2.3.4GLIBC_2.4GLIBC_2.2.5UH-HD\$(1Eev4A6ufH3peHgqfHT\$ HL\$(dH3AWAVAAUATL[]A\A]A^A_key = 0x%08xdecrypted flag = %snothing to see here;*3\$"...`

Running strings on the program shows that there are two of them that we might be interested and refereed to the key, and the flag. Now we’ll have to figure out how to get to them.

We can trace program execution as is, and figure out if we have any helpful information:

`binary@binary-VirtualBox:~/code/chapter5/level5\$ ltrace -i ./lvl5[0x400549] __libc_start_main(0x400500, 1, 0x7fff14981e98, 0x4006f0 <unfinished ...>[0x40050e] puts("nothing to see here"nothing to see here)                                                                        = 20[0xffffffffffffffff] +++ exited (status 1) +++binary@binary-VirtualBox:~/code/chapter5/level5\$`

After using objdump to get the full dump of the binary we can take a look, what’s being executed it’s is:

`0000000000400500 <.text>:  400500:       48 83 ec 08             sub    rsp,0x8  400504:       bf 97 07 40 00          mov    edi,0x400797  400509:       e8 a2 ff ff ff          call   4004b0 <puts@plt>  40050e:       b8 01 00 00 00          mov    eax,0x1  400513:       48 83 c4 08             add    rsp,0x8  400517:       c3                      ret  400518:       0f 1f 84 00 00 00 00    nop    DWORD PTR [rax+rax*1+0x0]  40051f:       00  400520:       31 ed                   xor    ebp,ebp  400522:       49 89 d1                mov    r9,rdx  400525:       5e                      pop    rsi  400526:       48 89 e2                mov    rdx,rsp  400529:       48 83 e4 f0             and    rsp,0xfffffffffffffff0  40052d:       50                      push   rax  40052e:       54                      push   rsp  40052f:       49 c7 c0 60 07 40 00    mov    r8,0x400760  400536:       48 c7 c1 f0 06 40 00    mov    rcx,0x4006f0  40053d:       48 c7 c7 00 05 40 00    mov    rdi,0x400500  400544:       e8 87 ff ff ff          call   4004d0 <__libc_start_main@plt>  400549:       f4                      hlt`

The block of code that starts at 0x4500 it’s pretty simple, prints out the string we’re seeing on the string. There are big pieces of unused code in .text, so we’ll have to read a bit through it.

We know that the challenge will use the strings we got before when printing, and maybe looking into any functions it might be using for printing that content would be useful for us. Let’s take a look at what other information we can collect.

`binary@binary-VirtualBox:~/code/chapter5/level5\$ nm -D lvl5                 w __gmon_start__                 U __libc_start_main                 U __printf_chk                 U puts                 U __stack_chk_fail`

One way that I did proceed on this exercise was looking at the strings being used, and the ones we found earlier. Firing up the binary with gdb, and looking stepping to the functions there is one thing I tried to figure out.

`binary@binary-VirtualBox:~/code/chapter5/level5\$ gdb lvl5GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1Copyright (C) 2016 Free Software Foundation, Inc.License GPLv3+: GNU GPL version 3 or later...(gdb) set disassembly-flavor intel(gdb) b *0x400544Breakpoint 1 at 0x400544(gdb) b *0x400500Breakpoint 2 at 0x400500(gdb) rStarting program: /home/binary/code/chapter5/level5/lvl5Breakpoint 1, 0x0000000000400544 in ?? ()(gdb) cContinuing.Breakpoint 2, 0x0000000000400500 in ?? ()(gdb) ni0x0000000000400504 in ?? ()(gdb) ni(gdb) x/i \$rip=> 0x400504:    mov    edi,0x400797(gdb) x/s \$edi0x400797:       "nothing to see here"(gdb) x/10s 0x400797 - 0x250x400772:       "\002"0x400774:       "key = 0x%08x\n"0x400782:       "decrypted flag = %s\n"0x400797:       "nothing to see here"0x4007ab:       ""0x4007ac:       "\001\033\003;@"0x4007b2:       ""0x4007b3:       ""0x4007b4:       "\a"0x4007b6:       ""`

At 0x400504 we see that the memory address to the string `nothing to see here` is being referenced, so looking a little backwards into that memory address we might be able to see the rest of them. Now we this in mind, we can look into the disassembly of the binary if the other two (0x400774 and 0x400782) are being referenced. Here is where I found them:

`  400620:       53                      push   rbx  400621:       be 74 07 40 00          mov    esi,0x400774  400626:       bf 01 00 00 00          mov    edi,0x1  40062b:       48 83 ec 30             sub    rsp,0x30  40062f:       64 48 8b 04 25 28 00    mov    rax,QWORD PTR fs:0x28  400636:        00 00  400638:       48 89 44 24 28          mov    QWORD PTR [rsp+0x28],rax  40063d:       31 c0                   xor    eax,eax  40063f:       48 b8 10 60 21 33 15    movabs rax,0x6223331533216010  400646:       33 23 62  400649:       c6 44 24 20 00          mov    BYTE PTR [rsp+0x20],0x0  40064e:       48 89 04 24             mov    QWORD PTR [rsp],rax  400652:       48 b8 45 65 76 34 41    movabs rax,0x6675364134766545  400659:       36 75 66  40065c:       48 89 44 24 08          mov    QWORD PTR [rsp+0x8],rax  400661:       48 b8 17 67 75 64 10    movabs rax,0x6570331064756717  400668:       33 70 65  40066b:       48 89 44 24 10          mov    QWORD PTR [rsp+0x10],rax  400670:       48 b8 18 35 76 62 11    movabs rax,0x6671671162763518  400677:       67 71 66  40067a:       48 89 44 24 18          mov    QWORD PTR [rsp+0x18],rax  40067f:       8b 1c 25 40 05 40 00    mov    ebx,DWORD PTR ds:0x400540  400686:       31 c0                   xor    eax,eax  400688:       89 da                   mov    edx,ebx  40068a:       e8 51 fe ff ff          call   4004e0 <__printf_chk@plt>  40068f:       48 8d 54 24 20          lea    rdx,[rsp+0x20]  400694:       48 89 e0                mov    rax,rsp  400697:       66 0f 1f 84 00 00 00    nop    WORD PTR [rax+rax*1+0x0]  40069e:       00 00  4006a0:       31 18                   xor    DWORD PTR [rax],ebx  4006a2:       48 83 c0 04             add    rax,0x4  4006a6:       48 39 d0                cmp    rax,rdx  4006a9:       75 f5                   jne    4006a0 <__printf_chk@plt+0x1c0>  4006ab:       31 c0                   xor    eax,eax  4006ad:       48 89 e2                mov    rdx,rsp  4006b0:       be 82 07 40 00          mov    esi,0x400782  4006b5:       bf 01 00 00 00          mov    edi,0x1  4006ba:       e8 21 fe ff ff          call   4004e0 <__printf_chk@plt>  4006bf:       31 c0                   xor    eax,eax  4006c1:       48 8b 4c 24 28          mov    rcx,QWORD PTR [rsp+0x28]  4006c6:       64 48 33 0c 25 28 00    xor    rcx,QWORD PTR fs:0x28  4006cd:       00 00`

If we set any breakpoint in this section of code it would never be executed, so we need to find a way to redirect the execution flow here. At 0x40053d we see that the start of the function is being passed to __libc_start_main, so we can replace that with the address we want:

`(gdb) rStarting program: /home/binary/code/chapter5/level5/lvl5Breakpoint 1, 0x0000000000400544 in ?? ()(gdb) x/10i \$rip - 0x15   0x40052f:    mov    r8,0x400760   0x400536:    mov    rcx,0x4006f0   0x40053d:    mov    rdi,0x400500=> 0x400544:    call   0x4004d0 <__libc_start_main@plt>   0x400549:    hlt   0x40054a:    nop    WORD PTR [rax+rax*1+0x0]   0x400550:    mov    eax,0x60104f   0x400555:    push   rbp   0x400556:    sub    rax,0x601048   0x40055c:    cmp    rax,0xe(gdb) set \$rdi = 0x400620(gdb) x/10i \$rip=> 0x400620:    push   rbx   0x400621:    mov    esi,0x400774   0x400626:    mov    edi,0x1   0x40062b:    sub    rsp,0x30   0x40062f:    mov    rax,QWORD PTR fs:0x28   0x400638:    mov    QWORD PTR [rsp+0x28],rax   0x40063d:    xor    eax,eax   0x40063f:    movabs rax,0x6223331533216010   0x400649:    mov    BYTE PTR [rsp+0x20],0x0   0x40064e:    mov    QWORD PTR [rsp],rax(gdb) cContinuing.key = 0x00400500decrypted flag = ea36cbE`64A35fb5d60e06bb1f[Inferior 1 (process 29664) exited normally]`

Now it does seems we’re getting somewhere, but still the flag does not seems valid, that could mean we have an incorrect key. A deeper look into the function we’re not executing could int us where the flag seems to be decoded and how they key is actually used.

`  400694:       48 89 e0                mov    rax,rsp  400697:       66 0f 1f 84 00 00 00    nop    WORD PTR [rax+rax*1+0x0]  40069e:       00 00  4006a0:       31 18                   xor    DWORD PTR [rax],ebx  4006a2:       48 83 c0 04             add    rax,0x4  4006a6:       48 39 d0                cmp    rax,rdx  4006a9:       75 f5                   jne    4006a0 <__printf_chk@plt+0x1c0>`

At 0x400694 the encoded flag pointed by rax and then there is a loop xoring each byte with the content of ebx. The value that’s being stored in ebx is 0x48, which is loaded at 0x40067f. It points to 0x00400500

One of the hints is that `The method of redirection is the key` , so if we wanted to point the execution of the binary to the address that would print the key, we could try to rewrite that value and patch the binary as we’ve done before.

We can use xxd to dump the challenge contents and then look for the sequence of bytes we need to replace `48 c7 c7 00 05 40 00` :

`00000500: 4883 ec08 bf97 0740 00e8 a2ff ffff b801  H......@........00000510: 0000 0048 83c4 08c3 0f1f 8400 0000 0000  ...H............00000520: 31ed 4989 d15e 4889 e248 83e4 f050 5449  1.I..^H..H...PTI00000530: c7c0 6007 4000 48c7 c1f0 0640 0048 c7c7  ..`.@.H....@.H..00000540: 0005 4000 e887 ffff fff4 660f 1f44 0000  ..@.......f..D..00000550: b84f 1060 0055 482d 4810 6000 4883 f80e  .O.`.UH-H.`.H...00000560: 4889 e576 1bb8 0000 0000 4885 c074 115d  H..v......H..t.]`

We correct the address, patch the binary and now we can validate our patch with object dump, it should looks similar

`  40052f:       49 c7 c0 60 07 40 00    mov    r8,0x400760  400536:       48 c7 c1 f0 06 40 00    mov    rcx,0x4006f0  40053d:       48 c7 c7 20 06 40 00    mov    rdi,0x400620  400544:       e8 87 ff ff ff          call   4004d0 <__libc_start_main@plt>`

For confirming this value we can use gdb again:

`binary@binary-VirtualBox:~/code/chapter5/level5\$ gdb fixed(gdb) set disassembly-flavor intel(gdb) b *0x4006a0Breakpoint 1 at 0x4006a0(gdb) rStarting program: /home/binary/code/chapter5/level5/fixedkey = 0x00400620Breakpoint 1, 0x00000000004006a0 in ?? ()(gdb) x/10i \$rip=> 0x4006a0:    xor    DWORD PTR [rax],ebx   0x4006a2:    add    rax,0x4   0x4006a6:    cmp    rax,rdx   0x4006a9:    jne    0x4006a0   0x4006ab:    xor    eax,eax   0x4006ad:    mov    rdx,rsp   0x4006b0:    mov    esi,0x400782   0x4006b5:    mov    edi,0x1   0x4006ba:    call   0x4004e0 <__printf_chk@plt>   0x4006bf:    xor    eax,eax(gdb) x/x \$ebx0x400620:       0x53(gdb) del breakpoints 1(gdb) cContinuing.decrypted flag = 0fa355cbec64a05f7a5d050e836b1a1f[Inferior 1 (process 29928) exited normally]`

By looking at this we can see that the xor value is the byte located at 0x400620: `400620: 53 push rbx` . Now we pass the flag to unlock the next level:

`binary@binary-VirtualBox:~/code/chapter5\$ ./oracle 0fa355cbec64a05f7a5d050e836b1a1f+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+| Level 5 completed, unlocked lvl6         |+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Run oracle with -h to show a hint`

And now we can move along to the next level.

--

--

--

## More from A bit off

A little bit of everything cybersecurity related. Experiments, tutorials and challenges

## Pablo Ramos

Infosec Researcher, traveller, kitesurfing enthusiast. I just like to think outloud