<?xml version="1.0" encoding="utf-8"?> 伪随机数的爆破–2

伪随机数的爆破–2

目录

  • 1. 简介
  • 2. 具体实现
  • 3. 总结

1 简介

php中的mt_rand是采用梅森旋转算法MT19937,但在php 7.1.0之前的版本中,其实现的不是标准算法,造成容易猜解。可以参考php里的随机数这篇文章。还有官方文档的changelog。并且已经存在很多工具用来爆破种子,例如著名的php_mt_seed。

这里我参考了php_mt_seed文章中引用的基于CUDA框架的爆破算法,自己稍作修改,可以看到用GPU爆破比cpu的速度要快很多。当然,这取决与你的显卡和CPU。

原始的cuda代码在这里mt_rand.cu

2 具体实现

由于要用clojure的gpu相关的库,要添加依赖到deps.edn:

{:deps {uncomplicate/neanderthal {:mvn/version "0.22.0"}}}

然后是gpu执行的设备代码, mt_rand_me.cu:

typedef unsigned int uint32_t;#define MT_N          (624)
#define N             MT_N                 /* length of state vector */
#define M             (397)                /* a period parameter */
#define hiBit(u)      ((u) & 0x80000000U)  /* mask all but highest   bit of u */
#define loBit(u)      ((u) & 0x00000001U)  /* mask all but lowest    bit of u */
#define loBits(u)     ((u) & 0x7FFFFFFFU)  /* mask     the highest   bit of u */
#define mixBits(u, v) (hiBit(u)|loBits(v)) /* move hi bit of u to hi bit of v */
#define twist(m,u,v)  (m ^ (mixBits(u,v)>>1) ^ ((uint32_t)(-(uint32_t)(loBit(u))) & 0x9908b0dfU))#define PHP_MT_RAND_MAX ((long) (0x7FFFFFFF)) /* (1<<31) - 1 */
#define RAND_RANGE(__n, __min, __max, __tmax) ((__min) + (long) ((double) ( (double) (__max) - (__min) + 1.0) * ((__n) / ((__tmax) + 1.0))))/*
   Calculate mt_rand after some amount of steps.
   Due to memory optimization 'step' must statisfy condition:
       step < N - M
