伪随机数的爆破--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相关推荐
- ctfshow-web入门-爆破wp
前置软件 最好是用火狐浏览器,FoxyProxy插件,burpsuite,ctfshow给的字典附件 如何配置的问题去别的博客搜,都有. web21(爆破base64加密后的账号密码) 这里访问题目的 ...
- GIVE_A_TRY.exe 逆向(NCK逆向初级第9,10,11课作业)
这个程序好像是一道CTF的题,对我这样的新手来说难度很大,解题过程中遇到了不少坑,还学到了新的反调试技巧.下面我将记录下我逆向这个程序的过程. 一.去花指令,过反调试,分析TLS回调函数功能 这个程序 ...
- PHP的伪随机数爆破
基础介绍 文中若有不当之处还请各位大佬多多点评 我的博客:https://whoamianony.top/ 公众号:WHOAMIAnony 随机数并不随机 首先需要声明的是,计算机不会产生绝对随机的随 ...
- php伪随机数爆破种子
一.前言 ctf中有很多php随机数的题目,考察方式一般如下: 给定一个随机数,求产生随机数的种子. 做这种题,先了解点知识 二.基础知识 php产生随机数 php 通过 以下两个函数产生随机数 mt ...
- ctfshow 爆破(web入门)
目录 web21 web22 web23 web24 web25 web26 web27 web28 web21 打开题目显示要登陆密码 随便输入123,123抓个包试试,发现Authorizatio ...
- python求梅森尼数_谈谈梅森旋转:算法及其爆破
https://liam.page/https://liam.page/https://liam.page/ 现代编程语言,大都在标准库中包含了随机库.例如,C++ 在 C++11 标准中添加了 ra ...
- ctfshow 爆破 web21-web28
爆破 爆破考察手段 burp intruder的使用 编写脚本寻找满足条件的解 伪随机 web21 burp抓包,发送到intruder模块,利用题中给出的脚本进行爆破,注意通过payload加工模块 ...
- 通过CTFShow例题掌握爆破方法
大家好,这里是KOKO师傅~ 之前我们以CTFShow的例题对信息收集类WEB题目进行了针对练习,今天我们继续进行爆破模块的针对练习! 爆破 1)最基本的爆破(web21) 这道题是很基本的爆破题目. ...
- 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 问 ...
- CTFshow—爆破、命令执行
Web入门: 爆破: web24伪随机数 通过mt_srand()分发种子(播种),有了种子后随机数也就确定了(随机就那一组了,因此说伪随机) mt_scrand() //播种 Mersenne Tw ...
最新文章
- linux安装emc的多路径软件,linux (centos)安装EMCPower多路径软件
- 德鲁克的17条思想精髓,读懂管理的本质
- C# 读写文件方法总结
- MySQL会回收使用中的连接吗_Node.js实现mysql连接池使用事务自动回收连接的方法示例...
- Hadoop MapReduce容错性分析
- oracle查询执行过的sql语句,如何查询已经执行过的SQL语句曾经的执行花费时间
- JPA –我应该成为懒惰的极端主义者吗?
- 为什么写C语言弹不出窗口,居然还有SB说C写不出窗口的..
- mvc 事务层切换数据源_Mvc 与 Flux 与 Redux的一些思考
- ucosii中消息队列、消息邮箱、信号量的区别
- 基于JavaScript实现配对游戏
- Activiti进阶(七)——排他网关(ExclusiveGateWay)
- 如何用prometheus监控k8s集群中业务pod的metrics
- DataGame : AIIA 2019
- 慕课软件质量保证与测试(第六章.课后作业)
- es配置中文和拼音分词器
- SLAM 中evo的使用(二) (evaluation of odometry) evo_traj/ape rpe/evo_ape说明与示例
- linux wrf 系统_WRF在Linux环境下的安装
- 用计算机语言说一局情话,计算机中的情话
- [论文阅读笔记]Deep Neural Networks are Easily Fooled:High Confidence Predictions for Unrecognizable Images