黑白程式

黑白程式

导航

初识逆向技术(转)

[原创]初识逆向技术
适合读者:逆向爱好者、程序员
前置知识:基本汇编代码阅读能力
Icefire:通常所谓的软件逆向工程是指:跟踪复原(或仿制)软件的编程过程、修改软件的部分代码、添加或者删除软件的部分功能等等。然而,要想达到自如地对软件跟踪与修改,既需要过

适合读者:逆向爱好者、程序员

前置知识:基本汇编代码阅读能力

Icefire:通常所谓的软件逆向工程是指:跟踪复原(或仿制)软件的编程过程、修改软件的部分代码、添加或者删除软件的部分功能等等。然而,要想达到自如地对软件跟踪与修改,既需要过硬的跟踪与识别技术,更需要对软件的基本结构做出较为透彻了解。尤其是软件的PE结构更是逆向技术中需要掌握的。因为你需要达到的某种目的,可能条件并不具备,你不得不在软件中做出适当补充与完善。即使是条件具备,没有恰当地使用好,可能目的达不到,还会引起软件崩溃。从本期开始,我们将和大家一起,逐步系统地了解逆向技术,看看它的神秘究竟在那里!

初识逆向技术

文/图 laoxuetong

逆向是很让人陶醉的一种技术,相信很多朋友都和我一样,喜欢研究它。当然,这就需要有几件上手的工具,以方便对软件进行跟踪与察看、修改与编辑。虽然各类工具非常多,但我推荐一下组合:

OllyDbg—Windows下优秀的跟踪调试软件。即可用于跟踪,也可以轻松地修改软件。

PEiD—性能不错的侦察软件。即可以用来查看软件编辑平台和侦查外壳,准备足够的插件还可以侦查软件的加密算法。

LordPE—PE文件查看与修改工具。条件不具备时你少不了它的帮助。

WinHex或UltraEdit—文本编辑工具。可任选一种或其它的,主要用于编辑一些文本类资源。

好,下面我们选定一个软件《WinPatrol v8.1.2.0》,看看我们能作些什么?

 

软件简单介绍

WinPatrol网络安全工具,可以探测出蠕虫、间谍程序、木马等恶意的程序。界面如图1所示:

图1

软件除了可以查看各种可能出现的项目及其相关信息外,你也可以设置对某一个项目的监视,用以跟踪监视可疑的病毒与木马的运行情况。软件启动后在任务栏会出现一只黑色的小狗,时不时掉转头来,煞是可爱。

软件运行有三种状态。它们分别是:未注册状态、注册于PLUS状态和注册于Professional状态。其中注册于PLUS状态和注册于Professional状态的界面略有不同,如图2、3所示:

 

2 注册于PLUS状态

 

3 注册于Professional状态

关于PLUS的注册方式,网上有现成的注册机,这里就不多说了。现在我想注册于Professional状态,那么我们能作些什么呢?

 

问题分析

通过对软件的跟踪发现,软件的注册验证并不复杂。有关代码如下:

读取名称:

00408CF1 PUSH 40                                      ; /Count = 40 (64.)

00408CF3 PUSH WinPatro.004276E0                       ; |Buffer = WinPatro.004276E0

00408CF8 PUSH 432                                     ; |ControlID = 432 (1074.)

00408CFD PUSH ESI                                     ; |hWnd

00408CFE CALL EDI                                     ; "GetDlgItemTextA

读取注册码:

00408D00 PUSH 20                                      ; /Count = 20 (32.)

00408D02 PUSH WinPatro.00427720                       ; |Buffer = WinPatro.00427720

00408D07 PUSH 430                                     ; |ControlID = 430 (1072.)

00408D0C PUSH ESI                                     ; |hWnd

00408D0D MOV EBX,EAX                                  ; |转移名称长度

00408D0F CALL EDI                                     ; "GetDlgItemTextA

判断:

00408D11 LEA EAX,DWORD PTR DS:[EBX-1]                 ;  名称长度-1

00408D14 TEST EAX,EAX

00408D16 JLE SHORT WinPatro.00408D33

00408D18 JMP SHORT WinPatro.00408D20

