OllyDbg简称OD,是一款具有可视化界面的用户模式调试器,结合了动态调试和静态分析,具有强大的反汇编引擎,能够识别数千个被C和Windows所使用的函数,并能将其参数注释出,能自动分析函数过程,循环语句,代码中的字符串等,非常容易上手,并且对异常的跟踪处理相当灵活,这些特性使得OllyDbg成为调试ring3级程序的首选工具,爱好者不断地修改,扩充OllyDbg,脚本执行能力和开发插件接口使得其变得越来越强大。

下面是OD的界面:

image.png

我们先对它的重要部分进行编号,然后详细介绍,

image.png

(1)首先我们介绍一下第一部分:

也就是这一部分:

image.png

使用OD打开目标程序后,OD会打开多个子窗口,单击各个标签按钮可以在各个子窗口之间切换,这些按钮依次对应Log窗口,Executable modules窗口,Memory窗口,Threads窗口,Windows窗口,Handles窗口,CPU窗口,Patches窗口,Call stack窗口,Breakpoints窗口,References窗口,Run trace窗口,Source窗口。

默认的当前窗口是CPU窗口,他在OD中是最重要的窗口,调试程序的绝大部分操作都要在这个窗口进行。他包含以下5个窗口:

1.反汇编窗口

2.寄存器面板

3.信息面板

4.数据面板

5.堆栈面板

这也是我们接下来将要介绍的2,3,4,5,6部分。


(2)CPU窗口的反汇编面板,也就是我们第2个标号的部分。

       反汇编面板窗口显示被调试程序的代码,它有4个列,分别是地址(address),机器码(hex dump),反汇编代码(disassembly),注释(comment)。最后一列注释栏显示相关API参数或运行简表,非常有用。

      address列:显示相对被单击地址的地址,再次双击返回到标准地址模式。

      hex dump列:设置或取消无条件断点,对应的快捷键是F2。

      disassembly列:条用汇编器,可直接修改汇编代码。

      comment列:允许增加或编辑注释,对应的快捷键是“;”键。


(3)寄存器面板窗口,也就是我们对应的第3个标号的地方.

       这里显示CPU各寄存器的值,支持浮点,MMX和3DNow!寄存器,可以单击鼠标右键或单击窗口标题切换显示寄存器的方式。


(4)信息面板窗口。

       动态跟踪时,显示与指令相关的各寄存器值,API函数调用提示和跳转提示信息。

image.png


(5)堆栈面板窗口。

       显示了堆栈的内容,即ESP指向地址的内容,堆栈窗口非常重要,各API函数和子程序等都利用它传递参数和变量等。

image.png


(6)数据面板窗口。

       以十六进制和字符方式显示文件在内存中的数据,要显示数据可点击鼠标右键“go to expression”命令或按“Ctrl+G”键打开地址窗口,输入地址。

image.png


OD常用快捷键:

    F2:设置断点,只要在光标定位的位置按F2键即可,在按一次F2键则会删除断点。

    F8:单步步过,每按一次这个键执行一条反汇编窗口中的一条指令,遇到call等子程序不进入其代码。

    F7:单步步入:功能同单步步过(F8)类似,区别是遇到call等子程序会进入其中,进入后首先会停留在子程序的第一条指令上。

    F4:运行到选定位置,作用就是直接运行到光标所在位置处暂停。

    F9:运行,按下这个键如果没有设置相应断点的话,被调试的程序将直接开始运行。

    ctrl+F9:执行到返回,此命令在执行到一个ret(返回指令)指令时暂停,常用于从系统部分返回到我们调试的程序部分。

    alt+F9:执行到用户代码,可用于从系统部分快速返回到我们调试的程序部分。

单步步入和单步步过:

F8在调试中用的很频繁,可以一句一句地单步执行汇编指令,遇到call指令不会跟进,而路过。

F7和F8功能键的主要差别就在于若遇到call,loop等指令,F8是路过,而F7是跟进去。

设置断点:

断点是调试器的一个重要功能,它能使程序中断在需要的地方,从而方便对其分析,常用的断点是INT3,其原理是ollydbg将断点处的代码设置为int3指令。

将光标移动到要设置断点的行,按F2键就可以设置了,也可以双击hex数据列。

设置断点可以让软件运行的时候停在设置断点的地方,以方便反复跟踪调试,当程序关闭时,ollydbg会将设置好的断点保存在UDD文件中,下次运行时还有效。

调试分析:

调试分析就是分析程序代码的意义,阅读这些代码时,首先要搞清楚各API函数的定义,还要弄明白那些汇编程序代码的具体含义。


本期就介绍到这里了,下一期我们开始讲解实战部分。

OllyDbg简称OD,是一款具有可视化界面的用户模式调试器,结合了动态调试和静态分析,具有强大的反汇编引擎,能够识别数千个被C和Windows所使用的函数,并能将其参数注释出,能自动分析函数过程,循环语句,代码中的字符串等,非常容易上手,并且对异常的跟踪处理相当灵活,这些特性使得OllyDbg成为调试ring3级程序的首选工具,爱好者不断地修改,扩充OllyDbg,脚本执行能力和开发插件接口使得其变得越来越强大。

下面是OD的界面:

image.png

我们先对它的重要部分进行编号,然后详细介绍,

image.png

(1)首先我们介绍一下第一部分:

也就是这一部分:

image.png

使用OD打开目标程序后,OD会打开多个子窗口,单击各个标签按钮可以在各个子窗口之间切换,这些按钮依次对应Log窗口,Executable modules窗口,Memory窗口,Threads窗口,Windows窗口,Handles窗口,CPU窗口,Patches窗口,Call stack窗口,Breakpoints窗口,References窗口,Run trace窗口,Source窗口。

默认的当前窗口是CPU窗口,他在OD中是最重要的窗口,调试程序的绝大部分操作都要在这个窗口进行。他包含以下5个窗口:

1.反汇编窗口

2.寄存器面板

3.信息面板

4.数据面板

5.堆栈面板

这也是我们接下来将要介绍的2,3,4,5,6部分。


(2)CPU窗口的反汇编面板,也就是我们第2个标号的部分。

       反汇编面板窗口显示被调试程序的代码,它有4个列,分别是地址(address),机器码(hex dump),反汇编代码(disassembly),注释(comment)。最后一列注释栏显示相关API参数或运行简表,非常有用。

      address列:显示相对被单击地址的地址,再次双击返回到标准地址模式。

      hex dump列:设置或取消无条件断点,对应的快捷键是F2。

      disassembly列:条用汇编器,可直接修改汇编代码。

      comment列:允许增加或编辑注释,对应的快捷键是“;”键。


(3)寄存器面板窗口,也就是我们对应的第3个标号的地方.

       这里显示CPU各寄存器的值,支持浮点,MMX和3DNow!寄存器,可以单击鼠标右键或单击窗口标题切换显示寄存器的方式。


(4)信息面板窗口。

       动态跟踪时,显示与指令相关的各寄存器值,API函数调用提示和跳转提示信息。

image.png


(5)堆栈面板窗口。

       显示了堆栈的内容,即ESP指向地址的内容,堆栈窗口非常重要,各API函数和子程序等都利用它传递参数和变量等。

image.png


(6)数据面板窗口。

       以十六进制和字符方式显示文件在内存中的数据,要显示数据可点击鼠标右键“go to expression”命令或按“Ctrl+G”键打开地址窗口,输入地址。

image.png


OD常用快捷键:

    F2:设置断点,只要在光标定位的位置按F2键即可,在按一次F2键则会删除断点。

    F8:单步步过,每按一次这个键执行一条反汇编窗口中的一条指令,遇到call等子程序不进入其代码。

    F7:单步步入:功能同单步步过(F8)类似,区别是遇到call等子程序会进入其中,进入后首先会停留在子程序的第一条指令上。

    F4:运行到选定位置,作用就是直接运行到光标所在位置处暂停。

    F9:运行,按下这个键如果没有设置相应断点的话,被调试的程序将直接开始运行。

    ctrl+F9:执行到返回,此命令在执行到一个ret(返回指令)指令时暂停,常用于从系统部分返回到我们调试的程序部分。

    alt+F9:执行到用户代码,可用于从系统部分快速返回到我们调试的程序部分。

单步步入和单步步过:

F8在调试中用的很频繁,可以一句一句地单步执行汇编指令,遇到call指令不会跟进,而路过。

F7和F8功能键的主要差别就在于若遇到call,loop等指令,F8是路过,而F7是跟进去。

设置断点:

断点是调试器的一个重要功能,它能使程序中断在需要的地方,从而方便对其分析,常用的断点是INT3,其原理是ollydbg将断点处的代码设置为int3指令。

将光标移动到要设置断点的行,按F2键就可以设置了,也可以双击hex数据列。

设置断点可以让软件运行的时候停在设置断点的地方,以方便反复跟踪调试,当程序关闭时,ollydbg会将设置好的断点保存在UDD文件中,下次运行时还有效。

调试分析:

调试分析就是分析程序代码的意义,阅读这些代码时,首先要搞清楚各API函数的定义,还要弄明白那些汇编程序代码的具体含义。


本期就介绍到这里了,下一期我们开始讲解实战部分。

IDA pro 7.0版本

用到的工具有IDA pro 7.0  ,被反汇编的是百度云(BaiduNetdisk_5.6.1.2.exe)。



首先,IDA pro的长相如下:

image.png


共有(File , Edit , Jump , Search , View , Debugger , Options , Windows , Help)9个模块,还有下面的诸多小菜单。

