1. 背景

1.1 Secure Boot介绍

在PC中,安全启动(Secure boot)是一种行业标准,旨在帮助设备仅使用原始制造商(OEM)信任的软件进行启动,当系统启动时,固件会检查每个启动软件的签名,防止非法软件的运行。

在车载信息安全中,安全启动是指在整车各个ECU的启动阶段做好安全确认和校验,以预防针对车载芯片的两种攻击。

  • 代码被恶意更改或攻击

  • 代码IP被非法读取或获取

1.2 应用背景

随着智能驾驶、智能座驾的发展,车辆内部ECU之间不仅可以通过总线技术通信,还可以通过V2X技术与车外设备通信。为了保证ECU中程序的安全,安全启动技术开始兴起。

目前多使用硬件安全模块(如HSM、HSE)来简化对芯片上代码加密和启动代码验证的工作,具备安全启动技术的HSM芯片,会利用芯片上OTP区域内存储的用户密钥信息对即将加载的软件进行多级安全验证,从而建立起可靠的安全信任链。

OTP区域是芯片上的一块区域,一般用于存储用户密钥信息,其原理与保险丝一致。芯片在出场后,OTP区域所有bit为1,当某个bit位被烧写为0时,就会彻底熔断该bit位,使其数值无法改变。也有一些芯片通过控制寄存器来控制bit位的值,其核心思想就是使某个内存区域的值无法改变。

2. Secure Boot实现

Secure Boot要实现的目标有两个:

  • 保护软件版本IP,防止代码被篡改

  • 解决信任问题,保证CPU加载的软件版本是由指定软件发布者发布的软件版本,而不是非法版本

通过对代码明文加密可以实现防止代码被篡改,而使用基于非对称加密的数字签名技术可以实现认证效果。

由于我对数字签名技术不太熟悉,这里着重学习一下数字签名的原理。

在安全启动过程中软件版本发布者可以使用RSA私钥来加密代码的信息摘要,生成数字签名,芯片则可使用对应的RSA公钥来对数字签名进行解密,从而验证版本的真实性。同时一旦验证,也具备不可抵赖性,因为只有软件版本的发布者才有私钥。

2.1 相关密码学知识

2.1.1 对称加密算法AES

AES作为一种对称加密算法,在加密和解密时使用同一个密钥,所以可以使用AES算法对代码明文加密,实现保护软件版本IP,防止代码被恶意篡改的目的。

在安全启动技术中,可以将代码明文用AES算法加密,然后将密文烧录到芯片的存储区,并将密钥烧录到芯片的OTP区。当HSM等安全硬件模块启动时,会将加密后的代码加载到内存中,并从OTP区读取AES密钥,将代码密文解密为明文。

2.1.2 哈希算法

哈希算法可以将任意一组数据变换为一组定长的数字指纹,该数字指纹也成为信息摘要,哈希算法具备两个特征:

  • 加密过程不可逆:意味着无法从信息摘要逆向推算出加密前的明文内容

  • 一一对应性:明文与信息摘要一一对应

在安全启动技术中,可以通过验证代码的信息摘要,来校验代码的完整性;也可以结合非对称加密算法,生成数字指纹,来实现认证工作。

2.1.3 非对称加密算法RSA

非对称加密算法拥有一对对应的公钥和私钥,可以使用私钥加密数据,再使用公钥解密数据。该技术可以应用在验证机制中。

2.1.4 数字证书

数字证书是一种权威性的文档,由证书签发机关(CA)签发的对用户公钥的认证,也称为“根证书”。数字证书的格式和验证方法需要遵循X.509国际标准,并包含以下内容:

  • 电子签证机关的信息

  • 公钥用户信息

  • 公钥

  • 有效期和数字签名等

2.2 实现策略

2.2.1 安全镜像文件生成

  1. 用户使用AES加密算法将代码明文转换为密文,并将AES密钥存储在OTP区

  2. 用户使用SHA256算法对代码密文进行哈希运算,得到该软件版本密文的信息摘要

  3. 用户生成包含密文信息摘要和RSA公钥信息的数字证书

  4. 用户使用SHA256算法对数字证书做哈希运算,得到数字证书的信息摘要,同时使用RSA私钥对数字证书的信息摘要加密,最终得到该用户的数字签名

