分享

【原创】pb程序调试初探

 imelee 2015-03-02
标 题: 【原创】pb程序调试初探
作 者: lzqgj
时 间: 2007-05-10,22:48:15
链 接: http://bbs./showthread.php?t=44277

软件名称:职称英语学习帮手(综合类)
破解工具:OD,shudepb,pbkill,winhex
破解目的:自用

最近要考职称英语,下载了个职称英语的软件来学习。
未注册的版本只能阅读每个部分第一篇,可惜我的银子不够,只好拿它开刀。
打开程序目录,顿时傻眼:PB程序。关于PB程序的调试可以说网上几乎还没有,可见非常困难。
没有反编译工具几乎是不可能完成的任务。而即使是反编译出来,如果编程功力不够,也很难看出注册方法和写注册机。
而爆破关键跳转目前在网上我还没有搜到跳转的机器码是什么。
调试过程的那个辛苦啊,我只想说:破解=运气+毅力。真的,运气可能是第一位的。

先找工具反编译。试了pbkill,只得到一堆if...else...end if之类的,一句代码也没有出来(可能是pbkill试用版吧?)
在网上又搜到另一个反编译工具shudepb,使用确实很好,支持全局搜索,大大方便找关键代码。
全局搜索提示:"对不起,你尚未注册,只能阅读每一部分的第一篇文章!欢迎注册!",找到以下代码:
//Has been Shielded.
index = PARENT.ddlb_text.finditem(PARENT.ddlb_text.text,1)
index ++
IF index > 1 AND gb_register = FALSE THEN //3
  PARENT.ddlb_text.text = PARENT.is_etitle
  messagebox("提示","对不起,你尚未注册,只能阅读每一部分的第一篇文章!欢迎注册!")
  THIS.setfocus()
  RETURN
END IF //3
ls_text = PARENT.ddlb_text.text(index)
IF ls_text = "" THEN //10
  index --
  PARENT.ddlb_text.text = PARENT.ddlb_text.text(index)
  RETURN
END IF //10
PARENT.ddlb_text.text = PARENT.ddlb_text.text(index)
PARENT.ddlb_text.triggerevent(selectionchanged!)
RETURN

这个就是点击“下篇”按钮时的过程,判断是否大于第一题和是否未注册,两者条件都满足时跳出NAG。
gb_register是个全局变量,是否注册的标志。再次搜索gb_register可以找到很多赋值语句,说明程序多处进行校验。
注册过程就不贴了,感觉还是比较复杂,我没看明白,只好想到用爆破的方法。于是艰苦的调试过程开始了。

