首页
社区
课程
招聘
[原创]ecGraph3D控件的注册算法分析
2009-1-16 12:36 7093

[原创]ecGraph3D控件的注册算法分析

2009-1-16 12:36
7093
ecGraph3D控件的注册算法分析
----和“一个外国人编写的名为ecGraph3D的三维控件的破解”

ecGraph3D的这个控件确实是一个好东西,如果谁能开发出立体几何接口来,将其使用于数学教学中将是非常有益的。

zhuliang先生已经对它进行了破解分析,我本不想再在破解上出风头了,想等别人来做算法分析这件事(见xiaoAngel的承诺)。无奈一直不见动静,只好将自己的研究拿出来献丑了。
作为算法分析,普遍认为VB较难,我恰好相反。原因是VB的数据结构决定了它的计算难度不可能很高(一般地)。VB的的东西的难点在于VB的多级结构指针的使用,让我们难以直接查看操作数是谁,以至于相应的函数做了些什么让人迷迷糊糊的,常谓之看不懂VB的函数是也。
另外,VB自己是一个懒主儿,一般是不会轻易做事的。如果想做点什么,大多数情况下是交给库函数的。如果库函数也做不了,他会告诉库函数,你找谁去解决(自己是不找的)。本文的情况就是如此。所以,怎么进入到ecGraph3D的领空,对一部分人来说可能还是一个新课题。

还是切入主题吧!
开发者给我们提供的范例,使我们大概知道注册码的一般形式,同时也蒙蔽了我们眼睛。

实测,注册码用应该划分为五段,前四段等长,第五段长度不定,原因见后。
计算难度不大,难的是对数据的观察。
当你能进入到ecGraph3D的领空,会来到这里:
110751F3  CALL NEAR DWORD PTR DS:[11001048]                ; 注册码长度
110751F9  CMP EAX,10
110751FC  JLE SHORT 11075236                               ; 长度必须大于16
110751FE  MOV DWORD PTR SS:[EBP-48],5
11075205  MOV DWORD PTR SS:[EBP-50],2
1107520C  LEA EDX,DWORD PTR SS:[EBP-50]
1107520F  PUSH EDX
11075210  PUSH 0D
11075212  MOV EAX,DWORD PTR SS:[EBP-38]
11075215  PUSH EAX
11075216  MOV EBX,DWORD PTR DS:[11001150]                  ; MSVBVM60.rtcMidCharBstr
1107521C  CALL NEAR EBX                                    ; 截取字符串

如果长度大于16位,则截取13--17位。
1107521E  MOV EDX,EAX
11075220  LEA ECX,DWORD PTR SS:[EBP-3C]
11075223  MOV EDI,DWORD PTR DS:[1100133C]                  ; MSVBVM60.__vbaStrMove
11075229  CALL NEAR EDI
1107522B  LEA ECX,DWORD PTR SS:[EBP-50]
1107522E  CALL NEAR DWORD PTR DS:[11001038]                ; MSVBVM60.__vbaFreeVar
11075234  JMP SHORT 11075242
11075236  MOV EDI,DWORD PTR DS:[1100133C]                  ; MSVBVM60.__vbaStrMove
1107523C  MOV EBX,DWORD PTR DS:[11001150]                  ; MSVBVM60.rtcMidCharBstr
11075242  MOV ECX,DWORD PTR SS:[EBP-38]
11075245  PUSH ECX
11075246  CALL NEAR DWORD PTR DS:[11001048]                ; 注册码长度
1107524C  CMP EAX,16
1107524F  JLE SHORT 1107527B                               ; 长度必须大于22
11075251  MOV DWORD PTR SS:[EBP-48],5
11075258  MOV DWORD PTR SS:[EBP-50],2
1107525F  LEA EDX,DWORD PTR SS:[EBP-50]
11075262  PUSH EDX
11075263  PUSH 13
11075265  MOV EAX,DWORD PTR SS:[EBP-38]
11075268  PUSH EAX
11075269  CALL NEAR EBX                                    ; 截取截取字符串