2.2.2 安全镜像文件验证

  1. 芯片复位启动后,通过硬件加密模块如HSM或者HSE先对烧录在Flash中的X.509标准数字证书公钥信息进行哈希运算,并与提前烧录到芯片OTP区域的公钥哈希值进行比对,如果结果一致,那么则可以确认公钥的合法性,这个就是整个信息安全信任链的第一个环节,也是十分重要的环节

  2. 公钥合法性确认后,硬件加密模块如HSM或HSE再利用数字证书的数字签名进行用户合法性鉴权。具体操作步骤就是通过上述确认的公钥对数字签名进行解密处理得到证书的哈希值,同时针对存储在Flash芯片上的证书重新进行哈希运算,对比两个哈希值是否一致,如果一致,则鉴权成功,合法性得到了保障

  3. 然后再利用硬件加密模块如HSM或HSE来重新计算Flash芯片上存储的软件版本的哈希值,即信息摘要,并与数字证书的信息摘要进行比对确认是否一致,如果匹配则说明代码没有被恶意篡改, 用户软件版本的完整性与安全性得到了保障

  4. 芯片硬件加密模块如HSM或HSE最终利用OTP区域提前存储的AES对代码进行解密处理,从而得到代码明文,最终便可以正常加载到CPU中启动运行

如果上述任意一个流程没有通过,将不会进行后续流程的校验,系统将停驻在boot中。

3. 参考链接

  1. 车载信息安全之Secure Boot实现策略

  2. 一文搞懂Secure Boot

1 汽车硬件安全模块

汽车可以看成一个大的IOT设备,所以汽车安全也可以借鉴IOT安全,汽车硬件安全模块构成如下:

1.1 平台引导完整性和信任链

1.1.1 硬件安全启动技术

通过数字签名检测汽车的启动加载程序和关键操作系统文件是否被篡改,以阻止恶意文件或者不受信任的系统运行,从而保障硬件可以安全启动。

1.1.2 可信执行技术

例如可信处理器模块,是指使用加密技术,为每个受信任的组件创建唯一标识符,以将启动环境的元素与已知产品进行准确比较,并阻止不匹配的组件的启动。

1.2 篡改检测和防止旁道攻击

对于密钥加密、算法模型、账号凭证以及其他有价值信息的编译和解密只在安全环境中进行,以保护信息免受逆向工程或者中间人监控。

1.3 安全存储

1.3.1 加密加速

这是最早的硬件安全形式之一,与其说是硬件防御,不如说是一种外设。加速加密是在硬件中而不是在软件中执行加密的硬件,这样不仅可以加速应用程序,还可以为硬件提供在软件中无法入侵的系统。

例如,软件版本的AES可能会被注入代码,从而使加密记过容易被攻击者撤销,但硬件版本的AES是不可改变的,不容易受到攻击。

1.3.2 主动内存保护

通过将指针检查功能嵌入硬件以防止缓冲区溢出漏洞。

1.4 安全通信

一般采取加密技术、认证技术、防窃听技术、防篡改技术、防重放技术等,在通信过程中使用硬件措施来保护数据的安全性。

1.5 安全调试与芯片丝印

通常可以通过芯片丝印查找到芯片型号;在芯片开发过程中,通过使用JTAG、SWD调试接口来调试程序,所以擦除丝印和关闭调试接口可以防止大部分黑客攻击。

2 参考链接

IoT Hardware Security Importance & Devices | Arrow.com // 了解硬件安全在物联网技术中日益增加的重要性

HSM简介

HSM是一个专用的硬件安全处理器,它以物理方式封装了安全功能,通常具有自己的处理器核心、各种内存(RAM、ROM、闪存等)和硬件密码加速器。用于提供加密和解密等安全功能,可以用于存储密钥和证书,并确保他们不会被恶意程序或攻击者访问。