现在我们点击File,选择Open打开一个文件,这里我们选择百度云盘PC端安装程序,出现如下图示:


image.png


这里我们直接默认OK即可。

此时,我们看到的视图是这样的:


image.png


然后我们对各个部分进行标号,单独进行介绍:


image.png


第一部分表示的是对不同代码块使用不同的颜色进行区分,我们可以直接点击相应的颜色块进行不同代码块的定位。

蓝色:表示代码段。

棕色:表示数据段。

红色:表示内核。

第二部分表示该程序的函数表,双击后可查看详细信息。


image.png


该函数对应的IDA View-A如下:


image.png


第三部分对应的就是整体程序或者某个函数的图标概述形式,可以大体把握功能和结构的走向。对整体的脱壳逆向有很大的帮助。


image.png


第四部分主要可以显示以下6部分信息:

(1)IDA View-A

(2)Hex View-1

(3)Structures

(4)Enums

(5)Imports

(6)Exports

其中IDA View-A表示的就是某个函数的图标架构,可以查看程序的逻辑树形图,把程序的结构更人性化地显示出来,方便我们的分析。

具体表示形式,上文中有截图可参考。

在Hex View-1中可以查看16进制代码,方便定位代码后使用其他工具修改,具体表示如下图所示:


image.png


在Stuuctures中可以查看程序的结构体:


image.png


在Enums中可以查看枚举信息:


image.png


在Imports中可以查看到输入函数,导入表即程序中调用到的外面的函数:


image.png


在Exports中可以查看到输出函数:


image.png


以上就是IDA主面板中的各个部分的功能介绍了。



接下来我们介绍9个菜单模块,即:

File , Edit , Jump , Search , View , Debugger , Options , Windows , Help

image.png

1.File 是用来打开,新建,装载一个应用程序的,这大家都知道的。

2.Edit 是用来编辑反汇编代码的,可以复制,筛选什么的。

3.Jump 是用来跳转的,可以有很多种类型的跳转,比如跳转到上一个位置或者下一个位置,跳转到某个指定的地址。还可以根据名字,函数来进行跳转,跳转到一个新的窗口,跳转某一个偏移量等等,总之很多了,具体大家可以慢慢积累了。这个模块就比较重要了。

4.Serach 是用来搜索的。

5.View 是用来选择显示方式的,或者显示某一特定模块信息的。比如以树形逻辑图显示,或者16进制形式显示。还可以单独显示某一特定信息,比如输入或者输出表等。

6.Debugger ,调试器被集成在IDA中,首先我们使用IDA装入文件,来生成数据库,用户可以使用反汇编功能,查看所有反汇编信息,这些均可以在调试器中进行和使用。

image.png

7.Options ,在这里可以进行一下常规性的设置。

8.Windows,

9.Help,使用IDA的一些帮助文档,检查更新等等。



使用IDA的一个大体步骤:

1.装入文件或程序

2.指令断点

3.程序运行

4.分析堆栈

5.添加监视

6.进行地址分析

7.单步跟踪

8.找到bug

9.使用硬件断点进行bug确认



本期就介绍到这里了,IDA有很多高级功能,会在之后的实战文章中进行讲解。

下一期我们将讲解《逆向动态调试之Ollydbg的使用》。

学完汇编,IDA,Ollydug我们就可以进行简单的逆向分析了。

IDA pro 7.0版本

用到的工具有IDA pro 7.0  ,被反汇编的是百度云(BaiduNetdisk_5.6.1.2.exe)。



首先,IDA pro的长相如下:

image.png


共有(File , Edit , Jump , Search , View , Debugger , Options , Windows , Help)9个模块,还有下面的诸多小菜单。

现在我们点击File,选择Open打开一个文件,这里我们选择百度云盘PC端安装程序,出现如下图示:


image.png


这里我们直接默认OK即可。

此时,我们看到的视图是这样的:


image.png


然后我们对各个部分进行标号,单独进行介绍:


image.png


第一部分表示的是对不同代码块使用不同的颜色进行区分,我们可以直接点击相应的颜色块进行不同代码块的定位。

蓝色:表示代码段。

棕色:表示数据段。

红色:表示内核。

第二部分表示该程序的函数表,双击后可查看详细信息。


image.png


该函数对应的IDA View-A如下:


image.png


第三部分对应的就是整体程序或者某个函数的图标概述形式,可以大体把握功能和结构的走向。对整体的脱壳逆向有很大的帮助。


image.png


第四部分主要可以显示以下6部分信息:

(1)IDA View-A

(2)Hex View-1

(3)Structures

(4)Enums

(5)Imports

(6)Exports

其中IDA View-A表示的就是某个函数的图标架构,可以查看程序的逻辑树形图,把程序的结构更人性化地显示出来,方便我们的分析。

具体表示形式,上文中有截图可参考。

在Hex View-1中可以查看16进制代码,方便定位代码后使用其他工具修改,具体表示如下图所示:


image.png


在Stuuctures中可以查看程序的结构体:


image.png


在Enums中可以查看枚举信息:


image.png


在Imports中可以查看到输入函数,导入表即程序中调用到的外面的函数:


image.png


在Exports中可以查看到输出函数:


image.png


以上就是IDA主面板中的各个部分的功能介绍了。



接下来我们介绍9个菜单模块,即:

File , Edit , Jump , Search , View , Debugger , Options , Windows , Help

image.png

1.File 是用来打开,新建,装载一个应用程序的,这大家都知道的。

2.Edit 是用来编辑反汇编代码的,可以复制,筛选什么的。

3.Jump 是用来跳转的,可以有很多种类型的跳转,比如跳转到上一个位置或者下一个位置,跳转到某个指定的地址。还可以根据名字,函数来进行跳转,跳转到一个新的窗口,跳转某一个偏移量等等,总之很多了,具体大家可以慢慢积累了。这个模块就比较重要了。

4.Serach 是用来搜索的。

5.View 是用来选择显示方式的,或者显示某一特定模块信息的。比如以树形逻辑图显示,或者16进制形式显示。还可以单独显示某一特定信息,比如输入或者输出表等。

6.Debugger ,调试器被集成在IDA中,首先我们使用IDA装入文件,来生成数据库,用户可以使用反汇编功能,查看所有反汇编信息,这些均可以在调试器中进行和使用。

image.png

7.Options ,在这里可以进行一下常规性的设置。

8.Windows,

9.Help,使用IDA的一些帮助文档,检查更新等等。



使用IDA的一个大体步骤:

1.装入文件或程序

2.指令断点

3.程序运行

4.分析堆栈

5.添加监视

6.进行地址分析

7.单步跟踪

8.找到bug

9.使用硬件断点进行bug确认



本期就介绍到这里了,IDA有很多高级功能,会在之后的实战文章中进行讲解。

下一期我们将讲解《逆向动态调试之Ollydbg的使用》。

学完汇编,IDA,Ollydug我们就可以进行简单的逆向分析了。

模糊测试是一种通过向目标系统提供非预期的输入并监视异常结果来发现软件漏洞的方法。

模糊测试(Fuzz testing)是一种发现安全漏洞的有效的测试方法,模糊测试将随机的坏数据插入程序,观察程序是否能容忍杂乱输入,模糊测试是不合逻辑的,只是产生杂乱数据攻击程序,采用模糊测试攻击应用程序可发现其他采用逻辑思维来测试很难发现的安全漏洞。

(早期其实是一种基于黑盒的随机的测试方法。)

 

模糊测试的特点:

1.Fuzzing测试的用例通常具备某种攻击性的畸形数据。

2.具备良好的自动化测试能力。

3.“蛮力”攻击方法。

4.很少出现误报

5.能够快速找到真正的漏洞,操作简单。

6.通常不是进行功能性测试,而是检查系统处理错误的能力,比如“入侵,破环,崩溃”。

7.不能保证系统中已经没有漏洞。

模糊测试的局限性和期望:

      1.访问控制漏洞

      2.设计逻辑不良

      3.后门

      4.内存破坏

      5.多阶段安全漏洞

 

模糊测试的常规步骤:

      1.识别测试目标

      2.识别用户输入

      3.生成Fuzz测试数据

      4.执行Fuzz测试数据

      5.监视异常

      6.确定可利用性

 

Fuzz测试中的主要方法:

1.    傻瓜Fuzz:随机破坏数据包,不考虑数据结构

2.    智能Fuzz:破坏数据包,但考虑数据结构,以及编码方法,如base-64编码,以及数据块之间的关系,如校验值,某些数据域是否存在的标志位,数据位的长度。

3.    黑盒Fuzz:发送畸形的数据,没有验证代码路径是否满足

4.    白盒Fuzz:发送畸形数据,验证了目标代码路径已经满足

5.    生成:自动产生Fuzz测试数据,并不基于任何前面的输入

6.    变异:根据缺陷模式,通过破坏有效的数据来产生Fuzz测试数据

7.    变异模版:使用变异模版作为输入,产生Fuzz缓存池并发送给测试软件。

 

(预生成测试用例,随机生成输入,人工协议编译测试,变异或强制性测试,自动协议生成测试)

 

Fuzz测试类型:

1.    本地模糊器(命令行模糊测试器,环境变量模糊测试器,文件格式模糊测试器)

2.    远程模糊测试器(网络协议模糊测试器,web应用模糊测试器)

3.    内存模糊测试器

4.    模糊测试框架

 

文件Fuzz测试

协议Fuzz测试

组件Fuzz测试

WebFuzz测试

 