如果长度大于22位,则截取19--23位。18位呢?必然是“-”了。
1107526B  MOV EDX,EAX
1107526D  LEA ECX,DWORD PTR SS:[EBP-20]
11075270  CALL NEAR EDI
11075272  LEA ECX,DWORD PTR SS:[EBP-50]
11075275  CALL NEAR DWORD PTR DS:[11001038]                ; MSVBVM60.__vbaFreeVar
1107527B  MOV ECX,DWORD PTR SS:[EBP-38]
1107527E  PUSH ECX
1107527F  CALL NEAR DWORD PTR DS:[11001048]                ; 注册码长度
11075285  CMP EAX,19
11075288  JLE SHORT 110752B4                               ; 长度必须大于25位
1107528A  MOV DWORD PTR SS:[EBP-48],80020004
11075291  MOV DWORD PTR SS:[EBP-50],0A
11075298  LEA EDX,DWORD PTR SS:[EBP-50]
1107529B  PUSH EDX
1107529C  PUSH 19
1107529E  MOV EAX,DWORD PTR SS:[EBP-38]
110752A1  PUSH EAX
110752A2  CALL NEAR EBX                                    ; 截取字符串

如果长度大于25位,则截取25位及其后续部分。所有未包含的部分(空挡)均为“-”号。
以上部分既包含了对注册码长度的检测,又做了提取对应字符串的工作。根据位置,分别设置为str3、str4、str5。剩下前两段待处理。

检测注册码第五段是否下列字符之一:
11075341  MOV DWORD PTR SS:[EBP-88],11008140               ; UNICODE "BDFHKMPQTWXAREYUSCGVZ"
1107534B  MOV DWORD PTR SS:[EBP-90],8
11075355  MOVSX EDX,SI
11075358  PUSH EDX
11075359  LEA EAX,DWORD PTR SS:[EBP-50]
1107535C  PUSH EAX
1107535D  CALL NEAR DWORD PTR DS:[11001248]                ; MSVBVM60.rtcVarBstrFromAnsi
11075363  PUSH 1
11075365  LEA ECX,DWORD PTR SS:[EBP-90]
1107536B  PUSH ECX
1107536C  LEA EDX,DWORD PTR SS:[EBP-50]
1107536F  PUSH EDX
11075370  PUSH 1
11075372  LEA EAX,DWORD PTR SS:[EBP-60]
11075375  PUSH EAX
11075376  CALL NEAR DWORD PTR DS:[11001250]                ; MSVBVM60.__vbaInStrVar
……
11075488  CALL NEAR DWORD PTR DS:[EAX+AB4]                 ; 求取注册码第五段每一位注册码在字符串中的位置号,得到数字串str1
以上部分循环检测注册码的第五部分中的字符是否是字符串"BDFHKMPQTWXAREYUSCGVZ"。如果是,返回所在位置号。如果不在,返回0。注意这里VB的判断情况与其它语言差异。
上述的字符串一共21位,所以位置号最大为21。但位置号不是直接使用的,而是做了减1再除以2的换算。所以产生的数字可以是一位,也可以是两位,使得字符串和数字串并非一一对应的关系。

