admin 管理员组

文章数量: 1087608

逆向需要基础

汇编:逆向之缘,漏洞之本

c:算法实现,目标恢复

Python:脚本处理(批处理),高效轻便

操作系统

Windows

Linux Unix

Android

Others

Max

相关工具

Reverse Engineer逆向分析(Windows平台的:)

静态分析工具:IDA

动态分析工具:OllyDbg;Windbg;gdb;

虚拟机:Vmware

二进制查看工具:Winhex;

渗透测试Penetration test:

Metasploit

W3AF

NMAP

web security网络安全

php

js

二进制查看工具

Winhex/Ultraedit(显示二进制代码、十六进制)、可以快速对字符串进行定位

exeScope——查看文件结构框架

查壳工具

PEID:(识别加密壳 zprotect、识别压缩壳 UPX。)

识别zprotect(是一种先进的加密壳,通过虚拟机加密,把要保护的代码放在虚拟机里来执行,创建新的指明系统,有效阻止代码还原和分析;代码乱序,代码会分散变形;动态代码结构,每次加密生成的文件都是不同的(每次保护方法都是不同的))(入口点:000C5825)

识别UPX加壳——压缩壳、程序开头插入一段代码(用于解压缩),(某种程度上,压缩也可以叫加密,压缩后的代码也是看不懂),程序变小,便于传输

壳的概念:自然界中,植物用它来保护种子,动物用它来保护身体;而我们说的壳指的是计算机软件里面的,用来保护某一个软件不被修改,或者缩小体积。

加壳分为加压缩壳和加加密壳——压缩壳使文件大小变小,便于在网上传播;有一定的保护作用(脱壳相对容易),你无法反汇编加壳程序。   加密壳:用各种手段保护软件不被脱壳,跟踪,文件大小不是他的目的甚至会变大

(经过大量的各种壳的脱壳经验)

手动脱壳的主要步骤——,寻找入口点,转储(dump)程序,修复转入函数(Import Table)
PEID/LoadPE/DIE/手动分析

静态分析工具

IDA——DataRescue出品(plugins插件)、Windows:IDA(R3)and plungins(插件)

交互式 功能非常完善、适应多处理器

把二进制程序转换成汇编程序(左边函数,右边框图是程序的实现(更易读,分析)hex view查看原本二进制文本、)
与Vmware联动,调试程序。与Qemu联动,调试固件。

动态分析工具

OllyDbg 反汇编窗口、寄存器窗口、数据窗口、堆栈窗口、信息窗口(用于ctf)!!!、、OllyDbg(R3)、WinDbg(R0)

Linux平台动态分析

gdb 命令行 gdb(R3)、kgdb(R0)

gdb插件peda:增强gdb显示,且增加一些命令

gdb插件gef:提供更多动态分析支持

VM image(虚拟机):Vmware、VirtualBox、Qemu。
注:应用调试为 R3,内核调试为 R0。

window平台内核调试

WinDbg轻量级的调试工具,安装小,内核开发,也可以进行用户级的调试

Linux平台内核调试kgdb

需要重新编译内核打开kgdb选项

非主流工具

符号执行:Angr,Z3

污点跟踪:Pin,Valgrind,TraintDroid

模糊测试:FileFuzz,AFL,Trinity,Peach

平台专用工具

Android:apktool,SMALI,BAKSMALI,Dex2JAR,JD-GUI

固件专用:Binwalk,firmwre-mod-kit,Qemu(动态模拟环境)、KVM(底层虚拟化环境)
Pwn环境搭建 - LInux工具
ida pro:静态反编译
gdb:动态调试
peda/gef/gdbinit:gdb插件
Checksec:elf安全性及运行平台
Objdump/readelf:elf的关键信息
ROPgadget:rop利用
pwntools:写exp和poc
Pwntools/zio:必备的库
one_gadget:寻找libc中exec(‘bin/sh’)的位置
libc-database:通过泄露的libc中函数地址查libc版本

逆向平台搭建

实验步骤:

(1) 下载虚拟机软件(如Vmware、VirtualBox等)并安装。利用已安装的虚拟机软件,架设一台Windows XP虚拟机。

(2) 在WinXP虚拟机中下载安装Winhex或Ultraedit,然后测试是否能运行。

(3) 在WinXP虚拟机中下载安装OllyDbg,然后测试是否能运行。

(4) 在WinXP虚拟机中下载安装IDA Pro,然后测试是否能运行。

(5) 在WinXP虚拟机中下载安装WinDbg,然后测试是否能运行。

(6) 在WinXP虚拟机中下载安装PEiD,然后测试是否能运行。

(7) 在WinXP虚拟机中下载安装eXeScope,然后测试是否能运行。

(8) 关闭之前打开的应用程序,创建虚拟机快照。

逆向作业

WinDbg是windows平台下对内核,应用程序,服务程序进行调试的工具。相

对VS而言更加小巧,功能却比VS丰富,支持内核模式和用户模式的调试

使用: WinDbg的调试模式——内核模式(Kernel-Mode)与用户模式(User-Mode)

1、内核模式(Kernel-Mode)——为了不让程序任意存取资源,对应x86的ring0层,操作

系统的核心部分,包括设备驱动程序都运行在该模式。

2、用户模式(User-Mode)——当CPU运行于User Mode时,对应于x86的ring3层,操

作系统的用户接口部分以及所有的用户应用程序都运行在该级别。

PDB文件:链接器自动生成;文件由两个部分构成,私有符号数据(private symbol data)和公共符号表(public symbol table)

私有符号数据(Private Symbol Data) :函数;全局变量;局部变量;用户定义的结构体,类,数据类型;源文件的名称和源文件中每个二进制指令的行号

公共符号表(Public Symbol Table):静态函数;全局变量(extern)

找到关键点 -> 长度判断 -> 逐个字符判断。

内核环境调试:1.增加环境变量path 2.windbg 按下Ctrl+s (symbol search path) 3.选择file->kernel debug 单击com标签 4,增加串口(串行端口),输出到命名管道,管道设置 5.启动对应支持调试的OS 6、管理员权限的cmd对应设置调整 7.连接成功

作业:

一、列举本次课程中提到的二进制查看工具、静态分析工具、动态分析工具、污点跟踪工具和模糊测试工具。每种类型的分析工具至少列举2种。