众所周知,PB程序类似于VB的pcode,是解释执行的,调试时在pbvm80.dll中转,
与pcode又有很大不同,你几乎找不到程序在什么地方进行比较,什么地方根据比较结果进行跳转(至少没有人公开过)。
用OD载入程序,运行,点“下篇”弹出NAG,回到OD,F12暂停,Alt+F9运行,回到程序点确定,程序中断,
不断F8单步执行(按住不放好了),最终发现程序在下面一段反复执行:
10CEEB52  MOV ECX,DWORD PTR SS:[EBP-20]
10CEEB55  XOR EAX,EAX
10CEEB57  ADD ECX,EDX
10CEEB59  MOV AX,WORD PTR DS:[ECX]
10CEEB5C  LEA EAX,DWORD PTR DS:[EAX+EAX*2]
10CEEB5F  SHL EAX,2
10CEEB62  MOV EBX,DWORD PTR DS:[EAX+10DF2B84]
10CEEB68  LEA EDX,DWORD PTR DS:[EDX+EBX*2+2]
10CEEB6C  MOV DWORD PTR DS:[ESI+14],EDX
10CEEB6F  MOV EDX,DWORD PTR SS:[EBP-24]
10CEEB72  PUSH EDX
10CEEB73  LEA EDX,DWORD PTR SS:[EBP-E8]
10CEEB79  PUSH EDX
10CEEB7A  PUSH EDI
10CEEB7B  PUSH ECX
10CEEB7C  PUSH ESI
10CEEB7D  CALL DWORD PTR DS:[EAX+10DF2B80]         --->关键,程序解释入口
10CEEB83  MOV DWORD PTR SS:[EBP-4],EAX
10CEEB86  MOV EAX,DWORD PTR DS:[EDI+24C]
10CEEB8C  ADD ESP,14
10CEEB8F  TEST EAX,EAX
10CEEB91  JE SHORT PBVM80.10CEEBAA
10CEEB93  PUSH EDI
10CEEB94  MOV DWORD PTR SS:[EBP-4],1
10CEEB9B  CALL PBVM80.10CEE640
10CEEBA0  ADD ESP,4
10CEEBA3  MOV DWORD PTR SS:[EBP-18],EAX
10CEEBA6  TEST EAX,EAX
10CEEBA8  JE SHORT PBVM80.10CEEBBF
10CEEBAA  MOV EAX,DWORD PTR DS:[ESI+38]
10CEEBAD  TEST EAX,EAX
10CEEBAF  JE SHORT PBVM80.10CEEBB8
10CEEBB1  MOV DWORD PTR SS:[EBP-4],0
10CEEBB8  MOV EAX,DWORD PTR DS:[ESI+18]
10CEEBBB  TEST EAX,EAX
10CEEBBD  JE SHORT PBVM80.10CEEB41

根据对pcode的了解,猜测10CEEB7D  CALL DWORD PTR DS:[EAX+10DF2B80]即是程序解释的入口。
不断跟踪发现解释原理是这样的:根据EAX值的不同,程序call到不同位置执行不同任务,
如读取程序的代码,然后解释执行程序等。
猜测当EAX=2AC或0C或18时,会读取原程序代码,等于其它一些数值时会执行原程序。
不能直接在10CEEB7D处下断,因为一返回程序就会中断。
于是对“下篇”按钮下WM_lbuttonup消息断点,点击后中断,返回OD,在10CEEB7D处下断,F9运行。
当EAX不等于2AC或0C或18时跟F7进去看看。经过n次(未统计,估计>200),
终于在EAX=93C时找到了需要的代码,跟进去程序为:
10D967B0  MOV ECX,DWORD PTR SS:[ESP+C]
10D967B4  PUSH EBX
10D967B5  PUSH ESI
10D967B6  PUSH EDI
10D967B7  MOV ESI,DWORD PTR DS:[ECX+10E]
10D967BD  XOR EBX,EBX
10D967BF  LEA EDX,DWORD PTR DS:[ESI-38]
10D967C2  MOV DWORD PTR DS:[ECX+10E],EDX
10D967C8 >MOV EDI,DWORD PTR DS:[ESI-1C]
10D967CB  MOV EAX,DWORD PTR DS:[EDX]
10D967CD  CMP EAX,EDI                      --->对应index > 1的比较
10D967CF  MOV EAX,1
10D967D4  SETG BL                                                    --->对应index > 1的比较
10D967D7  MOV WORD PTR DS:[EDX],BX
10D967DA  MOV BL,BYTE PTR DS:[EDX+4]
10D967DD  TEST AL,BL
10D967DF  JNZ SHORT PBVM80.10D967EA
10D967E1  TEST BYTE PTR DS:[ESI-18],AL
10D967E4  JNZ SHORT PBVM80.10D967EA
10D967E6  XOR EDX,EDX
10D967E8  JMP SHORT PBVM80.10D967EC
10D967EA  MOV EDX,EAX
10D967EC  MOV ESI,DWORD PTR DS:[ECX+10E]
10D967F2  OR DH,5
10D967F5  POP EDI
10D967F6  MOV WORD PTR DS:[ESI+4],DX
10D967FA  MOV EDX,DWORD PTR DS:[ECX+10E]
10D96800  POP ESI
10D96801  POP EBX
10D96802  MOV WORD PTR DS:[EDX+6],7
10D96808  MOV EDX,DWORD PTR DS:[ECX+10E]
10D9680E  MOV WORD PTR DS:[EDX+1A],0
10D96814  MOV EDX,DWORD PTR DS:[ECX+10E]
10D9681A  ADD EDX,1C
10D9681D  MOV DWORD PTR DS:[ECX+10E],EDX
10D96823  RETN

