最近在玩系统自带的freecell,XP下它带了1m的开局,但发现为什么总是随机开局都超不过几万,初步怀疑是不是种子有什么问题。
用od加载,定位rand函数,呵呵,原来是程序与dll之间的衔接有点小问题:
代码:
01003153 /$ 56 push esi 01003154 |. 6A 00 push 0 ; /timer = NULL 01003156 |. FF15 E4110001 call dword ptr [<&msvcrt.time>] ; \time 0100315C |. 50 push eax ; /seed 0100315D |. FF15 E8110001 call dword ptr [<&msvcrt.srand>] ; \srand,这句是初始化随机种子 01003163 |. 8B35 EC110001 mov esi, dword ptr [<&msvcrt.rand>] ; msvcrt.rand 01003169 |. 59 pop ecx 0100316A |. 59 pop ecx 0100316B |. FFD6 call esi ; [rand,连续三次计算随机数,看起来没什么问题 0100316D |. FFD6 call esi 0100316F |> FFD6 call esi 01003171 |. 83F8 01 cmp eax, 1 ;是否为0或者是负数 01003174 |.^ 72 F9 jb short 0100316F ;不符合要求则继续rand 01003176 |. 3D 40420F00 cmp eax, 0F4240 ;比较是否大于1M 0100317B |.^ 77 F2 ja short 0100316F 0100317D |. 5E pop esi 0100317E \. C3 retn
代码:
77C071D3 > E8 4D2D0000 call 77C09F25 77C071D8 8B48 14 mov ecx, dword ptr [eax+14] 77C071DB 69C9 FD430300 imul ecx, ecx, 343FD 77C071E1 81C1 C39E2600 add ecx, 269EC3 ; ASCII 02,"漓" 77C071E7 8948 14 mov dword ptr [eax+14], ecx 77C071EA 8BC1 mov eax, ecx 77C071EC C1E8 10 shr eax, 10 77C071EF 25 FF7F0000 and eax, 7FFF ;主要就是这两句,将dword直接截断为word,意味着很大于7fff(32767)的开局不会被随机取到 77C071F4 C3 retn
代码:
77C09F27 56 push esi 77C09F28 57 push edi 77C09F29 FF15 0410BE77 call dword ptr [<&KERNEL32.GetLastErr>; ntdll.RtlGetLastWin32Error 77C09F2F FF35 CCFAC277 push dword ptr [77C2FACC] 77C09F35 8BF8 mov edi, eax 77C09F37 FF15 4410BE77 call dword ptr [<&KERNEL32.TlsGetValu>; kernel32.TlsGetValue 77C09F3D 8BF0 mov esi, eax ;上一行和本行比较关键,取得随机数存放地 77C09F87 57 push edi 77C09F88 FF15 0412BE77 call dword ptr [<&KERNEL32.SetLastErr>; ntdll.RtlSetLastWin32Error 77C09F8E 5F pop edi 77C09F8F 8BC6 mov eax, esi 77C09F91 5E pop esi 77C071D8 8B48 14 mov ecx, dword ptr [eax+14] 77C071DB 69C9 FD430300 imul ecx, ecx, 343FD 77C071E1 81C1 C39E2600 add ecx, 269EC3 ; ASCII 02,"漓" 77C071E7 8948 14 mov dword ptr [eax+14], ecx 77C071EA 8BC1 mov eax, ecx 然后返回
by Fpc