首页
社区
课程
招聘
2
[原创]利用Lighthouse进行覆盖率统计及其优化
发表于: 2021-10-21 10:37 24613

[原创]利用Lighthouse进行覆盖率统计及其优化

2021-10-21 10:37
24613

利用Lighthouse进行覆盖率统计及其优化

TL;DR

介绍IDA覆盖率统计插件Lighthouse的使用,并对其覆盖率输出方式进行修改,获得可阅读的明文代码执行路径信息。

1. 背景

最近有统计覆盖率信息的需求,多方搜索后发现IDA插件Lighthouse具有统计覆盖率的功能,通过读取DynamoRIO或者Pin产生的覆盖率日志文件,在IDA中以图形化形式展现代码的详细执行路径。

 

DynamoRIO或Pin等插桩工具默认使用的日志文件格式为drcov格式,这是一种二进制格式,每个基本块的信息的都是以十六进制数据进行记录。虽然二进制形式的记录方式有利于提高性能,但是人工阅读困难。

2. Lighouse的基本使用

  1. 下载:Lighthouse

  2. 安装:

    在IDA中找到插件文件的目录:

    1
    import idaapi, os; print(os.path.join(idaapi.get_user_idadir(), "plugins"))

    将下载下来的源码中的/plugins/文件夹copy到上面命令执行结果的目录中,然后重启IDA。

  3. 获取drcov格式覆盖率统计日志文件:

    首先使用Pin或DynamoRIO获取覆盖率统计文件(这里以Pin为例):

    image-20211021095936735

    这里需要注意的是,Lighthouse默认使用的drcov文件版本为version 2,但是最新版的DynamoRIO生成的drcov文件的版本为version 3,所以在导入IDA时会提示文件格式错误。Lighthouse目前提供了pin和frida的覆盖率统计插件,DynamoRIO的需要做修改或者使用旧版本的DynamoRIO:

    image-20211021100214821

  4. IDA中导入日志文件:

    首先IDA加载要观察的可执行文件,然后File -> Load file -> Code coverage file...加载刚刚生成的日志文件:

    控制流图的蓝色基本块为执行了的基本块,右侧为coverage的overview信息

    image-20211021100546846

    同样进行F5之后,可以看到执行过的伪代码:

    image-20211021095735818

3. drcov文件格式

1. 简介

drcov是基于DynamoRIO框架的用于收集二进制程序覆盖率信息的一种工具,其收集的覆盖率信息格式即为drcov格式。因为其成熟高效的特点,很多进行覆盖率收集的工具都会使用这种格式。

 

DynamoRIO官方并未对drcov格式进行详细的说明,所以此处进行说明记录,希望能对后续的覆盖率信息收集工具的开发起到一定的作用

2. 详细格式

首先,drcov格式有一个包含一些metadata的头部:

1
2
DRCOV VERSION: 2
DRCOV FLAVOR: drcov

Lighthouse中只支持了version 2的格式;DRCOV FLAVOR是一个描述产生覆盖率信息的工具的字符串,并没有具体的实际作用。

 

然后,是在收集覆盖率信息的过程中加载的模块的映射的模块表:

1
2
3
4
5
6
7
8
9
10
11
Module Table: version 2, count 39
Columns: id, base, end, entry, checksum, timestamp, path
 0, 0x10c83b000, 0x10c83dfff, 0x0000000000000000, 0x00000000, 0x00000000, /Users/ayrx/code/frida-drcov/bar
 1, 0x112314000, 0x1123f4fff, 0x0000000000000000, 0x00000000, 0x00000000, /usr/lib/dyld
 2, 0x7fff5d866000, 0x7fff5d867fff, 0x0000000000000000, 0x00000000, 0x00000000, /usr/lib/libSystem.B.dylib
 3, 0x7fff5dac1000, 0x7fff5db18fff, 0x0000000000000000, 0x00000000, 0x00000000, /usr/lib/libc++.1.dylib
 4, 0x7fff5db19000, 0x7fff5db2efff, 0x0000000000000000, 0x00000000, 0x00000000, /usr/lib/libc++abi.dylib
 5, 0x7fff5f30d000, 0x7fff5fa93fff, 0x0000000000000000, 0x00000000, 0x00000000, /usr/lib/libobjc.A.dylib
 8, 0x7fff60617000, 0x7fff60647fff, 0x0000000000000000, 0x00000000, 0x00000000, /usr/lib/system/libxpc.dylib
 
 ... snip ...

模块表的头部有两种变体,都包含模块表中的条目数:

1
2
3
4
Format used in DynamoRIO v6.1.1 through 6.2.0
   eg: 'Module Table: 11'
Format used in DynamoRIO v7.0.0-RC1 (and hopefully above)
   eg: 'Module Table: version X, count 11'

每个版本的表格格式有些许不同:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
DynamoRIO v6.1.1, table version 1:
   eg: (Not present)
DynamoRIO v7.0.0-RC1, table version 2:
   Windows:
     'Columns: id, base, end, entry, checksum, timestamp, path'
   Mac/Linux:
     'Columns: id, base, end, entry, path'
DynamoRIO v7.0.17594B, table version 3:
   Windows:
     'Columns: id, containing_id, start, end, entry, checksum, timestamp, path'
   Mac/Linux:
     'Columns: id, containing_id, start, end, entry, path'
DynamoRIO v7.0.17640, table version 4:
   Windows:
     'Columns: id, containing_id, start, end, entry, offset, checksum, timestamp, path'
   Mac/Linux:
     'Columns: id, containing_id, start, end, entry, offset, path'

虽然有很多列的数值,但是实际上能于Lighthouse交互的数据只有以下几种:

  1. id: 生成模块表时分配的序号,稍后用于将基本块映射到模块。
  2. start, base: 模块开始的内存基地址。
  3. end: 模块结束的内存地址。
  4. path: 模块在硬盘上的存储路径。

最后,日志文件有一个基本块表,其中包含在收集覆盖信息时执行的基本块列表。虽然drcov可以以文本格式转储基本块表(使用-dump_text选项),但它默认以二进制格式转储表。


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

收藏
免费 2
支持
分享
赞赏记录
参与人
雪币
留言
时间
伟叔叔
为你点赞~
2023-3-18 05:52
PLEBFE
为你点赞~
2022-7-28 00:09
最新回复 (1)
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
2
你好博主,我make不成功,有错误,可以给看看嘛
2024-9-11 18:55
0
游客
登录 | 注册 方可回帖
返回

账号登录
验证码登录

忘记密码?
没有账号?立即免费注册