Syzkaller实战教程9: 获取种子的AST-Like格式

一. AST-Like格式详解

Syzkaller定义的AST(由Prog 结构体表示)定义了一个程序的整体结构,包含三大部分内容:
Prog结构体,Call结构体,Arg结构体。

1. Prog.go&AST-like包含的信息

prog.go 文件属于 syzkaller 项目,负责描述程序(program)的结构及其相关操作。程序由系统调用(syscalls)和它们的参数组成,这些程序用于在内核或虚拟化环境中进行模糊测试,寻找潜在的漏洞。该文件定义了 Prog(程序)的结构、系统调用的定义以及程序的各种操作方法。

1. Prog 结构体

该结构体表示一个程序,包含系统调用、注释等信息:

  1. Target: 程序的目标系统(例如 Linux 或其他支持的系统)。
  2. Calls: 该程序中包含的系统调用列表,每个系统调用由 Call 结构体表示。
  3. Comments: 对程序的注释信息。
  4. isUnsafe: 标记程序是否是以不安全模式反序列化的。
  • 实际意义:
  1. 表示一个完整的系统调用序列。
  2. 通过 Calls 字段存储多个 Call,每个 Call 表示一个具体的系统调用。
  3. 提供了操作序列的方法(如 RemoveCallFilterInplace 等),使得 syzkaller 可以灵活地调整测试用例。

2. Call 结构体

  1. 表示单个系统调用及其相关的参数:
  2. Meta: 系统调用的元数据,包括其名称和参数等。
  3. Args: 系统调用的参数列表。
  4. Ret: 系统调用的返回值,使用 ResultArg 结构体表示。
  5. Props: 系统调用的属性,如是否为异步调用、失败次数等。
  6. Comment:注释
  • 实际意义:
  1. 表示一个单独的系统调用。
  2. 包含系统调用的元信息(Meta)和参数(Args),以及返回值(Ret)。
  3. 通过 Props 字段支持一些特性(如是否异步执行)。

3. Arg 接口及其实现

  1. 该接口用于表示call结构体中系统调用的参数,每种类型的参数都有自己的实现。
  2. ConstArg: 表示常量参数。
  3. PointerArg: 表示指针参数。
  4. DataArg: 表示数据缓冲区参数。
  5. GroupArg: 表示一组参数(如结构体或数组)。
  6. UnionArg: 表示 union 类型的参数。
  7. ResultArg: 表示系统调用的返回值或引用其他返回值的参数。
  • 实际意义:
  1. 参数是系统调用的核心组成部分,syzkaller 通过多种类型的参数(如 ConstArgPointerArg 等)来精确表示系统调用的输入和输出。
  2. 每种参数类型对应不同的内存表示方式和操作逻辑。例如:
  3. ConstArg 表示常量值。
  4. PointerArg 表示指针及其指向的内容。
  5. DataArg 表示数据缓冲区。
  6. GroupArg 表示结构体或数组。
  7. UnionArg 表示联合体。
  8. ResultArg 表示返回值或引用。

4. 核心逻辑与工作流程

  1. 程序的创建和操作: Prog 结构体定义了一个程序的整体结构,可以包含多个系统调用。Prog 提供了多种方法来操作其内部的系统调用列表,如插入、移除和过滤系统调用。
  2. 参数的处理: 系统调用中的参数通过 Arg 接口的各种实现进行表示,不同类型的参数(如常量、指针、数据缓冲区等)有各自的结构和处理方式。
  3. 返回值与引用: ResultArg 结构体不仅可以表示系统调用的返回值,还可以引用其他系统调用的返回值。这使得多个系统调用可以共享某些资源或数据。

prog.go 文件是 syzkaller 项目中用于描述系统调用程序的核心部分。它提供了丰富的结构和方法来创建、操作和管理系统调用及其参数。通过这些结构和方法,syzkaller 可以构建、修改和执行复杂的系统调用序列,从而在操作系统中发现潜在的漏洞。

2. AST-like格式