以下部分是先对上述所得的数字串利用注册码的第四段、第三段进行换位变换,然后再利用内置的字符串(运行时由软还合成)进行变换,生成字符串的主程序。
11075532  CALL NEAR DWORD PTR DS:[EAX+A8C]                 ; 注册码第四段生成整数索引表
11075538  CMP WORD PTR SS:[EBP-A4],BX
1107553F  JNZ 110756F7
11075545  MOV EAX,DWORD PTR DS:[ESI]
11075547  LEA ECX,DWORD PTR SS:[EBP-40]
1107554A  PUSH ECX
1107554B  MOV EDX,DWORD PTR SS:[EBP-38]
1107554E  PUSH EDX
1107554F  PUSH ESI
11075550  CALL NEAR DWORD PTR DS:[EAX+A94]                 ; 利用索引表对str1换位得数字串str2
11075556  MOV EDX,DWORD PTR SS:[EBP-40]
11075559  MOV DWORD PTR SS:[EBP-40],EBX
1107555C  LEA ECX,DWORD PTR SS:[EBP-34]
1107555F  CALL NEAR EDI
11075561  MOV EAX,DWORD PTR SS:[EBP-34]
11075564  PUSH EAX
11075565  PUSH 11008170
1107556A  CALL NEAR DWORD PTR DS:[11001134]                ; MSVBVM60.__vbaStrTextCmp
11075570  TEST EAX,EAX
……
110755DD  LEA EAX,DWORD PTR SS:[EBP-A4]
110755E3  PUSH EAX
110755E4  MOV ECX,DWORD PTR SS:[EBP-3C]
110755E7  PUSH ECX
110755E8  PUSH ESI
110755E9  CALL NEAR DWORD PTR DS:[EDX+A8C]                 ; 利用注册码第三段生成整数索引表
110755EF  CMP WORD PTR SS:[EBP-A4],BX
110755F6  JNZ 110756F7
110755FC  MOV EDX,DWORD PTR DS:[ESI]
110755FE  LEA EAX,DWORD PTR SS:[EBP-40]
11075601  PUSH EAX
11075602  MOV ECX,DWORD PTR SS:[EBP-34]
11075605  PUSH ECX
11075606  PUSH ESI
11075607  CALL NEAR DWORD PTR DS:[EDX+A94]                 ; 利用索引表对str2换位得str3
1107560D  MOV EDX,DWORD PTR SS:[EBP-40]
11075610  MOV DWORD PTR SS:[EBP-40],EBX
……
1107567D  LEA ECX,DWORD PTR SS:[EBP-A4]
11075683  PUSH ECX
11075684  MOV EDX,DWORD PTR SS:[EBP+10]
11075687  MOV ECX,DWORD PTR DS:[EDX]
11075689  PUSH ECX
1107568A  PUSH ESI
1107568B  CALL NEAR DWORD PTR DS:[EAX+A9C]                 ; 利用字符串“”生成字符索引表
11075691  CMP WORD PTR SS:[EBP-A4],BX
11075698  JNZ SHORT 110756F7
1107569A  MOV EDX,DWORD PTR DS:[ESI]
1107569C  LEA EAX,DWORD PTR SS:[EBP-40]
1107569F  PUSH EAX
110756A0  MOV ECX,DWORD PTR SS:[EBP-34]
110756A3  PUSH ECX
110756A4  PUSH ESI
110756A5  CALL NEAR DWORD PTR DS:[EDX+AA0]                 ; 利用索引表和str3产生字符串