①二进制查看工具:Winhex,Ultraedit,exeScope

②查壳脱壳工具:PEiD,LoadPE,DIE

③静态分析工具:IDAandplugins

④动态调试工具:R3:OllyDbg,gdb;R0:Windbg,kgdb

⑤渗透测试工具:Metasploit,W3AF,NMAP,php,JavaScript

⑥虚拟机:Vmware,Qemu

⑦非主流工具:符号执行:Angr,Z3

污点跟踪:Pin,Valgrind,TraintDroid

模糊测试:FileFuzz,AFL,Trinity,Peach

⑧平台专用工具:固件专用:Binwalk,firmware-mod-kit,Qemu

Android专用:apktool,SMAL/BAKSMALI,Dex2JAR,JD-GUl

  1. 简述本次课程中的Reverse实战示例实现破解的过程。

利用静态分析工具IDA,main函数为程序的入口

从v5到v12的赋值语句,除了v12为0(字符数组最后一位为0),其它都是大整数,

一串的地址是连着的,上图中代码是从IDA从汇编推测出的源代码,v5到v12为字符数组

栈是从高字节生长到底地址空间,所以v6所占的四个字节其实是79h到76h,v5是从75到72

while语句中:要把输入的scanf的返回值同-1比较,常见的数据处理手段,只要不强制结束,就会不停的while循环,让用户输入数据

(scanf返回正整数,表示正确输入参数的个数;返回0,用户类型是不匹配的;返回-1,表示被强制结束(Windows下:用户按Ctrl+Z)(Linux下,用户按Ctrl+D))

字符串匹配:v4和v5进行匹配,(const char*)为强制类型转换,把v5的地址当初是一个字符串的首地址,如果两个字符串匹配的话,strcmp返回0,while会终止跳出,此时匹配的v5就是要得到的flag/密码

v5到v11的整数,按照字符解释,把整数转换成字符串(图中看起来是倒过来的,

因为栈是向着内存地址减小的方向增长。)

动态:OllyDbg

程序的Winmain函数入口点,文件入口;载入文件,Ctrl+G打开窗口,输入GetDlgItemTextA函数名;在USER32的地址空间,对应的代码处F2下断点;F9运行,点check,找到程序被截停的地方,按Alt+F9,返回到用户代码,Alt+B 即可跳转断点;判断语句改为NOP保存破解成功

静态分析:

① 打开 IDA 反编译,进入 main 函数

② 由变量定义可知 v5-v12 是字符数组

③ 由判断语句可知字符串 v5 就是 flag

④ 将数组转换为字符串,输入flag破解成功

动态分析:

① 运行程序,打开 OllyDbg,进入 WinMain 函数

② 找到 GetDlgItemTextA 函数

③ 地址空间是模块 USER32,在对应处 F2 下断点

④ F9 运行至截停,Alt+B 即可跳转断点;判断语句改为NOP保存,破解成功

三、简述本次课程中用OllyDbg找到程序入口的过程。

1、用 IDA 打开程序,在左边列表找到 _main 函数。

2、看反汇编窗口,push 四个参数 0、“you have been hacked”、“warning”、0。call 调用指令 messagebox,说明这确实是程序入口。

3、IDA 下面看到地址 401500,来到 OllyDbg, 右键-go to-expression 搜索地址跳转就行了。

OllyDbg工具的使用——找到程序真正入口

借助IDA,函数名function name处找到main函数,双击发现汇编代码,五个mo指令及call指令,看反汇编窗口,push 四个参数 0、“you have been hacked”、“warning”、0。call 调用指令 messagebox,main函数地址在底部(0000000000)401500(相对地址)、回到od,点右键,点goto-expression,输入地址401500,点follow expression,跳转到main函数,main函数处(也就是401500)F2按下断点,按F9运行,按F8运行到0x40150B,目前栈的情况,esp栈顶,bep栈底,连续两次F8,sub对esp做减法,按F8,栈顶为0x28FEB4减去14的值——0x28FEA0,两者之间为sub指令开辟出的栈空间(5个地址)

  1. 利用OllyDbg,参照课程中的爆破示例对该程序中的Serial功能进行爆破。

先利用dbg打开文件exp2,运行,上划找到try again 右键search for选择 all referenced string对应try again,将跳转指令jnz改为nop,save覆盖破解成功

  1. 程序放入ida未找到main函数,shift+f11 找到两行字符串“good job”,两个地址都记下来(0042F570,0042FBD8),去od看汇编并爆破。
  2. Ctrl+g跳转到0042FBD8,在jnz哪行,f2下断点,f9运行发现程序执行到底,不是爆破的地方,所以Ctrl+g跳转到0042F570,在jnz哪行下断点,f9没有执行到底
  3. 把跳转指令jnz换成nop,爆破成功,保存。

首先打开exp点击确定。 点击序列号“Serial”

随便输入一串字符串,比如123 点击“Check it Baby!” 退出

我们用OllyDbg打开exp file-open 点击打开-出现下面的反汇编窗口

右键-search for -文本字符串 滑到最底部,找到try again/God job这些字符串

想要输出成功信息“god job dude!”,前面可以设想有一个判断指令,在此设置一个断点,就是我们需要爆破的地方,进行尝试。

从下往上,我们先找到第一个0042FB0C地址,右键-follow in disassembler

回到窗口,f2设置断点,点击运行,序列号输入123,弹出try again,说明这个不是我们要爆破的地方。

继续,回到文本字符串,追踪0042F4DE字符串 右键-follow in disassembler

在0042F4D5设置断点,运行,123,点“check it baby”,框变成了灰色(说明暂停了,这条指令就是我们要爆破的地方)

双击-修改为nop 点击assemble 原本的指令变成了90-nop

继续运行,弹出congratz-god jub dude!,验证成功!

我们要爆破的对象就是进行跳转的指令

我们现在只是在内存里把代码段修改了,但是磁盘里的程序还没有修改,edit-copy to executable-all modifications

注意:记住这个地方,两个nop指令要同时选中

弹出一个新的窗口,