相关代码:https://github.com/google/syzkaller/blob/master/prog/prog.go

Syzkaller文档中提到的AST-like格式指的是 prog/prog.go 中定义的 prog 结构。这种格式用于Syzkaller内部,代表程序的抽象语法树,其中每个系统调用都被表示为一个 Call 结构。此 AST-like 表示结构化了系统调用序列,便于 Syzkaller 进行进一步的分析、变异和生成 fuzzing 测试用例。

Prog 的表示形式虽然不是传统意义上的 AST,但它确实具有类似 AST 的树形结构和递归特性,可以看作是专门为系统调用序列设计的领域特定 AST(Domain-Specific AST)。这种设计非常适合 syzkaller 的需求,使得它能够高效地生成、操作和分析系统调用序列。

Syzkaller 的 "AST-like" 表示是系统调用序列的中间形式,它类似于抽象语法树 (AST),但它的结构化方式更接近编程语言中对函数调用的表示。它由系统调用和参数构成的树形结构表示,存储在内存中,主要用于描述系统调用序列、执行流程和数据结构。

3. AST-like的转换

Syzkaller程序在不同阶段经历了多个格式转换:

  1. 生成阶段: syz-manager 生成或从 corpus.db 读取可逆二进制格式并反序列为AST-like格式的程序。
  2. 转换阶段: 在 syz-manager 内部,调用 prog.SerializeForExec(),将AST-like格式转换为exec二进制格式。
  3. 发送阶段: syz-manager 通过RPC发送exec格式给 syz-executor
  4. 执行阶段: syz-executor 直接执行收到的exec格式系统调用序列。

3.1 AST-like格式程序生成:

syzkaller首先将syzkaller/sys/linux/目录下装有描述(description)的txt声明文件生成amd.go文件,编译syzkaller后,能够读取系统调用的相关描述。

syz-manager 在运行过程中会根据生成策略和参考这些描述,生成"程序"的AST-like格式(即 prog.Program 结构)。

SQL
txt→(syz-extract提取常量const)→(syz-sysgen生成.go文件)→编译syzkaller供生成程序时参考

AST-like格式prog.Program 的内存表示形式,它定义了系统调用序列的结构,包括系统调用名称、参数、资源之间的关系等。

3.2 AST-LIKE转换文本格式

AST-like格式转换为文本格式: 当需要保存或展示程序时,Syzkaller会将程序从AST-like格式转换为可读的文本格式。这在程序的可视化、调试和存储(如corpus.db中)时非常有用。

1.syzkaller实现从AST-LIKE到文本格式的转化时,输入是AST-LIKE格式不是corpus.db中的二进制形式,相关的代码文件:https://github.com/google/syzkaller/blob/master/prog/encoding.go

encoding.go 文件的主要功能是序列化和反序列化程序(Prog),它涉及到如何 Prog 对象转换为文本数据并从文本数据中解析出程序对象。该文件还处理程序中的系统调用(Syscall)及其参数(Args)的编码与解码,支持多种不同的参数类型和复杂的数据结构。此外,还包括对自动生成参数(AUTO 类型)和条件性参数的处理。

1. 序列化与反序列化的核心逻辑

1.1 序列化:

  1. SerializeSerializeVerbose 方法用于 Prog 对象转化为紧凑或详细的文本表示。这些方法会遍历程序中的每一个系统调用(Call),并将其参数和属性按规则转化为文本格式。
  2. 序列化涉及不同类型的参数(如 ConstArgPointerArgDataArg 等)的编码,每种参数类型都有专门的序列化逻辑。

1.2 反序列化:

  1. Deserialize 方法从文本数据中解析出 Prog 对象,支持不同的模式(StrictNonStrictUnsafe 等),根据模式选择是否严格验证和修复错误。
  2. DeserializeExec 是执行数据的解码器,用于处理程序执行的具体编码。
  3. parseProg 和一系列 parseArg 函数是反序列化的核心,它们逐行扫描文本,并根据系统调用描述文件的定义来解析各类参数。

2. 参数的处理

