如何破解PB6.5编译的程序
(以下内容若有错误之处,还望来信指正)
以下所有均针对PowerBuilder6.5编译的伪码程序(即带有PBD的文件执行)。
PowerBuilder的伪码编译同VB伪码编译一样,同样是PB动态库(PBVM60.DLL),解释伪码执行。而PBVM60.DLL对取字符串、比较字符串、比较数值与我们常见到的c或汇编或delphi等等语言生成的执行文件不一样。
为此,我用PB6.5生成一段代码,然后跟踪,摸出一些经验:
我的Pb代码如下:(不要看有什么意思,纯粹为了研究)
string ls_t1,ls_t2,ls_444 long ll_l1,ll_l2,ll_l3
ll_l1 = 12325 ls_t1 = sle_1.text //看在PB中如何取字符串值。sle_1 是单行编辑框。 ls_t2 = '12325'
ll_l2 = integer(ls_t1) //看此处会触发什么 ll_l2 -= ll_l1 if ls_t1 <> 'fdfggfh' Then //研究PB的字符比较会调用什么。=========重点 ll_l2 = ll_l2 * 2 else ll_l3 = integer('24354') end if
if ll_l2 <> 3107 Then //研究PB如何进行数值比较,我们如何截取。==========重点 ls_444 = 'goto error' else MessageBox('error','dddd') //PB的messagebox调用那个API end if MessageBox('error','dddd') //PB的messagebox调用那个API ls_444 = 'goto oookkk' //研究PB如何赋字符串值
ll_l2 = integer(ls_t2) ll_l2 -= ll_l1
if ll_l2 <> 0 Then MessageBox('error','dddd') end if
上面的代码很乱,仅仅是为了追踪研究。
OK,现在用TRW2000加载执行,
首先用bpx hmemcpy (即所谓的万能断点):结果不中断,却在我气愤的用鼠标点击单行编辑框时触发(真莫名其妙)。
改用bpx getdlgitemtexta(getdlgITemtext) 也不中断。 用bpx Getwindowtexta 结果,每输入一个字符就中断,真烦人。 用bpx messageboxa OK,提示消息时,中断。 说明PB的MessageBox时调用MessageBoxA的API。 但这用处不大,PBD是解释伪码执行的,我几乎没有办法来找出那里是确定是否来弹出提示框。因为它一句一句的解释执行,弹出消息框的行与判断条件的行被PB隔的不知那里去了。
再用用lstrcmpa: 哈哈,比较字符串的地方被截取了,如下: KERNEL32!lstrcmpA 017F:BFF77304 PUSH EBX 017F:BFF77305 PUSH ESI 017F:BFF77306 PUSH EDI 017F:BFF77307 PUSH EBP 017F:BFF77308 PUSH DWORD 01F2 017F:BFF7730D PUSH DWORD BFFA21CB 017F:BFF77312 PUSH DWORD [FS:00] 017F:BFF77319 MOV [FS:00],ESP 017F:BFF77320 MOV EAX,ESP 017F:BFF77322 PUSH DWORD [EAX+24] 017F:BFF77325 PUSH DWORD [EAX+20] 017F:BFF77328 CALL BFF71247 017F:BFF7732D POP DWORD [FS:00] 017F:BFF77334 ADD ESP,BYTE +08 017F:BFF77337 POP EBP
你试试 D EAX 和 D EDI 你看到了什么,哈哈,你输入的字符串和要比较的字符串,那现在你要做的是什么,去做吧,什么??,不知道!!,拿笔记下另外一个字符串!!
那,是不是PB的字符串比较都是这个呢,我又写了乱七八糟的代码,然后同样可以这样获得。
好了,现在字符串比较可以轻松搞定,那又如何截取到数值比较呢??这比较烦了,还要看别人写的程序如何了。
你看到我写的代码了吗,用了不少integer函数,一般要比较数值时,它都会把你输入的字符串转为整型或者长整型数值,即一般会调用integer()或者long()函数。
我们现在就现以integer来做。
重新启动TRW2000,记住把PBVM60.DLL放到TRW2000的DLL目录,让TRW2000启动时读入PBVM60.DLL,这样我们就可以以PBVM60里的函数来设定断点了。
打入:bpx fninteger =====》PB的Integer()函数 执行。被中断 PBVM60!fnInteger 017F:10BB8180 MOV EAX,[ESP+04] 017F:10BB8184 SUB ESP,BYTE +70 017F:10BB8187 PUSH EBX 017F:10BB8188 PUSH EBP 017F:10BB8189 PUSH ESI 017F:10BB818A MOV ESI,[EAX] 017F:10BB818C PUSH EDI 017F:10BB818D PUSH ESI 017F:10BB818E XOR EBX,EBX 017F:10BB8190 CALL `PBVM60!ot_get_next_evaled_arg` 017F:10BB8195 MOV CL,[EAX+04] 017F:10BB8198 AND ECX,BYTE +01 017F:10BB819B MOV EBP,ECX 017F:10BB819D JNZ NEAR 10BB8269 017F:10BB81A3 XOR ECX,ECX 017F:10BB81A5 MOV CX,[EAX+06] 017F:10BB81A9 LEA EDI,[ECX-01] 017F:10BB81AC CMP EDI,BYTE +0A 017F:10BB81AF JA NEAR 10BB8262 017F:10BB81B5 XOR EDX,EDX 017F:10BB81B7 MOV DL,[EDI+10BB82B8] 017F:10BB81BD JMP NEAR [EDX*4+10BB82A4] 017F:10BB81C4 PUSH EAX 017F:10BB81C5 PUSH ESI 017F:10BB81C6 CALL `PBVM60!ot_get_valptr` 017F:10BB81CB MOV ESI,EAX 017F:10BB81CD TEST ESI,ESI 017F:10BB81CF JZ NEAR 10BB8269
按5下F12,然后按F10,会来到下面一段代码: ........
017F:10C8F62D CALL NEAR [EAX+10D48328] 017F:10C8F633 MOV [EBP-04],EAX 017F:10C8F636 MOV EAX,[ESI+34] 017F:10C8F639 ADD ESP,BYTE +14 017F:10C8F63C TEST EAX,EAX 017F:10C8F63E JZ 10C8F647 017F:10C8F640 MOV DWORD [EBP-04],00 017F:10C8F647 MOV EAX,[ESI+14] 017F:10C8F64A TEST EAX,EAX 017F:10C8F64C JZ 10C8F5F1 ........
再U 017F:10C8F5EE 会看到如下代码: 017F:10C8F5EE MOV EDI,[EBP-18] 017F:10C8F5F1 MOV EAX,[EBP+10] 017F:10C8F5F4 MOV EDX,[ESI+10] 017F:10C8F5F7 CMP EDX,[EAX+16] 017F:10C8F5FA JNC 10C8F64E 017F:10C8F5FC CMP DWORD [EBP-04],BYTE +01 017F:10C8F600 JNZ 10C8F64E 017F:10C8F602 MOV ECX,[EBP-20] 017F:10C8F605 XOR EAX,EAX 017F:10C8F607 ADD ECX,EDX 017F:10C8F609 PUSH EDI 017F:10C8F60A MOV AX,[ECX] 017F:10C8F60D LEA EAX,[EAX+EAX*2] 017F:10C8F610 SHL EAX,02 017F:10C8F613 MOV EBX,[EAX+10D4832C] 017F:10C8F619 LEA EDX,[EDX+EBX*2+02] 017F:10C8F61D MOV [ESI+10],EDX 017F:10C8F620 LEA EDX,[EBP+FFFFFF28] 017F:10C8F626 PUSH EDX 017F:10C8F627 MOV EDX,[EBP-14] 017F:10C8F62A PUSH EDX 017F:10C8F62B PUSH ECX 017F:10C8F62C PUSH ESI 017F:10C8F62D CALL NEAR [EAX+10D48328]
看到了吗, 这一句
017F:10C8F62D CALL NEAR [EAX+10D48328]是重点。
所有的伪码都要通过这一句进入执行。
我们再来看看一般一句代码执行完后,再进入CALL NEAR [EAX+10D48328] 几次,才执行下一句。
我们就研究这一段:
ll_l2 = integer(ls_t1) //看此处会触发什么 ll_l2 -= ll_l1 if ls_t1 <> 'fdfggfh' Then //研究PB的字符比较会调用什么。=========重点 ll_l2 = ll_l2 * 2 else ll_l3 = integer('24354') end if
if ll_l2 <> 3107 Then //研究PB如何进行数值比较,我们如何截取。==========重点 ls_444 = 'goto error' else MessageBox('error','dddd') //PB的messagebox调用那个API end if
首先是在l_l2 = integer(ls_t1) 调用integer时中断, 5个F12,1个F10到CALL NEAR [EAX+10D48328] 我们现在开始记录每一次进入CALL NEAR [EAX+10D48328] 一直到if ll_l2 <> 3107 Then 这条比较语句。
第一次进入: 017F:10D01170 MOV EAX,[ESP+08] =========》 017F:10D01170 017F:10D01174 XOR ECX,ECX 好像处理返回参数 017F:10D01176 PUSH ESI 017F:10D01177 PUSH EDI 017F:10D01178 MOV CX,[EAX+02] 017F:10D0117C MOV EAX,[ESP+14] 017F:10D01180 TEST ECX,ECX 017F:10D01182 JNG 10D0119A 017F:10D01184 MOV EDX,FFFFFFE6 017F:10D01189 MOV EDI,[EAX+010A] 017F:10D0118F ADD EDI,EDX 017F:10D01191 DEC ECX 017F:10D01192 MOV [EAX+010A],EDI 017F:10D01198 JNZ 10D01189 017F:10D0119A MOV ESI,[ESP+18] 017F:10D0119E MOV EDI,[EAX+010A]
第二次进入: 017F:10CFC0D0 MOV ECX,[ESP+08] ========》 017F:10CFC0D0 017F:10CFC0D4 XOR EAX,EAX 好像处理返回参数 017F:10CFC0D6 MOV AX,[ECX+02] 017F:10CFC0DA LEA EDX,[EAX+EAX*2] 017F:10CFC0DD LEA EAX,[EAX+EDX*4] 017F:10CFC0E0 MOV EDX,[ESP+0C] 017F:10CFC0E4 SHL EAX,1 017F:10CFC0E6 MOV ECX,EAX 017F:10CFC0E8 MOV EAX,[EDX+010A] 017F:10CFC0EE SUB EAX,ECX 017F:10CFC0F0 MOV DL,[EAX+04] 017F:10CFC0F3 MOV WORD [EAX+06],02 017F:10CFC0F9 MOVSX ECX,WORD [EAX] 017F:10CFC0FC AND EDX,BYTE +01 017F:10CFC0FF MOV [EAX],ECX
第三次进入: 017F:10D09C60 PUSH EBX ============》 017F:10D09C60 017F:10D09C61 PUSH ESI 好像处理返回参数 017F:10D09C62 MOV ESI,[ESP+14] 017F:10D09C66 MOV EBX,[ESP+10] 017F:10D09C6A PUSH EDI 017F:10D09C6B MOV EDX,[ESI+010A] 017F:10D09C71 ADD EDX,BYTE -1A 017F:10D09C74 MOV EAX,EDX 017F:10D09C76 MOV [ESI+010A],EDX 017F:10D09C7C CMP WORD [EBX+02],BYTE +00 017F:10D09C81 LEA ECX,[EAX-1A] 017F:10D09C84 MOV [ESI+010A],ECX 017F:10D09C8A JNA 10D09CD6 017F:10D09C8C MOV EDI,[ECX] 017F:10D09C8E MOV CL,[EAX+04]
第四次进入: 017F:10CFB8C0 MOV ECX,[ESP+08] ==============> 017F:10CFB8C0 017F:10CFB8C4 PUSH ESI 017F:10CFB8C5 MOV ESI,[ESP+10] 好像处理返回参数 017F:10CFB8C9 PUSH EDI 017F:10CFB8CA MOV EAX,[ESI+C2] 017F:10CFB8D0 MOV [ESP+14],EAX 017F:10CFB8D4 XOR EAX,EAX 017F:10CFB8D6 MOV AX,[ECX+02] 017F:10CFB8DA MOV ECX,[ESI+52] 017F:10CFB8DD CMP ECX,BYTE +03 017F:10CFB8E0 JNZ 10CFB918 017F:10CFB8E2 LEA EDX,[ESP+14] 017F:10CFB8E6 PUSH EAX 017F:10CFB8E7 PUSH EDX 017F:10CFB8E8 PUSH ESI 017F:10CFB8E9 CALL 10C329B0 017F:10CFB8EE ADD ESP,BYTE +0C
第五次进入: 017F:10CF9670 MOV ECX,[ESP+08] ==================> 017F:10CF9670 017F:10CF9674 PUSH ESI 好像准备下一条语句执行 017F:10CF9675 MOV ESI,[ESP+10] 017F:10CF9679 PUSH EDI 017F:10CF967A MOV EAX,[ESI+C2] 017F:10CF9680 MOV [ESP+14],EAX 017F:10CF9684 MOV AX,[ECX+02] 017F:10CF9688 CMP DWORD [ESI+52],BYTE +03 017F:10CF968C JNZ 10CF96C2 017F:10CF968E LEA EDX,[ESP+14] 017F:10CF9692 PUSH EAX 017F:10CF9693 PUSH EDX 017F:10CF9694 PUSH ESI 017F:10CF9695 CALL 10C329B0 017F:10CF969A ADD ESP,BYTE +0C 017F:10CF969D TEST EAX,EAX 017F:10CF969F JNZ 10CF96A4
第六次进入: 017F:10D0B130 PUSH EBX ==================> 017F:10D0B130 017F:10D0B131 PUSH EBP 执行了语句ll_l2 -= ll_l1 017F:10D0B132 PUSH ESI 017F:10D0B133 MOV ESI,[ESP+18] 017F:10D0B137 MOV EAX,[ESP+14] 017F:10D0B13B PUSH EDI 017F:10D0B13C MOV EBX,[ESI+010A] 017F:10D0B142 ADD EBX,BYTE -1A 017F:10D0B145 MOV [ESI+010A],EBX 017F:10D0B14B MOV DL,[EBX+04] 017F:10D0B14E AND EDX,BYTE +01 017F:10D0B151 CMP WORD [EAX+02],BYTE +00 017F:10D0B156 LEA EAX,[EBX-1A] 017F:10D0B159 MOV [ESP+1C],EDX 017F:10D0B15D MOV [ESI+010A],EAX
第七次进入: 017F:10CF9670 MOV ECX,[ESP+08] ==============> 017F:10CF9670 017F:10CF9674 PUSH ESI 017F:10CF9675 MOV ESI,[ESP+10] 好像准备下一条语句执行 017F:10CF9679 PUSH EDI 017F:10CF967A MOV EAX,[ESI+C2] 017F:10CF9680 MOV [ESP+14],EAX 017F:10CF9684 MOV AX,[ECX+02] 017F:10CF9688 CMP DWORD [ESI+52],BYTE +03 017F:10CF968C JNZ 10CF96C2 017F:10CF968E LEA EDX,[ESP+14] 017F:10CF9692 PUSH EAX 017F:10CF9693 PUSH EDX 017F:10CF9694 PUSH ESI 017F:10CF9695 CALL 10C329B0 017F:10CF969A ADD ESP,BYTE +0C 017F:10CF969D TEST EAX,EAX 017F:10CF969F JNZ 10CF96A4
[1] [2] 下一页 |