• 初识逆向技术(转)


    [原创]初识逆向技术
    适合读者:逆向爱好者、程序员
    前置知识:基本汇编代码阅读能力
    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函数,已备不时之用

  • 相关阅读:
    文件权限命令
    复制、移动文件及目录命令
    创建、删除文件及目录命令
    绝对路径和相对路径
    查找文件命令
    链接命令
    文本搜索命令
    编辑器 vim
    有参装饰器与迭代器
    闭包函数与装饰器
  • 原文地址:https://www.cnblogs.com/feng801/p/1583345.html
Copyright © 2020-2023  润新知