反序列化过程中,参数(Arg)是程序中最为重要的部分之一,程序通过解析这些参数来描述与操作系统交互的细节。不同的参数类型有不同的解析逻辑:

  1. ConstArg:表示常量值的参数,通过整数或标志位来解析。
  2. PointerArg:指针类型的参数,涉及内存地址的管理,有时候还需要处理特殊指针(如 AUTOANY)。
  3. DataArg:表示数据缓冲区。可以是静态长度的数据,也可以是动态长度的,序列化时会处理压缩或未压缩的字节流。
  4. GroupArg UnionArg:分别用于描述结构体和联合体类型的参数,递归处理其内部字段。
  5. ResultArg:表示系统调用的返回值,可以引用其他的 ResultArg,也可以直接返回常量。

3. 数据处理

  1. serializeDatadeserializeData 函数负责对数据类型参数(如字符串或压缩数据)的编码和解码。它们确保序列化后的数据能被正确解析并还原到原始数据状态。
  2. 对于压缩数据,特别处理了 Base64 编码和二进制数据的解码。

4. 地址和内存处理

  1. 地址(PointerArg)在序列化和反序列化过程中有特定的处理逻辑。代码使用 serializeAddrdeserializeAddr 函数对指针类型参数进行处理,并确保内存对齐(特别是在 VmaPointerArg 中)。
  2. encodingAddrBase 常量用于定义指针地址的基址,以确保不同环境中的地址解析一致。

5. 数据与十六进制转换:文件中的 hexToBytetoHexCharfromHexChar 等函数处理十六进制与字节流之间的转换,确保系统调用中的数据能以正确的格式表示和存储。

encoding.go 是 Syzkaller 项目中用于处理系统调用程序的序列化与反序列化的核心文件。它不仅支持多种复杂的参数类型,还通过灵活的错误处理和恢复机制,确保程序在系统调用描述变化时能够正确解析。此外,文件中的自动参数处理和条件性参数处理逻辑使得 Syzkaller 能够生成高度灵活且动态的系统调用程序,极大地增强了模糊测试的能力。

二. Trace2syz解析

解析的完整流程如下:

1. 系统调用转换

将strace跟踪的系统调用(parser.Syscall)解析为Syzkaller所需的系统调用(prog.call)。

2. 参数处理

解析和转换系统调用的参数,包括指针、数组、结构体、联合体、资源、缓冲区等。

3.内存分配

根据程序需求生成内存分配调用(如mmap),并将其添加到Syzkaller程序的开头。

4.返回值缓存

缓存系统调用返回的资源,用于后续系统调用中引用。

5.上下文管理

使用Context对象管理转换过程中所需的元信息,例如当前调用、目标平台、返回值缓存等。

1. Trace格式转换需求

一个转换示例如下:

输入trace格式:

Bash
open("/etc/passwd", O_RDONLY) = 3
read(3, "root:x:0:0:root:/root:/bin/bash\n", 4096) = 44
close(3) = 0

转换后的Syzkaller程序:

Bash
r0 = open(&(0x7f0000000000)='/etc/passwd\x00', 0x0, 0x0)
read(r0, &(0x7f0000000100)=""/4096, 0x1000)
close(r0)

这个转换过程涉及:

  1. 从文本格式的原始trace解析系统调用信息成中间表示(Tracetree)
  2. 提取调用名称、参数和返回值
  3. 类型推断和参数重建
  4. 生成符合Syzkaller格式的程序

主要代码文件:parser/parser.go: trace解析成中间表示

2. 转换流程

注意代码块中都只是该代码文件的简略表述:

// parser/parser.go
func Parse(data []byte) (*TraceTree, error) {
    // 1. 词法分析,将文本分割为token
    lexer := newLexer(data)
   
    // 2. 语法分析,构建语法树
    parser := newParser(lexer)
   
    // 3. 构建TraceTree结构
    tree := &TraceTree{
        Processes: make(map[int]*Process),
    }
}

3. 代码分析

parser.go