关于整数索引表:
整数索引表就是每个单元的内容都是整数(byte)的数组。数组大小为6,实际使用5单元(VB的特点)。产生方法:
110744AD  MOV EAX,1                                        ; i=1
110744B2  MOV DWORD PTR SS:[EBP-58],EAX                    ;i
110744B5  MOV EDI,DWORD PTR DS:[11001388]                  ; MSVBVM60.__vbaFreeStr
	110744BB  MOV ECX,0A                                       ; 外循环==>
	110744C0  CMP EAX,ECX                                      ; i>10?
	110744C2  JG 11074637
	110744C8  MOV ECX,0FF                                      ; FF
	110744CD  CALL NEAR DWORD PTR DS:[110011F0]                ; MSVBVM60.__vbaUI1I2
	110744D3  MOV BYTE PTR SS:[EBP-48],AL                      ; tmp=FF
	110744D6  MOV ESI,1                                        ; j=1
		110744DB  MOV EAX,0A                                       ; 内循环==>
		110744E0  CMP ESI,EAX                                      ; j>10?
		110744E2  JG 110745A4
		110744E8  MOV DWORD PTR SS:[EBP-6C],1
		110744EF  MOV DWORD PTR SS:[EBP-74],2
		110744F6  LEA ECX,DWORD PTR SS:[EBP-54]
		110744F9  MOV DWORD PTR SS:[EBP-C0],ECX
		110744FF  MOV DWORD PTR SS:[EBP-C8],4008
		11074509  LEA EDX,DWORD PTR SS:[EBP-74]
		1107450C  PUSH EDX
		1107450D  PUSH ESI
		1107450E  LEA EAX,DWORD PTR SS:[EBP-C8]
		11074514  PUSH EAX
		11074515  LEA ECX,DWORD PTR SS:[EBP-84]
		1107451B  PUSH ECX
		1107451C  CALL NEAR DWORD PTR DS:[11001158]                ; 读取一位
		11074522  LEA EDX,DWORD PTR SS:[EBP-84]
		11074528  PUSH EDX
		11074529  LEA EAX,DWORD PTR SS:[EBP-94]
		1107452F  PUSH EAX
		11074530  CALL NEAR DWORD PTR DS:[1100117C]                ; 转化为大写
		11074536  LEA ECX,DWORD PTR SS:[EBP-94]
		1107453C  PUSH ECX
		1107453D  LEA EDX,DWORD PTR SS:[EBP-64]
		11074540  PUSH EDX
		11074541  CALL NEAR DWORD PTR DS:[1100125C]                ; MSVBVM60.__vbaStrVarVal
		11074547  PUSH EAX
		11074548  CALL NEAR DWORD PTR DS:[1100106C]                ; 取ASCII码
		1107454E  MOV ECX,EAX
		11074550  CALL NEAR DWORD PTR DS:[110011F0]                ; MSVBVM60.__vbaUI1I2
		11074556  MOV BL,AL                                        ; 转移
		11074558  LEA ECX,DWORD PTR SS:[EBP-64]
		1107455B  CALL NEAR EDI
		1107455D  LEA EAX,DWORD PTR SS:[EBP-94]
		11074563  PUSH EAX
		11074564  LEA ECX,DWORD PTR SS:[EBP-84]
		1107456A  PUSH ECX
		1107456B  LEA EDX,DWORD PTR SS:[EBP-74]
		1107456E  PUSH EDX
		1107456F  PUSH 3
		11074571  CALL NEAR DWORD PTR DS:[1100105C]                ; MSVBVM60.__vbaFreeVarList
		11074577  ADD ESP,10
		1107457A  CMP BL,BYTE PTR SS:[EBP-48]                      ; str<=tmp 谁大?
		1107457D  JNB SHORT 1107458D
			1107457F  MOV BYTE PTR SS:[EBP-48],BL                      ; tmp<==str 小的替换大的
			11074582  MOV ECX,ESI
			11074584  CALL NEAR DWORD PTR DS:[110011A0]                ; MSVBVM60.__vbaI2I4
			1107458A  MOV DWORD PTR SS:[EBP-44],EAX                    ; 暂存j
		1107458D  MOV EAX,1
		11074592  ADD EAX,ESI
		11074594  JO 11074B1E
		1107459A  MOV ESI,EAX                                      ;j++
		1107459C  MOV EBX,DWORD PTR SS:[EBP+8]
		1107459F  JMP 110744DB                                     ; 内循环<==
	110745A4  MOV AX,WORD PTR SS:[EBP-44]                      ; j
	110745A8  CWD
	110745AA  MOV CX,0A
	110745AE  IDIV CX
	110745B1  MOVSX ESI,DX                                     ; j mod 10
	110745B4  CMP ESI,0B
	110745B7  JB SHORT 110745BF
	110745B9  CALL NEAR DWORD PTR DS:[11001184]                ; MSVBVM60.__vbaGenerateBoundsError
	110745BF  MOV EAX,DWORD PTR SS:[EBP-58]                    ; i
	110745C2  CDQ
	110745C3  MOV ECX,0A
	110745C8  IDIV ECX
	110745CA  MOV ECX,EDX                                      ; i mod 10
	110745CC  CALL NEAR DWORD PTR DS:[11001210]                ; MSVBVM60.__vbaUI1I4
	110745D2  MOV EDX,DWORD PTR DS:[EBX+194]                   ; 数组地址
	110745D8  MOV BYTE PTR DS:[EDX+ESI],AL                     ; 保存索引到数组
	110745DB  PUSH 0FF
	110745E0  LEA EAX,DWORD PTR SS:[EBP-74]
	110745E3  PUSH EAX
	110745E4  CALL NEAR DWORD PTR DS:[11001248]                ; MSVBVM60.rtcVarBstrFromAnsi
	110745EA  LEA ECX,DWORD PTR SS:[EBP-54]
	110745ED  PUSH ECX
	110745EE  MOVSX EDX,WORD PTR SS:[EBP-44]
	110745F2  PUSH EDX
	110745F3  PUSH 1
	110745F5  LEA EAX,DWORD PTR SS:[EBP-74]
	110745F8  PUSH EAX
	110745F9  CALL NEAR DWORD PTR DS:[1100104C]                ; MSVBVM60.__vbaStrVarMove
	110745FF  MOV EDX,EAX
	11074601  LEA ECX,DWORD PTR SS:[EBP-64]
	11074604  CALL NEAR DWORD PTR DS:[1100133C]                ; MSVBVM60.__vbaStrMove
	1107460A  PUSH EAX
	1107460B  PUSH 0
	1107460D  CALL NEAR DWORD PTR DS:[1100137C]                ; FF替换第j位
	11074613  LEA ECX,DWORD PTR SS:[EBP-64]
	11074616  CALL NEAR EDI
	11074618  LEA ECX,DWORD PTR SS:[EBP-74]
	1107461B  CALL NEAR DWORD PTR DS:[11001038]                ; MSVBVM60.__vbaFreeVar
	11074621  MOV EAX,1
	11074626  ADD EAX,DWORD PTR SS:[EBP-58]
	11074629  JO 11074B1E
	1107462F  MOV DWORD PTR SS:[EBP-58],EAX
	11074632  JMP 110744BB                                     ; 外循环<==