HSM通常由硬件和软件两部分组成:

  • 硬件部分:负责安全处理和密钥存储

  • 软件部分:提供HSM的接口和安全服务

HSM在车联网中的应用

在车联网中,HSM模块用作专用加密设备,用于保护敏感信息、促进安全通信并确保联网的车辆内关键操作的完整性,例如保护车辆间通信、保护固件更新以及确保可信软件执行。

为了满足车辆应用的特定标准,HSM提供与ECU应用程序之间的接口以及用于调试的接口。

目前已经有几家大型芯片制造商提供了具有车载规格架构的安全硬件模块,包括Infineon、ST Microelectronics、Renesas和NXP。从根本上说,HSM通过其自己的处理器核心来执行汽车应用场景所需的所有IT安全功能。

1. 车辆安全通信

HSM支持安全通信协议,比如TLS(传输层安全协议),用于加密车辆与其他设备之间的通信,以防窃听和数据篡改,可实现车辆内电子控制单元(ECU)之间的安全通信通道;提供数字证书和密钥保护,确保车辆通信的安全性和可靠性。

2. 车辆远程控制

HSM确保只有经过身份验证的用户才能访问远程启动、关闭车门、车窗等远程控制功能,以防车辆被未经授权的用户控制;HSM还可以提供安全的OTA(空中升级)机制,用于升级车辆系统的软件和固件,在固件更新时,HSM对固件进行身份验证,验证其完整性。

OTA:是一种通过无线通信技术实现远程更新设备固件或软件的方法

3. 车辆数据安全

车辆系统产生大量数据:车辆位置、驾驶行为等,HSM可以用于加密和保护车辆数据,确保数据的机密性和完整性。

4. 车辆防盗保护

HSM提供密钥管理功能:HSM提供数字签名和加密技术,用于保护车辆系统的代码和数据,防止恶意攻击和软件篡改;HSM还提供防盗保护功能,如车辆启动时,需要输入密码或者指纹识别。

HSM在固件签名中的应用

  1. 私钥保护:HSM保护签名私钥,确保签名过程的安全性;

  2. 签名生成:通过HSM生成数字签名,确保签名的安全性和可靠性;

  3. 密钥管理:管理密钥的生命周期,包括生成、存储和销毁;

固件签名常用工具:

  1. makecert   2. pvk2pfx    3. SignTool

HSM在车辆中的物理位置

为了更深刻的理解HSM是一个硬件模块这个概念,我查找了一下HSM在车辆中常见位置:

1. 主控制单元(ECU)

HSM常安装在车辆的中央控制系统或者动力总控制单元内部,这些主控制单元用于处理车辆的关键安全和通信任务。

2. 车载通信网关模块

当HSM被集成在车载通信网关模块中时,HSM负责管理里各个ECU之间的数据通信和安全保护,并在此提供安全加密、身份验证和数据保护。

3. 信息娱乐系统

当HSM被集成在信息娱乐系统中时,用于保护车辆的通信和娱乐数据安全,防止黑客攻击或数据泄露。

4. 电池管理系统(BMS)

HSM模块在此确保电池的安全监控和数据的加密传输。

参考链接

汽车电子领域的保卫者——HSM浅述_搜狐汽车_搜狐网汽车电子领域的保卫者——HSM浅述_搜狐汽车_搜狐网

https://www.freebuf.com/articles/web/363743.html

https://mp.weixin.qq.com/s/DulhqA1o0nnkYTQFjasWjg

https://blog.csdn.net/dianqicyuyan/article/details/138132331https://blog.csdn.net/dianqicyuyan/article/details/138132331

https://www.eet-china.com/mp/a213412.html //HSM攻击实例

https://www.i-newcar.com/index.php?m=home&c=View&a=index&aid=2010 //HSM、HSE、SHE区别

Fuzz简介

Fuzz是一种软件测试技术,其核心思想是将自动或者半自动生成的随机数据,输入到一个程序中,并监视程序异常,如崩溃、断言失败等,以发现程序漏洞。

根据测试数据生成的方式,可以将fuzz分为两种:

  • 基于生成的fuzz

  • 基于变异的fuzz