Fuzz测试之漏洞挖掘技术:

      作为攻击者,除了精通各种漏洞利用技术之外,要想有效的攻击,还必须掌握一些未公布的0day漏洞,作为安全专家,他们的本质工作就是抢在攻击者之前尽可能多地挖掘出软件中的漏洞。

面对二进制级别的软件,工业界普遍采用的是进行Fuzz测试,与基于功能性的测试有所不同,fuzz的主要目的是崩溃,中断,销毁。

Fuzz的测试用例往往是带有攻击性的畸形数据,用以触发各种类型的漏洞。Fuzz测试往往可以触发一个缓存区溢出漏洞,但却不能实现有效的exploit。

测试人员需要实时地捕捉目标程序抛出的异常,发生的崩溃和寄存器等信息,综合判断这些错误是不是真正的可利用漏洞。

 

Fuzz技术的思想就是利用“暴力”来实现对目标程序的自动化测试,然后监视检查其最后的结果,如果符合某种情况就认为程序可能存在某种漏洞或者问题。

利用不断地向目标程序发送或者传递不同格式的数据来测试目标程序的反应

 

我们在发现一些溢出漏洞的时候,往往是不断地给目标程序输入不同长度的字符串变量来测试目标程序是不是存在溢出漏洞的。

使用现成的fuzz工具,也叫fuzzer。

 

文件类型漏洞挖掘:

      一个file fuzz工具通常包括以下几个步骤:

(1)  以一个正常的文件模版作为基础,按照一定规则产生一批畸形文件。

(2)  将畸形文件逐一送入软件进行解析,并监视软件是否会抛出异常。

(3)  记录软件产生的异常信息,如寄存器状态,栈状态。

(4)  用日志或其他UI形式向测试人员展示异常信息,以进一步鉴定这些错误是否能被利用。

 

Blind Fuzz即通常所说的“盲测”,就是在随机位置插入随机的数据以生成畸形文件,然而现代软件往往使用非常复杂的私有数据结构。例如PPT,word,execl等,数据结构越复杂,解析逻辑越复杂,就越容易出现漏洞。复杂的数据结构通常具备以下特征:

1.    拥有一批预定义的静态数据

2.    数据结构的内容是可以动态改变的

3.    数据结构之间是嵌套的

4.    数据中存在多种数据关系

5.    有意义的数据被编码或压缩,甚至用另一种文件格式来存储,这些格式的文件被挖掘出来越来越多的漏洞。

 

Smart fuzz

      1.面向逻辑:测试前首先明确要测试的目标是解析文件的程序逻辑,而不是文件本身。复杂文件格式往往要经过多层解析,因此还需要明确测试用例正在试探的是那一层的解析逻辑,即明确测试“深度”以及畸形数据的测试“粒度”。

      2.面向数据类型:明确测试的逻辑目标后,在生成畸形数据时可以具有针对性的仅仅改动样本文件的特定位置,尽量不破坏其他数据依赖关系,这样使得改动的数据能够传递到测试的解析深度,而不会在上层的解析器中被破坏。

      3.基于样本:测试前首先构造一个合法的样本文件(也叫模版文件),这时样本文件里所有数据结构和逻辑必然都是合法的。然后以这个文件为模版,每次只改动一小部分数据和逻辑来生成畸形文件,这种方法也叫做“变异”。对于复杂文件来说,以现成的样本文件为基础进行畸形数据变异来生成畸形文件的方法要比上面两种的难度要小很多,也更容易实现。

 

面向数据类型测试:测试中可以生成的数据通常包括以下几种类型:

(1)  算术型:包括HEX,ASCII,Unicode,raw格式存在的各种数值

(2)  指针型:包括null指针,合法/非法的内存指针等。

(3)  字符串型:包括超长字符串,缺少终止符(0×00)的字符串等

(4)  特殊字符:包括#  @ <   >  \   /等等

 

面向数据类型测试是指能够识别不同的数据类型,并且能够针对目标数据的类型按照不同规则来生成数据。

我们来使用一款软件来看看FileFuzz的流程,这个软件的名称就叫做FileFuzz。在互联网上可以搜索到。

 

FTP漏洞挖掘:

      FTP服务全称为文件传输协议服务,其工作模式采用客户端/服务器的模式,也就是C/S模式。FTP服务在进行文件信息传输的时候采用FTP协议。FTP协议是基于TCP协议之上的一种明文协议,FTP协议默认情况下工作在21号端口。

FTPfuzz是专门用来测试FTP协议安全的工具,它的基本原理就是通过对FTP协议中的命令及命令参数进行脏数据替换,构造畸形的FTP命令并发送给被测试FTP服务程序。

在程序崩溃时我们也可以用ollydbg等程序进行调试,来发现更详细的错误信息帮助我们分析程序的漏洞。

 

Web Fuzz测试;

      测试方法:

(1)  设置目标环境

(2)  输入

(3)  GET  POST HEAD  PUT  DELETE TRACE  CONNECT  OPTIONS

(4)  请求URL

(5)  异常检测

 

主要web漏洞:

1.    拒绝服务

2.    跨站脚本

3.    SQL注入

4.    目录遍历/弱访问控制

5.    弱认证

6.    弱会话管理

7.    缓存区溢出

8.    未恰当支持的HTTP方法

9.    远程命令执行

10. 远程代码注入

11. 带有漏洞的库

12. HTTP相应分割

13. 跨站请求伪造

 

需要熟练掌握的技能:

1.HTTP状态码

2.Web服务器错误消息

3.中断连接

4.日志文件

5.时间日志

6.调试器


本期就介绍到这里了,下一期我们详细讲解一下《IDA Pro 7.0 的使用》。

模糊测试是一种通过向目标系统提供非预期的输入并监视异常结果来发现软件漏洞的方法。

模糊测试(Fuzz testing)是一种发现安全漏洞的有效的测试方法,模糊测试将随机的坏数据插入程序,观察程序是否能容忍杂乱输入,模糊测试是不合逻辑的,只是产生杂乱数据攻击程序,采用模糊测试攻击应用程序可发现其他采用逻辑思维来测试很难发现的安全漏洞。

(早期其实是一种基于黑盒的随机的测试方法。)

 

模糊测试的特点:

1.Fuzzing测试的用例通常具备某种攻击性的畸形数据。

2.具备良好的自动化测试能力。

3.“蛮力”攻击方法。

4.很少出现误报

5.能够快速找到真正的漏洞,操作简单。

6.通常不是进行功能性测试,而是检查系统处理错误的能力,比如“入侵,破环,崩溃”。

7.不能保证系统中已经没有漏洞。

模糊测试的局限性和期望:

      1.访问控制漏洞

      2.设计逻辑不良

      3.后门

      4.内存破坏

      5.多阶段安全漏洞

 

模糊测试的常规步骤:

      1.识别测试目标

      2.识别用户输入

      3.生成Fuzz测试数据

      4.执行Fuzz测试数据

      5.监视异常

      6.确定可利用性

 

Fuzz测试中的主要方法:

1.    傻瓜Fuzz:随机破坏数据包,不考虑数据结构

2.    智能Fuzz:破坏数据包,但考虑数据结构,以及编码方法,如base-64编码,以及数据块之间的关系,如校验值,某些数据域是否存在的标志位,数据位的长度。

3.    黑盒Fuzz:发送畸形的数据,没有验证代码路径是否满足

4.    白盒Fuzz:发送畸形数据,验证了目标代码路径已经满足

5.    生成:自动产生Fuzz测试数据,并不基于任何前面的输入

6.    变异:根据缺陷模式,通过破坏有效的数据来产生Fuzz测试数据

7.    变异模版:使用变异模版作为输入,产生Fuzz缓存池并发送给测试软件。

 

(预生成测试用例,随机生成输入,人工协议编译测试,变异或强制性测试,自动协议生成测试)

 

Fuzz测试类型:

1.    本地模糊器(命令行模糊测试器,环境变量模糊测试器,文件格式模糊测试器)

2.    远程模糊测试器(网络协议模糊测试器,web应用模糊测试器)

3.    内存模糊测试器

4.    模糊测试框架

 

文件Fuzz测试

协议Fuzz测试

组件Fuzz测试

WebFuzz测试

 

Fuzz测试之漏洞挖掘技术:

      作为攻击者,除了精通各种漏洞利用技术之外,要想有效的攻击,还必须掌握一些未公布的0day漏洞,作为安全专家,他们的本质工作就是抢在攻击者之前尽可能多地挖掘出软件中的漏洞。

面对二进制级别的软件,工业界普遍采用的是进行Fuzz测试,与基于功能性的测试有所不同,fuzz的主要目的是崩溃,中断,销毁。

Fuzz的测试用例往往是带有攻击性的畸形数据,用以触发各种类型的漏洞。Fuzz测试往往可以触发一个缓存区溢出漏洞,但却不能实现有效的exploit。

测试人员需要实时地捕捉目标程序抛出的异常,发生的崩溃和寄存器等信息,综合判断这些错误是不是真正的可利用漏洞。

 

Fuzz技术的思想就是利用“暴力”来实现对目标程序的自动化测试,然后监视检查其最后的结果,如果符合某种情况就认为程序可能存在某种漏洞或者问题。

利用不断地向目标程序发送或者传递不同格式的数据来测试目标程序的反应

 

我们在发现一些溢出漏洞的时候,往往是不断地给目标程序输入不同长度的字符串变量来测试目标程序是不是存在溢出漏洞的。

使用现成的fuzz工具,也叫fuzzer。

 

文件类型漏洞挖掘:

      一个file fuzz工具通常包括以下几个步骤:

(1)  以一个正常的文件模版作为基础,按照一定规则产生一批畸形文件。

(2)  将畸形文件逐一送入软件进行解析,并监视软件是否会抛出异常。

(3)  记录软件产生的异常信息,如寄存器状态,栈状态。

(4)  用日志或其他UI形式向测试人员展示异常信息,以进一步鉴定这些错误是否能被利用。

 

Blind Fuzz即通常所说的“盲测”,就是在随机位置插入随机的数据以生成畸形文件,然而现代软件往往使用非常复杂的私有数据结构。例如PPT,word,execl等,数据结构越复杂,解析逻辑越复杂,就越容易出现漏洞。复杂的数据结构通常具备以下特征:

1.    拥有一批预定义的静态数据

2.    数据结构的内容是可以动态改变的

3.    数据结构之间是嵌套的

4.    数据中存在多种数据关系

5.    有意义的数据被编码或压缩,甚至用另一种文件格式来存储,这些格式的文件被挖掘出来越来越多的漏洞。

 

Smart fuzz

      1.面向逻辑:测试前首先明确要测试的目标是解析文件的程序逻辑,而不是文件本身。复杂文件格式往往要经过多层解析,因此还需要明确测试用例正在试探的是那一层的解析逻辑,即明确测试“深度”以及畸形数据的测试“粒度”。

      2.面向数据类型:明确测试的逻辑目标后,在生成畸形数据时可以具有针对性的仅仅改动样本文件的特定位置,尽量不破坏其他数据依赖关系,这样使得改动的数据能够传递到测试的解析深度,而不会在上层的解析器中被破坏。

      3.基于样本:测试前首先构造一个合法的样本文件(也叫模版文件),这时样本文件里所有数据结构和逻辑必然都是合法的。然后以这个文件为模版,每次只改动一小部分数据和逻辑来生成畸形文件,这种方法也叫做“变异”。对于复杂文件来说,以现成的样本文件为基础进行畸形数据变异来生成畸形文件的方法要比上面两种的难度要小很多,也更容易实现。

 

面向数据类型测试:测试中可以生成的数据通常包括以下几种类型:

(1)  算术型:包括HEX,ASCII,Unicode,raw格式存在的各种数值

(2)  指针型:包括null指针,合法/非法的内存指针等。

(3)  字符串型:包括超长字符串,缺少终止符(0×00)的字符串等

(4)  特殊字符:包括#  @ <   >  \   /等等

 

面向数据类型测试是指能够识别不同的数据类型,并且能够针对目标数据的类型按照不同规则来生成数据。

我们来使用一款软件来看看FileFuzz的流程,这个软件的名称就叫做FileFuzz。在互联网上可以搜索到。

 

FTP漏洞挖掘:

      FTP服务全称为文件传输协议服务,其工作模式采用客户端/服务器的模式,也就是C/S模式。FTP服务在进行文件信息传输的时候采用FTP协议。FTP协议是基于TCP协议之上的一种明文协议,FTP协议默认情况下工作在21号端口。

FTPfuzz是专门用来测试FTP协议安全的工具,它的基本原理就是通过对FTP协议中的命令及命令参数进行脏数据替换,构造畸形的FTP命令并发送给被测试FTP服务程序。

在程序崩溃时我们也可以用ollydbg等程序进行调试,来发现更详细的错误信息帮助我们分析程序的漏洞。

 

Web Fuzz测试;

      测试方法:

(1)  设置目标环境

(2)  输入

(3)  GET  POST HEAD  PUT  DELETE TRACE  CONNECT  OPTIONS

(4)  请求URL

(5)  异常检测

 

主要web漏洞:

1.    拒绝服务

2.    跨站脚本

3.    SQL注入

4.    目录遍历/弱访问控制

5.    弱认证

6.    弱会话管理

7.    缓存区溢出

8.    未恰当支持的HTTP方法

9.    远程命令执行

10. 远程代码注入

11. 带有漏洞的库

12. HTTP相应分割

13. 跨站请求伪造

 

需要熟练掌握的技能:

1.HTTP状态码

2.Web服务器错误消息

3.中断连接

4.日志文件

5.时间日志

6.调试器


本期就介绍到这里了,下一期我们详细讲解一下《IDA Pro 7.0 的使用》。

代码静态分析技术

定义:是在不执行计算机程序的条件下,对源代码进行分析,找出代码缺陷。

执行方式:一般配合静态程序分析工具进行。

采用技术:数据分析流,机器学习,语义精简。

可检测类型:死锁,空指针,资源泄漏,缓存区溢出,安全漏洞,竟态条件。

用途:程序翻译/编译,程序优化重构,软件缺陷检测等。

对比:程序动态分析:需要实际执行程序

      程序理解:静态分析这一术语一般用来形容自动化工具的分析,而人工分析则往往叫做程序理解。

      优点:

      1.能够检测所有的代码级别可执行路径组合,快速,准确。

      2.直接面向源码,分析多种问题。

      3.在研发阶段开始找到并修复多种问题,节省大量时间,人力成本

(注意:静态分析不是万能的,测试是持续的过程)

 

静态分析的对象是windows内核模块,第三方驱动程序等不开源的二进制代码。

1.首先需要通过反汇编工具对模块进行处理,生成相应的汇编代码,然后在此基础上分析,检查程序的语法,结构,过程,接口等,恢复和重建程序的数据类型,结构和框架,验证程序功能,逻辑是否正确。

2.在静态分析过程中,关键的地方是要做到准确提取信息,不论是源程序还是二进制程序,利用静态分析技术都可以从中提取出控制流,表达式,接口和数据流等相关的信息。

3.由于程序本身可以看作是抽象的,复杂的数据结构集合,因此程序的静态分析技术主要是根据从程序中提取的相关信息,从不同角度对程序的数据结构进行重构,根据模型推导数据之间的逻辑转换关系。

 

常用数据结构:

      常用的数据结构包括函数调用图,抽象语法树,路径图等。

      其中函数调用图是利用程序中函数之间的调用关系建立起的模型,抽象语法树是利用程序语义建立起的模型。

 

建立好抽象语法树模型后,可以进一步获取到程序模块,函数的执行过程,以及它们中间数据流动的过程,通过恢复程序的函数关系,可以建立起函数模型,在此基础上,根据这些模型可以采用二进制对比技术,语法分析,规则检查,类型推导等多种方法对程序进行安全分析。

如。对程序代码进行对比检查可以采用二进制对比技术,通过对比补丁前后函数汇编代码的不同,可以快速定位补丁修改位置,然后进行分析,明确漏洞触发的原因,实现编写出针对该漏洞的验证代码。


如何分析缺陷:

      1.过程间分析:将考虑每一个合理的可执行路径

      2.获取一系列的函数定义:资源分配,调用

      3.数据流分析将跟踪所有应用中的不可信数据:source,sink,二者之间必须进行验证。

      4.某些使用智能静态分析

 

找到潜在bug其实只是难题之一:

     1. 消除误报非常难

      2.将复杂的缺陷解释出来很难

      3.只找潜在的一次性缺陷是很难的


动态调试技术:

动态调试技术在软件逆向工程领域也是一个很热门的概念,他是与静态分析技术相对而言的。静态分析技术是指破解者利用反汇编工具将二进制的可执行文件翻译成汇编代码,通过对代码的分析来破解软件。而动态调试则是指破解者利用调试器跟踪软件的运行,寻求破解的路径。

代码动态调试技术,一般是通过观察程序在运行过程中的状态,如寄存器内容,函数执行结果,内存使用情况等等,分析函数功能,明确代码逻辑,挖掘可能存在的漏洞。

代码流和数据流是动态调试技术通常要特别关注的两个方面。

 

代码动态调试的特征是:

      计算机必须真正运行被测试的程序,通过输入测试用例,对其运行情况即输入输出的对应关系进行分析,以达到检测的目的。

动态测试包括:

      1.功能确认和接口测试

      2.覆盖率分析

      3.性能分析

      4.内存分析

 

动态调试器:

      调试器一般都支持设置断点功能,通过在代码中设置断点,可以动态跟踪目标程序代码的执行情况,检测可能存在问题的函数调用。

    通过动态分析数据流,构造特殊输入数据来触发程序的潜在错误,对比运行得到的结果与期望获得的结果之间的差别,以便确定目标函数在安全方面有没有存在缺陷,并对比分析所得到的结果。

 

在dos环境下,最常用的调试工具是DEBUG,它的作用有:

1.    直接输入,更改,跟踪,运行汇编程序

2.    观察操作系统的内容

3.    查看ROM BIOS的内容

4.    观察更改RAM内部的设置值

5.    以扇区或文件的方式读写软盘数据等

调试器分类:用户模式调试器,内核模式调试器

在windows下有很多软件调试工具,使用比较广泛的工具有olldbg,softlCE等,由于内核程序是在内核态空间中运行的,所以普通用户态应用程序的调试工具,方法不适合用于内核程序,现在调试内核主要有一下三种方法:

1.    采用硬件调试器

2.    编写用于调试的驱动程序和中断处理函数,安装在内核里面,在操作系统内核中断的时候,硬件被它们接管。有softlCE,syserDebugger两种。

3.    微软在windows内核中添加了支持调试的相关服务。

Windows内核调试一般采用第三种方法,调试器采用微软提供的windbg,他能连接到微软服务器,下载与调试模块匹配的符号文件,用于显示当前代码所在函数的函数名称,便于分析人员跟踪。

 