parser.go 的主要功能是解析系统调用跟踪文件(trace 文件),将其转换为一个中间表示(TraceTree),以便后续进行分析。它的核心任务是逐行读取跟踪文件,解析每一行的系统调用信息、覆盖率信息,并将这些信息组织到一个层次化的数据结构中。

TraceTree Syscall在intermediateTypes.go文件中给出定义

转换流程如下:

  1. 逐行读取文件内容
  2. 解析系统调用:通过 parseSyscall 函数提取系统调用名称、参数、返回值等信息并构建 Syscall 对象。
  3. 解析覆盖率信息:通过 parseCoverage 函数提取覆盖率信息(如指令地址)并关联到对应的系统调用。
  4. 构建进程树:通过 TraceTreeProcess 数据结构,将系统调用与其所属的进程关联起来。
  5. 过滤无关行:跳过无关的行,例如包含 ERESTART 错误码或信号标记(+++---)。

TraceTree结构:

  1. TraceTree是最顶层的结构,包含了所有进程信息
  2. 每个Process包含了该进程下的所有系统调用
  3. 每个Syscall包含了我们之前看到的系统调用信息(名称、参数、返回值、覆盖率)

所以实际上,之前显示的Syscall结构是完整TraceTree结构的一个子集,它被包含在Process结构的Calls数组中,而Process又被存储在TraceTree的Ptree映射中。

Bash
TraceTree

└── Ptree (map[int]*Process)
    │
    ├── Process (PID 1)
    │   ├── Pid: 1
    │   ├── Calls: []*Syscall
    │   │   ├── Syscall
    │   │   │   ├── Name: "open"
    │   │   │   ├── Args: ["/etc/passwd", "O_RDONLY"]
    │   │   │   ├── Ret: 3
    │   │   │   └── Cover: [0x734, 0x735]
    │   │   └── ...
    │   ├── Parent: *Process
    │   └── Children: []*Process
    │
    └── Process (PID 2)
        └── ...

Bash
输入文本格式:
1234 open("/etc/passwd", O_RDONLY) = 3
Cover:0x734,0x735
1234 close(3) = 0
(1234为strace爬取内容的进程号,标识该系统调用对应的进程PID)

1.ParseLoop 开始逐行解析文件内容。
1.1对于第一行:1234 open("/etc/passwd", O_RDONLY) = 3
调用 parseSyscall
使用 StraceParse(表示解析strace的工具,本项目采用ragel和goyacc) 提取系统调用信息,生成一个 Syscall 对象:
Syscall{
    Name: "open",
    Args: []string{"/etc/passwd", "O_RDONLY"},
    Ret: 3,
    Cover: nil,
    Pid: 1234,
}

调用 tree.add(call)Syscall 添加到 TraceTree
如果 1234 进程不存在,则创建一个新的 Process
Process{
    Pid: 1234,
    Calls: []*Syscall{call}, // 包含当前系统调用
    Parent: nil,
    Children: nil,
}
新建后,将 Process 添加到 TraceTree.Ptree

1.2对于第二行:Cover:0x734,0x735
调用 parseCoverage
提取覆盖率信息,生成覆盖率地址列表:
[]uint64{0x734, 0x735}
将覆盖率信息添加到上一行的 Syscall 对象:
lastCall.Cover = []uint64{0x734, 0x735}

1.3对于第三行:1234 close(3) = 0
调用 parseSyscall
使用 StraceParse 提取系统调用信息,生成一个新的 Syscall 对象:
Syscall{
    Name: "close",
    Args: []string{"3"},
    Ret: 0,
    Cover: nil,
    Pid: 1234,
}
调用 tree.add(call)Syscall 添加到 TraceTree
Syscall 添加到 1234 进程的 Calls 列表。


2.生成TraceTree
TraceTree{
    Filename: "trace.txt",
    Ptree: map[int]*Process{
        1234: &Process{
            Pid: 1234,
            Calls: []*Syscall{
                {
                    Name: "open",
                    Args: []string{"/etc/passwd", "O_RDONLY"},
                    Ret: 3,
                    Cover: []uint64{0x734, 0x735},
                },
                {
                    Name: "close",
                    Args: []string{"3"},
                    Ret: 0,
                    Cover: nil,
                },
            },
            Parent: nil,
            Children: nil,
        },
    },
}

