接  xx学OD -- 内存断点(上)

0040140C  /$  60           PUSHAD

0040140D  |.  6A 00         PUSH 0     ; /RootPathName = NULL

0040140F  |.  E8 B4000000   CALL <JMP.&KERNEL32.GetDriveTypeA> ; \

                           :调用GetDriveTypeA得到本程序所在的盘的类型  放入eax这里是03

00401414  |. A2 EC334000  MOV BYTE PTR DS:[4033EC],Al  知道刚才的03怎么来的了

00401419  |. 6A 00         PUSH 0  ; /pFileSystemNameSize = NULL

0040141B  |.  6A 00         PUSH 0    ; |pFileSystemNameBuffer = NULL

0040141D  |.  6A 00         PUSH 0   ; |pFileSystemFlags = NULL

0040141F  |.  6A 00         PUSH 0     ; |pMaxFilenameLength = NULL

00401421  |.  6A 00         PUSH 0  ; |pVolumeSerialNumber = NULL

00401423  |.  6A 0B         PUSH 0B   ; |MaxVolumeNameSize = B (11.)

00401425 |.689C334000PUSHCrackHea.0040339C |VolumeNameBuffer= CrackHea.0040339C

0040142A  |.  6A 00         PUSH 0  ; |RootPathName = NULL

0040142C  |.  E8 A3000000   CALL <JMP.&KERNEL32.GetVolumeInformation>; 

;调用GetVolumeInformationA函数获得该盘的卷标放入VolumeNameBuffer(40339C)

00401431  |.  8D35 9C334000 LEAESI,DWORD PTR DS:[40339C]地址40339C送到ESI

00401437  |.  0FB60D EC3340>  MOVZX  ECX,  BYTE PTR   DS:[4033EC]     无符号扩展ECX=0000 0003

0040143E  |.  33FF          XOR EDI,EDI

 

00401440  |>  8BC1          MOV EAX,ECX

00401442  |.  8B1E MOV EBX,  DWORD PTR   DS:[ESI]    把卷标作为数值送到EBX(584E4957)

00401444  |.  F7E3          MUL EBX ;  (EDX,EAX) =  EAX*EBX

00401446  |.  03F8          ADD EDI,EAX  放到EDI

00401448  |.  49            DEC ECX      ;ECX-1

00401449  |.  83F9 00       CMP ECX,0    ;循环ECX(3次)

0040144C  |.^ 75 F2         JNZ SHORT CrackHea.00401440

 

0040144E  |.  893D 9C334000 MOV DWORD PTR DS:[40339C], EDI

把计算后值送内存地址40339C, 这就是我们后来在ESI中看到的值

00401454  |.  61            POPAD

00401455  \.  C3            RETN

 分析到这可以得知基本算法是这样的:

先用GetDriveTypeA函数获取磁盘类型参数(参数为3),再用GetVolumeInformationA函数获取这个crackme程序所在分区的卷标。如这个Crackme程序放在桌面(C:\Documents and Settings\Administrator\桌面)而C盘设置的卷标是WINXP,则这里获取的就是 WINXP,

WINXP的ASCII码为“584E4957”这里有一个问题,值得注意

原来在数据窗口中看到的地址40339C处的16进制代码是“57494E58”,即“WINXP”

9fcf14fe9312a624d6887d13.jpg

但经过地址00401442处的那条MOV  EBX,  DWORD PTR   DS:[ESI] 指令后,

却发现EBX中的值是“584E4957”,正好把我们上面那个“57494E58”反过来了。

指令MOV EBX,DWORD PTR DS:[ESI]等同于MOV EBX,DWORD PTR DS:[40339C]。

注意这里是DWORD,即“双字”,由4个连续的字节构成。而取地址为40339C的双字单元中的内容时,我们应该得到的是“584E4957”,即由高字节到低字节顺序的值。因此经过MOV EBX,DWORD PTR DS:[ESI]这条指令,就是把从地址40339C开始处的值送到EBX,所以我们得到了“584E4957”。

看算法:

取磁盘类型参数做循环次数,再取卷标值ASCII码的逆序作为数值,有了这两个值就开始计算了。现在我们把磁盘类型值作为n,卷标值ASCII码的逆序数值作为a,最后得出的结果作为b,有这样的计算过程:

第一次:b   a * n

第二次:b   a * (n - 1) + b

第三次:b   a * (n - 2) + b

第n次:b   a * 1 + b

可得出公式为b     a * [n + (n - 1) + (n - 2) +…+ 1]       a * [n * (n + 1) / 2]

记得在比较   0040132D |. 3BC6 CMP  EAX, ESI  之前还有一句对ESI的操作。

00401405  |.  81F6 53757A79   XOR   ESI,  797A7553即

这里算出来的b最后还要和797A7553H异或一下才是真正的注册码。

 通过分析这个程序的算法,我们发现这个注册算法是有漏洞的。如果我的分区没有卷标的话,则卷标值为0,最后的注册码就是797A7553H,即十进制2038068563。而如果你的卷标和我一样,且磁盘类型一样的话,注册码也会一样,并不能真正做到一机一码。

内存断点简单加密算法 取硬盘信息去操作。。