WinDbg

      Windbg能进行三种调试:远程调试,dump调试,本地调试。

      Windbg主要设计用于双机调试:调试机和被调试机。

      通常为了调试过程中的方便以及保护被调试机的稳定,将被调试机设置在虚拟机内,虚拟软件通常不能直接管理硬件,也需要运行在一个真实的操作系统中,虚拟机和真实系统之间通过把串行端口模拟成命名管道的方式来通信,其做法是在虚拟机中建立一个虚拟的串行端口,把它映射到真实系统的一个命名管道上,虚拟软件软件把对这个串行端口的读写转换为对真实系统中命名管道的读写,然后就可以使用windbg连接命令管道与虚拟机中的内核调试模块通信,实现了一台机器上进行双机调试的目的。

 

Olydbg(在后期详细讲解

      目前最流行的调试工具是OllDbg,成为当今最流行的调试解密工具,同时还支持插件扩展功能,是目前最强大的调试工具。


本期就讲解到这里了,下一期将讲解《Fuzzing分析技术》,即模糊测试分析技术在漏洞挖掘中的应用。

代码静态分析技术

定义:是在不执行计算机程序的条件下,对源代码进行分析,找出代码缺陷。

执行方式:一般配合静态程序分析工具进行。

采用技术:数据分析流,机器学习,语义精简。

可检测类型:死锁,空指针,资源泄漏,缓存区溢出,安全漏洞,竟态条件。

用途:程序翻译/编译,程序优化重构,软件缺陷检测等。

对比:程序动态分析:需要实际执行程序

      程序理解:静态分析这一术语一般用来形容自动化工具的分析,而人工分析则往往叫做程序理解。

      优点:

      1.能够检测所有的代码级别可执行路径组合,快速,准确。

      2.直接面向源码,分析多种问题。

      3.在研发阶段开始找到并修复多种问题,节省大量时间,人力成本

(注意:静态分析不是万能的,测试是持续的过程)

 

静态分析的对象是windows内核模块,第三方驱动程序等不开源的二进制代码。

1.首先需要通过反汇编工具对模块进行处理,生成相应的汇编代码,然后在此基础上分析,检查程序的语法,结构,过程,接口等,恢复和重建程序的数据类型,结构和框架,验证程序功能,逻辑是否正确。

2.在静态分析过程中,关键的地方是要做到准确提取信息,不论是源程序还是二进制程序,利用静态分析技术都可以从中提取出控制流,表达式,接口和数据流等相关的信息。

3.由于程序本身可以看作是抽象的,复杂的数据结构集合,因此程序的静态分析技术主要是根据从程序中提取的相关信息,从不同角度对程序的数据结构进行重构,根据模型推导数据之间的逻辑转换关系。

 

常用数据结构:

      常用的数据结构包括函数调用图,抽象语法树,路径图等。

      其中函数调用图是利用程序中函数之间的调用关系建立起的模型,抽象语法树是利用程序语义建立起的模型。

 

建立好抽象语法树模型后,可以进一步获取到程序模块,函数的执行过程,以及它们中间数据流动的过程,通过恢复程序的函数关系,可以建立起函数模型,在此基础上,根据这些模型可以采用二进制对比技术,语法分析,规则检查,类型推导等多种方法对程序进行安全分析。

如。对程序代码进行对比检查可以采用二进制对比技术,通过对比补丁前后函数汇编代码的不同,可以快速定位补丁修改位置,然后进行分析,明确漏洞触发的原因,实现编写出针对该漏洞的验证代码。


如何分析缺陷:

      1.过程间分析:将考虑每一个合理的可执行路径

      2.获取一系列的函数定义:资源分配,调用

      3.数据流分析将跟踪所有应用中的不可信数据:source,sink,二者之间必须进行验证。

      4.某些使用智能静态分析

 

找到潜在bug其实只是难题之一:

     1. 消除误报非常难

      2.将复杂的缺陷解释出来很难

      3.只找潜在的一次性缺陷是很难的


动态调试技术:

动态调试技术在软件逆向工程领域也是一个很热门的概念,他是与静态分析技术相对而言的。静态分析技术是指破解者利用反汇编工具将二进制的可执行文件翻译成汇编代码,通过对代码的分析来破解软件。而动态调试则是指破解者利用调试器跟踪软件的运行,寻求破解的路径。

代码动态调试技术,一般是通过观察程序在运行过程中的状态,如寄存器内容,函数执行结果,内存使用情况等等,分析函数功能,明确代码逻辑,挖掘可能存在的漏洞。

代码流和数据流是动态调试技术通常要特别关注的两个方面。

 

代码动态调试的特征是:

      计算机必须真正运行被测试的程序,通过输入测试用例,对其运行情况即输入输出的对应关系进行分析,以达到检测的目的。

动态测试包括:

      1.功能确认和接口测试

      2.覆盖率分析

      3.性能分析

      4.内存分析

 

动态调试器:

      调试器一般都支持设置断点功能,通过在代码中设置断点,可以动态跟踪目标程序代码的执行情况,检测可能存在问题的函数调用。

    通过动态分析数据流,构造特殊输入数据来触发程序的潜在错误,对比运行得到的结果与期望获得的结果之间的差别,以便确定目标函数在安全方面有没有存在缺陷,并对比分析所得到的结果。

 

在dos环境下,最常用的调试工具是DEBUG,它的作用有:

1.    直接输入,更改,跟踪,运行汇编程序

2.    观察操作系统的内容

3.    查看ROM BIOS的内容

4.    观察更改RAM内部的设置值

5.    以扇区或文件的方式读写软盘数据等

调试器分类:用户模式调试器,内核模式调试器

在windows下有很多软件调试工具,使用比较广泛的工具有olldbg,softlCE等,由于内核程序是在内核态空间中运行的,所以普通用户态应用程序的调试工具,方法不适合用于内核程序,现在调试内核主要有一下三种方法:

1.    采用硬件调试器

2.    编写用于调试的驱动程序和中断处理函数,安装在内核里面,在操作系统内核中断的时候,硬件被它们接管。有softlCE,syserDebugger两种。

3.    微软在windows内核中添加了支持调试的相关服务。

Windows内核调试一般采用第三种方法,调试器采用微软提供的windbg,他能连接到微软服务器,下载与调试模块匹配的符号文件,用于显示当前代码所在函数的函数名称,便于分析人员跟踪。

 

WinDbg

      Windbg能进行三种调试:远程调试,dump调试,本地调试。

      Windbg主要设计用于双机调试:调试机和被调试机。

      通常为了调试过程中的方便以及保护被调试机的稳定,将被调试机设置在虚拟机内,虚拟软件通常不能直接管理硬件,也需要运行在一个真实的操作系统中,虚拟机和真实系统之间通过把串行端口模拟成命名管道的方式来通信,其做法是在虚拟机中建立一个虚拟的串行端口,把它映射到真实系统的一个命名管道上,虚拟软件软件把对这个串行端口的读写转换为对真实系统中命名管道的读写,然后就可以使用windbg连接命令管道与虚拟机中的内核调试模块通信,实现了一台机器上进行双机调试的目的。

 

Olydbg(在后期详细讲解

      目前最流行的调试工具是OllDbg,成为当今最流行的调试解密工具,同时还支持插件扩展功能,是目前最强大的调试工具。


本期就讲解到这里了,下一期将讲解《Fuzzing分析技术》,即模糊测试分析技术在漏洞挖掘中的应用。

软件逆向的定义:

软件逆向工程是通过反汇编和调试等手段,分析计算机程序的二进制可执行代码从而获得程序的算法细节和实现原理的技术。

研究对象:没有公开源代码的计算机程序,主要是已经经过编译的二进制可执行代码(如win32平台上的PE文件,包括exe,dll等文件格式)。

软件逆向的分类:

(1)  系统级逆向:大范围分析观察,整体把握

(2)  代码级逆向:程序二进制码中提取设计理念和算法

软件逆向步骤:

(1)  研究保护方法,去除保护功能:解码/反汇编(目标二进制代码)

(2)  反汇编目标软件,定位功能函数:中间语言翻译(汇编或类汇编代码)

(3)  分析汇编代码:数据流分析(各级中间语言)

(4)  修改汇编代码或还原高级源代码:其他分析和优化(高级抽象代码)

软件逆向工具:

(1)  Ollydbg:动态追踪工具,插件较好较多

(2)  Windbg:用户态和内核态调试工具

(3)  IDA:交互式反汇编器

(4)  PEID:著名的查壳工具

(5)  C32Asm:反汇编程序,可直接修改软件内部代码,有十六进制编辑模式

软件逆向的主要应用:

(1)  软件破解:破解软件的版权让用户不支付授权费用就可以使用软件的全部功能。

(2)  病毒和恶意程序的分析:恶意程序的传播机制和危害并设计出解,分析病毒解决办法。

(3)  系统漏洞分析:分析漏洞原理,设计补丁程序或者编写利用程序(Exploit)

(4)  分析不公开的文件格式,协议等

(5)  分析windows或mac平台上的硬件驱动程序编写linux下的相应驱动

(6)  挖掘消费电子产品的潜能

(7)  挖掘操作系统未文档化的API,发现更多内幕

(8)  计算机犯罪取证


软件开发基础知识:

目前通用的编程语言有两种形式:汇编语言和高级语言

汇编语言的实质和机器语言是相同的,都是直接对硬件操作,只不过指令采用英文缩写的标识符,更容易识别和记忆。汇编程序通常由三部分组成:指令,伪指令,宏指令。

高级语言所编写的程序不能直接被计算机识别,必须经过转换(目标代码即机器码)才能被执行,按照转换方式可将他们分为两类:

(1)  解释类:边翻译边执行

(2)  编译类:先翻译在执行

 

C语言的特点:

(1)  c语言允许直接访问物理地址,可以直接对硬件进行操作

(2)  c语言程序代码质量高,程序执行效率高

(3)  c语言使用范围大,可移植性好


常见的汇编指令:

(1)汇编大多是指汇编语言,汇编程序。把汇编语言翻译成机器语言的过程称为汇编。在汇编语言中,用符号代替机器语言的二进制码,就把机器语言变成了汇编语言。

(2)用汇编语言编写的程序,机器不能直接识别,要由一种程序将汇编语言翻译成机器语言,这种起翻译作用的程序叫汇编程序,汇编程序是系统软件中语言处理的系统软件。

(3)由于汇编更接近机器语言,能够直接对硬件进行操作,生成的程序与其他的语言相比具有更高的运行速度,占用更小的内存,因此在一些对于时效性要求很高的程序,许多大型程序的核心模块以及工业控制方面大量应用。

(4)关于汇编语言的种类,可以说有多少中不同内核的CPU,就有多少种汇编语言。

(5)不同内核的CPU,必须有对应的汇编语言编译器将汇编语言编写的程序编译成对应CPU的机器语言代码,CPU才能正确识别和执行这些代码。

(6)不同架构的CPU的汇编指令集并不相同。

(7)不同的汇编程序有不同的汇编语言规定。

(8)常用的汇编程序有ASM,MASM,TASM,OPTASM等。

 

寄存器:

寄存器是存储信息的单元或者说是器件,这里讨论的寄存器都是CPU中的寄存器,位于CPU内部,而内存位于CPU外部。

对于一个汇编程序员来说,CPU中主要可以使用的也就是寄存器而已,汇编程序员可以使用指令来读写CPU中的寄存器,从而实现对于CPU的控制,当然,不同的CPU,寄存器的个数和结构都是不一样的。

8086 CPU中寄存器总共为14个,且均为16位(32位和64位均已16位为基础)

即 AX BX  CX  DX SP  BP  SI DI  IP  FLAG CS  DS  SS  ES共14个。这14个寄存器按照一定的方式又分为通用寄存器,控制寄存器,段寄存器。

 

通用寄存器:

AX,BX,CX,DX称作为数据寄存器:

AX:累加寄存器,也称为累加器

BX:基地址寄存器

CX:计数器寄存器

DX:数据寄存器


SP和BP又称作为指针寄存器:

       SP:堆栈指针寄存器

       BP:基指针寄存器


SI和DI又称作为变址寄存器:

       SI:源变址寄存器

       DI:目的变址寄存器

 

控制寄存器:

       IP:指令指针寄存器

       FLAG:标志寄存器

 

段寄存器:

       CS:代码段寄存器

       DS:数据段寄存器

       SS:堆栈段寄存器

       ES:附加段寄存器

 

堆栈:

       堆栈都是一种数据项按序排序的数据结构,只能在一端(称为栈顶)对数据项进行插入和删除。主要功能是暂时存放数据和地址,通常用来保护断电和现场。

       堆:队列优先,先进先出

       栈:先进后出

堆栈中定义了一些操作,两个最重要的是PUSH和POP。

PUSH操作在堆栈的顶部加入一个元素,POP操作相反,在堆栈顶部移去一个元素,并将堆栈的大小减一。

 

机器语言:用二进制编码表示每条指令,是计算机能直接识别和执行的语言。

汇编语言:是用助记符,符号和数字等来表示指令的程序设计语言,它与机器语言指令是一一对应的。

   

重点掌握常用指令功能及应用:

       常用传送指令

       加减法指令

       逻辑运算和移位指令

       控制转移指令

       字符(串)输入输出功能调用


(1)  数据传送指令:MOV/XCHG,PUSH/POP,LEA

(2)  算数运算类指令:ADD/ADC/INC,SUB/SBB/DEC/CMP/NEG,MUL/IMUL,DIV/IDIV

(3)  位操作类指令:AND/OR/XOR/NOT/TEST

(4)  控制转移类指令:JMP/JCC/LOOP,CALL/RET,INT n

(5)  处理机控制类指令:NOP

 

Inter 8086指令系统共有117条基本指令:

可分为6个功能组:

(1)  数据传送类指令

(2)  算数运算类指令

(3)  位操作类指令

(4)  串操作类指令

(5)  控制转移类指令

(6)  处理机控制类指令

 

1.    数据传送类指令:

数据传送是计算机中最基本,最重要的一种操作,传送指令也是最常用的一类指令,传送指令把数据从一个位置传送到另一个位置。

除标志寄存器传送指令外,均不影响标志位。

重点掌握一下指令:

MOV   XCHG   PUSH  POP   LEA

(1)  传送指令MOV:把一个字节或操作数从源地址传送至目的地址。

(2)  交换指令XCHG:把两个地方的数据进行互换。

寄存器与寄存器之间对换数据

寄存器与存储器之间对换数据

不能在存储器与存储器之间对换数据

(3)  进栈指令PUSH:

Push r16/m16/seg  操作过程:1. SP<-SP-2  2.SS:[SP]<-r16/m16

同理POP是出栈指令,操作与PUSH相反。

 

2.    算数运算类指令:

四则运算是计算机经常进行的一种操作,算术运算指令实现二进制(十进制)数据的四则运算。

注意算术运算类指令对标志的影响

掌握ADD/ADC/INC   ,  SUB/SBB/DEC/NEG/CMP

熟悉 MUL/IMUL   ,  DIV/IDIV

理解 CBW/CWD  ,  DAA/DAS ,  AAA/AAS/AAM/AAD

(1)  加法指令ADD:

功能:ADD指令将源与目的操作数相加,结果送到目的操作数

ADD指令按状态标志的定义相应设置状态标志

ADD reg, imm/reg/mem  reg<-reg+imm/reg/mem

(2)  带进位加法指令ADC:

ADC指令将源与目的的操作数相加,在加上进位CF标志,结果送到目的操作数

ADC指令按状态标志的定义相应设置状态标志

ADC指令主要与ADD配合,实现多精度加法运算

ADD reg , imm/reg/mem

ADC mem , imm/reg

(3)  增量指令INC:

INC指令对操作数加1(增量)

INC指令不影响进位CF标志,按定义设置其他状态标志

INC reg/mem    reg/mem<-reg/mem+1

(4)  减法指令SUB:

SUB指令将目的操作数减去源操作数,结果送到目的操作数

SUB指令按照定义相应设置状态标志

SUB reg , imm/reg/mem    reg<-reg-imm/reg/mem

(5)  带借位减法指令SBB:

SBB指令将目的操作数减去源操作数,在减去借位CF(进位),结果送到目的操作数。

SBB指令主要与SUB配合,实现多精度减法运算

SBB reg , imm/reg/mem    reg<-reg-imm/reg/mem-CF

(6)  减量指令DEC:

DEC指令对操作数减1(减量)

DEC reg/mem    reg/mem<-reg/mem-1

INC指令和DEC指令都是单操作数指令,主要用于对计数器和地址指针的调整。

(7)  求补指令NEG:

NEG指令对操作数执行求补运算:用0减去操作数,然后结果返回操作数,求补运算也可以表达成,将操作数按位取反后加1

NEG指令对标志的影响与用0作减法的SUB指令一样

NEG reg/mem     reg/mem<-0-reg/mem

(8)  比较指令CMP:

CMP指令将目的操作数减去源操作数,按照定义相应设置状态标志

CMP指令执行的功能与SUB指令类似,但结果不回送目的操作数。

CMP reg , imm/reg/mem    reg—imm/reg/mem

 

3.    位操作指令:

位操作指令以二进制为基本单位进行数据的操作,这是一类常用的指令。

(1)逻辑运算指令:ADD(与)  OR(或)  XOR(异或)  NOT(非)   TEST(测试)

(2)移位指令:SHL(逻辑左移)   SHR(逻辑右移)   SAL(算术左移)   SAR(算术右移)

(3)循环移位指令:ROL(左循环移位)   ROR(右循环移位)   RCL(带进位左循环移位)   RCR(带进位右循环移位)

1)逻辑运算指令ADD:对两个操作数执行逻辑与运算,结果送到目的操作数。ADD des , src     des<-des^src

2)逻辑运算指令OR:对两个操作数执行逻辑或运算,结果送到目的操作数,OR dest , src       dest<-destv src