保存为一个新的可执行文件,运行,可以看到爆破成功 !

  1. 1.以下哪一种工具是二进制查看工具?(C)
    A. IDA B. gdb C. WinHex D. Ollydbg
    2.以下哪一种工具是压缩壳加壳工具?(B)
    A. PEiD B. UPX C. Zprotect D. Vmware
    3.以下哪一种是Linux平台常用的动态分析工具?(A)
    A. gdb B. WinDbg C. Ollydbg D. IDA
    4.以下哪一种是Windows平台常用的静态分析工具?(D)
    A. gdb B. WinDbg C. Ollydbg D. IDA
    5.以下哪一种工具可以提供Ring0级的动态分析?(C)
    A. OllyDbg B. PEiD C. WinDbg D. IDA
    6.进程地址空间分为哪些部分?
    答:Text 文本、Data 数据、Heap 堆、Unused Memory 未用空间、Stack 栈
    7.栈顶保存在哪个寄存器?栈底保存在哪个寄存器?
    答:SP、BP
    8.简述栈帧是什么。
    答:指系统为函数调用单独分配的那部分栈空间。当运行中的程序调用另一个函数时,就要进入一个新的栈帧。
  2. search 来到关键函数GetDlgItemTexA。

第一个cmp,输入长度eax=0x8,否则跳转

第二个cmp,第6位=char(0x2D)=‘-’,否则跳转

第三个cmp,第1位 shl ecx,1 表示左移一位,char(0x64/2)=char(0x32)=‘2’,否则跳转

第四个cmp,第8位 test al,al 表示可以随意输入,否则跳转

第五个cmp,第5位=char(0x2B)=‘+’,否则跳转

第六个cmp,第2位 add edx,0xA 表示加0xA,char(0x44-0xA)=‘:’

第七个cmp,第4位=char(0x2E)=‘.’

第八个cmp,第7位=char(0x4D)=‘M’

第九个cmp,第3位 add ecx,0xA 表示加0xA,char(0x33-0xA)=‘)’

首先,利用OllyDbg打开exp3,运行,输入123123,右键search for -文本字符串-只有一个,右键选项定位到CPU,上划

cmp eax8是表示序列号有8位

cmp byte esp+9 2D右键follow in dump首位为0开始数,数到第九位,恰好就是我们输入的第六位3-对应的acsii码33-说明2D就是序列号的第六位,2D经过查表为-

movsx esp+4(第一位) 经过shl左移(对于二进制来说就是乘以2,放大两倍),cmp64就是和64比较,也就是原本的数就是32,对应的是2

esp+0B test al,al逗号是与运算,al只能是0,test不能是0,所以al是1~9的任意数字

esp+8是第五位,是2B也就是加号

esp+5是第二位,add 0A,再和44比较cmp,所以是44-0A即3A,所以是:

esp+7是第四位,sub 2E所以是.

esp+6是第三位,add 0A 在和33cmp,所以是33-0A为29,对应)

esp+0A是第7位,4D是M

最终结果是2:).±M5

  1. 简答

1、简述 JNZ 和 JZ 指令的用法及区别。

JNZ(jump if not zero):结果不为0(或不相等)则转移。

JZ(jump if zero):结果为0(或相等)则转移。

2、简述 TEST 指令的用法。

TEST:对两个参数逻辑与运算,并根据结果设置标志寄存器,结果不会保存。

3、简述 MOVSX 指令的用法。

MOVSX:带符号扩展传送指令。

MOVZX:无符号扩展传送指令。

例1、MOV BX,-12;10001100 符号位为1

MOVSX EBX,BX;(EBX)= FFFF FFF4H

例2、MOV CL,8;00001000 符号位为0

MOVSX EDX,CL;(EDX)= 0000 0008H

例3、MOV AH,11;无符号位

MOVZX ECX,AH;(ECX)= 0000 0011H

例4、MOV AX,9H;无符号位

MOVZX EBX,AX;(EBX)= 0000 0009H

4、简述进行程序爆破的思路。

通过search找到相关函数,跳转指令(如JNZ、JZ)一般就是爆破点,然后在程序中输入参数调试,看懂汇编代码和栈帧中的变量,就能逐个比对得到正确序列号。

5、一条注册码判断指令为cmp byte ptr ss:[esp+0x9],0x2D。请解释:

a)这条指令是如何访问内存的;

通过栈指针访问栈顶esp向上第9个地址。

b)这条指令的含义是什么。

通过cmp比较字符串ss和十六进制数2D。

6、简述MD5算法流程。

1、Append Padding Bits(填充bits)

2、Append Length(填充长度)

3、Initialize MD Buffer(初始化向量)

4、Process Message in 16-Word Blocks(复杂的函数运算)

八、注册序列码分析

先在ida打开exp4,、找到GetdigitemTextA函数,找到call指令对应的地址00401AD8,在ollydbg中下断点,找到核心位置or eax,eax;根据输入的用户名会自动生成一个MD5对应的序列号密码,这里用于contrast对比我们输入的序列号,call CM2.00401B79,然后进行比较,看注册码的四个部分,上面就有得到的序列号。

  1. 动态分析:先在ida打开,看到两个关键函数(md5加密和异或函数),对name进行加密,再一系列异或。最终得到的十六进制数组就是注册码。

再od打开,下断点,name输入’yydl’,运行。直接看到经过两个函数后的序列号。

Sub_401000:加密函数,对name进行md5加密

Sub_401b79:异或函数,异或string得出注册码

  1. 静态分析:md5加密直接用网站,主要分析异或函数。自己计算的意思。。

Yydl进行md5加密,得v0,name[0] name[1] name[2] name[3]

string异或函数后,得到注册码,,加密的函数被分为四段,各个段进行各自的运算操作,如图。最终根据name’yydl’写脚本计算出注册码。

  1. 作业简答题

(1)文字简述PE文件编译器的编程思路。

1、编写DOS头:IMAGE_DOS_HEADER

2、编写NT头:IMAGE_NT_HEADERS

3、编写文件头:IMAGE_FILE_HEADER

4、编写数据目录:IMAGE_DATA_DIRECTORY

5、编写节头:IMAGE_SECTION_HEADER

6、编写导入表:IMAGE_DIRECTORY_ENTRY_IMPORT

7、编写导出表:IMAGE_DIRECTORY_ENTRY_EXPORT

8、编写主函数 int main( )

九、

1、扩展PE头(OptionHeader):内存镜像基址/程序默认载入基址(ImageBase)变化。

2、导出表(ExportTable):地址变化。

二、分析为什么会出现这样的差异。

