现在的位置: 首页 > 综合 > 正文

从一套商业软件的pj过程看编程方式对pbd的保护(实践篇)

2013年09月14日 ⁄ 综合 ⁄ 共 5401字 ⁄ 字号 评论关闭

以前零星地发表过对pbd的看法,都出于想象,不管有用没用,我是有在编程中运用数种。到今天把pbd反编译做出来后,再把反混淆问题也搞定后,出于测试目的,我动手pj了一个pos的商业软件。

 

因为pbd如果用OD调试,一直跟进去都是pbvm的函数和内核的一些dll内转。就如同看一部电视剧,你无法还原小说原本一样。所以说还是得用到pbd反编译器,这也是现在解释性语言(java,js,c#,php)要pj必须要用的工具。但是针对这些解释性语言,又出于商业保护有开发出混淆器,混淆器从流程,字节码的等效替换,文字和数字的加密上进行保护。其他的语言我不知道,pb的混淆器大凡只用到1.0的简易版,这个简易版只构建三种模式的假跳转,来混合到p-code改变程序走向,而且将原来有行规律的语句彻底拆分。从而使得阅读性变差,而且极差。而且移除基于调试目的的行数和断行参数。从而致使pbkiller无法开展工作(纠正一下错误:pbkiller只使用原debug参数来format他的留行,并非使用其来断行,我以前几篇文字中此说法有误,就是说pbkiller断行是依靠码本身,只用debug来还原原始的行分布,如空行。去掉那个参数后,pbkiller的行都挤在一起。)。但是这个混淆是比较弱的,也可能是作者基于商业目的保留一些高级混淆方法(不得而知),我花一周时间已经大致弄好反混淆。基本实现原理就是识别并去除假跳转,然后将零散的p-code得以重新组合成句,并根据码去断行,整理并尽量还原成未混淆前的顺序,再利用之前开发的基础,来还原成各种statement。而正常的操作码,混淆器并未涉及去做java混淆器那样的等效处理(也许是有所保留)。结果就是轻易搞定反混淆。

 

我们现在就来pj一个商业的pos:

1. 大致看了他的验证过程,知道哪些限制。

2. 发现该软件给有测试期,在测试区内功能放开,但是注册时还要插狗。在几乎重要的功能界面都设置有时间检测。也就是试用期大于30天提示,大于300天彻底不能用(注意1:时间限制好像是被证明过的一种很SB方法,如果没有做功能限制的话)

3. 大致找到注册的地方。因为界面,函数等太多,大致用修改pbd文件名的方法,缩小范围,最后定为在主文件abc.exe,其中有个uo上面很多此类函数。用pbdecomplier打开,顿时傻眼:因为编码规则和命名很规范(注意2),从而从名字上大致知道哪些函数进行提示和验证时间过期。用反编译打开函数查看。并理清了哪些外部dll,哪些函数调用哪些函数。如此种种。函数还是太多。所以用ue打开主文件,从里面搜索弹出框上的关键字,搜到几处,记录下绝对位置,然后在pbdecomplier中查看每个函数的位置,顿时明白这个提示是在哪个函数里,打开pbdecomplier的“移除混淆码”和“查看原始p-code”和“skip process statement”处理过程。看到某函数如下:

//----------------------------------------------------------------------------------------------------------------------------

1534FFFF:(0000004A/0000004A)   L._._.J.F.F: 19B8FFFF/00000000:  li_days <= 30 and li_days > 0
1BBCFFFF:(0000004A/0000004B)   _._._.J.X.F: 19F4FFFF/00000000:  //vcJP0102033900INSERT
19F4FFFF:(0000004A/0000004C)          li_ret = messagebox("系统提示","提醒您:~n~n您正在使用的是某某测试版,还没有注册, " ,请你在" + string(li_days) + "之内注册")

11B4FFFF:(0000004A/0000004D)   _._._.J.X.F: 0F6AFFFF/00000000:  //vcJP0102033900INSERT

-----------------------------------------------------------------------------------------------------------------------------//

如果在这里把判断逻辑改了就能一直提示下去(注意3),li_days在前面判断出来如果时间超30天就是成负数。那很简单,我把and改or即可搞定此问题嘛(注意3:任何pj的人都没兴趣去看你的代码,他们只关注跳转,这也是所有计算机程序中的弱点)pbdecomplier在反混淆时已经给出了每个代码行的绝对路径和还原后的行号(1534FFFF:(0000004A/0000004A)),因为打开了“查看原始p-code”的功能,我们可以直接定位到混淆前的样子所在的地方,并迅速找到跳转的码,和需要修改的码。

//-----------------------------------------------------------------------------------------------------------------------------

00001534:xx 00 11 00         [Line/Step]: 0000004A/2
00001538:xx 00 2D 00 F0 00         [Line/Step]: 0000004A/3
0000153E:xx 00 00 00         [Line/Step]: 0000004A/3
00001542:xx 00 F8 09 /nearby:9F 3F 26 85         [Line/Step]: 0000004A/3
000009F8:xx 00 02 00 Ignore pcode
000009FC:xx 00 00 00         [Line/Step]: 0000004A/4
00000A00:xx 00 5C 15 /nearby:0C 1D B8 71         [Line/Step]: 0000004A/4
0000155C:xx 00         [Line/Step]: 0000004A/5
0000155E:xx 00 01 00         [Line/Step]: 0000004A/5
00001562:xx 00 BE 1C /nearby:8C B4 BE A0         [Line/Step]: 0000004A/5
00001CBE:xx 00 11 00         [Line/Step]: 0000004A/6
00001CC2:xx 00 7A 15 /nearby:C4 E7 E6 C9         [Line/Step]: 0000004A/6
0000157A:xx 00 00 00 00 00         [Line/Step]: 0000004A/7
00001580:xx 00 02 00 Ignore pcode
00001584:xx 00 7C 00 /nearby:2F AA 9F 6F         [Line/Step]: 0000004A/8
0000007C:xx 00         [Line/Step]: 0000004A/9
0000007E:xx 00 96 15 /nearby:8C BE 63 02         [Line/Step]: 0000004A/9
00001596:98 00         [Line/Step]: 0000004A/10
00001598:99 00 00 00         [Line/Step]: 0000004A/10
0000159C:9A 00 B8 1B /nearby:7B D4 BD 01         [Line/Step]: 0000004A/10
00001BB8:xx 00 B8 19 /nearby:03 00 F4 19         [Line/Step]: 0000004A/10

操作码用xx代替,以免不必要的麻烦。98,99,9A也是假设的操作码。
-------------------------------------------------------------------------------------------------------------------------------//

我们在00001596:xx 00         [Line/Step]: 0000004A/10处找到关键的and逻辑。根据码表,修改成另外一个码就是or了。

那在此函数的偏移量之后搜索:98 00 99 00 00 00 9A 00 B8 1B,定位到一个地方。然后修改一个byte,把本机时间修改到2020年测试。虽然软件提示你需要在负的几千天内注册,但是因为逻辑被改,就只有永远提示的份了。

 

如此算突破了对测试版时间的限制,至于messagebox,也是可以修改或者增补一个假跳进去跳过即可不提示。

 

如此修改后还发现其他几个地方对时间同样有验证,如此炮制,并搜索特征码(注意4:这个软件在多处对时间的限制都是30天和300天,我直接在所有pbd中搜索特征码,结果三分钟全部改掉!所以不带随机性的死板写法,是个祸,还有就是文字提示,我搜一下就知道哪个文件里存在有提示。)。

 

做zc机。因为反混淆后的代码有部分错误,所以要写一个zc机是不太可能的。因为代码结合注册表,数据库,程序,多地多时进行校验,虽然改掉一些地方。但是保不准在某些地方你不能过多地修改。所谓别人有防范未然之预见呢。

 

所以我考虑的思路是写一个单独的exe程序管理注册算法。然后再送入参数到主程序中执行,并在某个验证的地方结合这个送入参数即可。

 

总而言之,言而总之。我pj的过程的依据都是pbd保护的弱点。最近我在考察写PE加载器把pb文件加载到内存后解密执行,也就是壳,虽然壳能被脱壳,但是可能pb的壳没人愿意有兴趣,或者先对pbd做混淆和伪造处理再加壳,这样就算脱壳,也还有层保护,如果壳未脱,然什么都不要谈了。如此不至于让什么都不懂的人借助一些工具反而把程序老手的程序给pj了吧,我是这么想的。但是对这些还不懂,还没法编程,正在了解网上的例子。另外是调试了一个简单的程序,试图看能否在vm中增补一些汇编码达到对文件格式更改或者是修改部分地方的参数,比如把关键参数恒加上一个值,在vm中再减掉,或者把关键参数的位置移动一下或者跟其他参数交换一下,这样反编译器就彻底不行了。因为这个vm的修改可以带有相当大的随机性。每家的软件可以被改得不一致。另外一个对代码混淆也还有一些更好的办法,也就是通过人眼能识别但是电脑无法识别的逻辑去做假跳。或者设计好一些陷阱等。还有反编译器的缓冲区都是固定的,可以致使其缓冲区溢出。比如超大的数组,反编译就不见得能显示全。程序的千百次继承也是分析的一个难点,如果用户不知道要把祖先对象一起分析后才能得到后继者的完整的属性列表这个道理,对象的属性就无法被反编译出来。这是可以利用的一些个方面。不过我自己的考虑,程序要保护得好,方法必须多,而且静默处理对反破解绝对是一个好方法。所谓明枪易躲暗箭难防。黄国筹先生说的pbni因为用的少,跟用外部dll没什么两样。因为不是你写在dll或者pbx2pbd处理过就没事,关键是电脑程序都是靠逻辑判断和跳转执行的。有些事情没办法。

 

而至于说代码流程混淆(ljtt的这个pb混淆器)和文字移除(本地变量,一些属性名称等)都对保护无济于事,因为流程可以还原,文字可以重新命名(就像编程时拖一个控件,ide自动命名一样),而一些系统内部属性虽然能抹掉,但是也可以从vm中找到其编号并还原。

 

还有一点是pb混淆器给人一种误解,认为其非常安全,其实shudepb早已经反混淆成功。

*关于powershield是否存在后门?*2010-3-31补充

今天早上醒来,突然想到一个很重要的问题。在powershield中有一个选项是“混淆后是否进行代码校验”,试想,c语言编译器有这个选项吗?没有,因为c是编译成低阶的类似goto方式的代码块,还没有任何方法,任何人能把它反编译出来还原成原始码。那为什么powershield就能校验呢。我的估计是在混淆时,它不是插入了很多假跳转来改变流程和拆分语句吗,一定是有一个标志来回溯混淆前的真实语句所在的位置!那才能实现快速的把混效过的代码与混淆前的代码进行对比。否则按照我写反混淆的思路来做,至少不太可能原原本本的能还原混淆前的样子。虽然目前尚未找到任何线索。但是我可以确定地说,powershield如果存在可以直接还原的标志位,可以最快速地把混淆过的代码毫无错误地进行还原。也就有后门。如无则否。

 

 

也包括其他一些有名无名的高人。还有部分人能从p-code中搜索到逻辑比较和跳转用的码,而且经过多次测试他们不需要反编译看代码,而直接尝试改码。

 

不过在程序写法上,要尽可能地考虑我以上的pj依赖的地方。我希望这篇文章能对大家有点帮助和启发。

以上讨论是纯技术讨论,并不涉及任何其他目的。请编辑在看到此文时特别注意。不要一下给del了。

 

抱歉!评论已关闭.