3)逻辑运算指令XOR:对两个操作数执行逻辑异或运算,结果送到目的操作数。XOR dest , src

4)逻辑运算指令NOT:对一个操作数执行逻辑非运算。NOT reg/mem,按位取反,原来的0的位变1,原来的1的位变0

 

4.    控制转移类指令:

用于实现分支,循环,过程等程序结构,是仅次于传送指令的常用指令。

重点掌握:JMP/JCC/LOOP  ,   CALL/RET

INT n/IRET 常用系统功能调用

一般了解:LOOPZ/LOOPNZ   INTO

(1)  无条件转移指令JMP:

JMP label;程序转向label标号指定的地址(标号要在程序其他位置标出)

只要执行无条件转移指令JMP,不需要任何条件,就使程序转到指定的目的地址处,从目标地址开始执行指令。

操作数是要转移到的目标地址。

转移原理:1.程序的执行地址,是由段寄存器CS和指令指针IP共同确定的,即当前指令的地址为CS:IP。2.程序的跳转是通过修改CS和IP的值来实现的。

(2)  条件转移指令JCC:

Jcc label  ; 条件满足,发生转移:IP<-IP+8位位移量;条件不满足,顺序执行。

指定的条件cc如果成立,程序转移到由标号label指定的目标地址去执行指令,条件不成立,则程序将顺序执行下一条指令。