基本规律:
对字符串中的字符在本字符串中的大小按原序存放求出顺序号。如:ABCDE,则顺序号为12345;BACDE,则顺序号为21345等等。结果填充数组。
利用上述方法分别对注册码的第四段、第三段求出对应的数组,为后续的换位提供依据。

换位方法:
这部分的代码较长,免去代码部分,直接给出仿真代码:
假设:
    B=array(1,2,3,4,5)
    n = Len(in2)   'in2为数字串
    ztmp = Space(n)'作等长的空格串
    t = 1
    For j = 1 To 5
        index = b(j)
        For i = 1 To n
            If index <= 6 Then
                Mid(ztmp, index, 1) = Mid(in2, t, 1)
                index = index + 5
                t = t + 1
            End If
        Next
        If t = n + 1 Then Exit For '如果全部做过交换则退出
    Next

关于字符索引表:
符索引表就是每个单元存放的是字符串的数组,其存放的数字串右1位的,也有两位的,但并非规律存放,也不是所有的数字串都存在。这个数组的产生代码较长,但对于一个ActiveX来说是固定的。不过对于VB的东西来说,观察起来稍微麻烦。如果不找到合适的位置,很难知道数组中的元素是什么。
建立字符索引表使用一个字符串和一个数字串数组:
字符串:"ECGRAPHDDD"。这个是软换合成的。
数字串数组:
11073F64  MOV DWORD PTR SS:[EBP-C0],11008170               ;"0"
11073F9A  MOV DWORD PTR SS:[EBP-D0],1100CEC8               :"1"
11073FD2  MOV DWORD PTR SS:[EBP-E0],1100D090               ; UNICODE "31"
11073FFE  MOV DWORD PTR SS:[EBP-F0],1100CD08               ; UNICODE "32"
1107402A  MOV DWORD PTR SS:[EBP-100],1100C444              ; UNICODE "33"
11074056  MOV DWORD PTR SS:[EBP-110],1100B810              ; "6"
11074082  MOV DWORD PTR SS:[EBP-120],1100D09C              ; UNICODE "34"
110740AE  MOV DWORD PTR SS:[EBP-130],1100D0A8              ; UNICODE "35"
110740DA  MOV DWORD PTR SS:[EBP-140],1100D0B4              ; UNICODE "36"
11074103  MOV DWORD PTR SS:[EBP-150],110094E4              ; "9"
1107412F  MOV DWORD PTR SS:[EBP-160],1100D0C0              ; UNICODE "37"
1107415B  MOV DWORD PTR SS:[EBP-170],1100D0CC              ; UNICODE "38"
11074187  MOV DWORD PTR SS:[EBP-180],1100D0D8              ; UNICODE "39"
110741B3  MOV DWORD PTR SS:[EBP-190],1100D0E4              ; UNICODE "30"
110741DF  MOV DWORD PTR SS:[EBP-1A0],1100D0F0              ; "5"
1107420B  MOV DWORD PTR SS:[EBP-1B0],1100D0F8              ;"4"
11074237  MOV DWORD PTR SS:[EBP-1C0],1100D100              ; UNICODE "71"
11074263  MOV DWORD PTR SS:[EBP-1D0],1100D10C              ; UNICODE "72"
1107428F  MOV DWORD PTR SS:[EBP-1E0],11008FC0              ; "0"
110742BB  MOV DWORD PTR SS:[EBP-1F0],1100D118              ; "8"
110742E7  MOV DWORD PTR SS:[EBP-200],1100D120              ; "2"
11074313  MOV DWORD PTR SS:[EBP-210],1100D128              ; UNICODE "73"
1107433F  MOV DWORD PTR SS:[EBP-220],1100D134              ; UNICODE "74"
1107436B  MOV DWORD PTR SS:[EBP-230],1100D140              ; UNICODE "75"
11074397  MOV DWORD PTR SS:[EBP-240],1100D14C              ; UNICODE "76"
110743C3  MOV DWORD PTR SS:[EBP-250],1100D158              ; UNICODE "77"
110743EF  MOV DWORD PTR SS:[EBP-260],1100D164              ; UNICODE "78"
1107441B  MOV DWORD PTR SS:[EBP-270],1100D170              ; UNICODE "79"
11074447  MOV DWORD PTR SS:[EBP-280],1100D17C              ; UNICODE "70"