4. trace2syz.go

strace 跟踪的系统调用日志转换为Syzkaller 可执行的输入格式的程序(prog.Prog),

trace2syz 的输入是结构化的中间表示(并不是parser/parser.go中表示多进程的Tracetree,而是parser/intermediateTypes.go中定义的Trace格式),而不是原始的 strace 文件。

1. Trace的定义

在parser.g0中,Trace被定义为一个系统调用的列表:

//Trace is just a list of system calls
type Trace struct{
    Calls []*Syscall
}

Trace是一个简单的结构,包含一个Ca11s字段,表示系统调用的列表。其中的每个系统调用用Syscal1类型表示。

2. Syscall的定义

Syscal1是Trace中每个调用的表示形式:

//Syscallstruct is the IR type for any system call
typeSyscallstruct{
    CallName string //系统调用名称
    Args     []IrType //系统调用的参数   
    Pid      int64 //进程ID
    Ret      int64 //返回值 
    Cover    []uint64 //覆盖信息
    Paused    bool //是否被信号中断
    Resumed   bool //是否恢复
}

关键点如下:

1.CallName:系统调用的名称,例如open或read

2.Args:系统调用的参数,使用IrType表示。

3.Pid:发起系统调用的进程D。

4.Ret:系统调用的返回值。

5.Cover:覆盖信息(如果有)。

6.Paused和Resumed:表示系统调用是否被中断以及是否恢复。

parser.Parse 解析一个 strace 文件时,它会生成一个 TraceTreeTraceTree 包含多个 Trace,每个 Trace 对应一个进程的系统调用。

trace2syz 需要的是单进程的系统调用序列,而不是整个 TraceTreeTraceTree 中提取单个进程的 Trace,可以通过 TraceTreeTraceMap 字段实现。

三. AST-Like格式提取

Bash
基于syzkaller版本:
commit df3dc63b8ba0b52ca67025f5b55cd4356b3eda75 (HEAD)
Author: Taras Madan <tarasmadan@google.com>
Date:   Wed Nov 6 12:48:54 2024 +0100
对syz-db.go进行处理,修改unpack函数使其在对corpus.db进行解包时保存AST格式内容

  1. crashes文件夹中的文件名:在将运行后的corpus.db通过syz-db进行unpack时,程序的文件名都是这个程序对应的唯一哈希值。在将这些文本格式的POC重新进行pack打包成corpus.db时,syzkaller也会校验文件名对应的哈希值是否正常。
  2. syz-db只有在进行pack操作且发现POC文件名和其哈希值不符时才会进行中间格式AST的转换(反序列化),unpack操作时则是直接从corpus.db中读取二进制内容写入到文件中形成我们人类阅读的文本格式。因此需要额外补充代码进行AST格式的保存。本工作针对syz-db.go的unpack方法进行修改,增加了AST结构的读取和保存步骤。

1. 修改syz-db.go后

Bash
1.新增相关引用
2.新增AST结构体定义,用以存储AST-Like内容
3.修改unpack函数,在执行unpack函数时保存AST-Like格式内容

2. 重新编译syz-db工具

make db

3. 使用unpack方法对某个corpus.db进行解包

./bin/syz-db unpack test.db UNPACK/
./bin/syz-db unpack corpus.db UNPACK/
./bin/syz-db pack waitPack test.db
  1. 解包后得到五种结果(依据syz-db.go的不同版本有一定区别,但txt和JSON文件必然存在)
  2. txt 文件 提供了调用的文本格式,由corpus.db的二进制内容直接写入,适合人类快速查看。
  3. AST_文件夹内的JSON 文件 提供了详细的参数类型和结构信息,保存的具体内容由人工定义的结构体控制,适合程序分析。
  4. AST_文件夹内的TXT文件(与txt进行区别,本文中采用大写进行表述) 提供了更接近程序内部表示的信息,包含内存地址,适合深入调试。
  5. target.txt:每个程序分析的统计信息,如调用次数、是否有注释等。
  6. 对prog的go格式保存(输出打印),保留了完整的prog的内容。