操作数label是短转移指令,要跳转的地址必须距当前IP地址-128~+127个单元的范围之内

Jcc指令不影响标志,但要利用标志,根据利用的标志位不同,16条指令分为3种情况:

1)       判断单个标志位状态

2)       比较无符号数高低

3)       比较有符号数大小

(3)  循环指令LOOP:

循环指令是一种特殊的转移指令,当满足某条件时,反复执行一系列操作,知道不满足为止。

格式: LOOP label

循环指令利用CX寄存器作为计数器

(4)  子程序指令:

子程序是完成特定功能的一段程序

当主程序(调用程序)需要执行这个功能时,采用CALL调用指令转移到该子程序的起始处执行

当运行完子程序功能后,采用RET返回指令回到主程序继续执行

子程序通常是与主程序分开完成特定功能的一段程序,程序中有时要反复的实现相同的功能只不过参数不同而已,把仅参数不同功能重复的程序编写成为子程序,执行这个功能时,就可以调用该子程序,执行完成后在返回主程序。

CALL指令分成4中类型:

1)       CALL label; 段内调用,相对寻址。

2)       CALL r16/m16;段内调用,间接寻址

3)       CALL far ptr label;段间调用,直接寻址

4)       CALL far ptr mem;段间调用,间接寻址

(5)  中断指令:

中断是一种改变程序执行顺序的方法,在程序运行时,遇到某些需要紧急处理的情况,如停电,数据的实时接收,溢出等,处理器暂停主程序的执行,转去执行中断处理程序。

中断分类:内部中断,外部中断

中断指令:INT

INT i8

IRET:中断返回指令,实现中断返回

INTO:溢出中断指令

 

5.    处理机控制类指令:

对CPU状态进行控制的指令。

NOP CS:SS:DS:ES

LOCK  HLT  ESC  WAIT

(1)  空操作指令NOP:不执行任何操作,但占用一个字节存储单元,空耗一个指令执行周期。

(2)  NOP常用于程序调试,在需要预留指令空间时用NOP填充,代码空间多余时也可以用NOP填充,还可以用NOP实现软件延时。

(3)  事实上,NOP和XCHG,AX,的指令代码一样都是90H

(4)  段超越前缀指令:在允许段超越的存储器操作数之前,使用段超越前缀指令,将采用指定的段寄存器寻址操作数。

CS:使用代码段的数据

SS:使用堆栈段的数据

DS:使用数据段的数据

ES:使用附加段的数据

 

6.    伪指令

没有对应的机器码的指令,最终不被CPU所执行。伪指令是由编译器来执行的指令,编译器根据伪指令来进行相关的编译工作。

segment和ends是一对成对使用的伪指令,这是在写可被编译器编译的汇编程序时,必须要用到的一对伪指令。

segment和ends的功能是定义一个段,segment说明一个段开始,ends说明一个段结束。

一个段必须有一个名称来标识,使用格式为:

        段名 segment

        段名 ends

一个汇编程序是由多个段组成的,这些段被用来存放代码,数据或当作栈空间来使用。

一个有意义的汇编程序中至少要有一个段,这个段用来存放代码。

end是一个汇编程序的结束标记,编译器在编译汇编程序的过程中,如果碰到了伪指令end,就结束对源程序的编译。

不要搞混end和ends




本期就讲解到这里啦,下一期我们继续《代码的静态与动态分析技术》,这是属于汇编层面的分析。

软件逆向的定义:

软件逆向工程是通过反汇编和调试等手段,分析计算机程序的二进制可执行代码从而获得程序的算法细节和实现原理的技术。

研究对象:没有公开源代码的计算机程序,主要是已经经过编译的二进制可执行代码(如win32平台上的PE文件,包括exe,dll等文件格式)。

软件逆向的分类:

(1)  系统级逆向:大范围分析观察,整体把握

(2)  代码级逆向:程序二进制码中提取设计理念和算法

软件逆向步骤:

(1)  研究保护方法,去除保护功能:解码/反汇编(目标二进制代码)

(2)  反汇编目标软件,定位功能函数:中间语言翻译(汇编或类汇编代码)

(3)  分析汇编代码:数据流分析(各级中间语言)

(4)  修改汇编代码或还原高级源代码:其他分析和优化(高级抽象代码)

软件逆向工具:

(1)  Ollydbg:动态追踪工具,插件较好较多

(2)  Windbg:用户态和内核态调试工具

(3)  IDA:交互式反汇编器

(4)  PEID:著名的查壳工具

(5)  C32Asm:反汇编程序,可直接修改软件内部代码,有十六进制编辑模式

软件逆向的主要应用:

(1)  软件破解:破解软件的版权让用户不支付授权费用就可以使用软件的全部功能。

(2)  病毒和恶意程序的分析:恶意程序的传播机制和危害并设计出解,分析病毒解决办法。

(3)  系统漏洞分析:分析漏洞原理,设计补丁程序或者编写利用程序(Exploit)

(4)  分析不公开的文件格式,协议等

(5)  分析windows或mac平台上的硬件驱动程序编写linux下的相应驱动

(6)  挖掘消费电子产品的潜能

(7)  挖掘操作系统未文档化的API,发现更多内幕

(8)  计算机犯罪取证


软件开发基础知识:

目前通用的编程语言有两种形式:汇编语言和高级语言

汇编语言的实质和机器语言是相同的,都是直接对硬件操作,只不过指令采用英文缩写的标识符,更容易识别和记忆。汇编程序通常由三部分组成:指令,伪指令,宏指令。

高级语言所编写的程序不能直接被计算机识别,必须经过转换(目标代码即机器码)才能被执行,按照转换方式可将他们分为两类:

(1)  解释类:边翻译边执行

(2)  编译类:先翻译在执行

 

C语言的特点:

(1)  c语言允许直接访问物理地址,可以直接对硬件进行操作

(2)  c语言程序代码质量高,程序执行效率高

(3)  c语言使用范围大,可移植性好


常见的汇编指令:

(1)汇编大多是指汇编语言,汇编程序。把汇编语言翻译成机器语言的过程称为汇编。在汇编语言中,用符号代替机器语言的二进制码,就把机器语言变成了汇编语言。

(2)用汇编语言编写的程序,机器不能直接识别,要由一种程序将汇编语言翻译成机器语言,这种起翻译作用的程序叫汇编程序,汇编程序是系统软件中语言处理的系统软件。

(3)由于汇编更接近机器语言,能够直接对硬件进行操作,生成的程序与其他的语言相比具有更高的运行速度,占用更小的内存,因此在一些对于时效性要求很高的程序,许多大型程序的核心模块以及工业控制方面大量应用。

(4)关于汇编语言的种类,可以说有多少中不同内核的CPU,就有多少种汇编语言。

(5)不同内核的CPU,必须有对应的汇编语言编译器将汇编语言编写的程序编译成对应CPU的机器语言代码,CPU才能正确识别和执行这些代码。

(6)不同架构的CPU的汇编指令集并不相同。

(7)不同的汇编程序有不同的汇编语言规定。

(8)常用的汇编程序有ASM,MASM,TASM,OPTASM等。

 

寄存器:

寄存器是存储信息的单元或者说是器件,这里讨论的寄存器都是CPU中的寄存器,位于CPU内部,而内存位于CPU外部。

对于一个汇编程序员来说,CPU中主要可以使用的也就是寄存器而已,汇编程序员可以使用指令来读写CPU中的寄存器,从而实现对于CPU的控制,当然,不同的CPU,寄存器的个数和结构都是不一样的。

8086 CPU中寄存器总共为14个,且均为16位(32位和64位均已16位为基础)

即 AX BX  CX  DX SP  BP  SI DI  IP  FLAG CS  DS  SS  ES共14个。这14个寄存器按照一定的方式又分为通用寄存器,控制寄存器,段寄存器。

 

通用寄存器:

AX,BX,CX,DX称作为数据寄存器:

AX:累加寄存器,也称为累加器

BX:基地址寄存器

CX:计数器寄存器

DX:数据寄存器


SP和BP又称作为指针寄存器:

       SP:堆栈指针寄存器

       BP:基指针寄存器


SI和DI又称作为变址寄存器:

       SI:源变址寄存器

       DI:目的变址寄存器

 

控制寄存器:

       IP:指令指针寄存器

       FLAG:标志寄存器

 

段寄存器:

       CS:代码段寄存器

       DS:数据段寄存器

       SS:堆栈段寄存器

       ES:附加段寄存器

 

堆栈:

       堆栈都是一种数据项按序排序的数据结构,只能在一端(称为栈顶)对数据项进行插入和删除。主要功能是暂时存放数据和地址,通常用来保护断电和现场。

       堆:队列优先,先进先出

       栈:先进后出

堆栈中定义了一些操作,两个最重要的是PUSH和POP。

PUSH操作在堆栈的顶部加入一个元素,POP操作相反,在堆栈顶部移去一个元素,并将堆栈的大小减一。

 

机器语言:用二进制编码表示每条指令,是计算机能直接识别和执行的语言。

汇编语言:是用助记符,符号和数字等来表示指令的程序设计语言,它与机器语言指令是一一对应的。

   