1、UPX(压缩程序):可以完成代码的压缩和实时解压执行,且不会影响程序的执行效率。

① UPX加壳:先在程序的开头插入一段代码,再将程序的其他地方做压缩(加密),因为压缩后的程序比较难看懂。

最初代码的形式:7==>8==>9==>5==>6

UPX压缩后形式:1==>2==>3==>4==>5==>6

执行时候的形式:1==>7==>8==>9==>5==>6

② UPX脱壳:解压缩功能是依靠第一步时插入的代码完成。

因为开头插入了代码,所以文件头字节数、程序入口改变。因为部分代码进行了加密,所以节表地址改变,进而引起之后的导出表地址改变。

2、Zprotect(加密程序):注重对代码的处理,拥有良好的稳定性和兼容性。

① ZProtect加壳包含IAT(Import Address Table,导入地址表)加壳技术,导致表的地址都发生了变化。

② ZProtect加壳过程中需要去掉随机基址,所以程序默认载入基址(ImageBase)变化。

十、简答:

1.PE文件格式是什么?在WINDOWS系统中有哪些类型的文件属于PE文件?

Portable Execaple(可移植,可执行),它是 Win32 可执行文件的标准格式。

Win32 可执行文件,.EXE、.DLL、*.OCX 等,都是 PE 格式。

2.简述WINDOWS平台下病毒运行的一般流程。

一般来说,病毒先于HOST程序获得控制权。运行Win32病毒的流程如下:

① 用户点击或系统自动运行HOST程序;

② 装载HOST程序到内存;

③ 通过PE文件中的 AddressOfEntryPoint+imageBase,定位程序入口;

④ 从第一条语句开始执行病毒代码;

⑤ 病毒主体代码执行完毕,将控制权交给HOST程序原来的入口代码;

⑥ HOST程序继续执行。

3.简述获取PE文件中重要数据结构(数据目录表中各个项目)的方法。

① 从 DOS header 定位到 PE header;

② 从 optional header 读取到 data directory 地址;

③ 将 IMAGE_DATA_DIRECTORY 结构尺寸(8 bytes)乘上1(索引号),得到 import symbols 的位置信息;

④ 将上面结果加上 data directory 地址,就得到了所查询数据结构信息的 IMAGE_DATA_DIRECTORY 结构项。

4.一个程序要调用外部DLL中的函数,是直接调用这个函数吗?如果不是,是如何调用的?

不是。而是将CALL指令转到同一个 .text 节中的 JMP DWORD PTR[XXXXXXXX] 类型的指令。

  1. DLL/EXE要引出一个函数给其他DLL/EXE使用,有两种实现方法。分别是什么?

① 通过函数名引出。例:DLL可以通过函数名引出,假设要引出名为 GetSysConfig 的函数,那么其他DLL/EXE若要调用这个函数必须以该函数名。

② 通过序数引出。 序数是唯一指定DLL中某个函数的16位数字,在所指向的DLL里是独一无二的。例:DLL可以通过序数引出,假设是16,那么其他DLL/EXE若要调用这个函数必须以该值作为GetProcAddress调用参数。

1.列举3种可以用于调试器检测的Windows API。

GetDlgItemTextA()、strcmp()、ShellExecute()等。

2.列举3种可以用于调试器检测的Windows数据结构。

哈希表、递归、链表等。

3.简述用软件断点识别调试器的原理。

① 软件断点:X86系统中为中断指令INT 3。当程序执行到 INT 3 时,引发软件中断。

操作系统的 INT 3 中断处理器会寻找注册在该进程上的调试处理程序,因而调试器就有了上下其手的机会。

② 硬件断点:X86系统提供8个调试寄存器(DR0~DR7)和2个MSR用于硬件调试。

4.列举3种可以干扰调试器的方法。

① 花指令:隐藏指令,干扰分析。

② 动态加/解密代码:干扰分析。

③ 异常处理机制:加大跟踪难度。

5.花指令是什么?有什么作用?

花指令:故意将错误的机器指令放在了错误的位置。

作用:设计者希望使破解者反汇编的时候出错。

6.简述手动脱壳的常用技术。

单步跟踪法、ESP定律法、内存镜像法、一步到达OEP法、最后一次异常法、模拟跟踪法、“SFX”法。

7.Stolen code是什么技术?如何解决?

Stolen code:软件脱壳中被修改的代码。

解决:到达OEP后补上stolen code里的代码。

8.SEH是什么?有什么作用?

SEH:Structured Exception Handling,结构化异常处理。

作用:Windows提供给程序设计者强有力的处理程序异常的武器。

进程地址空间:Text Segment:代码段 — 指令

Data Segment:数据段 — 全局变量)

Heap Segment:堆 — malloc/free、存储动态分配数据

Stack Segment:栈 — 函数参数、局部变量、返回地址

栈的操作方式:push/pop

栈的生长方向:高地址→低地址

栈帧:指系统为函数调用单独分配的那部分栈空间。

当运行中的程序调用另一个函数时,就要进入一个新的栈帧。

原来函数的栈帧称为调用者的帧,新的栈帧称为当前帧。

被调用的函数运行结束后当前帧全部收缩,回到调用者的帧。

ebp 指向当前帧底部

esp 指向当前帧顶部

OllyDbg:

一、基本用法

F2:设置断点。在光标位置按F2键即可,再按则会删除。

F7:单步步入。每按一次执行一条指令,遇到CALL等子程序进入。

F8:单步步过。每按一次执行一条指令,遇到CALL等子程序不进入。

F4:被调试的程序将直接开始运行,到光标所在位置处暂停。

F9:被调试的程序将直接开始运行。

Ctrl+F9:执行到返回指令。用于从系统地址空间返回到我们调试的程序地址空间。

Alt+F9:执行到用户代码。用于从系统地址空间快速返回到我们调试的程序地址空间。

ALT+M:查看程序的加载模块,用于分析程序主文件结构。

二、汇编基本指令

MOV:传送字或字节。如 MOV A B ,就是将B中的字传给A。

PUSH:把字压入堆栈。如 PUSH A ,就是把A中的字压入栈。

CALL:子程序调用指令。如 CALL SUM,调用子程序 SUM。

JNZ/JNIE:运算结果不为零转移,标志位 ZF=0 时跳转。

JZ/JE:运算结果为零转移,标志位 ZF=1 时跳转。

