首页
论坛
课程
招聘
[原创]另类方法攻破程序壁垒---充分利用程序验证的漏洞
2010-9-8 11:43 6968

[原创]另类方法攻破程序壁垒---充分利用程序验证的漏洞

2010-9-8 11:43
6968
另类方法攻破程序壁垒---充分利用程序验证的漏洞
作者:cntrump
工具:VB Decompiler Lite, OllyDbg
        由于正在学习软件汉化相关的知识,遇到了需要汉化非标准资源的情况,于是在网上一搜,就找到了汉化新世纪网站,下载了xxplus,该软件使用VB编译.该程序虽然已经停止更新了,但是功能依然够用,目前依然是汉化非标的首选辅助工具之一.
        安装后先看程序说明,如果不注册,将会有好几个功能不能使用.对于这种情况,一般有两种解决方案,一是制作出注册机一劳永逸,二是通过爆破解除程序的功能限制.
        试用注册一下程序,提示需要重启来验证注册码正确性,这种情况的话,要么是真的重启验证,要么是程序虚晃一枪,用来代替注册错误提示的障眼法.为了验证是哪一种情况,我们用VB Decompiler载入程序进行辅助分析,找到注册按钮处理事件的伪代码如下:
Private Sub OK_Click() '430C40
…略去无关代码
…
  loc_00430D76: mov var_6C, 0040E474h ; "Plase input user name!"
…
  loc_00430D9B: call [00401120h] ; MsgBox(arg_1, arg_2, arg_3, arg_4, arg_5)
…
  loc_00430DB3: call [00401070h] ; RegSetValueEx(%x1, %x2, %x3, %x4, %x5, %x6, %x7)
…中间略去了很多代码
  loc_00430E16: mov var_6C, 0040E4D8h ; "To check the register code, you need restart this software."
  loc_00430E1D: mov var_74, 00000008h
  loc_00430E24: call [0040130Ch] ; RegSetValueEx(%x1, %x2, %x3, %x4, %x5, %x6, %x7)
 …
  loc_00430E3B: call [00401120h] ; MsgBox(arg_1, arg_2, arg_3, arg_4, arg_5)
…
  loc_00430E53: call [00401070h] ; RegSetValueEx(%x1, %x2, %x3, %x4, %x5, %x6, %x7)
…
  loc_00430E6F: call [004012B4h] ; RegSetValueEx(%x1, %x2, %x3, %x4, %x5, %x6, %x7)
…
  loc_00430E88: call [0040112Ch] ; RegSetValueEx(%x1, %x2, %x3, %x4, %x5, %x6, %x7)
…
…
  loc_00430EA8: call [004010C8h] ; RegSetValueEx(%x1, %x2, %x3, %x4, %x5, %x6, %x7)
  loc_00430EAE: lea ecx, var_24
  loc_00430EB1: call [00401388h] ; RegSetValueEx(%x1, %x2, %x3, %x4, %x5, %x6, %x7)
…
…省略了后面的代码


  很明显,程序只是把用户和注册码保存到注册表中然后提示重启程序进行验证就完事了.这样进行注册验证的过程就应该在主窗口的from_load事件中了,因为这个程序是使用自然编译的,不是P-Code,跟踪起来就和普通的程序没有区别了,但是由于我不懂VB,在跟踪的时候很快就迷失在了相似的指令中,VB的函数比API要难记…
        就在我准备要给作者汇钱要个注册码的时候,突然看到了程序的关于对话框,看到了红色的Unregister version,直觉告诉我还有一线希望!在VB Decompiler中查看关于窗体:

VERSION 5.00
Begin VB.Form Form2
….省略无关部分
    Begin Label aRegInfo
      Caption = "Unregister version"
      ForeColor = &HFF&
      Left = 120
      Top = 1965
      Width = 3405
      Height = 255
    End
…
…

Attribute VB_Name = "关于对话框"


可以知道程序原始的文字就是Unregister version,那么这个窗口的form_load过程中肯定存在注册验证代码,用VB Decompiler查看from_load代码如下:

Private Sub Form_Load() '423E90
…
…
  loc_00423ED0: xor ebx, ebx			;ebx清零,ebx=0
  loc_00423ED2: cmp [00439134h], bx		; [00439134h]是一个全局变量,和0比较
  loc_00423ED9: mov var_18, ebx
  loc_00423EDC: mov var_1C, ebx
  loc_00423EDF: jz 00423F85h			;如果[00439134h]为零就跳
  loc_00423EE5: mov edx, [esi]
  loc_00423EE7: push esi
  loc_00423EE8: call [edx+00000304h]
  loc_00423EEE: push eax
  loc_00423EEF: lea eax, var_1C
  loc_00423EF2: push eax
  loc_00423EF3: call [00401118h] ; Set (object)
  loc_00423EF9: mov ecx, [00439130h] ; 
  loc_00423EFF: mov edi, eax
  loc_00423F01: push 0040DC0Ch ; "Register to:"	;如果上面的跳转实现了,这里就不会执行
  loc_00423F06: push ecx
…
  loc_00423FBF: retn 0004h