Bash
 .go 文件本质上是一个序列化后的程序状态快照,它以 Go 语言的语法格式保存了程序运行时的数据结构。

1. AST-Like格式分析

 1. txt 文件

  • 内容:包含系统调用的原始文本表示。
  • 信息:展示了调用的名称和参数的基本结构,但缺乏参数的详细类型和结构信息。
  • 用途:用于快速查看调用序列,适合人类阅读。

在指定的UNPACK文件夹内,存放了corpus.db中二进制文件直接转换为的文本格式txt文件:

Bash
add_key$user(&(0x7f0000000000), 0x0, 0x0, 0x0, 0xffffffffffffffff)
add_key$keyring(&(0x7f0000004880), &(0x7f00000048c0)={'syz', 0x2}, 0x0, 0x0, 0xfffffffffffffffe)

2. JSON 文件

  • 内容:以 JSON 格式详细描述了每个调用,包括调用名称、属性、参数类型、参数值、返回值等。
  • 信息:提供了参数的类型信息(如 PointerArg, DataArg 等),以及每个参数的详细结构(如子参数)。
  • 用途:适合程序解析和进一步分析,因为它结构化且详细。

注意:JSON格式中所有获取的字段/结构,都是仿造syzkaller中的Prog, Call,Args结构体进行构建和获取,所以会导致初版代码不能获取ANY,AUTO等关键字,因为没有进行单独的说明。为了获取这些关键字,需要进行单独的处理。

在指定的UNPACK文件夹内的AST_子文件夹内,存放了提取的AST-like格式json文件:

Bash
{
  "calls": [
    {
      "name": "add_key$user",
      "props": {
        "FailNth": 0,
        "Async": false,
        "Rerun": 0
      },
      "args": [
        {
          "type": "*prog.PointerArg",
          "dir": "in",
          "value": 0,
          "size": 8,
          "sub_args": [
            {
              "type": "*prog.DataArg",
              "dir": "in",
              "value": "7573657200",
              "size": 5
            }
          ]
        },
        {
          "type": "*prog.PointerArg",
          "dir": "in",
          "value": 0,
          "size": 8
        },
        {
          "type": "*prog.PointerArg",
          "dir": "in",
          "value": 0,
          "size": 8
        },
        {
          "type": "*prog.ConstArg",
          "dir": "in",
          "value": 0,
          "size": 8
        },
        {
          "type": "*prog.ResultArg",
          "dir": "in",
          "value": 18446744073709551615,
          "size": 4
        }
      ],
      "return": {
        "type": "*prog.ResultArg",
        "dir": "out",
        "value": 0,
        "size": 4
      }
    },
    {
      "name": "add_key$keyring",
      "props": {
        "FailNth": 0,
        "Async": false,
        "Rerun": 0
      },
      "args": [
        {
          "type": "*prog.PointerArg",
          "dir": "in",
          "value": 18560,
          "size": 8,
          "sub_args": [
            {
              "type": "*prog.DataArg",
              "dir": "in",
              "value": "6b657972696e6700",
              "size": 8
            }
          ]
        },
        {
          "type": "*prog.PointerArg",
          "dir": "in",
          "value": 18624,
          "size": 8,
          "sub_args": [
            {
              "type": "*prog.GroupArg",
              "dir": "in",
              "size": 5,
              "sub_args": [
                {
                  "type": "*prog.DataArg",
                  "dir": "in",
                  "value": "73797a",
                  "size": 3
                },
                {
                  "type": "*prog.ConstArg",
                  "dir": "in",
                  "value": 2,
                  "size": 1
                },
                {
                  "type": "*prog.ConstArg",
                  "dir": "in",
                  "value": 0,
                  "size": 1
                }
              ]
            }
          ]
        },
        {
          "type": "*prog.ConstArg",
          "dir": "in",
          "value": 0,
          "size": 8
        },
        {
          "type": "*prog.ConstArg",
          "dir": "in",
          "value": 0,
          "size": 8
        },
        {
          "type": "*prog.ResultArg",
          "dir": "in",
          "value": 18446744073709551614,
          "size": 4
        }
      ],
      "return": {
        "type": "*prog.ResultArg",
        "dir": "out",
        "value": 0,
        "size": 4
      }
    }
  ]
}