基于生成的fuzz需要了解程序的构成知识,比如要对协议fuzz的话,需要了解协议规范,字段含义等,来构建一个协议模型,使用模型来生成测试用例。基于生成的fuzz方法优点是构建的测试用例易于通过程序验证,能测试到更深此次的代码;缺点是在没有配置文件等先验知识的情况下,难以分析测试用例的格式。

基于变异的fuzz是根据已知的数据样本,通过对某个字段变异,来生成新的测试用例。比如可以打乱整个数据包、把数据包的某个部分替换掉。基于变异的fuzz关键思路是在数据包中放入大量随机数据。基于变异的模糊测试不需要对协议规约有很深的理解,其效率主要取决于测试样本的丰富程度以及所选用的变异算法,如果变异策略过于简单,会导致大部分测试数据被系统的浅层,逻辑所丢弃,达不到深入测试的目的。

一个基于变异的网络协议的Fuzz过程如下:

  1. 获得目标协议的正常数据包
  2. 用变异数据替换该数据包中的某些部分
  3. 用发包器向目标应用发包
  4. 观察目标应用的反应

在工控系统中,fuzz主要用来对工控设备使用的网络通信协议进行测试。工控网络通信协议可以分为两类:

  • 基础通信协议:ARP、IP、ICMP、TCP、UDP

  • 通用服务协议:HTTP、FTP、SNMP

对于基础通信协议和通用协议,可以用传统的fuzz工具,如Peach、Sulley进行测试,但由于工控协议大多私有,不同厂商使用自己的专有协议,导致传统的fuzz工具难以直接适用于工控系统,针对工控系统协议的fuzz可分为以下两种情况:

(1)标准公开的工控协议

一些已经公开标准的协议比如S7comm,可以采用基于生成发fuzz方法。可以根据协议规范,生成模型,通过对协议字段进行错误注入、对报文结构进行变异,对报文序列(标识上下文状态)进行变换来检测设备在处理异常时可能存在的漏洞。

(2)私有协议

对于未公开标准的私有协议,可以采用基于变异的fuzz方法。首先捕获私有协议正常的交互数据作为样本,在其基础上进行变异。

peach

peach支持基于生成和基于变异的fuzz方法,其特点是可扩展性,这运行它支持多种格式、网络协议、应用协议等,使其适用于Android设备、装置驱动程序以及嵌入式硬件的安全测试。

peach使用流程为:

  1. 创建数据、状态模型
  2. 选择/配置Publisher
  3. 配置代理、监视器
  4. 配置日志

优点:

  1. 支持多种协议和格式

  2. 高度可定制化

  3. 支持分布式测试,可以使用多台机器同时进行模糊测试,从而提高测试效率

  4. 支持状态跟踪,peach可以跟踪目标系统的状态变化,确保测试能覆盖到更多执行路径和状态

  5. 跨平台支持,peach支持Windows、Linux和macOS

缺点:

  1. peach更适合协议和格式的测试,不太适合GUI、游戏等测试

  2. 分布式测试对硬件资源要求较高

Modbus简介

Modbus是一个通用的总线通信协议,属于应用层协议。它不依赖于硬件总线,协议标准公开并支持多种电气接口,所以广泛应用于工业控制系统中。

Modbus是一主多从的通信协议,在Modbus通信中,只有一个主设备可以发送请求,其他从设备接收主设备的数据并响应,从设备可以是任何外围设备,比如I/O传感器、阀门、网络驱动器等。也就是说Modbus不能同步通信,总线上每次只有一个数据进行传输,即主设备发送,从设备应答;如果主设备不发送请求,总线上就没有数据传输。

Modbus通讯物理接口可以选用串口(RS232、RS485、RS422等),也可以选择以太网接口,对应的通信方式也有三种:

  • Modbus-TCP/IP

  • Modbus-RTU/Modbus-ASCII

  • Modbus-PLUS

Modbus存储区

