VB 调试之 P-Code 替换操作码
使用工具
- OllyDbg 1.10原版,简称
OD
; OD
汉化
和插件
均来自互联网;- CrackMe 和 opcodes.txt来自互联网,仅供学习使用;
- 文中特殊数字均是
HEX
,为了书写方便采用DEC
;
分析思路
运行程序,程序会先弹出一个 NAG 窗口,点击确定后弹出主窗体:
导入
OD
开始分析,首先按照常规思路,既然有弹窗,肯定会使用 API:rtcMsgBox
:查看 API 列表,找到
rtcMsgBox
设置断点,然后运行程序;程序中断后,在栈窗口
反汇编窗口跟随
到返回位置:在调用位置设置断点,然后重载并运行程序;
调用指令是
CALL EAX
,当前 EAX 值为 401000,Ctrl + G
跳转到 401000,正是rtcMsgBox
:按下
-
减号键,回到断点位置,既然是调用函数,CALL 上面的指令就是它的参数,这种传参方式在 P-Code 中很常见,还没有完,继续;CALL 的参数到底是什么呢?
根据上面的代码逻辑,获取一个操作码后无条件跳转了,所以,
JMP
以上的代码与 CALL 无关;因此,CALL 的参数应该是
JMP
向下,直到CALl
;给参数起始位置设置断点,因为中间包含
JE
跳转,为了防止跳转,同时给JE
也设置断点,重载并运行程序;这里的戏就很精彩了,程序中断在参数位置:
然后按下
Ctrl + A
分析程序,在信息窗口发现跳转至此处的位置太多,如果挨个儿去跟,那就相当精彩了;同时,EAX 中有一个操作码
OA
,为啥它是操作码?因为根据 P-Code 的惯例,接下来既然要获取参数了,且代码没有执行,那 EAX 中存放的就是上一步的结果,而 P-Code 的逻辑就是先获取操作码,紧接着就是获取参数,那就说明,接下来获取的参数既是 CALL 的参数,也是OA
操作码的参数,So,OA
肯定是一个操作码;数据窗口跟随 ESI,发现
OA
位于当前 ESI 之前,地址是:401AD2;既然接下来要执行 CALL 也就是
rtcMsgBox
函数了,那么OA
在 P-Code 中是否就是rtcMsgBox
呢?继续运行程序,直到将要获取下一个操作码:
标志性的获取操作码的语句,接下来要获取的操作码是
36
,同时也反向说明,在这行代码之前,OA
操作码是一直有效的;而且,
OA
的参数是两个:因为操作了两次 ESI,同时,位于
OA
和36
之间的数据被分别放入了 ECX 和 EDI;大胆的猜测一下,如果
OA
就是rtcMsgBox
,那么替换它是否就能跳过弹窗呢?重载程序,在数据窗口 goto 到
OA
,也就是 401AD2:打开
opcode.txt
,发现07
与OA
参数数量和参数大小都相同,且07
没有副作用:如上图所示:
OA
表示调用指针(ptr)指向的函数,且没有返回值,4 字节大小,有 2 个参数,参数一 2 字节,参数二 2 字节(4 2 2 2);07
表示 PUSH 值到堆栈,4 字节大小,有 2 个参数,参数一 2 字节,参数二 2 字节(4 2 2 2);
这里不用
0B
替换OA
的原因是:CALL 的副作用要比 PUSH 大的多;所以,替换
0A
为07
:需要注意的是:替换操作码时,两个操作码的参数数量和参数大小必须完全相同,且替换的操作码对程序的运行没有副作用;
然后运行程序:
没有出现 NAG 窗口,直接显示程序主窗体;
保存修改到可执行文件,运行程序:
修改依然没有问题,完工!