• 标 题:如何破解PB6.5编译的程序 (23千字)
    发信人:Leafred
    时 间:2001-5-2 21:43:23
    详细信息:

    标题:如何破解PB6.5编译的程序
    作者:Leafred
    主页:http://leafred.126.com/

    如何破解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

    第八次进入:
    017F:10CFB7C0 MOV EAX,[ESP+08] ===================> 017F:10CFB7C0 
    017F:10CFB7C4 XOR ECX,ECX
    017F:10CFB7C6 XOR EDX,EDX 好像现设置要比较的字符串
    017F:10CFB7C8 PUSH ESI 先取出来
    017F:10CFB7C9 MOV CX,[EAX+04]
    017F:10CFB7CD MOV DX,[EAX+02]
    017F:10CFB7D1 MOV ESI,[ESP+10]
    017F:10CFB7D5 SHL ECX,10
    017F:10CFB7D8 MOV EAX,[ESI+C2]
    017F:10CFB7DE OR ECX,EDX
    017F:10CFB7E0 PUSH ECX
    017F:10CFB7E1 PUSH EAX
    017F:10CFB7E2 PUSH ESI
    017F:10CFB7E3 CALL `PBVM60!ob_get_const`
    017F:10CFB7E8 MOV ECX,[ESI+010A]
    017F:10CFB7EE MOV [ECX],EAX

    第九次进入:
    017F:10D05EB0 PUSH EBX ======》 此段代码进行字符串比较,调用lstrcmpA
    017F:10D05EB1 PUSH EBP if ls_t1 <> 'fdfggfh' Then 
    017F:10D05EB2 PUSH ESI 此处代码未全部拷贝。
    017F:10D05EB3 MOV ESI,[ESP+18]
    017F:10D05EB7 PUSH EDI
    017F:10D05EB8 MOV EAX,[ESI+010A]
    017F:10D05EBE LEA EBX,[EAX-1A]
    017F:10D05EC1 LEA EBP,[EBX-1A]
    017F:10D05EC4 MOV [ESI+010A],EBP
    017F:10D05ECA TEST BYTE [EBP+04],01
    017F:10D05ECE JNZ 10D05EDE
    017F:10D05ED0 TEST BYTE [EBX+04],01
    017F:10D05ED4 JNZ 10D05EDE
    017F:10D05ED6 XOR EAX,EAX
    017F:10D05ED8 MOV [ESP+1C],EAX
    017F:10D05EDC JMP SHORT 10D05EEA
    017F:10D05EDE MOV DWORD [ESP+1C],01

    第十次进入:
    017F:10D0A560 MOV EAX,[ESP+0C] =========================> 017F:10D0A560
    017F:10D0A564 MOV EDX,[EAX+010A] 好像处理if then
    017F:10D0A56A ADD EDX,BYTE -1A
    017F:10D0A56D MOV [EAX+010A],EDX
    017F:10D0A573 MOV EAX,EDX
    017F:10D0A575 TEST BYTE [EAX+04],01
    017F:10D0A579 JNZ 10D0A581
    017F:10D0A57B CMP WORD [EAX],BYTE +00
    017F:10D0A57F JNZ 10D0A592
    017F:10D0A581 MOV ECX,[ESP+08]
    017F:10D0A585 MOV EDX,[ESP+04]
    017F:10D0A589 XOR EAX,EAX
    017F:10D0A58B MOV AX,[ECX+02]
    017F:10D0A58F MOV [EDX+10],EAX

    第十一次进入:
    017F:10CFB8C0 MOV ECX,[ESP+08] =================> 017F:10CFB8C0 
    017F:10CFB8C4 PUSH ESI
    017F:10CFB8C5 MOV ESI,[ESP+10] 好像处理if then
    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:10CFB510 MOV ECX,[ESP+08] =========================> 017F:10CFB510 
    017F:10CFB514 MOV EAX,[ESP+0C] 这段代码好像设置乘数 2
    017F:10CFB518 PUSH ESI
    017F:10CFB519 XOR ESI,ESI
    017F:10CFB51B MOV SI,[ECX+04]
    017F:10CFB51F XOR EDX,EDX
    017F:10CFB521 MOV DX,[ECX+02]
    017F:10CFB525 MOV ECX,[EAX+010A]
    017F:10CFB52B SHL ESI,10
    017F:10CFB52E OR EDX,ESI
    017F:10CFB530 POP ESI
    017F:10CFB531 MOV [ECX],EDX
    017F:10CFB533 MOV EDX,[EAX+010A]
    017F:10CFB539 MOV WORD [EDX+04],1D00
    017F:10CFB53F MOV ECX,[EAX+010A]

    第十四次进入:
    017F:10D08AF0 MOV EDX,[ESP+0C] ===================> 017F:10D08AF0
    017F:10D08AF4 PUSH EBX
    017F:10D08AF5 PUSH ESI
    017F:10D08AF6 MOV ESI,[EDX+010A]
    017F:10D08AFC LEA ECX,[ESI-34]
    017F:10D08AFF MOV [EDX+010A],ECX
    017F:10D08B05 MOV EAX,[ESI-1A]
    017F:10D08B08 IMUL EAX,[ECX] =====> 这里执行 ll_l2 * 2 EAX=2
    017F:10D08B0B MOV [ECX],EAX
    017F:10D08B0D MOV BL,[ECX+04]
    017F:10D08B10 MOV EAX,01
    017F:10D08B15 TEST AL,BL
    017F:10D08B17 JNZ 10D08B22
    017F:10D08B19 TEST [ESI-16],AL
    017F:10D08B1C JNZ 10D08B22
    017F:10D08B1E XOR ECX,ECX

    第十五次进入:
    017F:10D09C60 PUSH EBX ======================> 017F:10D09C60
    017F:10D09C61 PUSH ESI
    017F:10D09C62 MOV ESI,[ESP+14] 处理if then
    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:10D0A540 MOV ECX,[ESP+08] =======================> 017F:10D0A540
    017F:10D0A544 MOV EDX,[ESP+04] 处理if then
    017F:10D0A548 XOR EAX,EAX
    017F:10D0A54A MOV AX,[ECX+02]
    017F:10D0A54E MOV [EDX+10],EAX
    017F:10D0A551 MOV EAX,01
    017F:10D0A556 RET 
    017F:10D0A557 NOP 
    017F:10D0A558 NOP 
    017F:10D0A559 NOP 
    017F:10D0A55A NOP 
    017F:10D0A55B NOP 
    017F:10D0A55C NOP 
    017F:10D0A55D NOP 
    017F:10D0A55E NOP 
    017F:10D0A55F NOP 
    017F:10D0A560 MOV EAX,[ESP+0C]
    017F:10D0A564 MOV EDX,[EAX+010A]
    017F:10D0A56A ADD EDX,BYTE -1A
    017F:10D0A56D MOV [EAX+010A],EDX

    第十七次进入:
    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:10CFB510 MOV ECX,[ESP+08] ========================> 017F:10CFB510
    017F:10CFB514 MOV EAX,[ESP+0C]
    017F:10CFB518 PUSH ESI
    017F:10CFB519 XOR ESI,ESI 好像设置要比较的一个数值3107
    017F:10CFB51B MOV SI,[ECX+04]
    017F:10CFB51F XOR EDX,EDX
    017F:10CFB521 MOV DX,[ECX+02]
    017F:10CFB525 MOV ECX,[EAX+010A]
    017F:10CFB52B SHL ESI,10
    017F:10CFB52E OR EDX,ESI
    017F:10CFB530 POP ESI
    017F:10CFB531 MOV [ECX],EDX
    017F:10CFB533 MOV EDX,[EAX+010A]
    017F:10CFB539 MOV WORD [EDX+04],1D00
    017F:10CFB53F MOV ECX,[EAX+010A]

    第十九次进入:
    017F:10D05C40 MOV EDX,[ESP+0C] =====================> 017F:10D05C40
    017F:10D05C44 PUSH EBX 进行 if ll_l2 <> 3107 Then
    017F:10D05C45 PUSH ESI
    017F:10D05C46 PUSH EDI
    017F:10D05C47 MOV ESI,[EDX+010A]
    017F:10D05C4D XOR EBX,EBX
    017F:10D05C4F LEA ECX,[ESI-34]
    017F:10D05C52 MOV [EDX+010A],ECX
    017F:10D05C58 MOV EDI,[ESI-1A]
    017F:10D05C5B MOV EAX,[ECX]
    017F:10D05C5D CMP EAX,EDI =======》EDI处存放了3107
    017F:10D05C5F MOV EAX,01 EAX是ll_l2的值。
    017F:10D05C64 SETNZ BL
    017F:10D05C67 MOV [ECX],BX
    017F:10D05C6A MOV BL,[ECX+04]
    017F:10D05C6D TEST AL,BL
    017F:10D05C6F JNZ 10D05C7A


    OK,现在我们总结一下:

    XXXX:10C8F62D CALL NEAR [EAX+10D48328]
    该处是PBVM60解释入口处,可以直接在次设定断点。
    此处地址10C8F62D 是不变的。

    一般算法代码:(除法还进一步研究)

    减法:
    017F:10D0B1F6 MOV ECX,[EAX]
    017F:10D0B1F8 MOV AX,[ECX+04]
    017F:10D0B1FC MOV ESI,EAX
    017F:10D0B1FE AND EAX,FFFE
    017F:10D0B203 AND ESI,BYTE +01
    017F:10D0B206 OR EDX,ESI
    017F:10D0B208 OR EAX,EDX
    017F:10D0B20A MOV [ECX+04],AX
    017F:10D0B20E MOV EDX,[EBX]
    017F:10D0B210 SUB [ECX],EDX ===========》 EDX 处存放减数
    017F:10D0B212 POP EDI
    017F:10D0B213 POP ESI
    017F:10D0B214 POP EBP
    017F:10D0B215 MOV EAX,01
    017F:10D0B21A POP EBX
    017F:10D0B21B RET 

    加法:
    017F:10D08310 MOV EDX,[ESP+0C]
    017F:10D08314 PUSH EBX
    017F:10D08315 PUSH ESI
    017F:10D08316 MOV ESI,[EDX+010A]
    017F:10D0831C LEA ECX,[ESI-34]
    017F:10D0831F MOV [EDX+010A],ECX
    017F:10D08325 MOV EAX,[ESI-1A]
    017F:10D08328 ADD EAX,[ECX] ==========》 EAX 为加数
    017F:10D0832A MOV [ECX],EAX
    017F:10D0832C MOV BL,[ECX+04]
    017F:10D0832F MOV EAX,01
    017F:10D08334 TEST AL,BL
    017F:10D08336 JNZ 10D08341
    017F:10D08338 TEST [ESI-16],AL
    017F:10D0833B JNZ 10D08341
    017F:10D0833D XOR ECX,ECX
    017F:10D0833F JMP SHORT 10D08343
    017F:10D08341 MOV ECX,EAX
    017F:10D08343 MOV ESI,[EDX+010A]
    017F:10D08349 OR CH,1D
    017F:10D0834C MOV [ESI+04],CX
    017F:10D08350 MOV ECX,[EDX+010A]
    017F:10D08356 POP ESI
    017F:10D08357 POP EBX
    017F:10D08358 MOV WORD [ECX+06],02
    017F:10D0835E MOV ECX,[EDX+010A]

    乘法:
    017F:10D08AF0 MOV EDX,[ESP+0C]
    017F:10D08AF4 PUSH EBX
    017F:10D08AF5 PUSH ESI
    017F:10D08AF6 MOV ESI,[EDX+010A]
    017F:10D08AFC LEA ECX,[ESI-34]
    017F:10D08AFF MOV [EDX+010A],ECX
    017F:10D08B05 MOV EAX,[ESI-1A]
    017F:10D08B08 IMUL EAX,[ECX] =========》 EAX 乘数
    017F:10D08B0B MOV [ECX],EAX
    017F:10D08B0D MOV BL,[ECX+04]
    017F:10D08B10 MOV EAX,01
    017F:10D08B15 TEST AL,BL
    017F:10D08B17 JNZ 10D08B22
    017F:10D08B19 TEST [ESI-16],AL
    017F:10D08B1C JNZ 10D08B22
    017F:10D08B1E XOR ECX,ECX
    017F:10D08B20 JMP SHORT 10D08B24
    017F:10D08B22 MOV ECX,EAX
    017F:10D08B24 MOV ESI,[EDX+010A]
    017F:10D08B2A OR CH,1D
    017F:10D08B2D MOV [ESI+04],CX
    017F:10D08B31 MOV ECX,[EDX+010A]
    017F:10D08B37 POP ESI
    017F:10D08B38 POP EBX
    017F:10D08B39 MOV WORD [ECX+06],02
    017F:10D08B3F MOV ECX,[EDX+010A]

    字符串比较:
    017F:10D05EEE PUSH EBP
    017F:10D05EEF PUSH ESI
    017F:10D05EF0 CALL `PBVM60!ot_get_valptr`
    017F:10D05EF5 PUSH EBX
    017F:10D05EF6 PUSH ESI
    017F:10D05EF7 MOV EDI,EAX
    017F:10D05EF9 CALL `PBVM60!ot_get_valptr`
    017F:10D05EFE PUSH EAX
    017F:10D05EFF PUSH EDI
    017F:10D05F00 CALL `KERNEL32!lstrcmpA` =========》EAX 和 EDI 存放的
    017F:10D05F06 MOV EDI,EAX 字符串比较
    017F:10D05F08 MOV EAX,[ESP+1C]
    017F:10D05F0C NEG EDI
    017F:10D05F0E SBB EDI,EDI
    017F:10D05F10 NEG EDI ========》 OK则EDI 为 0,否则 1
    017F:10D05F12 JMP SHORT 10D05F18
    017F:10D05F14 MOV EDI,[ESP+18]
    017F:10D05F18 MOV ECX,[ESP+18]
    017F:10D05F1C CMP WORD [ECX+02],BYTE +00
    017F:10D05F21 JZ 10D05F2E
    017F:10D05F23 PUSH EBX
    017F:10D05F24 PUSH ESI
    017F:10D05F25 CALL `PBVM60!ot_free_val_ptr`
    017F:10D05F2A MOV EAX,[ESP+1C]
    017F:10D05F2E MOV EDX,[ESP+18]
    017F:10D05F32 CMP WORD [EDX+04],BYTE +00
    017F:10D05F37 JZ 10D05F44
    017F:10D05F39 PUSH EBP
    017F:10D05F3A PUSH ESI
    017F:10D05F3B CALL `PBVM60!ot_free_val_ptr`

    数值比较:
    017F:10D05C58 MOV EDI,[ESI-1A]
    017F:10D05C5B MOV EAX,[ECX]
    017F:10D05C5D CMP EAX,EDI =========》 执行比较,EDI 比较数
    017F:10D05C5F MOV EAX,01
    017F:10D05C64 SETNZ BL
    017F:10D05C67 MOV [ECX],BX
    017F:10D05C6A MOV BL,[ECX+04]
    017F:10D05C6D TEST AL,BL
    017F:10D05C6F JNZ 10D05C7A
    017F:10D05C71 TEST [ESI-16],AL
    017F:10D05C74 JNZ 10D05C7A
    017F:10D05C76 XOR ECX,ECX
    017F:10D05C78 JMP SHORT 10D05C7C
    017F:10D05C7A MOV ECX,EAX
    017F:10D05C7C MOV ESI,[EDX+010A]
    017F:10D05C82 OR CH,05
    017F:10D05C85 POP EDI
    017F:10D05C86 MOV [ESI+04],CX
    017F:10D05C8A MOV ECX,[EDX+010A]
    017F:10D05C90 POP ESI
    017F:10D05C91 POP EBX
    017F:10D05C92 MOV WORD [ECX+06],07
    017F:10D05C98 MOV ECX,[EDX+010A]
    017F:10D05C9E ADD ECX,BYTE +1A
    017F:10D05CA1 MOV [EDX+010A],ECX
    017F:10D05CA7 RET 



    PB7.0基本上与PB6.5相同,只不过入口不同而已,它的解释入口是:
    XXXX:1135BEEE CALL NEAR [EAX+11450E28],
    即入口地址是XXXX:1135BEEE