LEA :装入有效地址。如 LEA DX,string,把偏移地址存到DX。

REP :按计数寄存器 CX/ECX 中指定的次数重复执行。

MOVSX:先符号扩展,再传送。

RET :子程序返回指令。

XOR :异或运算。

AND :与运算。

CMP :比较。

DEC :减1。

INC:加1。

ADD:加法。

SUB:减法。

TEST :测试。

在DOS环境下有四种基本的可执行文件格式

 批处理文件,以.BAT结尾的文件

 设备驱动文件,是以.SYS结尾的文件,如CONFIG.SYS

 COM文件,是以.COM结尾的纯代码文件

 没有文件头部分,缺省情况下总是从0x100H处开始执行,

没有重定位项,所有代码和数据必须控制在64K以内

 EXE文件,是以.EXE结尾的文件

 文件以英文字母“MZ”开头,通常称之为MZ文件

 MZ文件有一个文件头,用来指出每个段的定义,以及重定

位表。.EXE文件摆脱了代码大小最多不能超过64K的限制

,是DOS下最主要的文件格式

 在Windows 3.0/3.1的可执行文件,在MZ文件头之后又有

一个以“NE”开始的文件头,称之为NE文件

 在Win32位平台可执行文件格式:可移植的可执行文件

(Portable Executable File)格式,即PE格式。MZ文件头

之后是一个以“PE”开始的文件头

MZ文件格式-Mark Zbikowski

 .EXE文件由三部分构成:文件头、重定位表和二进制代码

 允许代码、数据、堆栈分别处于不同的段,每一段都可以是64KB

程序编译后:

0000:0000 9A78563412 call far 1234:5678

程序加载器的重定位工作,就是将程序中需要重定位

的地方,都加上程序的加载地址。

这个程序被加载到了内存中的1111段处。那么完成重

定位后,代码应该是这样:

1111:0000 9A78564523 call far 2345:5678

NE是New Excutable的缩写,是16位Windows可

执行文件的标准格式,这种格式基本上没用了

 NE在MZ文件头之后添加了一个以“NE”开始的文

件头

Win32可执行文件,如*.EXE、.DLL、.OCX等,

都是PE格式

 PE的意思就是Portable Executable(可移植、可执

行),它是Win32可执行文件的标准格式

 由于大量的EXE文件被执行,且传播的可能性最大

,因此,Win32病毒感染文件时,基本上都会将

EXE文件作为目标

计算机病毒也是程序或者程序代码,

而且也是可执行的,否则无法感染、

破坏、隐藏等,其病毒文件也是遵循

PE的格式结构

一般来说,病毒往往先于HOST程序获得控制权。运行

Win32病毒的一般流程示意如下:

 ①用户点击或系统自动运行HOST程序;

 ②装载HOST程序到内存;

 ③通过PE文件中的AddressOfEntryPoint+ImageBase,

定位第一条语句的位置(程序入口);  ④从第一条语句开始执行(这时执行的其实是病毒代码);  ⑤病毒主体代码执行完毕,将控制权交给HOST程序原来的

入口代码;

 ⑥HOST程序继续执行

有了DOS头,程序在DOS下执行,

DOS就能识别这是个有效的执行体。

DOS Stub是有效的

DOS的可执行的代码,

因而在不支持PE文件格式DOS下运行,

它调用中断21H的功能9显示

This program cannot be run in DOS mode

相对虚拟地址 (Relative Virtual Address,RVA)

 相对虚拟地址是一个相对于PE文件映射到内存的

基地址的偏移量

相对虚拟地址是一个相对于PE文件映射到内存的

基地址的偏移量

 基地址VA通常为0x00400000

DOS头与DOS插桩程序

 PE结构中紧随MZ文件头之后的DOS插桩程序(DOS Stub)

 可以通过IMAGE_DOS_HEADER结构来识别一个合法的

DOS头  可以通过该结构的e_lfanew(偏移60,32bits)成员来找到

PE开始的标志0x00004550(“PE\0\0”)  病毒通过“MZ”、“PE”这两个标志,初步判断当前程序

是否是目标文件——PE文件。如果要精确校验指定文件是

否为一有效PE文件,则可以检验PE文件格式里的各个数

据结构,或者仅校验一些关键数据结构。大多数情况下,

没有必要校验文件里的每一个数据结构,只要一些关键数

据结构有效,就可以认为是有效的PE文件

紧接着DOS Stub的是PE header

 PE header是IMAGE_NT_HEADERS的简称,即

NT映像头(PE文件头),存放PE整个文件信息分

布的重要字段,包含了许多PE装载器用到的重要

域。

 在支持PE文件结构的操作系统中执行时,PE装载

器将从DOS MZ header中找到PE header的起始

偏移量,从而跳过DOS Stub直接定位到真正的

文件头

什么重要数据结构?

如:导入目录-导入函数(

引入函数 import)

一个引入函数是被某模块

调用但又不在调用模块中

的函数,位于一个或者更

多的DLL里,因而要保留

一些函数信息,包括函数

名及其驻留的DLL名。

怎么样获得PE文件中重要数据结构?

从 DOS header 定位到 PE header

从 optional header 读取 data directory

的地址。

IMAGE_DATA_DIRECTORY 结构尺寸乘

上找寻结构的索引号。例如,欲获取

import table的位置信息,必须用

IMAGE_DATA_DIRECTORY 结构尺

寸(8 bytes)乘上1(import table在

data directory中的索引号)。

将上面的结果加上data directory地址,就

得到包含所查询数据结构信息的

IMAGE_DATA_DIRECTORY 结构项

反调试技术

分类

调试器检测

IsDebuggerPresent调试器存不存在

CheckRemoteDebuggerPresent

NtQueryInformationProcess

调试器测试

BeingDebugged属性

调试器检测

ProcessHeap属性

PE文件格式

数据目录表

代码节,可执行,可读,但不可写。

代码节

引入函数节就是引入表

引入表import table

间接调用函数

通过引入表间接调用函数

程序每次载入,程序的真实地址可能都不一样,可能会有问题,在代码节里,

引出函数节

已知函数名,获取函数地址

已知函数序数,获取函数地址

引出函数实例

作业答案

JNZ JZ

jnz等同于jne,jnz就是:jump not zero

test指令

test all判断操作数是不是0,c语言的if(比较)一般都会编译成test指令,为什么不用cmp比较?效率比cmp高

