1、逆向分析逆向分析1.1.逆向工程概述逆向工程概述2.2.调试器和反汇编器调试器和反汇编器3.3.逆向分析实例逆向分析实例4.4.断点断点5.5.专用工具专用工具逆向工程逆向工程逆向工程,Reverse Engineering,R.E.工程(Engineering):从原理到产品逆向工程的基本思想:从产品到原理(再到产品)军事中的逆向工程USA,Boeing B-29USSR,TU-4军事中的逆向工程前苏联SVD狙击步枪国产79/85狙击步枪软件逆向工程软件逆向工程是通过反汇编和调试等手段,分析计算机程序的二进制可执行代码从而获得程序的算法细节和实现原理的技术。研究对象:没有公开源代码的计算机程
2、序,主要是已经经过编译的二进制可执行代码(如Win32平台上的PE文件,包括exe,dll等文件格式)与开放源代码的开源软件不同,用户无法修改已经编译成型的可执行文件,或者无法获知程序内部的算法。逆向工程类似于软件工程中的“黑盒”测试。需要借助跟踪调试手段,从二进制机器代码开始分析程序。工作过程与软件工程相反,这就是“逆向工程”这个名词中“逆向”的来源。软件逆向工程逆向工程的主要应用软件破解(cracking):破解软件的版权保护措施,让用户不支付授权费用就可以无限制使用软件的全部功能;病毒和恶意程序(malware)分析:分析病毒、恶意程序的传播机制和危害并设计出解决办法;系统漏洞分析:分析
3、漏洞原理,设计补丁程序或者编写利用程序(Exploit)。分析不公开的文件格式、协议等;分析Windows或Mac平台上的硬件驱动程序,编写linux下的相应驱动;挖掘消费电子产品的潜能;挖掘操作系统未文档化的API,发现更多系统内幕;计算机犯罪取证逆向工程的其他应用逆向工程的历史最早出现在20世纪80年代,APPLEII主机上的游戏破解。逆向工程最早的应用是软件破解。合法性至今存在很大争议。Windows End-User License Agreement总结逆向工程的分析方法是从一个已经成型的产品开始逐步向下分解,以期最后在更高的层次上抽象出产品的技术细节。目目 录录1.1.逆向工程概述
4、逆向工程概述2.2.调试器和反汇编器调试器和反汇编器3.3.逆向分析实例逆向分析实例4.4.断点断点5.5.专用工具专用工具调试器和反汇编器逆向工程的研究对象:特定硬件平台上的可执行二进制代码逆向工程的研究手段:跟踪与调试两种关键工具:调试器和反汇编器调试器调试器(Debugger):加载被调试的目标程序(或进程),并对它进行动态跟踪和调试。与源码调试的区别:是对程序的二进制可执行代码直接进行调试。各种语言开发环境中自带的调试器功能有限,难以胜任逆向工程的需要。采用专门的调试器常用调试器-SoftICERing0级内核调试器;通过网络进行远程调试;支持单机的、源程序级的调试能力;支持Windo
5、wsNT/9x,功能强大;常用调试器-OllyDBGOllyDBG(简称ODBG)工作在Ring3下,无需注册免费使用,最新版本是1.10。书中使用ODBG进行实例讲解。12341.反汇编窗口2.寄存器窗口3.堆栈窗口4.转存(dump)窗口常用调试器-WinDBGWinDBG是微软出品的调试器,可以用于源代码调试和系统内核调试,还能分析dump文件,和Windows结合紧密。WinDBG是基于命令使用的调试器。反汇编器反汇编的概念:把二进制代码翻译成汇编助记符。调试器中自带简单的反汇编引擎,但是这些反汇编引擎功能有限,专业反汇编器可以更好的分析代码。xor ebx,ebx0 x33,0 xD
6、B汇编助记符二进制代码汇编反汇编反汇编器IDAProIDAPro(InteractiveDisassemblyPro)功能强大,能反汇编多种硬件平台的指令集,配有众多的反汇编选项;能根据目标程序的编译器识别出很多函数和参数甚至结构体并且自动标注。支持改名,内建简单调试器以及支持很多高级功能。反汇编器W32DASMW32Dasm是一个轻量级的反汇编工具对小型文件进行反汇编时速度很快它的优点是使用方便容易上手,缺点是难以对大的文件进行反编译。目目 录录1.1.逆向工程概述逆向工程概述2.2.调试器和反汇编器调试器和反汇编器3.3.逆向分析实例逆向分析实例4.4.断点断点5.5.专用工具专用工具实例
7、1直接内存查看Win32进程内存空间当进程开始后,各种数据和资源会以一定结构组织起来映射到主存。默认情况下,Win32系统上每个用户进程可以占有2GB的私有地址空间,操作系统占有剩下的2GB地址空间。进程的代码和各种资源都会在进程内存空间里出现,可以用内存查看工具查看进程内存以获取一些信息例如字符串等。实例1cont.运行目标程序BS.Crackme.2.exe主窗口上有两个文本框,分别用于输入用户名和序列号这两个注册信息。在用户名文本框中输入用户名newbie,下面随便填入一个注册码11223344,点击check按钮,crackme弹出一个对话框提示输入的注册码错误。暂时关闭对话框。打开W
8、inHEX,点击工具栏上的OpenRAM按钮,弹出对话框选择想要打开的进程内存。选中PrimaryMemory后点击OK打开BS.Crackme.2.exe的进程内存空间。实例1cont.12crackme是特意选择给出的特例,程序通过用户名计算出注册码,然后直接用字符串比较函数明码比较输入的假注册码和真注册码是否一致,并且在比较后没有及时清除内存中暂时保存的真正的注册码。基于编程经验,真假注册码在内存中的位置相距不远,可以尝试搜索内存中的“假注册码”,并在周围寻找正确结果。按Ctrl+F打开文本搜索对话框,填入11223344并且选择ANSI编码在内存尽心查找定位。实例1cont.“1122
9、3344”在内存中一共出现了两次,在第二次的内存附近可以看到输入的用户名和假注册码,在假注册码的下面是一串数字,猜测是正确注册码。将这个字符串填进crackme的主界面,点击check按钮显示注册成功。实例1cont.这个crackme是特意选择的例子,仅仅为了说明问题,并不具有普遍适用性。用查看内存的方法之所以能够起作用,根本原因还是程序中计算注册码后使用了明文字符串比较,并且没有及时清除内存中的敏感信息。实例1cont.实例2实例2的仍然使用实例1的BS.Crackme.2.exe利用调试器根据注册信息找到注册码计算的代码,并且通过跟踪计算过程逆向出注册码的计算过程。Crackme的注册流
10、程:填入注册信息后计算出正确的注册码并与从用户界面上输入的注册码进行比较;结果正确则弹出对话框提示注册成功,反之提示失败。从编程角度来说,一般会在校验过后在用户界面上或者用弹出对话框的形式给用户是否已经注册成功的提示,用于提示的代码应该距离注册码校验的地方不远可以通过观察程序的提示信息(或者其他注册成功的表现)来定位计算和校验注册码的关键代码。可以利用提示字符串作为切入点来完成逆向工程的任务。ODBG有一个强大的字符串引用查找插件UltraStringReference,可以在程序中搜索ASCII和Unicode编码的字符串。在反汇编窗口中点击右键,在选项菜单中可以看到有UltraString
11、Reference的选项,选择第一项FindASCII。搜索完毕后ODBG会显示搜索结果,可以看到注册成功时显示的“correctwaytogo,yougotit.”。实例2实例2在该字符串上双击,ODBG就会自动跳转到对该字符串引用的反汇编代码处。向上卷动一些代码鼠标点击0 x00401542这行代码使之高亮显示,按F2键在这里设置断点,然后按F9让程序运行起来,切换到crackme的界面。填入用户名和注册码点击check按钮以后ODBG捕捉到断点,程序被中断,ODBG自动激活,并且eip就停在断点地址0 x00401542上。这时就可以用调试器来跟踪程序。单步运行,观察堆栈和内存数据,可以
12、了解注册流程。函数在开始处定义了3个CString类型的字符串,分别用于存放用户名、用户输入的注册码和由程序计算的真正注册码。实例2点击check按钮后,函数调用CWnd:GetDlgItemText()函数取得用户界面上文本框控件里用户输入的内容。函数用一个循环来根据用户名计算注册码,结果放在一个无符号整型变量uRegCode中;在完成计算后,将调用CString:Format()函数将这个无符号整型值格式化输出到strCode中(CString类型)。在进入循环之前,uRegCode变量已经有了一个初值0 x81276345用于计算注册码。每次从注册用户名中取出一个字符,将其加到uRegC
13、ode上,然后异或uRegCode和i左移8位的值(i在这里是循环控制变量),接着计算用户名长度uLen和i的乘积并对结果取反再与i+1相乘。实例2计算过程可以用下面的程序来表达:for(i=0;i uLen;i+)uRegCode=(uRegCode+strUserNamei)(i 8)*(i+1)*(uLen*i);在计算过程结束之后,存放在uRegCode中的正确注册码被放入eax寄存器中并作为CString:Format()的参数压栈,最后调用CString:Format()将这个值格式化输出到strCode中,并与通过CWnd:GetDlgItemText()取得的用户输入的注册码进
14、行比较。也可以在CString:Format()这里下个断点观察内存验证结果。分析出了注册算法,可以为这个crackme编写一个简单的算法注册机(也称keygen,KeyGenerator)。实例2或者可以通过修改代码来完成,就是使用在解密技术上称为“爆破”的方法实现。在0 x40163B处函数调用一个子函数进行字符串比较,返回的结果放在eax中,然后用test指令测试eax中的值是否为0,并根据结果用一个跳转来实现程序流程的控制。修改“关键跳转”的跳转条件。实例2这里要用到ODBG的汇编功能,所谓汇编就是从指定的地址开始写入我们自己的代码。在jnz这条代码上双击,或者按空格键,将弹出一个汇编
15、窗口,这样就可以开始汇编了。修改代码有一个原则,就是修改后的代码字节数必须少于或者等于被修改的那条指令代码的长度,否则汇编后会影响到后面我们不想改变的代码。(80X86指令集各条指令的长度是不一样的,汇编前后字节数必须一样)可以有两个方法:第一,把jnz改成jz,改换跳转实现的条件;第二,把这条跳转指令全部修改为nop。实例2目目 录录1.1.逆向工程概述逆向工程概述2.2.调试器和反汇编器调试器和反汇编器3.3.逆向分析实例逆向分析实例4.4.断点断点5.5.专用工具专用工具断点概念高级语言编写的源代码经过编译连接之后生成的目标代码数量巨大,在海量的代码中我们关心的关键代码往往只占很小一部分
16、而且在通常的情况下无法确知这些代码的位置。断点的作用就是在恰当的时机中断正在被调试的进程的执行,并把进程的控制权交给调试器,调试器接管进程的控制权之后,就能对进程进行跟踪调试。断点有很多种类型,如:函数执行断点,各种内存访问断点,IO端口读写断点,中断向量断点,消息断点等。其中最为常用的是函数执行断点。例如要在程序中获得对话框中一个文本框中用户输入的文本,就会用到GetWindowText()函数。如果对MessageBox()函数下断点,每当程序运行到调用MessageBox()函数的地方就会被调试器中断。实例3实例是PhoxCM3.EXE,该程序采用序列号保护机制,逆向的目标是找出序列号
17、运行一下目标程序,随便输入一个序列号,软件检测序列号错误以后弹出对话框提示“WrongCode!”。实例3在反汇编窗口的右键菜单里找到“查找”选项,在弹出的子菜单中选择“当前模块中的名称”,ODBG自动搜索程序中调用的函数,并将它们在窗口中列出。可以看到窗口中从User32.dll中输入的GetWindowTextA()函数,在上面点击右键,选择“在每个参考上设置断点”,ODBG会给程序中所有引用到GetWindowTextA()函数的地方加上断点。实例3断点设置好之后,按F9让程序运行起来。在界面上的文本框中输入注册码,点击OK按钮之后程序执行到GetWindowTextA()函数就会被中
18、断下来。GetWindowTextA()函数执行完成后,将缓冲区的首地址存入ebx寄存器,然后调用了GetWindowTextLengthA()函数取得用户输入的注册码长度并比较注册码长度是否等于12H。如果长度不符合就从0 x4011BB处跳走,调用MessageBox()提示注册失败。实例3再向下看代码,发现程序连续对存放注册码的字符数组中的一组字符做比较,如果都等于预先设定的值,则注册成功。所以正确的注册码长度应该为18位,形式应该为FiXreXWorXxXSuXXxX,其中大写X的位置可以用任意字符替换。目目 录录1.1.逆向工程概述逆向工程概述2.2.调试器和反汇编器调试器和反汇编器
19、3.3.逆向分析实例逆向分析实例4.4.断点断点5.5.专用工具专用工具专用工具目前Windows操作系统上有多种语言开发平台,每种语言的编译器在编译源代码生成Win32平台上的可执行程序时都有各自不同的特点。根据这些特点,可以针对各种编译器编译的程序使用不同的专用工具,方便我们的逆向分析。例如由VisualFoxPro,Java开发的程序可以直接通过专用反编译工具反编译到源代码;部分的.Net程序可以通过Reflector反编译到源代码;Delphi开发的程序可以在调试之前首先使用DEDE分析;VB编译的软件可以用专用的WKT调试器进行P-Code的调试等等。前面没有提及该工具,适当介绍。P
20、E信息信息查查看工具看工具PEiD一般直接反汇编或者用调试器调试之前我们通常都会先用一些PE文件查看工具先期获取一些PE文件的信息,如程序使用什么编译器编译的,查看区段,是否已经被加壳等。PE信息查看工具有很多种,比如PE-Scan,PEiD,Language2000,FileInfo等。其中前3个工具是运行在Windows图形界面下的,FileInfo是命令行工具但它的侦测能力最强。PEiD可以用插件的形式进行功能扩展,例如可以用OEPFinder插件找到程序OEP,KryptoAnalyzer插件可以在PE文件中检查一些密码学算法的特征签名,帮助确定程序中究竟使用了哪些密码学算法。Delp
21、hi程序分析工具DEDEDEDE是一款可以快速分析用Delphi编写的可执行文件的工具,可以从可执行文件分析生成dfm窗体信息文件,直接反汇编函数代码,识别字符串,输入函数,异常处理,类中的成员,各种组件以及使用的库等很多有用信息。DEDE最新版本是3.5在窗体标签页中双击模块名称就可以打开DFM窗体编辑器,同时DEDE自动创建对应的窗体供我们比较可以在窗体上直接点击控件,属性监视器会自动的显示对应控件的属性。如果修改了控件属性,DEDE可以和其他资源编辑器一样将改动保存到可执行文件中。Delphi程序分析工具DEDE过程标签页中可以看到各个控件关联到不同事件上的过程名和过程地址。例如上图中SpeedButton1按钮的OnClick事件过程地址就是00457BAC,在调试器中给这个地址下断点之后运行程序并且点击SpeedButton1按钮,就能直接中断在过程入口处。对于其他一些函数和过程,只要知道入口地址,点击OFFS按钮填入地址就能从指定的地址开始反汇编代码。Delphi程序分析工具DEDE