Modbus协议规定了4个存储区,分别是0,1,2,3,可以通过读写寄存器访问。其中1、4区是可读可写的,1、3区是只读的。

  • 0区:输出线圈,可读可写的布尔变量,PLC地址范围为00001-09999,协议地址范围是0000H-FFFFH

  • 1区:输入线圈,只读布尔变量,PLC地址范围为10001-19999,协议地址范围是0000H-FFFFH

  • 3区:输入寄存器,只读寄存器,PLC地址范围为30001-39999,协议地址范围是0000H-FFFFH

  • 4区:保持寄存器,可读可写寄存器,PLC地址范围为40001-49999,协议地址范围是0000H-FFFFH

这里要着重注意一下PLC地址与协议地址的区别

PLC地址与协议地址

PLC地址是指存放于控制器中的地址,地址的第一位表示寄存器类型(1区、2区、3区、4区),协议地址是指通信时使用的寄存器地址,地址范围都是0000H-FFFFH,这里要主要的是,PLC地址0x00001对应的协议地址是0x0000,PLC地址0x10001对应的协议地址也是0x0000,3、4区也一样,不用担心在使用modbus读写寄存器时出错,因为访问不同寄存器的功能码不同,比如访问PLC地址0x00001使用的功能码是01,默认访问1区寄存器,所以就不存在寻址冲突啦。

Modbus TCP/IP 报文格式

Modbus TCP/IP报文格式如下图所示:

MBAP报头

  • 事务元标识符:2个字节,Modbus请求/响应事务处理的识别码

  • 协议识别符:2个字节,0000表示Modbus协议

  • 长度:2个字节

  • 单元标识符:1个字节,串行链路或其他总线上连接的远程从站的识别码

功能码

Modbus常用功能码如下,当主设备发起一个功能码为01的请求时,此时PDU结构为:

  • MBAP报头

  • 功能码:0x01(1个字节)

  • 起始地址:可选范围为0x0000~0xFFFF(2个字节)

  • 线圈数量:可选范围为1~2000(2个字节)

数据

数据域不确定,由具体的功能决定

Fuzz过程

搭建环境

使用MODSIM模拟modbus协议:

使用modbus数据采集工具modscan监测数据:

协议分析

由于Modbus主要用于读写寄存器,所以这里使用modscan修改某个寄存器的值,并使用wireshark抓包:

写寄存器的数据包如下,Modbus/TCP的报文为:9d 00 00 00 00 06 01 06 00 01 00 06,其中06是功能码,写寄存器,00 01是地址,00 06是写入目标寄存器的值,本次测试计划对写入寄存器的值进行变异。

pit文件编写

在安装好peach之后,将安装包中的模板文件复制一份,更名为modbus.xml,根据分析好的报文来修改模板文件。

DataModel

1
2
3
4
5
6
7
8
9
10
<DataModel name="send_data">
<Block name="mod_write_reg">
<Number name="01" size="16" value="9d 00" valueType="hex" signed="false" multable="false"/> <!--标识符-->
<Number name="02" size="16" value="00 00" valueType="hex" signed="false" multable="false"/> <!--标识符-->
<Number name="03" size="16" value="00 06" valueType="hex" signed="false" multable="false"/> <!--长度-->
<Number name="04" size="16" value="01 06" valueType="hex" signed="false" multable="false"/> <!--标识符和功能码(06)-->
<Number name="05" size="16" value="00 01" valueType="hex" signed="false" multable="false"/> <!--地址-->
<Number name="06" size="16" value="00 06" valueType="hex" signed="false" /> <!--数据-->
</Block>
</DataModel>

StateModel

StateModel定义了如何给目标发送和接收数据。

1
2
3
4
5
6
7
<StateModel name="TheState" initialState="Initial">
<State name="Initial">
<Action type="output">
<DataModel ref="send_data"/>
</Action>
</State>
</StateModel>

Agent

由于我使用的是modbus模拟器,所以在测试过程中无法实时监测设备状态,所以监视器选择Socket,对被测设备进行主动监听。

Socket是更精确级别的监听,可以查看端口是否存在,但Socket会使Fuzz测试速度变慢。

1
2
3
4
5
6
<Agent name="TheAgent">
<Monitor name="Socket">
<Param name="Host" value="172.29.152.130" />
<Param name="Port" value="502" />
</Monitor>
</Agent>

