Universe 1.63注册码生成分析及注册机原码(中)
作者:Maomao[CCG]
我们追进算注册码的CALL,看到下面的程序段:
0177:00416844 PUSH EBP
0177:00416845 MOV EBP,ESP
0177:00416847 PUSH BYTE -01
0177:00416849 PUSH DWORD 004754B9
0177:0041684E MOV EAX,`DOSMGR_BackFill_Allowed`
0177:00416854 PUSH EAX
0177:00416855 MOV `DOSMGR_BackFill_Allowed`,ESP
0177:0041685C SUB ESP,BYTE +2C
0177:0041685F PUSH DWORD 0048DCCC
0177:00416864 LEA EAX,[EBP-30]
0177:00416867 PUSH EAX
0177:00416868 CALL 00416CC2
0177:0041686D ADD ESP,BYTE +08
0177:00416870 MOV [EBP-34],EAX
0177:00416873 MOV ECX,[EBP-34]
0177:00416876 MOV [EBP-38],ECX
0177:00416879 MOV DWORD [EBP-04],00
0177:00416880 MOV EDX,[EBP-38]
0177:00416883 PUSH EDX
0177:00416884 MOV EAX,[EBP+08]
0177:00416887 PUSH EAX
0177:00416888 CALL 00417020
0177:0041688D MOV [EBP-2C],AL
0177:00416890 MOV DWORD [EBP-04],FFFFFFFF
0177:00416897 LEA ECX,[EBP-30]
0177:0041689A CALL 00455C64
0177:0041689F MOV ECX,[EBP-2C]
0177:004168A2 AND ECX,FF
0177:004168A8 TEST ECX,ECX
0177:004168AA JZ 004168B3
0177:004168AC XOR EAX,EAX
0177:004168AE JMP 00416997
0177:004168B3 CALL 0042A6D0
0177:004168B8 MOV [EBP-24],EAX
0177:004168BB MOV DWORD [EBP-10],00
0177:004168C2 MOV DWORD [EBP-20],01
0177:004168C9 MOV DWORD [EBP-1C],00
0177:004168D0 JMP SHORT 004168DB
以上是一些无太多关系的操作,主要是姓名和注册码的存取和转换,下面来到重点了:
0177:004168D2 MOV EDX,[EBP-1C]
0177:004168D5 ADD EDX,BYTE +01
0177:004168D8 MOV [EBP-1C],EDX
0177:004168DB MOV ECX,[EBP+08]
0177:004168DE CALL 00403460 <=====计算姓名的位数
0177:004168E3 CMP [EBP-1C],EAX <=====EBP-1C是指针,用于取字符
0177:004168E6 JNL 00416937
0177:004168E8 MOV EAX,[EBP-1C] <=====指针送入EAX
0177:004168EB PUSH EAX
0177:004168EC MOV ECX,[EBP+08] <=====这里D
*ECX 可以看到用户名"Maomao[CCG]"
0177:004168EF CALL 00417000 <=====取指针所指字符到AL
0177:004168F4 MOVSX ECX,AL <=====送入ECX
0177:004168F7 MOV [EBP-28],ECX <=====临时寄存这个字符(下面还要用到)
0177:004168FA MOV EDX,[EBP-10] <=====取累加器中的数据(EBP-10为累加器)
0177:004168FD ADD EDX,[EBP-28] <=====相加
0177:00416900 MOV [EBP-10],EDX <=====结果送入累加器,下一次再使用
0177:00416903 MOV EAX,[EBP-1C] <=====取指针到EAX
0177:00416906 AND EAX,80000001 <=====与0x80000001
AND
(当指针为奇数时结果为0,偶数数结果为1)
0177:0041690B JNS 00416912
0177:0041690D DEC EAX
0177:0041690E OR EAX,BYTE -02
0177:00416911 INC EAX
0177:00416912 TEST EAX,EAX <=====判断奇偶
0177:00416914 JZ 0041691F
0177:00416916 MOV DWORD [EBP-20],FFFFFFFF <=====偶位时送符号位-1
0177:0041691D JMP SHORT 00416926
0177:0041691F MOV DWORD [EBP-20],01
<=====奇位时送符号位1
0177:00416926 MOV ECX,[EBP-20]
<=====取符号位
0177:00416929 IMUL ECX,[EBP-28]
<=====取临时寄存的字符与符号相乘(偶数位结果为负)
0177:0041692D MOV EDX,[EBP-10]
<=====取累加器中的值
0177:00416930 ADD EDX,ECX
<=====再相加(如果是偶数位就是相减了)
0177:00416932 MOV [EBP-10],EDX
<=====送入累加器
0177:00416935 JMP SHORT 004168D2
<=====取下一字符
上面这段程序完成奇位字符相加两次,偶位字符一加一减(等于不运算)。结果为所有奇位字符和的二倍。
紧接着:
0177:00416937 MOV EAX,[EBP-10]
<=====取累加器中的值
0177:0041693A MOV [EBP-18],EAX
<=====送入[EBP-18]
0177:0041693D MOV ECX,[EBP-10]
<=====取累加器中的值到ECX
0177:00416940 IMUL ECX,[EBP-10] <=====相乘(相当于求平方)
0177:00416944 MOV [EBP-10],ECX
<=====结果送入累加器
0177:00416947 MOV EDX,[EBP-10]
<=====取累加器中的值
0177:0041694A ADD EDX,[EBP-18]
<=====与刚才保存的[EBP-18]相加
0177:0041694D MOV [EBP-10],EDX
<=====结果送入累加器
0177:00416950 MOV EAX,[EBP-10]
<=====累加器送入EAX
0177:00416953 PUSH EAX
0177:00416954 CALL 0042A6C0
<=====保存中间值到[0048E7E8],此call略
0177:00416959 ADD ESP,BYTE +04
以上程序完成求形如(X*X+X)的结果,其中X为第一段累加运算的结果。接下来:
0177:0041695C MOV DWORD [EBP-1C],00 <=====指针清0
0177:00416963 JMP SHORT 0041696E
0177:00416965 MOV ECX,[EBP-1C]
0177:00416968 ADD ECX,BYTE +01
<=====指针加1
0177:0041696B MOV [EBP-1C],ECX
0177:0041696E MOV EDX,[EBP-1C]
0177:00416971 CMP EDX,[00497808] <=====[00497808]为循环计数器,值为3
0177:00416977 JNL 00416980 <=====大于或等于时结束运算
0177:00416979 CALL 0042A6E0 <=====运算的call
0177:0041697E JMP SHORT 00416965
0177:00416980 CALL 0042A6E0 <=====再运算一次
0177:00416985 MOV [EBP-14],EAX
<=====保存结果
0177:00416988 MOV EAX,[EBP-24]
0177:0041698B PUSH EAX
0177:0041698C CALL 0042A6C0
0177:00416991 ADD ESP,BYTE +04
0177:00416994 MOV EAX,[EBP-14] <=====取回结果
0177:00416997 MOV ECX,[EBP-0C]
0177:0041699A MOV `DOSMGR_BackFill_Allowed`,ECX
0177:004169A1 MOV ESP,EBP
0177:004169A3 POP EBP
0177:004169A4 RET
以上这段完成四次循环运算,结果保存在EAX中。看来还要跟进0177:00416980的CALL 0042A6E0。
跟进后,是这样的程序段:
0177:0042A6E0 MOV EAX,[0048E7E8] <=====取加保存的中间结果
0177:0042A6E5 PUSH DWORD 78B30C40 <=====放一个辅助运算数0x78B30C40
0177:0042A6EA CDQ
0177:0042A6EB PUSH BYTE +00
0177:0042A6ED PUSH DWORD 25A2A40D <=====放另一个辅助运算数0x25A2A40D
0177:0042A6F2 PUSH EDX
0177:0042A6F3 PUSH EAX
0177:0042A6F4 CALL 00441870 <=====第一次运算
0177:0042A6F9 ADD EAX,BYTE +01 <=====运算结果加1
0177:0042A6FC ADC EDX,BYTE +00
0177:0042A6FF PUSH EDX
0177:0042A700 PUSH EAX
0177:0042A701 CALL 0042A760 <=====第二次运算
0177:0042A706 ADD ESP,BYTE +0C
0177:0042A709 MOV [0048E7E8],EAX <=====保存中间结果,下次使用
0177:0042A70E RET
第一次运算的call:
0177:00441870 MOV EAX,[ESP+08]
0177:00441874 MOV ECX,[ESP+10]
0177:00441878 OR ECX,EAX
0177:0044187A MOV ECX,[ESP+0C] <=====取辅助运算数0x25A2A40D
0177:0044187E JNZ 00441889
0177:00441880 MOV EAX,[ESP+04] <=====取累算的结果
0177:00441884 MUL ECX <=====两数相乘送入ECX
0177:00441886 RET 10
第二次运算的call:
0177:0042A760 PUSH EBP
0177:0042A761 MOV EBP,ESP
0177:0042A763 PUSH EBX
0177:0042A764 MOV EAX,[EBP+08] <=====取累算的结果
0177:0042A767 MOV EDX,[EBP+0C]
0177:0042A76A MOV EBX,[EBP+10] <=====取辅助运算数0x78B30C40
0177:0042A76D DIV EBX <=====相除(商到EAX,余数到EDX)
0177:0042A76F MOV EAX,EDX <=====只取余数
0177:0042A771 POP EBX
0177:0042A772 POP EBP
0177:0042A773 RET
这段程序主要完成形如 [(X*0x25A2A40D)+1] mod 0x78B30C40 的功能,并且要重复运算4次!
OK,可以整理一下了:
注册算码程序首先取用户名的奇位字符的2倍累加,对结果再进行形如(X*X+X)的运算,然后循环四次,循环中进行形如 [(X*0x25A2A40D)+1]
mod 0x78B30C40 的运算,结果为正确的注册码。
到这里就结束了吗?没有,还有注册机的制作,请看下篇:C++Builder的注册机原码
(中篇完~~~)