movsx指令

有符号数,正数高位是0,负数高位是1

程序爆破

exp-eg.

byte ptr dbyte

md5算法

加密算法逆向

设计一个相对安全的加密程序,账号密码经过加密

首先了解使用了怎样的加密算法

利用peid插件krypto ANAlyzer来扫描是哪种加密算法

md5算法

添加消息长度

数据加密处理

找入口

下断点,看是由于name 还是serial才停止

利用ida看代码:模块之间的跳转关系更加清晰

f5把汇编代码变成c语言(自动生成),并不是源代码

核心位置

逆向相关工具介绍

逆向需要基础

汇编:逆向之缘,漏洞之本

c:算法实现,目标恢复

Python:脚本处理(批处理),高效轻便

操作系统

Windows

Linux Unix

Android

Others

Max

相关工具

Reverse Engineer逆向分析(Windows平台的:)

静态分析工具:IDA

动态分析工具:OllyDbg;Windbg;gdb;

虚拟机:Vmware

二进制查看工具:Winhex;

渗透测试Penetration test:

Metasploit

W3AF

NMAP

web security网络安全

php

js

二进制查看工具

Winhex/Ultraedit(显示二进制代码、十六进制)、可以快速对字符串进行定位

exeScope——查看文件结构框架

查壳工具

PEID:(识别加密壳 zprotect、识别压缩壳 UPX。)

识别zprotect(是一种先进的加密壳,通过虚拟机加密,把要保护的代码放在虚拟机里来执行,创建新的指明系统,有效阻止代码还原和分析;代码乱序,代码会分散变形;动态代码结构,每次加密生成的文件都是不同的(每次保护方法都是不同的))(入口点:000C5825)

识别UPX加壳——压缩壳、程序开头插入一段代码(用于解压缩),(某种程度上,压缩也可以叫加密,压缩后的代码也是看不懂),程序变小,便于传输

壳的概念:自然界中,植物用它来保护种子,动物用它来保护身体;而我们说的壳指的是计算机软件里面的,用来保护某一个软件不被修改,或者缩小体积。

加壳分为加压缩壳和加加密壳——压缩壳使文件大小变小,便于在网上传播;有一定的保护作用(脱壳相对容易),你无法反汇编加壳程序。   加密壳:用各种手段保护软件不被脱壳,跟踪,文件大小不是他的目的甚至会变大

(经过大量的各种壳的脱壳经验)

手动脱壳的主要步骤——,寻找入口点,转储(dump)程序,修复转入函数(Import Table)
PEID/LoadPE/DIE/手动分析

静态分析工具

IDA——DataRescue出品(plugins插件)、Windows:IDA(R3)and plungins(插件)

交互式 功能非常完善、适应多处理器

把二进制程序转换成汇编程序(左边函数,右边框图是程序的实现(更易读,分析)hex view查看原本二进制文本、)
与Vmware联动,调试程序。与Qemu联动,调试固件。

动态分析工具

OllyDbg 反汇编窗口、寄存器窗口、数据窗口、堆栈窗口、信息窗口(用于ctf)!!!、、OllyDbg(R3)、WinDbg(R0)

Linux平台动态分析

gdb 命令行 gdb(R3)、kgdb(R0)

gdb插件peda:增强gdb显示,且增加一些命令

gdb插件gef:提供更多动态分析支持

VM image(虚拟机):Vmware、VirtualBox、Qemu。
注:应用调试为 R3,内核调试为 R0。

window平台内核调试

WinDbg轻量级的调试工具,安装小,内核开发,也可以进行用户级的调试

Linux平台内核调试kgdb

需要重新编译内核打开kgdb选项

非主流工具

符号执行:Angr,Z3

污点跟踪:Pin,Valgrind,TraintDroid

模糊测试:FileFuzz,AFL,Trinity,Peach

平台专用工具

Android:apktool,SMALI,BAKSMALI,Dex2JAR,JD-GUI

固件专用:Binwalk,firmwre-mod-kit,Qemu(动态模拟环境)、KVM(底层虚拟化环境)
Pwn环境搭建 - LInux工具
ida pro:静态反编译
gdb:动态调试
peda/gef/gdbinit:gdb插件
Checksec:elf安全性及运行平台
Objdump/readelf:elf的关键信息
ROPgadget:rop利用
pwntools:写exp和poc
Pwntools/zio:必备的库
one_gadget:寻找libc中exec(‘bin/sh’)的位置
libc-database:通过泄露的libc中函数地址查libc版本

实验

利用OllyDbg分析EXP3中注册码的每一位应当是什么

第一次写的这么顺畅!!感动!

首先,利用OllyDbg打开exp3,运行,输入123123,右键search for -文本字符串-只有一个,右键选项定位到CPU,上划

cmp eax8是表示序列号有8位

cmp byte esp+9 2D右键follow in dump首位为0开始数,数到第九位,恰好就是我们输入的第六位3-对应的acsii码33-说明2D就是序列号的第六位,2D经过查表为-

movsx esp+4(第一位) 经过shl左移(对于二进制来说就是乘以2,放大两倍),cmp64就是和64比较,也就是原本的数就是32,对应的是2

esp+0B test al,al逗号是与运算,al只能是0,test不能是0,所以al是1~9的任意数字

逻辑与,符号为“&&”,只有两个操作数都是真,结果才是真

esp+8是第五位,是2B也就是加号

esp+5是第二位,add 0A,再和44比较cmp,所以是44-0A即3A,所以是:

esp+7是第四位,sub 2E所以是.

esp+6是第三位,add 0A 在和33cmp,所以是33-0A为29,对应)

esp+0A是第7位,4D是M

最终结果是2:).±M5

Reverse实战和OllyDbg使用

进程和程序

程序运行之后,操作系统会为程序内存中创建一个数据结构,称之为进程。

进程和程序是两个概念,程序本质上来说就是存储在磁盘上的代码,exe运行起来之后系统会创立一个进程,进程是存放在内存中的数据结构,一个程序可以运行多次,操作系统会为这个程序创建多个进程,进程的地址空间分为几个段,几个部分代码段——程序指令

数据送到CPU,执行程序

数据段

数据段——存放一些全局变量(并不是所有数据都存放在数据段,编译器在编译时能够预支在地址空间中存放在数据段里的变量)

