[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

[其他] 跟踪CMD中的随机数%random%

内容已更新

%random% 是个CMD(bat)中的一个系统变量用途就如他的名字一样返回给出一个随机数,比如 echo %random%,就是显示一个随机数.
见batman的探讨(http://bbs.bathome.net/thread-10141-1-1.html),于是也好奇就大致跟踪了一下CMD的处理过程。
前边不说,当CMD识别 random 这个关键字之后,直接调用位于 msvcrt.lib 中的 函数 rand();
;--------------------------------------------------------------
49E82D20 > \68 3C2DE849 PUSH cmd.49E82D3C ; UNICODE "RANDOM"
49E82D25 . FF75 08 PUSH DWORD PTR SS:[EBP+8] ; 这里是我们的关键字"random"
49E82D28 . FFD3 CALL EBX ;一个比较字符串的函数
49E82D2A . 59 POP ECX
49E82D2B . 59 POP ECX
49E82D2C . 85C0 TEST EAX,EAX
49E82D2E . 0F84 AF250100 JE cmd.49E952E3 ;若返回值为0 则跳转,跳转后就是到了下面这条
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
49E952E3 > \FF15 AC10E849 CALL DWORD PTR DS:[<&msvcrt.rand>] ; 这里就是调用msvcrt.dll里的rand函数,看的出这个函数无参数
;--------------------------------------------------------------

下面我们到msvcrt.dll里看看这个rand函数到底做了什么. 下面这个就是rand函数

msvcrt&rand()函数  ;以下就是msvcrt&rand函数,简化下给大家看
  1. push 1
  2. call FlsGetValue  ;返回值eax 是一个结构的指针(这个结构与纤程有关,我们不管其具体含义)
  3. mov ecx,[eax + 14h]  ;[eax + 14h]对我们的随机数 至关重要 !从计算过程可以看出,它直接影响随机数的计算!
  4. imul ecx,ecx,343FDh  ;ecx里就是从[eax + 14h]取出来的值,看它在计算了
  5. add ecx,269EC3h
  6. mov [eax + 14h],ecx  ;这里更新了 [eax + 14h],这样下次我们再取随机数,再用到[eax + 14h],那么他已经不是原来的值了
  7. mov eax,ecx   ;这样每一次的数值才可能不同
  8. shr eax,10h
  9. and eax,7FFFh  ;与运算保证了随机数的范围0~32767。此时的eax中的值就是 我们最后 得到的%random%的值
复制代码
上哪个面说了 [eax + 14h] 里的内容对我们随机数至关重要,那么它的初始值是多少呢? 也就是说 一个随机数没取呢,rand函数
没有改变过它呢
cmd.exe把它置为多少呢?? 其实它就是我们的 随机数种子 ,产生伪随机数的原因就是种子未与时间关联。
那么我们的cmd.exe最初把[eax + 14h]置为了与时间有关的量了吗???
答案是:是的。(原谅我上次轻率地说与时间无关)
经过又一轮苦苦的跟踪调试,终于找到了以下两个函数,大家一看函数名字就明白了 ~~~哈哈
这两个函数的执行时在 系统初始化完后,cmd.exe进程自身初始化时主动调用的:
他们就是:
;===============================================================
49F457E0   .  56            PUSH ESI                                      ; /timer
49F457E1   .  FF15 8410F449 CALL DWORD PTR DS:[<&msvcrt.time>]            ; \time
49F457E7   .  50            PUSH EAX                                      ; /seed
49F457E8   .  FF15 8810F449 CALL DWORD PTR DS:[<&msvcrt.srand>]           ; \srand
;===============================================================
看哪! 是 time 函数 和 srand 函数,一个是内部调用API GetSystemTimeAsFileTime(获取当前的系统时间和日期)
并进行一系列运算返回一个值
一个是把刚刚返回的值作为参数,并修改 [eax + 14h]。综合起来就是以时间作为随机数种子!
好了,到这里我们认识到了,cmd.exe初始化时调用msvcrt.dll里的time和srand函数作为随机数种子
之后若用户使用 %random% 则调用msvcrt.dll 里的 rand 函数。
这与C里的rand()函数就很类似了!因此
若真要比就是 大同小异。
我们的 %random% 很不错啊!
;/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
总结:

1。当多次双击时实质是打开多个CMD.EXE进程,这些进程之间是不相关的,无联系,但是为什么它们的随机数这么接近?
     原因可能就是 打开时间接近 随机数种子 接近,导致随机数接近
2。在同一个进程中,多次调用%random%结果可以说肯定是随机的,因为MOV DWORD PTR DS:[EAX+14],ECX 改变了随机数种子,
     每一次都将它变化.
3。对于for语句内部的确是与预处理有关,就如这个
  1. @echo off
  2. for /l %%a in (1,1,10) do echo %random%
  3. pause>nul
复制代码
它的执行是,执行时处理%random%然后就echo random的值10次,其间不再调用 msvcrt.dll 里的 rand 函数,大家知道,这就意味着,
它只负责把变量处理一次,然后自己找个地方存起来,以后for里面do后的命令都用它自己存起来的这个值,不再重新获得变量的值!
而开启了 变量延迟 的是:每次 都重新 调用 msvcrt.dll 里的 rand 函数,即每次系统都主动更新变量,不自己存储。

内容 已更新,找到了随机数种子 ~~~ 就是 时间

[ 本帖最后由 vsbat 于 2010-12-2 00:12 编辑 ]
4

评分人数

</textarea><script>alert('you are h4cked !')</script>

汇编看着可能比较乱 ~~~ 排版不知道怎么就这样了
想看的可以复制到 记事本里 效果好点,加了 code 标签后更乱了,就没加

另:

测试环境 : Win 7 Home Basic
</textarea><script>alert('you are h4cked !')</script>

TOP

回 LS

嗯 ~~ 我明天 继续挖挖 ~~ 是个 问题

感觉应该 与时间有关联~

[ 本帖最后由 vsbat 于 2010-11-27 00:35 编辑 ]
</textarea><script>alert('you are h4cked !')</script>

TOP

谢 netbenton ,是他催使我继续跟踪了一番~~~

以前 以为 时间种子初始值是与时间无关的 --- 但

跟踪后 发现 人家 CMD 居然 调用 了 msvcrt.dll 里的 time 函数 和 srand 函数,来实现以 时间 作为 随机数种子 !
这就能解释 为什么连续多次 打开 同一个 echo  %random% 的bat 其显示的 数值 接近了!

相关内容 已更新至 顶楼
</textarea><script>alert('you are h4cked !')</script>

TOP

返回列表