Test

Test用于配置一个指定的fuzzing测试,配置内容包括一个Publisher和其他选项组合成一个stateModel。

1
2
3
4
5
6
7
8
9
10
11
<Test name="Default">
<Agent ref="TheAgent"/>
<StateModel ref="TheState"/>
<Logger class="File">
<Param name="Path" value="logs"/>
</Logger>
<Publisher class="tcp.Tcp"> <!--指定通信方式为tcp-->
<Param name="Host" value="="172.29.152.1"/>
<Param name="Port" value="502"/>
</Publisher>
</Test>

Publisher

Publisher是Peach发送和接收数据的IO接口。

测试过程

运行peach.exe,fuzz正常运行:

关闭MODSIM之后,查看peach日志,可以看到peach检测出一个异常:

总结

这次主要是学习peach的用法,对modbus写寄存器功能的数据部分进行变异,看别人说如果只是发送合法的功能码,对数据部分进行编译会导致fuzz的时间非常长,所以要通过逆向固件先找到模糊测试点,再精确地进行fuzz,这块知识点要mark一下,后续继续学习。

参考链接

https://blog.csdn.net/as480133937/article/details/123197782[详解Modbus通信协议---清晰易懂-CSDN博客](https://blog.csdn.net/as480133937/article/details/123197782)

7.Peach 监听模块【工业控制系列】 - 奋斗的安卓勇士Blog

工控网络协议模糊测试:用peach对modbus协议进行模糊测试 - FreeBuf网络安全行业门户

工控安全研究:基于Peach的Modbus协议模糊测试 - 安全内参 | 决策者的网络安全知识库

工具:Peach_peach工具-CSDN博客

背景

在学习二进制时,GDB是必不可少的工具。我经常使用GDB来动态调试一个ELF文件,但是却不能准确、完整地说出GDB调试的原理,所以在这里总结一下。
GDB能attach 到一个正在运行的进程中,以实时获取进程中的内存数据、增加断点、查看当前运行状态下函数变量值、修改寄存器的值。其基本的调试功能是通过系统调用ptrace实现的。GDB有本地调试和远程调试两种模式:

  • 本地调试:GDB与目标程序在同一台电脑中

  • 远程调试:GDB与目标程序不在同一台电脑,此时需要GdbServer,GdbServer与目标程序在同一个设备中,GDB可以通过串口或者RSP协议(GDB Remote Serial Protocol协议)通信

    gdb工作流程

    直接调试目标程序

    当在终端输入命令gdb ./test时,此时gdb启动并从头开始调试test,gdb工作流程如下:

  1. 操作系统启动gdb进程,gdb进程fork出一个子进程

  2. 子进程调用系统函数ptrace(PTRACE_TRACEME , …)

  3. 子进程调用execve加载,执行目标程序test
    示例如下:
    首先使用gdb ./pwn,建立追踪关系,接着使用pstree -p | grep 'pwn',可以看到pwn程序的父进程为gdb。
    gdb_pwn.jpg

    使用attach调试已运行程序

    当在终端输入命令gdb attach -p $pid时,gdb调试一个已经在运行中的程序,此时gdb的工作流程为:

  4. gdb成为test进程的父进程

  5. test进程进入TASK_TRACED,表示当前进程正在被追踪,此时test进程会停下来,等待gdb的命令,在TASK_TRACED状态下的进程只接受ptace指定的PTRACE_DETACH和PTRACE_CONT请求,从而唤醒进程执行操作

  6. 发送给test进程的信号会被转发给父进程,除了SIGKILL

  7. 父进程收到信号后对子进程进行修改,实现对子进程的调试

示例如下:

  • 首先运行目标程序:./pwn
  • 接着使用ps -a查看pwn的进程号,如下图所示,为6161
  • 使用gdb调试已经运行的pwn程序gdb attach -p 6161,(此时可能有报错ptrace: Operation not permitted,使用root即可解决)
  • 查看pwn对应的父进程ps -ef | grep 6161,可以看到gdb为pwn进程的父进程