3. TXT 文件

  • 内容:以文本格式描述了程序及其调用的详细信息。
  • 信息:类似 JSON 文件,但以更接近程序内部表示的方式展示,包含指针和参数的引用信息。
  • 用途:适合技术人员理解程序的内部表示,可用于调试。

在指定的UNPACK文件夹内的AST_子文件夹内,存放了接近程序内部表示的信息,包含内存地址和对应系统调用在syzkaller本地文件中的引用序号:

Bash
Program 0a2d19d1eb7ac95b84290923ab9ab75a7a8e6f60:
Call 0: add_key$user
  Arg 0: &{{13457 0} 0 0 0xc0054bf2c0}
  Arg 1: &{{12879 0} 0 0 <nil>}
  Arg 2: &{{12390 0} 0 0 <nil>}
  Arg 3: &{{8432 0} 0}
  Arg 4: &{{15614 0} <nil> 0 0 18446744073709551615 map[]}
  Return: &{{15743 1} <nil> 0 0 0 map[]}
Call 1: add_key$keyring
  Arg 0: &{{13451 0} 18560 0 0xc0054bf3e0}
  Arg 1: &{{12879 0} 18624 0 0xc004f07040}
  Arg 2: &{{6176 0} 0}
  Arg 3: &{{6176 0} 0}
  Arg 4: &{{15614 0} <nil> 0 0 18446744073709551614 map[]}
  Return: &{{15615 1} <nil> 0 0 0 map[]}
 
#
以上内容对应的系统调用序列为: 
add_key$user(&(0x7f0000000000), 0x0, 0x0, 0x0, 0xffffffffffffffff)
add_key$keyring(&(0x7f0000004880), &(0x7f00000048c0)={'syz', 0x2}, 0x0, 0x0, 0xfffffffffffffffe)
# 参数分析:
add_key$user有5个参数,所以对应的有Arg0~Arg4 五个参数

字段分析:

Bash
Program 0a2d19d1eb7ac95b84290923ab9ab75a7a8e6f60
#
对应源码中的key,是该系统调用序列的哈希值
add_key$user
# 对应源码中的call.Meta.Name,也就是函数/方法名,add_key才是系统调用名
Arg 0: &{{13457 0} 0 0 0xc0054bf2c0}
# 对应源码中的call.Args,其中13457为Ref号,对应amd64.go文件中add_key$user
# 的各个参数的标识号

如下图所示,Name为这段内容具体的方法名,CallName是Syzkaller内系统调用名,一个CallName可以声明多个Name。同时下命的fs,dir,flags等,都是这个Name对应的方法所需的参数,Ref后的数字是标识这个Name对应参数的唯一标识。

TXT中Arg的数量和txt中对应系统调用的参数数量相同,值对应。例如Call1的

Bash
  Arg 2: &{{6176 0} 0}
  Arg 3: &{{6176 0} 0}

对应的是0x0和0x0这两个参数

Bash
add_key$keyring(&(0x7f0000004880), &(0x7f00000048c0)={'syz', 0x2}, 0x0, 0x0, 0xfffffffffffffffe)

4. target.txt文件

在运行unpack(选定的解压文件夹)路径下的target.txt包含了每个程序分析的统计信息,如调用数量、是否有注释等

Bash
# 程序的唯一哈希值
Program Analysis for 0a6ff38c8801aaf2d7eba9a1f3a91aaa51bc3792:
Number of Calls: 2
Has Comments: false

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值