*/
__device__
uint32_t mt_rand( uint32_t seed, int step )
{uint32_t p0,p1,pM,cs;   // cs - value current state array cellint i; init stepcs = seed & 0xffffffffU;for( i = 1; i <= step; i++ )   // corect is ( i = 1; i < N; i++ )cs = ( 1812433253U * ( cs ^ (cs >> 30) ) + i ) & 0xffffffffU;p0 = cs;cs = ( 1812433253U * ( cs ^ (cs >> 30) ) + i ) & 0xffffffffU;p1 = cs;for( i = step + 2; i <= step + M; i++ )   // corect is ( i = 1; i < N; i++ )cs = ( 1812433253U * ( cs ^ (cs >> 30) ) + i ) & 0xffffffffU;pM = cs;//for( i = 1; i <= step + M; i++ )   // corect is ( i = 1; i < N; i++ )//    cs = ( 1812433253U * ( cs ^ (cs >> 30) ) + i ) & 0xffffffffU;//    if( i == step + 0 ) p0 = cs;//    if( i == step + 1 ) p1 = cs;//    if( i == step + M ) pM = cs;//} reload (twist) stepuint32_t x = twist( pM, p0, p1 );x ^= x >> 11;x ^= (x << 7) & 0x9d2c5680U;x ^= (x << 15) & 0xefc60000U;x ^= x >> 18;x = (long)(x >> 1);return x;
}__device__
uint32_t mt_rand_mm( uint32_t seed, int step, int min, int max )
{return RAND_RANGE( mt_rand( seed, step ), min, max, PHP_MT_RAND_MAX );
}// 上面的代码直接取自mt_rand.cuextern "C"
__global__
void mt_rand_find(uint32_t sseed, //测试的种子uint32_t* values, // 已知的随机数序列uint32_t length, // 已知随机数序列的长度int min, // 最小值int max, // 最大值bool *found, // 是否找到的标记uint32_t* sols // 用于保存找到的seed结果)
{uint32_t gid = blockDim.x * blockIdx.x + threadIdx.x;// 这里会有很多个GPU线程同时执行,所以把结果保存在sols数组中,每个线程一个数组项// gid相当于线程顺序id,每个线程测试一个seed// 整个函数相当于多个GPU线程同时对[sseed, sseed+总的线程数量]范围内的数字作为种子进行爆破uint32_t seed = sseed + gid;sols[ gid ] = 0;for(int i = 0; i < length; i++){uint32_t x = mt_rand_mm(seed, i, min, max);if(!(values[i] == x)) return;}*found = true;        // indicate that we found solutionsols[ gid ] = seed;   // here is solution
}//只用一个线程,用于测试rand
extern "C"
__global__
void mt_rand_one( uint32_t seed, int step, int min, int max, uint32_t* ret)
{uint32_t x = mt_rand_mm( seed, step, min, max);*ret = x;
}

最后是clojure的host代码:

(require '[uncomplicate.clojurecuda.core :refer :all])
(require '[uncomplicate.commons.core :refer :all]);; 初始化设备
(init)
(device-count)
;; => 1
;; 显卡个数;; 选择gpu和上下文,device的参数为显卡id
(def my-gpu (device 0))
(def ctx (context my-gpu));; 设置当前上下文
(current-context! ctx)
(def php-rand (slurp "./mt_rand_me.cu"));; 编译并导出函数,本机要安装CUDA toolkit
;; 具体过程参考https://dragan.rocks/articles/18/Interactive-GPU-Programming-1-Hello-CUDA
(def rand-program (compile! (program php-rand)))
(def rand-module (module rand-program))
(def mt-rand-find(function rand-module "mt_rand_find"))
(def mt-rand-one(function rand-module "mt_rand_one"))(def threads 2000000) ;; GPU线程数量
(def size threads) ;; 保存GPU计算结果的数组大小,等同于GPU线程数量(def bool-size 1) ;; boolean类型的长度,c内存表示
(def uint-size 4) ;; uint 类型的长度,c内存表示
(def max-rand (int (dec (Math/pow 2 31))))(defn find-rand-one-block[n values & [opts]](let [found (mem-alloc bool-size)_ (memcpy-host! (byte-array [0]) found)min (get opts :min 0)max (get opts :max max-rand);; 复制values到gpu内存values-len (count values)values-match (mem-alloc (* uint-size values-len))_ (memcpy-host! (int-array values) values-match);; 分配保存结果的数组的内存sols-len (* size uint-size)sols (mem-alloc sols-len)_ (launch! mt-rand-find (grid-1d size)(parameters nvalues-matchvalues-lenminmaxfoundsols))ret-found (-> (memcpy-host! found (byte-array 1))first)ret-sols (memcpy-host! sols (int-array size))];; 释放GPU内存(release sols)(release values-match)(release found)(when-not (zero? ret-found)(println "block:" n "ret found:" ret-found)(filter (comp not zero?) ret-sols))))(def max-blocks (/ 0xffffffff (+ size 1)))
(defn find-all-seed"在32位地址空间中寻找匹配vals序列的种子"[vals & [opts]](doseq [n (range (int (Math/ceil max-blocks)))](let [rs (find-rand-one-block (* size n) vals opts)](when rs(doseq [r rs](println "found:" (Integer/toUnsignedString r)))))))(time (find-all-seed [617664816]))
;; block: 28000000 ret found: 1
;; found: 28833322
;; block: 368000000 ret found: 1
;; found: 368690622
;; block: 2398000000 ret found: 1
;; found: 2398389484
;; "Elapsed time: 15790.4927 msecs"(defn rand-one[seed & [opts]](let [step (get opts :step 0)ret (mem-alloc 50)min (get opts :min 0)max (get opts :max max-rand)_ (launch! mt-rand-one (grid-1d 1)(parameters seed step min max ret))ret-sols (memcpy-host! ret (int-array 1))](release ret)(first ret-sols)))(comment;; 测试是否和php中生成的结果一致(rand-one 1234 {:step 0})
;; => 1741177057(rand-one 1234 {:step 1})
;; => 1068724585;; 可以看到和php中生成的结果一致,*注意*,在php7.1以上mt_srand用MT_RAND_PHP参数,;; 用于生成和php5采用的mt_rand算法一致的结果
;; php -r 'mt_srand(1234,MT_RAND_PHP); echo mt_rand()."---".mt_rand(). "\n";'
;; 1741177057---1068724585);; 清理环境
(release rand-module)
(release rand-program)
(release ctx)

php_mt_seed的结果:

$ time php_mt_seed 617664816
Found 3, trying 3690433088 - 3690987519, speed 112249734 seeds per second
seed = 28833322seed = 368690622seed = 2398389484Found 3
Found 3, trying 4261412864 - 4294967295, speed 112251741 seeds per second
real    0m38.282s
user    0m0.000s
sys     0m0.000s

下面测试随机字符串序列,如下php代码:

<?php
function randStr($l=4){$ret="";$chars="qwertyuiopasdfghjklzxcvbnm1234567890QWERTYUIOPASDFGHJKLZXCVBNM";for($i=0;$i<$l;$i++)    $ret.=$chars[mt_rand(0,strlen($chars))];return $ret;
}mt_srand( 6688991, MT_RAND_PHP );
echo randStr(5);
?>

randStr结果是:A4MFO

现在根据randStr的结果猜解出seed,先用clojure来实现:

;; 首先要获得随机序列转换为字符串的转换表,才能把字符串转换回随机数序列。
;; 这里假定已经有了这个表
(def chars "qwertyuiopasdfghjklzxcvbnm1234567890QWERTYUIOPASDFGHJKLZXCVBNM")(defn rand-strs->rand-seq"把随机结果字符串转换回随机数字序列"[strs](mapv #(->> (str %1)(.indexOf chars))strs));; randStr结果
(def result "A4MFO")(def rand-seq (rand-strs->rand-seq result))
rand-seq
;; => [46 29 61 49 44](def max-r (count chars))
max-r
;; => 62(time (find-all-seed rand-seq {:max max-r}))
;; block: 6000000 ret found: 1
;; found: 6688991
;; block: 200000000 ret found: 1
;; found: 201323601
;; block: 3658000000 ret found: 1
;; found: 3658569207
;; block: 3892000000 ret found: 1
;; found: 3893347456
;; "Elapsed time: 20043.783126 msecs"

随着要测试的序列增大,速度会降低,而且max值比较小,会有很多个符合结果序列的种子。

下面测试php_mt_seed的效果:

$ time php_mt_seed 46 46 0 62 29 29 0 62 61 61 0 62 49 49 0 62 44 44 0 62
Found 3, trying 3690Pattern: EXACT-FROM-63 EXACT-FROM-63 EXACT-FROM-63 EXACT-FROM-63 EXACT-FROM-63seed = 6688991seed = 201323601seed = 3658569207seed = 3893347456Found 4
Found 4, trying 4261412864 - 4294967295, speed 107807449 seeds per second
real    0m39.848s
user    0m0.000s
sys     0m0.000s

可以看到就算测试的序列增加,php_mt_seed的速度也比较稳定,可能它是在一次rand计算中比较整个序列的,所以不管序列有多长,对速度没什么影响,而我这里的GPU代码,序列中每个值的比较都要调用mt_rand,而mt_rand再根据step去计算结果,因此mt_rand_find的执行时间会随着序列长度的增加而增加,只做个简单的比较,这里就不再优化算法实现了。

3 总结

可以看到GPU的速度非常快,对于一个数字的计算,本机测试大概16秒,而php_mt_seed大概要38秒。主要是因为GPU的线程数量很多,示例中开了2000000线程,我只是无脑开,对于CUDA编程没有研究过,通过这次实验,体验下GPU编程。

作者: ntestoc

Created: 2019-03-17 周日 09:00

转载于:https://www.cnblogs.com/ntestoc/p/10535488.html

伪随机数的爆破--2相关推荐

  1. ctfshow-web入门-爆破wp

    前置软件 最好是用火狐浏览器,FoxyProxy插件,burpsuite,ctfshow给的字典附件 如何配置的问题去别的博客搜,都有. web21(爆破base64加密后的账号密码) 这里访问题目的 ...

  2. GIVE_A_TRY.exe 逆向(NCK逆向初级第9,10,11课作业)

    这个程序好像是一道CTF的题,对我这样的新手来说难度很大,解题过程中遇到了不少坑,还学到了新的反调试技巧.下面我将记录下我逆向这个程序的过程. 一.去花指令,过反调试,分析TLS回调函数功能 这个程序 ...

  3. PHP的伪随机数爆破

    基础介绍 文中若有不当之处还请各位大佬多多点评 我的博客:https://whoamianony.top/ 公众号:WHOAMIAnony 随机数并不随机 首先需要声明的是,计算机不会产生绝对随机的随 ...

  4. php伪随机数爆破种子

    一.前言 ctf中有很多php随机数的题目,考察方式一般如下: 给定一个随机数,求产生随机数的种子. 做这种题,先了解点知识 二.基础知识 php产生随机数 php 通过 以下两个函数产生随机数 mt ...

  5. ctfshow 爆破(web入门)

    目录 web21 web22 web23 web24 web25 web26 web27 web28 web21 打开题目显示要登陆密码 随便输入123,123抓个包试试,发现Authorizatio ...

  6. python求梅森尼数_谈谈梅森旋转:算法及其爆破

    https://liam.page/https://liam.page/https://liam.page/ 现代编程语言,大都在标准库中包含了随机库.例如,C++ 在 C++11 标准中添加了 ra ...

  7. ctfshow 爆破 web21-web28

    爆破 爆破考察手段 burp intruder的使用 编写脚本寻找满足条件的解 伪随机 web21 burp抓包,发送到intruder模块,利用题中给出的脚本进行爆破,注意通过payload加工模块 ...

  8. 通过CTFShow例题掌握爆破方法

    大家好,这里是KOKO师傅~ 之前我们以CTFShow的例题对信息收集类WEB题目进行了针对练习,今天我们继续进行爆破模块的针对练习! 爆破 1)最基本的爆破(web21) 这道题是很基本的爆破题目. ...

  9. CTF_Web:php伪随机数mt_rand()函数+php_mt_seed工具使用

    CTF_Web:php伪随机数mt_rand函数漏洞 0x00 问题描述 0x01 mt_rand函数 0x02 CTF例题 0x03 php_mt_seed工具使用 0x04 参考文章 0x00 问 ...

  10. CTFshow—爆破、命令执行

    Web入门: 爆破: web24伪随机数 通过mt_srand()分发种子(播种),有了种子后随机数也就确定了(随机就那一组了,因此说伪随机) mt_scrand() //播种 Mersenne Tw ...

最新文章

  1. linux安装emc的多路径软件,linux (centos)安装EMCPower多路径软件
  2. 德鲁克的17条思想精髓,读懂管理的本质
  3. C# 读写文件方法总结
  4. MySQL会回收使用中的连接吗_Node.js实现mysql连接池使用事务自动回收连接的方法示例...
  5. Hadoop MapReduce容错性分析
  6. oracle查询执行过的sql语句,如何查询已经执行过的SQL语句曾经的执行花费时间
  7. JPA –我应该成为懒惰的极端主义者吗?
  8. 为什么写C语言弹不出窗口,居然还有SB说C写不出窗口的..
  9. mvc 事务层切换数据源_Mvc 与 Flux 与 Redux的一些思考
  10. ucosii中消息队列、消息邮箱、信号量的区别
  11. 基于JavaScript实现配对游戏
  12. Activiti进阶(七)——排他网关(ExclusiveGateWay)
  13. 如何用prometheus监控k8s集群中业务pod的metrics
  14. DataGame : AIIA 2019
  15. 慕课软件质量保证与测试(第六章.课后作业)
  16. es配置中文和拼音分词器
  17. SLAM 中evo的使用(二) (evaluation of odometry) evo_traj/ape rpe/evo_ape说明与示例
  18. linux wrf 系统_WRF在Linux环境下的安装
  19. 用计算机语言说一局情话,计算机中的情话
  20. [论文阅读笔记]Deep Neural Networks are Easily Fooled:High Confidence Predictions for Unrecognizable Images

热门文章

  1. js 实现表格合并单元格
  2. 如何根据经纬度查询地理位置
  3. Google Chrome 启动 0x0000005 崩溃问题的解决方法
  4. 13个Python必备的知识,建议收藏
  5. Excel2016 保存\复制 卡死问题解决
  6. matlab simulink仿真实现电力电子的整流电路
  7. css 设置背景图一半_CSS背景颜色 背景图片 居中 重复 固定样式background经验篇
  8. Google离去,百度就能制衡?
  9. MapReduce实现商品推荐算法(用户购买向量*商品同现矩阵)
  10. 网站建设以后如何处理死链接页面