其中一个数字的字符串在OD中观察不到,是我添加进来的。
上述数据不是在最终结果中直接使用,而是构造字符索引数组使用的。构造出的字符索引数组的内容仍是数字串,内容对这个控件来说是固定的。

产生最终结果字符串方法:
假设字符索引数组已经制作好,下面的代码将利用字符索引数组来产生最终结果:
11074B96  CALL NEAR DWORD PTR DS:[11001048]                ; 输入的长度
11074B9C  MOV DWORD PTR SS:[EBP-7C],EAX
11074B9F  MOV ESI,1                                        ; i=1
11074BA4  MOV EBX,DWORD PTR SS:[EBP+8]
11074BA7  MOV EDI,DWORD PTR DS:[1100133C]                  ; MSVBVM60.__vbaStrMove
11074BAD  CMP ESI,DWORD PTR SS:[EBP-7C]                    ; i>n?
11074BB0  JG 11074D26
11074BB6  MOV DWORD PTR SS:[EBP-3C],1
11074BBD  MOV DWORD PTR SS:[EBP-44],2
11074BC4  LEA EDX,DWORD PTR SS:[EBP-2C]
11074BC7  MOV DWORD PTR SS:[EBP-5C],EDX
11074BCA  MOV DWORD PTR SS:[EBP-64],4008
11074BD1  LEA EAX,DWORD PTR SS:[EBP-44]
11074BD4  PUSH EAX
11074BD5  PUSH ESI
11074BD6  LEA ECX,DWORD PTR SS:[EBP-64]
11074BD9  PUSH ECX
11074BDA  LEA EDX,DWORD PTR SS:[EBP-54]
11074BDD  PUSH EDX
11074BDE  CALL NEAR DWORD PTR DS:[11001158]                ; 读取输入一位--两次交换后的数字串
11074BE4  LEA EAX,DWORD PTR SS:[EBP-54]
11074BE7  PUSH EAX
11074BE8  CALL NEAR DWORD PTR DS:[1100104C]                ; MSVBVM60.__vbaStrVarMove
11074BEE  MOV EDX,EAX                                      ; 保存位置
11074BF0  LEA ECX,DWORD PTR SS:[EBP-30]
11074BF3  CALL NEAR EDI
11074BF5  MOV ECX,DWORD PTR DS:[EBX]
11074BF7  LEA EDX,DWORD PTR SS:[EBP-34]
11074BFA  PUSH EDX
11074BFB  LEA EAX,DWORD PTR SS:[EBP-30]
11074BFE  PUSH EAX
11074BFF  PUSH EBX
11074C00  CALL NEAR DWORD PTR DS:[ECX+AA8]                 ; 查找