继续跟踪,当EAX=804时,跟进得到如下代码:
10D95580  MOV ECX,DWORD PTR SS:[ESP+C]
10D95584  PUSH EBX
10D95585  PUSH ESI
10D95586  XOR EBX,EBX
10D95588  MOV ESI,DWORD PTR DS:[ECX+10E]
10D9558E  LEA EDX,DWORD PTR DS:[ESI-38]
10D95591  MOV DWORD PTR DS:[ECX+10E],EDX
10D95597  MOV AX,WORD PTR DS:[EDX]
10D9559A >CMP AX,WORD PTR DS:[ESI-1C]       --->对应gb_register = FALSE的比较
10D9559E  MOV EAX,1
10D955A3  SETE BL                           --->对应gb_register = FALSE的比较
10D955A6  MOV WORD PTR DS:[EDX],BX
10D955A9  MOV BL,BYTE PTR DS:[EDX+4]
10D955AC  TEST AL,BL
10D955AE  JNZ SHORT PBVM80.10D955B9
10D955B0  TEST BYTE PTR DS:[ESI-18],AL
10D955B3  JNZ SHORT PBVM80.10D955B9
10D955B5  XOR EDX,EDX
10D955B7  JMP SHORT PBVM80.10D955BB
10D955B9  MOV EDX,EAX
10D955BB  MOV ESI,DWORD PTR DS:[ECX+10E]
10D955C1  OR DH,5
10D955C4  MOV WORD PTR DS:[ESI+4],DX
10D955C8  MOV EDX,DWORD PTR DS:[ECX+10E]
10D955CE  POP ESI
10D955CF  POP EBX
10D955D0  MOV WORD PTR DS:[EDX+6],7
10D955D6  MOV EDX,DWORD PTR DS:[ECX+10E]
10D955DC  MOV WORD PTR DS:[EDX+1A],0
10D955E2  MOV EDX,DWORD PTR DS:[ECX+10E]
10D955E8  ADD EDX,1C
10D955EB  MOV DWORD PTR DS:[ECX+10E],EDX
10D955F1  RETN

找到比较代码还是不能爆破的,因为这些代码是在pbvm80.dll中,程序的正确运行是需要它的。
还要找到原程序的代码并修改。这个可没有现成经验。
我的修改思路是将index > 1改成index > 99999(随便你修改),(gb_register是变量,不容易修改的)
在10D967C8 >MOV EDI,DWORD PTR DS:[ESI-1C]处观察ESI-1C的值为A09420,对A09420下硬件写入断点,
运行时会中断很多次,在最后中断在10D9559A >CMP AX,WORD PTR DS:[ESI-1C]的前一次看,
得到程序读入1F30658处的值(即0),在数据窗口中显示为:
01000000390001000300F40931000100000039000100010006,用Winhex打开程序,搜索,
找到地址:0013AC27处,修改0100为FFFF,保存。
再次运行程序,点下篇,没有NAG了吧?
实际程序还没有爆破完全,但是功能限制已经取消了。

小结一下:
10CEEB7D  CALL DWORD PTR DS:[EAX+10DF2B80] 是PB程序解释入口,EAX值不同代表不同功能
我猜测EAX=93C时比较是否大于,EAX=804时比较逻辑值是否相等。
其它的值代表的含义希望大家继续跟踪贴出来分享。

调试程序好累,写文章更累。真的需要很好地耐心。休息一下,明天继续爆破注册。那个稍微容易点。                                 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多