00408D1A LEA EBX,DWORD PTR DS:[EBX]

00408D20 CMP BYTE PTR DS:[EAX+4276E0],20              ; 名称最后一位是空格么?

00408D27 JNZ SHORT WinPatro.00408D30

00408D29 DEC EAX

00408D2A TEST EAX,EAX

00408D2C JG SHORT WinPatro.00408D20

00408D2E JMP SHORT WinPatro.00408D33

00408D30 LEA EBX,DWORD PTR DS:[EAX+1]                 ; 还原名称长度

00408D33 MOVSX EAX,BYTE PTR DS:[427721]               ; 取出注册码第二位

00408D3A ADD BL,40                                    ; 名称长度+0x40=注册码第二位

00408D3D MOVZX EDX,BL

00408D40 CMP EAX,EDX                                  ; 比较

00408D42 JE SHORT WinPatro.00408D9B                   ; 相等则跳

00408D44 PUSH 200

00408D49 LEA ECX,DWORD PTR SS:[ESP+D0]

00408D50 PUSH ECX

00408D51 PUSH 26C

00408D56 CALL WinPatro.0041A290                       ; 读取注册不成功消息

00408D5B XOR EDX,EDX

00408D5D MOV DX,WORD PTR DS:[42C100]

00408D64 ADD ESP,0C

00408D67 LEA EAX,DWORD PTR SS:[ESP+CC]

注册不成功消息:

00408D6E PUSH EDX                                     ; /LanguageID

00408D6F PUSH 40040                                   ; |Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL|40000

00408D74 PUSH WinPatro.00427DC0                       ; |Title = "WinPatrol Professional"

00408D79 PUSH EAX                                     ; |Text

00408D7A PUSH ESI                                     ; |hOwner

00408D7B CALL DWORD PTR DS:[<&USER32.MessageBoxExA>] ; "MessageBoxExA

00408D81 POP EDI

00408D82 POP ESI

00408D83 XOR EAX,EAX

00408D85 POP EBX

00408D86 MOV ECX,DWORD PTR SS:[ESP+2C0]

00408D8D CALL WinPatro.0041B575

00408D92 ADD ESP,2C4

00408D98 RETN 10

00408D9B CALL WinPatro.0041B060                       ; 相等跳到这里--读写注册表

00408DA0 TEST EAX,EAX

00408DA2 JE WinPatro.00408F6F

00408DA8 PUSH 200

00408DAD LEA ECX,DWORD PTR SS:[ESP+D0]

00408DB4 PUSH ECX

00408DB5 PUSH 26D

00408DBA CALL WinPatro.0041A290                       ; 读取注册有效的信息

00408DBF XOR EDX,EDX

00408DC1 MOV DX,WORD PTR DS:[42C100]

00408DC8 ADD ESP,0C

00408DCB LEA EAX,DWORD PTR SS:[ESP+CC]                ; 

注册成功消息:

00408DD2 PUSH EDX                                     ; /LanguageID

00408DD3 PUSH 40040                                   ; |Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL|40000

00408DD8 PUSH WinPatro.00427DC0                       ; |Title = "WinPatrol Professional"

00408DDD PUSH EAX                                     ; |Text

00408DDE PUSH ESI                                     ; |hOwner

00408DDF CALL DWORD PTR DS:[<&USER32.MessageBoxExA>] ; "MessageBoxExA

从上可以看出,注册码的第二位应该是“名称长度+0x40。如果是,则可以注册成PLUS版。如果不是,则不能注册。通过仔细跟踪看到,注册码并没有由注册名计算而来,所以也就是非明码比较范畴。这类软件一般不宜做内存注册机。

那么,这种情况下能不能让软件自动显示正确的注册码呢?经过思索和试验,发现也完全可做到。

 

准备工作

要显示注册码,需要一个消息盒,这东西通常需要调用API。请出LordPE来看一看,看软件为我们实现目标准备了相应条件没有。启动LordPE,如图4所示:

图4

选PE编辑器,打开需要查看的文件,如图5所示:

图5

单击 打开,出现第一个对话框,如图6所示:

图6

选择目录,出现第二个对话框,如图7所示:

图7

点击导入表右侧的第一个按钮出现第三个对话框,如图8所示:

图8

在这个对话框的上面查找USER32.DLL,则在下面出现这个文件中所有被使用的函数名称及其调用方法。如图9所示:

图9

从图中可以看到,软件包含了对函数MessageBox的调用。这为我们制作自显示注册码方案提供极大方便了,不需要作过多的操劳了。

调用对话框函数MessageBox通常需要4个参数,其中两个默认状态下为0。另两个一个是对话框的标题一个是对话框要显示的内容。另外,在调用时还必须遵守PE格式文件的规则。否则,轻则不能跨平台使用,重则软件不能启动。请注意,这个软件调用的不是MessageBoxA,而是MessageBoxExA。主要区别在于增加了语系识别。这些问题在进行软件逆向时必须进行学习与研究,逐步掌握并融会贯通。这里我们暂时不讲了。

 

实施手术

调用MessageBox的反汇编代码的一般形式形如:

PUSH 0                                   ; /Style = MB_OK|MB_APPLMODAL

PUSH Address1                            ; |Title = "<消息盒标题>"

PUSH Address2                            ; |Text = "<消息盒内容>"

PUSH 0                                   ; |hOwner = NULL

CALL <JMP.&USER32.MessageBoxA>           ; "MessageBoxA

JMP Address3

JMP DWORD PTR DS:[<&USER32.MessageBoxA>] ; USER32.MessageBoxA

其中Address1对应着你的标题资源在内存中的位置,一般情况下地址是固定的。Address2对应着需要现实的内容在内存中的位置,大多数情况下地址是动态的,要根据情况加以利用。Address3是显示完毕后,应该返回到软件相应位置的地址,是固定的。值得注意的是,最后的两个跳转的顺序不能颠倒,否则软件不能正确地工作。

在添加这些代码时,上述三个地址可以先随意输入,等将代码输入完成、标题地址设置好、跳转地址找好再集中处理。而第二个跳转的地址可将软件已使用的地址复制过来(见未注册提示框位置)。当然,也可以根据PeiD中显示的地址计算。

好,现在选择合适的跳转点。因为软件需要用到名称长度,所以应该选择在恢复名称长度的位置跳转,即:

00408D30 LEA EBX,DWORD PTR DS:[EAX+1]                 ; 还原名称长度

00408D33 MOVSX EAX,BYTE PTR DS:[427721]               ; 取出注册码第二位

00408D3A ADD BL,40                                    ; 名称长度+0x40=注册码第二位

因为这一行语句后面用到,所以必须在添加的代码里加上占用的代码部分。在程序后面的空余位置添加好代码,并将00408D33这一行改为:

JMP < 添加代码入口>

并且让:

Address2=<消息盒标题>

Address3=<消息盒内容>

而消息盒标题紧放在添加代码的后面。经过这样设计,我的代码及存放位置如图10所示:

图10

紧随其后是标题数据。当你注册时,点击Apple后会出现如下图11所示的信息:

图11

怎么样?注册码出来了吧。而且还已经真的替你注册了,是不是很爽?!

容易么?看来很容易。但又不容易!如果软件本身不带MessageBox函数,实现起来就有些麻烦。能办到么?当然能。甚至可以直接使用,但不能互相交流及跨平台使用。

我不止想做到这些,还想做一些其它的事情;我的软件加壳了,不脱壳能否实现一些附加功能;能添加菜单项么?能添加或删除图像么?没位置存放我所添加的内容了,等等,等等。只要你能跟着我们学习,都是可以实现的。不过要记住,这里研究的是逆向技术,非软件开发。所以你如果想在试用版上处理成正式版,那倒不如自己开发了。

逆向方法小结

l         检查或者添加MessageBox函数

l         准备好MessageBox函数的反汇编代码

l         准备好消息盒中显示的数据地址

l         准备好合适的跳转点

l         在选定的合适位置输入代码和数据

l         检验、调试所作的工作

l         收集相关API函数,已备不时之用

posted on 2009-10-14 16:30  黑白程式  阅读(471)  评论(0编辑  收藏  举报