Heap堆——malloc动态分配(程序执行时,临时为一个变量,操作系统为一个变量申请一个空间),存储动态分配数据,free(用于释放掉,否则会内存泄露,在程序结束之前没有办法再使用这段内存,如果内存空间较小,而内存泄露出现情况较多的情况下,可能会导致进程的进行会因为空间不够而终止)

未使用的内存空间

Unused Memory未使用的内存空间——处在堆和栈之间,Heap增长方向从底地址向高地址方向增长,比如申请一个内存,Heap就会增长一个内存,free就会往回缩,栈的增长方向是从高地址向底地址方向增长,就是为栈预留的空间(对于堆来讲,生长方向是向上的,也就是向着内存地址增加的方向;对于栈来讲,它的生长方式是向下的,是向着内存地址减小的方向增长。)

栈——函数参数;局部变量;返回地址。

栈有两种操作方式push和pop:push是往栈内压入数据,导致栈往低处生长;pop从栈中弹出,栈会缩小;Unused Memory就是为栈预留的空间

栈帧

简述本次课程中的Reverse实战示例实现破解的过程:

Reverse实战:

静态分析工具IDA

首先,运行一个exe程序,找flag。

打开IDA汇编窗口,main函数为程序的入口,汇编语言自动翻译成c语言的程序(伪代码),(翻译到c为:sp+79h,bp-18h,(h表示16进制))ebp esp(对应过去为bp sp)是栈寄存器

利用静态分析工具IDA,main函数为程序的入口

从v5到v12的赋值语句,除了v12为0(字符数组最后一位为0),其它都是大整数,一串的地址是连着的,上图中代码是从IDA从汇编推测出的源代码,v5到v12为字符数组

栈是从高字节生长到底地址空间,所以v6所占的四个字节其实是79h到76h,v5是从75到72

while语句中:要把输入的scanf的返回值同-1比较,常见的数据处理手段,只要不强制结束,就会不停的while循环,让用户输入数据

(scanf返回正整数,表示正确输入参数的个数;返回0,用户类型是不匹配的;返回-1,表示被强制结束(Windows下:用户按Ctrl+Z)(Linux下,用户按Ctrl+D))

字符串匹配:v4和v5进行匹配,(const char*)为强制类型转换,把v5的地址当初是一个字符串的首地址,如果两个字符串匹配的话,strcmp返回0,while会终止跳出,此时匹配的v5就是要得到的flag/密码

v5到v11的整数,按照字符解释,把整数转换成字符串(图中看起来是倒过来的,因为栈是向着内存地址减小的方向增长。)

 

v5到v12 8个变量每个差4个字节(int占4个字节)

栈是从高字节生长到底地址空间,所以v6所占的四个字节其实是79h到76h,v5是从75到72

一串的地址是连着的,上图中代码是从IDA从汇编推测出的源代码,原本函数不一定是这么写的

从v5到v12的赋值语句,除了v12为0(字符数组最后一位为0),其它都是大整数

while语句中:要把输入的scanf的返回值同-1比较,常见的数据处理手段,只要不强制结束,就会不停的while循环,让用户输入数据

(scanf返回正整数,表示正确输入参数的个数;返回0,用户类型是不匹配的;返回-1,表示被强制结束(Windows下:用户按Ctrl+Z)(Linux下,用户按Ctrl+D))

字符串匹配:v4和v5进行匹配,(const char*)为强制类型转换,把v5的地址当初是一个字符串的首地址,如果两个字符串匹配的话,strcmp返回0,while会终止跳出,此时匹配的v5就是要得到的flag/密码

v5到v11存放7个整数,v12是0

v5到v11的整数,按照字符解释,把整数转换成字符串(图中看起来是倒过来的,因为栈是向着内存地址减小的方向增长。)

编写程序,在服务器端对于用户输入的密码。比如服务器的密码检测程序,密码不能以明码的方式写,要进行加密,并非绝对安全,可能会有窃听攻击(因为对于用户输入的密码,也会加密,在网络上传输,和服务器存储的密码进行比较;攻击者可能无法破解加密,但是可以截获网络传输的数据包,假如密码不变的话,下一次攻击者将截获的数据包发送一下,同样可以进入到入侵输入密码的程序,这就是常见的重放攻击,冒充用户,为了抵抗这样的攻击,要添加随机数,要将随机数同密码一同加密,然后在服务器中解密,再进行比较,这样的话每次数据包中传输的时候都不一样,就可以规避重放攻击)

动态分析工具OllyDbg

反汇编窗口:地址、机器码和汇编指令

寄存器窗口:程序执行就是一条条的指令和相关的数据送到CPU,按照一定的顺序依次地执行,每条指令在执行时的情况,以及了解他的操作数是什么

信息窗口:存放OllyDbg对反汇编结果推测的信息,跳转,调用等

数据窗口:查看内存中某个地址存放的数据,指针的应用,内存地址中存放的数据

堆栈窗口:参数、变量、研究程序的控制流

打开及附加

TraceMe:序列号判断程序

反汇编窗口中:

00开头,是虚拟地址,系统为每一个进程都分配了内存空间,称为进程的地址空间,对于程序指定的变量等等他们的地址是从00开始的,为虚拟地址,对应的物理地址,就是操作系统为这个进程分配的空间的首地址,为进程的基址,就是在内存中的位置

Ctrl+G打开这个窗口,输入函数名,确定。

动态:OllyDbg

程序的Winmain函数入口点,文件入口

载入文件,Ctrl+G打开窗口,输入 GetDlgItemTextA 函数名

在USER32的地址空间,对应的代码处F2下断点

F9运行,点check,找到程序被截停的地方,按Alt+F9,返回到用户代码,Alt+B 即可跳转断点;判断语句改为NOP保存,破解成功

ollydbg破解和windbg的使用

OBE教学理念

OllyDbg工具的使用

找到程序真正入口

借助IDA

函数名function name处找到main函数,

双击发现汇编代码,五个mo指令及call指令,main函数地址

在底部(0000000000)401500(相对地址)、回到od,点右键,点goto-expression,输入地址401500,点follow expression,跳转到main函数,main函数处(也就是401500)F2按下断点,按F9运行,

按F8运行到0x40150B,目前栈的情况,

esp栈顶

bep栈底

连续两次F8,sub对esp做减法