很明显,窗体在加载的时候,会对一个全局变量进行判断,如果不是零,那么就显示Register to:也就是注册给xx了,这说明,程序进行了注册验证之后会把结果保存到这个全局变量,成功为非零,失败为零,程序会在运行过程中判断这个全局变量,以确定当前运行模式是注册模式还是试用模式,按照这个思路,我们只要找出程序中对这个全局变量进行判断的地方,然后进行修改,让程序以注册模式运行,那么我们的目的就达到了.
        现在关键问题来了,如何找出全部的判断位置呢?如果有源码,我们可以直接搜索变量的出现的位置,但是现在想看源码是不可能的.别忘了我们还有神器VB Decompiler,用它就可以,VB Decompiler有一个可以说是很鸡肋的功能---字符串查找,听起来不错吧?查找字符串,很正常呀,OD都有专门的字符串搜索插件,怎么能说这个功能是鸡肋呢?嗯,虽然表面看起来是这样的,但是它的功能和OD的字符串搜索插件完全不一样, VB Decompiler的字符串查找功能是在代码窗口中查找文本,而不是找程序中的字符串!所以说是鸡肋一点也不过份,不过有一句怎么说来着?金子在需要它的人眼里才会发光!现在这个功能可是派上了大用场,能轻易解决我们现在的问题---查找所有00439134h变量出现的位置!
        由于VB Decompiler反汇编代码的时候,是从当前选择的地址一直往下反汇编,直到代码段全部反汇编完为止,这也是为什么在反汇编时很慢的原因.既然VB Decompiler有这样的特点,那么肯定要为我们所用,只要从程序流程最开始的地方进行反汇编,那么整个程序的流程就会全部被反汇编在代码窗口中了!然后再利用它的字符串搜索功能,搜索00439134h这个字符串,不就能找到所有使用该变量的位置了吗?哈哈,我都要给我自己下跪了~~
        我们从程序主窗口的form_load开始反汇编,然后搜索00439134h:
查找到的结果如下:
之前一直没有用到OD,其实OD的用处只有一个,那就是修改程序代码~~

第1处:
  loc_0041675C: cmp word ptr [00439134h], 0000h
  loc_00416764: jz 4167D4h						;nop这句
第2处:
  loc_00416DFC: cmp word ptr [00439134h], 0000h
  loc_00416E04: jz 416E74h						;nop这句
第3处:
  loc_00417E83: cmp word ptr [00439134h], 0000h
  loc_00417E8B: jz 00417F17h					;nop这句
第4处:
  loc_0041A62C: cmp [00439134h], di
  loc_0041A633: jnz 0041A6F5h					;改为jmp
第5处:
  loc_0041AEF0: cmp [00439134h], bx
  loc_0041AEF7: jnz 0041AFB9h					;改为jmp
第6处:
  loc_0041B71F: cmp [00439134h], bx
  loc_0041B726: jnz 0041B7E8h					;改为jmp
第7处:
  loc_00423ED2: cmp [00439134h], bx
  loc_00423ED9: mov var_18, ebx
  loc_00423EDC: mov var_1C, ebx
  loc_00423EDF: jz 00423F85h					;nop这句


OK,现在保存文件,运行看看效果,发现程序的关于对话框已经变为Register to:了,再看看试用版中不能使用的功能,也全部能使用了,至此,大功告成!用dUP2做一个补丁吧,下次再安装的时候直接打上补丁就行了.
        如果去跟踪验证过程,那么将是和作者肉搏,但是程序只用一个全局变量来作为注册标志,我们就可以智取,相比之下成本要小多了.
附一个补丁截图,由于是国产软件,补丁就不发了.

看雪招聘平台创建简历并且简历完整度达到90%及以上可获得500看雪币~

上传的附件:
收藏
点赞0
打赏
分享
最新回复 (8)
雪    币: 412
活跃值: 活跃值 (67)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
大头和尚 活跃值 2010-9-8 13:24
2
0
VB Decompiler很少使用,感谢LZ分享心得。千里之堤,溃于蚁穴。呵呵,找到了一点点蛛丝马迹就能打开思路
雪    币: 194
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
任磊镭 活跃值 2010-9-9 22:05
3
0
柳暗花明又一村啊。学习了。
雪    币: 64
活跃值: 活跃值 (11)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
xiaobaozi 活跃值 1 2010-9-9 22:44
4
0
零兄威武啊!~~~~~膜拜
雪    币: 13
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Greater 活跃值 2010-9-10 16:21
5
0
楼主犀利
我佩服啦
顶起
雪    币: 20
活跃值: 活跃值 (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
蓝色炫影 活跃值 2010-9-11 01:37
6
0
其实可以考虑在程序的某个函数中,加上条指令直接把那个全局变量的值修改掉,也就不用在乎有多少地方读取了这个变量了
雪    币: 2166
活跃值: 活跃值 (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
lofrank 活跃值 2010-9-15 10:13
7
0
同意6楼说法,直接把值修改了就好了,也不需要一处处去找被调用的地方了
雪    币: 34
活跃值: 活跃值 (99)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
月光爱人 活跃值 2010-9-15 14:10
8
0
我现在的能力还不能读懂你们的对话 。。。学习
雪    币: 117
活跃值: 活跃值 (26)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
ninymay 活跃值 2 2011-1-14 15:30
9
0
欣赏楼主遵守版规的精神,支持国产软件,但也可以学习反组译,并行不悖^^
游客
登录 | 注册 方可回帖
返回