查找分为两步,先用一位数字试找。如果找不到,再不上一位查找。
查找数字串中的一位在字符索引数组中的位置。如果找到,其位置号+0x40后转化为字符(VB的特有方式)。
另外,如果字符处在第21、22位,则32位用"."代替,22位用空格" "代替。
11074C06  MOV EDX,DWORD PTR SS:[EBP-34]
11074C09  MOV DWORD PTR SS:[EBP-34],0
11074C10  LEA ECX,DWORD PTR SS:[EBP-20]
11074C13  CALL NEAR EDI
11074C15  LEA ECX,DWORD PTR SS:[EBP-30]
11074C18  CALL NEAR DWORD PTR DS:[11001388]                ; MSVBVM60.__vbaFreeStr
11074C1E  LEA ECX,DWORD PTR SS:[EBP-54]
11074C21  PUSH ECX
11074C22  LEA EDX,DWORD PTR SS:[EBP-44]
11074C25  PUSH EDX
11074C26  PUSH 2
11074C28  CALL NEAR DWORD PTR DS:[1100105C]                ; MSVBVM60.__vbaFreeVarList
11074C2E  ADD ESP,0C
11074C31  MOV EAX,DWORD PTR SS:[EBP-20]
11074C34  PUSH EAX
11074C35  PUSH 11008170
11074C3A  CALL NEAR DWORD PTR DS:[11001134]                ; MSVBVM60.__vbaStrTextCmp
11074C40  TEST EAX,EAX
11074C42  JNZ 11074CC9                                     ;如果找到就跳
11074C48  MOV EAX,2
11074C4D  MOV DWORD PTR SS:[EBP-3C],EAX
11074C50  MOV DWORD PTR SS:[EBP-44],EAX
11074C53  LEA ECX,DWORD PTR SS:[EBP-2C]
11074C56  MOV DWORD PTR SS:[EBP-5C],ECX
11074C59  MOV DWORD PTR SS:[EBP-64],4008
11074C60  LEA EDX,DWORD PTR SS:[EBP-44]
11074C63  PUSH EDX
11074C64  PUSH ESI
11074C65  LEA EAX,DWORD PTR SS:[EBP-64]
11074C68  PUSH EAX
11074C69  LEA ECX,DWORD PTR SS:[EBP-54]
11074C6C  PUSH ECX
11074C6D  CALL NEAR DWORD PTR DS:[11001158]                ; 如果未找到,则截取两位
11074C73  LEA EDX,DWORD PTR SS:[EBP-54]
11074C76  PUSH EDX
11074C77  CALL NEAR DWORD PTR DS:[1100104C]                ; MSVBVM60.__vbaStrVarMove
11074C7D  MOV EDX,EAX
11074C7F  LEA ECX,DWORD PTR SS:[EBP-30]
11074C82  CALL NEAR EDI
11074C84  MOV EAX,DWORD PTR DS:[EBX]
11074C86  LEA ECX,DWORD PTR SS:[EBP-34]
11074C89  PUSH ECX
11074C8A  LEA EDX,DWORD PTR SS:[EBP-30]
11074C8D  PUSH EDX
11074C8E  PUSH EBX
11074C8F  CALL NEAR DWORD PTR DS:[EAX+AA8]                 ; 查找
11074C95  MOV EDX,DWORD PTR SS:[EBP-34]
11074C98  MOV DWORD PTR SS:[EBP-34],0
11074C9F  LEA ECX,DWORD PTR SS:[EBP-20]
11074CA2  CALL NEAR EDI
11074CA4  LEA ECX,DWORD PTR SS:[EBP-30]
11074CA7  CALL NEAR DWORD PTR DS:[11001388]                ; MSVBVM60.__vbaFreeStr
11074CAD  LEA EAX,DWORD PTR SS:[EBP-54]
11074CB0  PUSH EAX
11074CB1  LEA ECX,DWORD PTR SS:[EBP-44]
11074CB4  PUSH ECX
11074CB5  PUSH 2
11074CB7  CALL NEAR DWORD PTR DS:[1100105C]                ; MSVBVM60.__vbaFreeVarList
11074CBD  ADD ESP,0C
11074CC0  ADD ESI,1
11074CC3  JO 11074D94
11074CC9  MOV EDX,DWORD PTR SS:[EBP-24]
11074CCC  PUSH EDX
11074CCD  MOV EAX,DWORD PTR SS:[EBP-20]
11074CD0  PUSH EAX
11074CD1  CALL NEAR DWORD PTR DS:[1100109C]                ; 组合
11074CD7  MOV EDX,EAX
11074CD9  LEA ECX,DWORD PTR SS:[EBP-24]
11074CDC  CALL NEAR EDI
11074CDE  MOV EAX,1
11074CE3  ADD EAX,ESI
11074CE5  JO 11074D94
11074CEB  MOV ESI,EAX
11074CED  JMP 11074BAD
经过这段代码后,如果不出意外,就得到最终需要的字符串。

