首页
社区
课程
招聘
[原创]X86C++反汇编01.IDA和提取签名
发表于: 2025-5-24 18:03 453

[原创]X86C++反汇编01.IDA和提取签名

2025-5-24 18:03
453

79eK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6T1M7s2y4W2L8X3c8Q4x3X3g2F1k6i4c8Q4x3V1k6@1K9s2u0W2j5h3c8Q4x3X3b7@1x3e0g2Q4x3X3b7I4i4K6u0V1x3g2)9J5k6h3S2@1L8h3H3`.

用VC6.0新建一个控制台工程

img

img

编译成 debug 和 Release 2个版本

应ida分别查看2种版本的程序

高版本ida 可能会直接定位到函数入口,正常情况下,我们需要先调试找到关键,找到关键以后点再通过调试设置api断点,读写断点等,找到程序的关键点,我们再来逆向,很少有把函数从main函数开始从头逆向到尾的,通常是卡一处关键点,看一出关键功能,看关键功能怎么处理的, 因此需要先调试在用ida打开

ida 可以通过快捷键 G 输入地址点回车,跳到该地址, 按 ESC 键 可以退回原来的地址

找函数入口

必须是低版本的adi,高版本会自动帮你找到

用vs2019 建一个控制台程序

Release

img

点击第二个jmp 然后往下找,找到 3 个push 在一起,下面是个call 的,说明那个call就是到main函数,双击改call即可找到main函数

img

Debug

右键选择代码视图

img

debug那么是2个call,第二个call就类似与Release 版的jmp

双击过去后往下找

img

找mian 函数主要要卡关键点

一般exit 上面就是main函数

img

exit上2个call 就是main函数

img

还有1种方法就是找分支结构,分支结构结束就是

img

3个push

img

快捷键 n 可以对函数名重新命名

img

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 键配合

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

img

上面代码明显看出不合理, 跳转到到 +1的位置,相当于指令中间 所以肯定是有花指令

选中 401010 按d键,强制解释为数据

img

选中 40101E 按 c 键,强制解释为代码 相当于跳过了 10101d这行代码

代码解读

img

安全选项是防止溢出的 就是 main函数的 { } 返回地址前面有一个 类似于校验值的全局变量,它的值 跟线程id,进程id,内核数量,系统时间相关它的值是 刚进函数就设置的

img

IDA窗口

img

名字窗口 d表示数据 f 表示函数 i 表示导入 a开头表示字符串 41

img

IDA函数名称识别

img

通过ida 可以一看到部分信息被识别出来了,但是部分信息并没有被识别出来

下面的点击进去有经验的可以发现是一个 printf 函数,没经验的可以通过ida的签名功能来自动识别

img


签名简介

  • 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的实现

    img

    (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文件

    img

    用 ida 打开 printf.obj

    img

    img

    转成了机器码,+号代表没显示完,一般显示5字节或8字节,取决于你屏幕宽度

    img

    换成5字节 ,提特征要提机器代码序列,且与地址无关, 因此下面 53,56,be........固定的机器指令等可以作为特征码, 6c 00 00 00 ...这类地址的就不行,因为,因为环境一旦发生改变,地址就会变,因此要用通配符....., 人工提太累,因此需要借助工具

    img


    • 签名: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) 需要将该路径配置到环境变量

    img

    • 提取特征步骤:
      • 1.cmd提取特征:pcf xxx.obj(会生成xxx.pat文件);
      • 2.将.pat文件发送到文本编辑器中:pcf xxx.obj(会生成xxx.pat文件);

    img

    img

    • 签名步骤:
      • 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项表示此签名被使用了几次。

      img

      img

      把 .sig文件复制到指定位置

      img

      img

      img

      img

      img

      • printf 函数示例:

      img

      img

      • 注意:高版本的IDA 能够直接提取制作lib中的所有特征码和签名。

      a.高版本IDA工具制作lib签名

      高版本可以直接制作lib的签名
      指令:pcf [lib名].lib 
      原因:pcf自动识别是否为lib,如果为lib则调用plb.exe
      
      忽略名字命令:
      sigmake -r [pat签名].pat [sig签名名字].sig

      (2)IDA签名自动制作

      • 采用脚本语言
      • lib2sig.bat 用例:cmd命令--lib2sig libc
      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位的,按回车跳过就可以

      img

      • run.bat 用例:cmd命令 -- run libc
      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

      保存环境

      img

      那么到入口点的时候肯定会恢复环境

      img

      恢复环境肯定会访问这块数据,下个数据访问断点就可以了

      img

      img

      原入口 入口前有2可retn.可以看出这是一个 aspack的壳img

      从原入口环境看环境看该程序是 bc++ 写的,因为 开始 jmp 跳走,跳过的是一组字符串

      img

      方法二:

      因为是 aspack 的壳,可以直接往下找,找到2个ret,

      img

      不确定是哪个,2个都下断点,运行看断到了哪个

      img

      断下来的这个就是

      img

      到了入口点直接脱壳

      模拟装载只要模拟的像,很多保护系统都会失效,(节区属性恢复,环境恢复),把目标可执行文件二进制数据放到装载器里面,装载器不读文件直接读大数组,就是一个壳

      img



      [培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

      收藏
      免费 2
      支持
      分享
      最新回复 (0)
      游客
      登录 | 注册 方可回帖
      返回