按F8,栈顶为0x28FEB4减去14的值——0x28FEA0

两者之间为sub指令开辟出的栈空间(5个地址)

继续F8

windbg

利用OllyDbg破解exp可执行文件

首先打开exp

点击确定。

点击序列号“Serial”

随便输入一串字符串,比如123

点击“Check it Baby!”

退出

我们用OllyDbg打开exp

file-open

点击打开-出现下面的反汇编窗口

右键-search for -文本字符串

滑到最底部,找到try again/God job这些字符串

想要输出成功信息“god job dude!”,前面可以设想有一个判断指令,在此设置一个断点,就是我们需要爆破的地方,进行尝试。

从下往上,我们先找到第一个0042FB0C地址,右键-follow in disassembler

回到窗口,f2设置断点,点击运行,序列号输入123,弹出try again,说明这个不是我们要爆破的地方。

继续,回到文本字符串,追踪0042F4DE字符串

右键-follow in disassembler

在0042F4D5设置断点,运行,123,点“check it baby”,框变成了灰色(说明暂停了,这条指令就是我们要爆破的地方)

双击-修改为nop

点击assemble

(做法都是一样的,原来做过一遍,原文件有改变,所以后续采用了老师的PPT)

原本的指令变成了90-nop

继续运行,弹出congratz-god jub dude!,验证成功!

我们要爆破的对象就是进行跳转的指令

我们现在只是在内存里把代码段修改了,但是磁盘里的程序还没有修改,edit-copy to executable-all modifications

注意:记住这个地方,两个nop指令要同时选中

弹出一个新的窗口,

保存为一个新的可执行文件,运行,可以看到爆破成功 !

期末试卷

一、计算题(30 分,每空 3 分)

  1. 请根据以下反汇编语句计算合法的 Serial 值,在相关计算位置填写计算过程的注释,分析注
    册码具体的可见字符。当输入 Serial 值为“123123”时(1、2、3 的 ASCii 码为 31、32、33),
    使用 OllyDBG 工具查看 esp 寄存器在数据窗口处的跟随如下:
    0019F4AC: D8 3F 0C 0F 31 32 33 31 32 33 00 00 D0 13 40 00
    部分可能用到的 ASCII 可显示字符如下:
    004013E7 . cmp eax,0x8 ;
    004013EA . jnz short Crackme3.00401449;此处弹出校验不成功
    004013EC . cmp byte ptr ss:[esp+0x9],0x2A ;
    004013F1 . jnz short Crackme3.00401449
    004013F3 . movsx ecx,byte ptr ss:[esp+0x4]
    004013F8 . shl ecx,1;
    004013FA . cmp ecx,0x44;
    004013FD . 75 4A jnz short Crackme3.00401449
    004013FF . 8A4424 0B mov al,byte ptr ss:[esp+0xB]
    00401403 . test al,al ; _
    00401405 . je short Crackme3.00401449
    00401407 . cmp byte ptr ss:[esp+0x8],0x21;
    0040140C . jnz short Crackme3.00401449
    0040140E . movsx edx,byte ptr ss:[esp+0x5]
    00401413 . add edx,0xA
    00401416 . cmp edx,0x2D;_
    00401419 . jnz short Crackme3.00401449
    0040141B . movsx eax,byte ptr ss:[esp+0x7]
    00401420 . sub eax,0x2A ;
    00401423 . jnz short Crackme3.00401449
    00401425 . cmp byte ptr ss:[esp+0xA],0x2B ; _
    0040142A . jnz short Crackme3.00401449
    0040142C . movsx ecx,byte ptr ss:[esp+0x6]
    00401431 . add ecx,0xA
    00401434 . cmp ecx,0x2F;
    00401437 . jnz short .00401449
    00401439 . push 0x0 ;
    0040143B . push 0x0
    0040143D . push Crackme3.00403020 ; Serial is Correct!!!
    00401442 call MessagBoxA;最终的 serial 值为:

二、算法分析题(25 分,每题 5 分)

请分析以下各段代码所实现的反调试功能,文字描述核心反调试算法的实现原理,
以及反调试功能的实现效果等。
1、BOOL CheckDebug()
{
__try
{
__asm
{
pushfd
or word ptr[esp], 0x100
popfd
nop
}
}
__except(1)
{
return FALSE;
}
return TRUE;
}


2、BOOL CheckDebug()
{
DWORD time1, time2;
__asm
{
rdtsc
mov time1, eax
rdtsc
mov time2, eax
}
if (time2 - time1 < 0xff)
{
return FALSE;
}
else
{
return TRUE;
}
}


3、BOOL CheckDebug()
{
DWORD errorValue = 12345;
SetLastError(errorValue);
OutputDebugString(“Test for debugger!”);
得分
《逆向分析技术》试卷第3页共4页
if (GetLastError() == errorValue)
{
return TRUE;
}
else
{
return FALSE;
}
}


4、BOOL CheckDebug()
{
char fib[1024] = {0};
DeleteFiber(fib);
return (GetLastError() != 0x57);
}


5、BOOL CheckDebug()
{
int result = 0;
__asm
{
mov eax, fs:[30h]
mov al, BYTE PTR [eax + 2]
mov result, al
}
return result != 0;
}


三、综合题(45 分,每题 15 分)

1、请列举在 windows 平台下对目标程序逆向分析过程中的几类典型工具,包括以下
几类:

1)静态分析工具(不少于 1 个);

2)动态分析工具(包括应用层及内核层,不少于 2 个);

3)二进制分析工具(不少于 2 个);

4)PE 格式查看工具(不少于 1个)。并简单描述各工具在逆向分析过程中的具体功能。
2、目标 Crackme 程序包含一个输入框,没有明确标记是用户名或密码,使用 IDA 查
看,发现字符串被混淆,程序逻辑混乱,且汇编语句无法反编译,使用 OD 加载并
单步调试,发现会运行至 ExitProcess 函数,而后退出。请描述对目标程序分析及破
解的基本思路,包括有可能遇到的几种典型情况及尝试解决思路。
3、待分析的目标程序如果存在加壳保护,一般来说有需要哪些步骤用来确认加的是
哪一类壳以及具体哪一种壳?对简单的壳,脱壳过程中一般采用哪些经典的方法?
以其中一种方法为例,具体描述其中的操作步骤。

本文标签: 技术