所谓不出意外,就是这个字符串还必须满足一定的条件。看下述代码:
比较点1:
1107588A  CALL NEAR DWORD PTR DS:[11001048]                ; MSVBVM60.__vbaLenBstr
11075890  CMP EAX,0A                                       ; 关键比较1
11075893  JNZ 11075953

这里告诉我们,结果字符串必须是10位的,多了少了都不成。
这就为我们提出了难题:注册码第五段转化得到的数字串长度本来就不固定(还非一一对应关系),又经过两次换位变换,经过变换后的数字串中的数字(或两位的组合)还不一定出现在字符索引数组中。这样一来,计算出的字符串不是长了就是短了,很难理性地得到合适的字符串。唯一可行的办法就是穷举。

当上述需要的条件满足时,下面的问题就好解决了:
首先,将注册码的第一、二两端重新组合(就是去掉注册码的第一个“-”连接符),再看看所计算得到的字符串是否在其中:
比较点2:
11075900  CALL NEAR DWORD PTR DS:[11001290]                ; MSVBVM60.__vbaInStr
11075906  CMP EAX,1                                        ; 关键比较2
11075909  JNZ SHORT 11075953
1107590B  MOV DWORD PTR SS:[EBP-24],-1                     ; 设置注册码正确的标志

注意这个标志的值为-1.

爆破点选择与设置:
可用于爆破的位置有三个,一个是11075893处的跳转,可NOP掉;一个是11075909处的跳转,也可NOP掉;第三个是下属代码处:
1107599F    8B45 14      MOV EAX,DWORD PTR SS:[EBP+14]
110759A2    66:8B4D DC   MOV CX,WORD PTR SS:[EBP-24]                      ; 读取标志
110759A6    66:8908      MOV WORD PTR DS:[EAX],CX                         ; 保存
110759A9    33C0         XOR EAX,EAX

可修改为:
1107599F    8B45 14      MOV EAX,DWORD PTR SS:[EBP+14]
110759A2    66:C700 FFFF MOV WORD PTR DS:[EAX],0FFFF                      ; 读取标志
110759A7    90           NOP
110759A8    90           NOP
110759A9    33C0         XOR EAX,EAX

这是按照VB自身的要求进行修改的。至于按照zhuliang先生的文章:
http://bbs.pediy.com/showthread.php?t=79278
进行修改后也确能正常工作,那应该是比尔给我们制造的糊涂!

[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

收藏
点赞7
打赏
分享
最新回复 (1)
雪    币: 349
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
jerrylhj 2009-1-16 14:52
2
0
精彩,俺一直对算法分析没什么突破。
游客
登录 | 注册 方可回帖
返回