重点掌握常用指令功能及应用:

       常用传送指令

       加减法指令

       逻辑运算和移位指令

       控制转移指令

       字符(串)输入输出功能调用


(1)  数据传送指令:MOV/XCHG,PUSH/POP,LEA

(2)  算数运算类指令:ADD/ADC/INC,SUB/SBB/DEC/CMP/NEG,MUL/IMUL,DIV/IDIV

(3)  位操作类指令:AND/OR/XOR/NOT/TEST

(4)  控制转移类指令:JMP/JCC/LOOP,CALL/RET,INT n

(5)  处理机控制类指令:NOP

 

Inter 8086指令系统共有117条基本指令:

可分为6个功能组:

(1)  数据传送类指令

(2)  算数运算类指令

(3)  位操作类指令

(4)  串操作类指令

(5)  控制转移类指令

(6)  处理机控制类指令

 

1.    数据传送类指令:

数据传送是计算机中最基本,最重要的一种操作,传送指令也是最常用的一类指令,传送指令把数据从一个位置传送到另一个位置。

除标志寄存器传送指令外,均不影响标志位。

重点掌握一下指令:

MOV   XCHG   PUSH  POP   LEA

(1)  传送指令MOV:把一个字节或操作数从源地址传送至目的地址。

(2)  交换指令XCHG:把两个地方的数据进行互换。

寄存器与寄存器之间对换数据

寄存器与存储器之间对换数据

不能在存储器与存储器之间对换数据

(3)  进栈指令PUSH:

Push r16/m16/seg  操作过程:1. SP<-SP-2  2.SS:[SP]<-r16/m16

同理POP是出栈指令,操作与PUSH相反。

 

2.    算数运算类指令:

四则运算是计算机经常进行的一种操作,算术运算指令实现二进制(十进制)数据的四则运算。

注意算术运算类指令对标志的影响

掌握ADD/ADC/INC   ,  SUB/SBB/DEC/NEG/CMP

熟悉 MUL/IMUL   ,  DIV/IDIV

理解 CBW/CWD  ,  DAA/DAS ,  AAA/AAS/AAM/AAD

(1)  加法指令ADD:

功能:ADD指令将源与目的操作数相加,结果送到目的操作数

ADD指令按状态标志的定义相应设置状态标志

ADD reg, imm/reg/mem  reg<-reg+imm/reg/mem

(2)  带进位加法指令ADC:

ADC指令将源与目的的操作数相加,在加上进位CF标志,结果送到目的操作数

ADC指令按状态标志的定义相应设置状态标志

ADC指令主要与ADD配合,实现多精度加法运算

ADD reg , imm/reg/mem

ADC mem , imm/reg

(3)  增量指令INC:

INC指令对操作数加1(增量)

INC指令不影响进位CF标志,按定义设置其他状态标志

INC reg/mem    reg/mem<-reg/mem+1

(4)  减法指令SUB:

SUB指令将目的操作数减去源操作数,结果送到目的操作数

SUB指令按照定义相应设置状态标志

SUB reg , imm/reg/mem    reg<-reg-imm/reg/mem

(5)  带借位减法指令SBB:

SBB指令将目的操作数减去源操作数,在减去借位CF(进位),结果送到目的操作数。

SBB指令主要与SUB配合,实现多精度减法运算

SBB reg , imm/reg/mem    reg<-reg-imm/reg/mem-CF

(6)  减量指令DEC:

DEC指令对操作数减1(减量)

DEC reg/mem    reg/mem<-reg/mem-1

INC指令和DEC指令都是单操作数指令,主要用于对计数器和地址指针的调整。

(7)  求补指令NEG:

NEG指令对操作数执行求补运算:用0减去操作数,然后结果返回操作数,求补运算也可以表达成,将操作数按位取反后加1

NEG指令对标志的影响与用0作减法的SUB指令一样

NEG reg/mem     reg/mem<-0-reg/mem

(8)  比较指令CMP:

CMP指令将目的操作数减去源操作数,按照定义相应设置状态标志

CMP指令执行的功能与SUB指令类似,但结果不回送目的操作数。

CMP reg , imm/reg/mem    reg—imm/reg/mem

 

3.    位操作指令:

位操作指令以二进制为基本单位进行数据的操作,这是一类常用的指令。

(1)逻辑运算指令:ADD(与)  OR(或)  XOR(异或)  NOT(非)   TEST(测试)

(2)移位指令:SHL(逻辑左移)   SHR(逻辑右移)   SAL(算术左移)   SAR(算术右移)

(3)循环移位指令:ROL(左循环移位)   ROR(右循环移位)   RCL(带进位左循环移位)   RCR(带进位右循环移位)

1)逻辑运算指令ADD:对两个操作数执行逻辑与运算,结果送到目的操作数。ADD des , src     des<-des^src

2)逻辑运算指令OR:对两个操作数执行逻辑或运算,结果送到目的操作数,OR dest , src       dest<-destv src

3)逻辑运算指令XOR:对两个操作数执行逻辑异或运算,结果送到目的操作数。XOR dest , src

4)逻辑运算指令NOT:对一个操作数执行逻辑非运算。NOT reg/mem,按位取反,原来的0的位变1,原来的1的位变0

 

4.    控制转移类指令:

用于实现分支,循环,过程等程序结构,是仅次于传送指令的常用指令。

重点掌握:JMP/JCC/LOOP  ,   CALL/RET

INT n/IRET 常用系统功能调用

一般了解:LOOPZ/LOOPNZ   INTO

(1)  无条件转移指令JMP:

JMP label;程序转向label标号指定的地址(标号要在程序其他位置标出)

只要执行无条件转移指令JMP,不需要任何条件,就使程序转到指定的目的地址处,从目标地址开始执行指令。

操作数是要转移到的目标地址。

转移原理:1.程序的执行地址,是由段寄存器CS和指令指针IP共同确定的,即当前指令的地址为CS:IP。2.程序的跳转是通过修改CS和IP的值来实现的。

(2)  条件转移指令JCC:

Jcc label  ; 条件满足,发生转移:IP<-IP+8位位移量;条件不满足,顺序执行。

指定的条件cc如果成立,程序转移到由标号label指定的目标地址去执行指令,条件不成立,则程序将顺序执行下一条指令。

操作数label是短转移指令,要跳转的地址必须距当前IP地址-128~+127个单元的范围之内

Jcc指令不影响标志,但要利用标志,根据利用的标志位不同,16条指令分为3种情况:

1)       判断单个标志位状态

2)       比较无符号数高低

3)       比较有符号数大小

(3)  循环指令LOOP:

循环指令是一种特殊的转移指令,当满足某条件时,反复执行一系列操作,知道不满足为止。

格式: LOOP label

循环指令利用CX寄存器作为计数器

(4)  子程序指令:

子程序是完成特定功能的一段程序

当主程序(调用程序)需要执行这个功能时,采用CALL调用指令转移到该子程序的起始处执行

当运行完子程序功能后,采用RET返回指令回到主程序继续执行

子程序通常是与主程序分开完成特定功能的一段程序,程序中有时要反复的实现相同的功能只不过参数不同而已,把仅参数不同功能重复的程序编写成为子程序,执行这个功能时,就可以调用该子程序,执行完成后在返回主程序。

CALL指令分成4中类型:

1)       CALL label; 段内调用,相对寻址。

2)       CALL r16/m16;段内调用,间接寻址

3)       CALL far ptr label;段间调用,直接寻址

4)       CALL far ptr mem;段间调用,间接寻址

(5)  中断指令:

中断是一种改变程序执行顺序的方法,在程序运行时,遇到某些需要紧急处理的情况,如停电,数据的实时接收,溢出等,处理器暂停主程序的执行,转去执行中断处理程序。

中断分类:内部中断,外部中断

中断指令:INT

INT i8

IRET:中断返回指令,实现中断返回

INTO:溢出中断指令

 

5.    处理机控制类指令:

对CPU状态进行控制的指令。

NOP CS:SS:DS:ES

LOCK  HLT  ESC  WAIT

(1)  空操作指令NOP:不执行任何操作,但占用一个字节存储单元,空耗一个指令执行周期。

(2)  NOP常用于程序调试,在需要预留指令空间时用NOP填充,代码空间多余时也可以用NOP填充,还可以用NOP实现软件延时。

(3)  事实上,NOP和XCHG,AX,的指令代码一样都是90H

(4)  段超越前缀指令:在允许段超越的存储器操作数之前,使用段超越前缀指令,将采用指定的段寄存器寻址操作数。

CS:使用代码段的数据

SS:使用堆栈段的数据

DS:使用数据段的数据

ES:使用附加段的数据

 

6.    伪指令

没有对应的机器码的指令,最终不被CPU所执行。伪指令是由编译器来执行的指令,编译器根据伪指令来进行相关的编译工作。

segment和ends是一对成对使用的伪指令,这是在写可被编译器编译的汇编程序时,必须要用到的一对伪指令。

segment和ends的功能是定义一个段,segment说明一个段开始,ends说明一个段结束。

一个段必须有一个名称来标识,使用格式为:

        段名 segment

        段名 ends

一个汇编程序是由多个段组成的,这些段被用来存放代码,数据或当作栈空间来使用。

一个有意义的汇编程序中至少要有一个段,这个段用来存放代码。

end是一个汇编程序的结束标记,编译器在编译汇编程序的过程中,如果碰到了伪指令end,就结束对源程序的编译。

不要搞混end和ends




本期就讲解到这里啦,下一期我们继续《代码的静态与动态分析技术》,这是属于汇编层面的分析。