X86C++反汇编01.IDA和提取签名
用VC6.0新建一个控制台工程!(./notesimg/1656999246660-5bc3f391-eea4-4382-b28c-890aac061afc.png)
!(./notesimg/1656999406717-bf417644-8e98-43cb-956c-447235b8c06e.png)
编译成 debug和 Release 2个版本
应ida分别查看2种版本的程序
高版本ida 可能会直接定位到函数入口,正常情况下,我们需要先调试找到关键,找到关键以后点再通过调试设置api断点,读写断点等,找到程序的关键点,我们再来逆向,很少有把函数从main函数开始从头逆向到尾的,通常是卡一处关键点,看一出关键功能,看关键功能怎么处理的, 因此需要先调试在用ida打开
ida 可以通过快捷键 **G** 输入地址点回车,跳到该地址,按 **ESC** 键 可以退回原来的地址
## 找函数入口
必须是低版本的adi,高版本会自动帮你找到
用vs2019 建一个控制台程序
### Release
!(./notesimg/1657002688703-afd19805-baff-478f-8acb-ccb64ed35593.png)
点击第二个jmp 然后往下找,找到 3 个push 在一起,下面是个call 的,说明那个call就是到main函数,双击改call即可找到main函数
!(./notesimg/1657002886897-cd11fd68-7c51-4608-9328-cc2535431bdb.png)
### Debug
右键选择代码视图
!(./notesimg/1657003166400-b23c6144-9452-45da-8f32-fea26f5e9358.png)
debug那么是2个call,第二个call就类似与Release 版的jmp
双击过去后往下找
!(./notesimg/1657003496324-13370bfa-ec71-4c00-ac00-5fe6885085e8.png)
找mian 函数主要要卡关键点
一般exit 上面就是main函数
!(./notesimg/1657003911603-43a75cef-84b2-4c4e-a6bc-cdb59cf5f205.png)
exit上2个call 就是main函数
!(./notesimg/1657004819319-b8d29407-cb69-44aa-9fe5-7c99696f3951.png)
还有1种方法就是找分支结构,分支结构结束就是
!(./notesimg/1657004976223-e815f675-9468-441c-b8e9-29d690c0fef9.png)
3个push
!(./notesimg/1657005105310-9529d3fd-1b35-48e2-8c2e-9af21e599ea4.png)
快捷键 **n** 可以对函数名重新命名
!(./notesimg/1657005079190-53df4051-e157-48a5-a8c4-2b21dab27cdb.png)
## IDA的使用
---
1. IDA对Debug版本和Release版本可执行文件有所区别,一般Debug可执行可以识别符号,Release版本则识别不了。
2. .idb文件:IDA生成的文件,里面存储了注释等信息
3. IDA分析后有自己的一套命名规则,如下:
- 子程序 sub_地址
- 标号:loc_标号
- 局部变量:
- - sub:子程序
- loc:标号
- arg:参数
- lpMem:内存首地址
- var:局部变量
- byte等类型:全局变量
### IDA常用快捷键
- **Ctrl + "+" --> 展开代码**
- **N --> 修改名字,修改一处,其他地方也会跟随改变**
- **D --> 修改数据类型定义**
- **Alt + D --> 新增数据类型定义**
- **C --> 按代码解析**
- **A --> 按ASCII字符串解析,如需解析为其它类型字符串,在Edit→String中设置**
- **; --> 添加注释**
- **shift + F5(:View→Open subviews→Signatures):添加新签名 -- 右键"Apply new Signatures"→选择新签名.sig文件**
#### 规避花指令
D 和 C 键配合
```c++
int main(int argc, char* argv[])
{
int n = 6;
scanf("%d",&n);
__asm{
jnp NEXT
jp NEXT
_emit 0xe9 // _emit 相当于 db
NEXT:
}
printf("Hello World! %d\n",n);
return 0;
}
```
VC 不支持 db
!(./notesimg/1657018764401-4dbbd851-f79e-4b3c-bde5-8f533355bc1d.png)
上面代码明显看出不合理, 跳转到到 +1的位置,相当于指令中间 所以肯定是有花指令
选中 401010 按d键,强制解释为数据
!(./notesimg/1657018873492-a5f9b40f-75df-400a-94de-045601f4ad84.png)
选中 40101E 按 c 键,强制解释为代码 相当于跳过了 10101d这行代码
#### 代码解读
!(./notesimg/1657019828308-aa75eda5-d1f3-49ff-a393-c94c39ee78e2.png)
安全选项是防止溢出的 就是 main函数的 {} 返回地址前面有一个 类似于校验值的全局变量,它的值 跟线程id,进程id,内核数量,系统时间相关它的值是 刚进函数就设置的
!(./notesimg/1657020610559-7beed69c-ab4d-42d2-a555-c5c6e008c716.png)
### IDA窗口
!(./notesimg/1657017511727-f194a557-f810-48e5-bcfd-b858d0aa00cd.png)
名字窗口 d表示数据 f 表示函数 i 表示导入 a开头表示字符串 41
!(./notesimg/1657017640939-3b844680-b9d1-4608-887c-53c0d892e93d.png)
## IDA函数名称识别
!(./notesimg/1657005491825-fa4cbe56-6114-4ca9-b73b-faf9064abf27.png)
通过ida 可以一看到部分信息被识别出来了,但是部分信息并没有被识别出来
下面的点击进去有经验的可以发现是一个 printf 函数,没经验的可以通过ida的签名功能来自动识别
!(./notesimg/1657005564313-93f015f8-6d15-4646-9d70-92af20d464d8.png)
---
#### 签名简介
- **IDA可以识别函数名以及参数等信息,IDA是用过SIG文件识别已知函数信息。在安装IDA的时候,已经将常用的库制作为SIG文件,放置在安装目录的SIG文件夹下。**
- **函数签名:**SIG文件也成为签名文件
- **作用:**利用此功能可识别第三方提供的库函数,从而简化分析流程
**以低版本C库函数为例**
#### 1. 低版本库函数实现位置:
**以VC6.0为例:../VC98/Lib**
- **各种C库函数的实现,缩写规则:**
- - **无缩写 - 静态库原始版本**
- **D - Debug调试版**
- **I- 该实现在动态链接库中,msvcrt.dll,实现在DLL里**
- **MT - 多线程版,IDA查看可发现新增了临界区的处理,Enterlock....**
- **P - C++版本**
**lib的本质:多个.obj的组合**
**查看lib有多少obj 的 link选项:** **link -lib /list libc.lib**
注意: 如果main函数前面有_mtinit 被调用,说明是多线程
#### 2. link中 -lib链接选项
- -lib命令针对静态库版本,常用命令选项:
- - list:可查看指定lib包含的obj。
- - - 用例:link -lib /list libc.lib。
- - extract:从指定lib中进行提取函数.obj。
- - - 用例:link -lib /extract:build\intel\st_obj\xxx.obj libc.lib(会提取生成xxx.obj文件)。
用ida 打开 libc.lib,找到printf的实现
!(./notesimg/1657006616122-be83432a-350c-44a0-a872-078df9ad82e5.png)
###
### (1)IDA签名手动制作
通过cmd实现提取 obj
link -lib 查看对应的指令
link -lib /list libc.lib 查看 libc.lib 里面的所有 .obj信息
找到 printf.obj 的完整路径
link -lib /EXTRACT:build\intel\st_obj\printf.obj libc.lib 提取obj文件
!(./notesimg/1657007629255-044d3030-9b99-4b74-a94a-c498c3a9090d.png)
用 ida 打开printf.obj
!(./notesimg/1657007772273-5e645a05-a5b0-49fa-8adc-cda9dd8e740a.png)
!(./notesimg/1657007788107-1d468064-f866-46e6-ae0a-c8ffd2657df5.png)
转成了机器码,+号代表没显示完,一般显示5字节或8字节,取决于你屏幕宽度
!(./notesimg/1657007801814-fa7145cc-921e-4399-b0f7-e93958df1fd9.png)
换成5字节,提特征要提机器代码序列,且与地址无关,因此下面 53,56,be........固定的机器指令等可以作为特征码,6c 00 00 00 ...这类地址的就不行,因为,因为环境一旦发生改变,地址就会变,因此要用通配符....., 人工提太累,因此需要借助工具
!(./notesimg/1657007910792-a9108601-908d-4b56-b31e-db94d2a2d41a.png)
---
- **签名:**IDA并不认识特征码所对应的文本文件,IDA的签名文件格式为.sig。IDA将一直常用的特征码汇至sig文件夹(D:\IDA_Pro_v7.5_Portable\sig),签名就是为满足特征描述的指令进行标记。
#### 1. 需要的工具
- **pcf.exe :提取特征码**
- - 命令:pcf.exe 【lib文件内部的obj路径】 待提取的lib文件
- 原理:对二进制提取特征码,重定位的数据使用通配符代替。
- **sigmake.exe:对.pat特征文件执着sig签名文件**
- **注意:两个工具的使用都需要添加环境变量。**
#### 2. 提取特征及签名
- **特征码:**
- - 可以作为特征码的例子:固定机器码。
- 不可作为特征码的例子:偏移值。
- 通配符:不指定长度 = *(..两个点表1个*);1:1长度 = ?。
- **提取特征工具:**pcf.exe(D:\idapro75\Flair\binn) 需要将该路径配置到环境变量
!(./notesimg/1657009161777-f87af5fe-3a9c-462d-9d10-b748c178b7e6.png)
- **提取特征步骤:**
- - 1.cmd提取特征:pcf xxx.obj(会生成xxx.pat文件);
- 2.将.pat文件发送到文本编辑器中:pcf xxx.obj(会生成xxx.pat文件);
!(./notesimg/1657009485285-64901ab7-5a70-4f6b-8f10-f72e74da591a.png)
!(./notesimg/1657009253537-dec5c445-31f0-4c9e-9128-7a1de700cde1.png)
- **签名步骤:**
- - sigmake -n"MyPrintf" printf.pat printf.sig
- (会生成xxx.sig文件);
- - - sigmake -n"mysig for printf" *.pat allsigname.sig(将当前目录下所有.pat打包成1个.sig);
- - 将xxx.sig文件复制至IDA→sig→pc目录下。
- IDA中添加签名,表头 #func项表示此签名被使用了几次。
!(./notesimg/1657009623304-0b01c872-d598-4fff-9875-352826000885.png)
!(./notesimg/1657009671064-fca018da-746a-4bd3-9370-71110ebb6aae.png)
把 .sig文件复制到指定位置
!(./notesimg/1657009878449-fc7a2f63-cd63-400f-b606-d614695b6b55.png)
!(./notesimg/1657009974008-17e42aea-8425-4204-8638-26c1e96c3866.png)
!(./notesimg/1657010005868-f61085e0-15d9-462c-9185-046d01fadee2.png)
!(./notesimg/1657010494682-6506c26c-169a-45d9-96f7-5203e9f11034.png)
!(./notesimg/1657010473269-16754c41-746e-4547-804e-1fcd994d9de5.png)
- **printf 函数示例:**
!(./notesimg/1639397356907-d786a059-a3a2-44e8-a7f1-b319e0a88102.png)
!(https://cdn.nlark.com/yuque/0/2021/png/1773393/1639398082229-1ee5bb26-1851-4294-ba1a-34c0425a1238.png)
- 注意:高版本的IDA 能够直接提取制作lib中的所有特征码和签名。
#### a.高版本IDA工具制作lib签名
```c++
高版本可以直接制作lib的签名
指令:pcf .lib
原因:pcf自动识别是否为lib,如果为lib则调用plb.exe
忽略名字命令:
sigmake -r .pat .sig
```
### (2)IDA签名自动制作
- 采用脚本语言
- lib2sig.bat 用例:cmd命令--lib2siglibc
```bash
md %1_objs // 创建文件夹
cd %1_objs // 进入文件夹
//找这个目录下的所有文件 每一个文件名替换掉 %1,
//然后执行指令link -lib /extract:%%1文件名.lib, 提取obj文件
for /f %%i in ('link -lib /list %1.lib') do link -lib /extract:%%i %1.lib
// pause //暂停
//找到这个文件下的所有.obj文件 执行pcf文件名 提取特征码生成文件
for %%i in (*.obj) do pcf %%i
//生成sig文件,备注名就是库的名称,把当前目录的所有.pat文件打包生成一个.sig
sigmake -n"%1.lib" *.pat %1.sig
//如果存在拓展名为 .exc的文件,Name把内容重定向到 abc.exc
if exist %1.exc for %%i in (%1.exc) do find /v ";" %%i > abc.exc // 删除;
//把abc.esc文件内容前四行删除
if exist %1.exc for %%i in (%1.exc) do > abc.exc more +2 "%%i" // 删除;
//把abc.exc 文件内容拷贝到指定文件
copy abc.exc %1.exc // 复制文件
//删除abc.exc文件
del abc.exc // 删除制文件
//再次执行指令
sigmake -n"%1.lib" *.pat %1.sig
//将.sig文件拷贝到上级目录区
copy %1.sig ..\%1.sig
//返回上级目录
cd ..
//删除 _objs文件夹目录里面的所有文件
del %1_objs /s /q
//删除 _objs文件夹
rd %1_objs
```
如果失败. libc用全路径
运行中出现下面问题,那是因为该函数非32位的,按回车跳过就可以
!(./notesimg/1657025740866-15ccd634-f31a-4c92-8d39-36e7157a6b6b.png)
- **run.bat 用例:cmd命令 -- run libc**
```bash
md %1_objs
cd %1_objs
for /f %%i in ('link -lib /list %1.lib') do link -lib /extract:%%i %1.lib
for %%i in (*.obj) do pcf %%i
sigmake -n"%1.lib" *.pat %1.sig
```
导出签名主要不是用于库函数,而是商业分析
### PCF.exe脱壳
esp脱壳 32位程序在32位系统下脱壳,64位程序在64位系统下脱壳
#### 方法1
保存环境
!(./notesimg/1657015532438-007f7d00-9c69-4835-b60a-0be3d771c9a0.png)
那么到入口点的时候肯定会恢复环境
!(./notesimg/1657015749525-205d1a40-dd24-491e-b528-2998bcb7e66f.png)
恢复环境肯定会访问这块数据,下个数据访问断点就可以了
!(./notesimg/1657015812408-c2ba2e43-66dd-4bec-b187-041843de5a96.png)
!(./notesimg/1657015915240-2d71de21-d8d6-49c0-88f8-7933395f6a4e.png)
原入口入口前有2可retn.可以看出这是一个aspack的壳!(./notesimg/1657015996222-bf34aa96-f0d4-4aaa-a1f3-7b3762e25715.png)
从原入口环境看环境看该程序是 bc++ 写的,因为开始 jmp 跳走,跳过的是一组字符串
!(./notesimg/1657016114586-b5c741a7-2220-4b7c-a556-f93402652616.png)
#### 方法二:
因为是 aspack 的壳,可以直接往下找,找到2个ret,
!(./notesimg/1657016627163-6f0ab78a-a41b-467b-bb91-bfb5cc179b93.png)
不确定是哪个,2个都下断点,运行看断到了哪个
!(./notesimg/1657016801036-e7f96df5-4f06-4a47-9412-e57484f5b1f4.png)
断下来的这个就是
!(./notesimg/1657016901693-94ece3a5-a106-493a-be4a-d50b8afb1b08.png)
到了入口点直接脱壳
模拟装载只要模拟的像,很多保护系统都会失效,(节区属性恢复,环境恢复),把目标可执行文件二进制数据放到装载器里面,装载器不读文件直接读大数组,就是一个壳
!(./notesimg/1657026413525-560dcff5-dfc4-4701-bfe1-80effadfd9a3.png)
学习!!!
页:
[1]