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 ; 截取字符串
代码:
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 ; 截取截取字符串
代码:
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 ; 截取字符串
以上部分既包含了对注册码长度的检测,又做了提取对应字符串的工作。根据位置,分别设置为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
上述的字符串一共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"
上述数据不是在最终结果中直接使用,而是构造字符索引数组使用的。构造出的字符索引数组的内容仍是数字串,内容对这个控件来说是固定的。
产生最终结果字符串方法:
假设字符索引数组已经制作好,下面的代码将利用字符索引数组来产生最终结果:
代码:
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
这就为我们提出了难题:注册码第五段转化得到的数字串长度本来就不固定(还非一一对应关系),又经过两次换位变换,经过变换后的数字串中的数字(或两位的组合)还不一定出现在字符索引数组中。这样一来,计算出的字符串不是长了就是短了,很难理性地得到合适的字符串。唯一可行的办法就是穷举。
当上述需要的条件满足时,下面的问题就好解决了:
首先,将注册码的第一、二两端重新组合(就是去掉注册码的第一个“-”连接符),再看看所计算得到的字符串是否在其中:
比较点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 ; 设置注册码正确的标志
爆破点选择与设置:
可用于爆破的位置有三个,一个是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
http://bbs.pediy.com/showthread.php?t=79278
进行修改后也确能正常工作,那应该是比尔给我们制造的糊涂!