pwn_pid.jpg
attach_pid.jpg
pid.jpg

ptrace

ptrace是Linux内核提供的一个用于进程追踪的系统调用函数,其接口声明如下,通过ptrace,gdb可以读写目标进程test的指令空间、数据空间、堆栈和寄存器的值,并且gdb进程接管了test进程所有信号,操作系统发送给目标进程的信号都会被gdb截获。

1
2
3
#include <sys/ptrace.h>
long ptrace(enum __ptrace_request request, pid_t pid,
void *addr, void *data);

ptrace的参数非常重要,这里参考大佬博客

request PTRACE_TRACEME、PTRACE_ATTACH PTRACE_TRACEME表示被追踪进程调用,让父进程来追踪自己。通常是gdb调试新进程时使用。
PTRACE_ATTACH父进程attach到正在运行的子进程上,这种追踪方式会检查权限,普通用户无法追踪root用户下的进程
PTRACE_PEEKTEXT、PTRACE_PEEKDATAPTRACE_PEEKUSERPTRACE_GETREGS 表示读取子进程内存,寄存器等内容
PTRACE_POKETEXT,PTRACE_POKEDATA,PTRACE_POKEUSR 表示修改子进程的内存,寄存器的内容
PTRACE_CONTPTRACE_SYSCALL, PTRACE_SINGLESTEP PTRACE_CONT表示重新启动被追踪进程
PTRACE_SYSCALL每次进入或者退出系统调用时都会触发一次SIGTRAP(Trace/breakpoint trap),strace的追踪系统调用就是通过该配置进行追踪的,进入时获取参数,退出时获取系统调用返回值
PTRACE_SINGLESTEP 每执行完一次指令之后会触发一次sigtrap,支持获取当前进程的内存/寄存器状态。gdb的next指令通过该选项实现
PTRACE_DETACH, PTRACE_KILL 解除父子进程之间的追踪关系
如果父进程在在子进程前结束,则会自动解除追踪关系。
pid
表示要跟踪的进程pid
addr
表示要跟踪的进程pid
data 根据前面设置的requet选项而变化,比如要开始追踪时则设置request= PTRACE_CONT,同时将data设置为对应signal数字(SIGTRAP – 5)。

GDB实现原理

GDB断点实现

当使用gdb为程序设置断点时,gdb实现如下:

  1. gdb将断点处指令修改为INT 3,同时保存断点信息以及修改前的指令

  2. 当子进程(test)执行到断点时,出发INT 3终端,产生SIGTRAP信号

  3. ptrace将子进程的SIGTRAP信号发送给父进程(gdb),父进程与保存的断点信息对比,通过确认INT 3指令的未知,来确认当前信号是否因为断点产生

  4. 若是,将断点处的INT 3指令替换为原指令,将PC指针回退一步,等待用户输入命令,否则继续执行代码

    GDB单步调试实现

    当使用gdb单步调试一个程序时,gdb实现如下

  5. gdb与test建立追踪关系,此时ptrace系统调用的参数为PTRACE_ATTACH

  6. 获取test进程的EIP和ESP的值,其中EIP存放CPU将要执行的下一条指令,ESP中存放当前栈帧的地址

  7. 通过ptrace的PTRACE_SINGLESTEP参数不断将EIP和ESP向下移动,每执行一条指令,寄存器指针移动一次,直到指针达到栈尾,结束调试

参考链接

https://www.cnblogs.com/sewain/articles/14131927.html //原来gdb的底层调试原理这么简单

https://blog.csdn.net/mrhesongze/article/details/81980397 //GDB调试二进制和符号表symbol分开的程序
https://blog.csdn.net/Z_Stand/article/details/108395906 //一文带你看透GDB实现原理
https://blog.csdn.net/wohu1104/article/details/124934068 //gdb三种调试方式

Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub.

Quick Start

Create a new post

1
$ hexo new "My New Post"

More info: Writing

Run server

1
$ hexo server

More info: Server

Generate static files

1
$ hexo generate

More info: Generating

Deploy to remote sites

1
$ hexo deploy

More info: Deployment