简介

P-code是一种专为逆向工程而设计的寄存器传输语言。该语言通用性强,可以对不同处理器的行为进行建模,将对不同处理器的分析放入一个通用框架中,促进retargetable的分析算法和应用开发。

P-code的工作原理是将单个处理器指令转换为一组p-code操作,这些操作将处理器状态的一部分作为输入和输出变量(varnodes),这组唯一的p-code操作(和opcode区分)包含一组相当紧凑的由通用处理器执行的算术和逻辑操作。将指令直接转换为这些操作称为raw p-code。raw p-code可用于直接模拟指令执行,并且通常遵循相同的控制流,尽管它可能会添加一些自己的内部控制流。

P-code专门设计用于方便地构建数据流图,以便对反汇编后的指令进行后续分析。Varnodes和p-code操作符可以显式地视为这些图中的节点。生成raw p-code是图构造中必要的第一步,但还需要执行其他步骤,这会引入一些新的操作符。特别地其中两个新操作符MULTIEQUALINDIRECT用于图的构建过程,其他操作符可以在图的后续分析和转换过程中引入,并帮助保持恢复数据类型关系。最后,一些p-code操作CALL、CALLIND、RETURN可能会在分析期间更改其输入和输出varnode,导致它们不再和raw p-code形式匹配。

Ghidra的初始程序分析生成的p-code和varnode是原始(raw)的,因为仅用于表示指令的语义,很少或没有从高级语言中分析收集到的高级语义信息。Ghidra在反编译期间,p-code和varnodes被refined和关联到抽象的局部变量和源码级别的数据结构,称之为high p-code,因为它与 Ghidra中包含反编译信息的数据结构绑定,例如HighVariables和HighFunctions

Ghidra默认情况下显示的p-code可读性较好:

然而在script中获取和处理的时候是未经翻译的原始形式,显示raw p-code的方法:Edit - Tool Options - Listing Fields - Pcode Field - Display Raw Pcode,例子:

high p-code举例(script时应该叫PcodeOpAST):

(register, 0x20, 4) CALL (ram, 0x13438, 8) , (unique, 0x10000051, 4) , (const, 0x0, 4)
(ram, 0x1d3330, 4) INDIRECT (ram, 0x1d3330, 4) , (const, 0x24, 4)
(stack, 0xffffffffffffffdc, 4) INDIRECT (stack, 0xffffffffffffffdc, 4) , (const, 0x24, 4)
(unique, 0x10000051, 4) COPY (const, 0xfa5da8, 4)
(register, 0x64, 1) INT_SLESS (register, 0x20, 4) , (const, 0x0, 4)---  CBRANCH (ram, 0x1d3318, 1) , (register, 0x64, 1)---  CALL (ram, 0x136c0, 8) , (register, 0x20, 4) , (const, 0x0, 4) , (const, 0x0, 4)
(ram, 0x1d3330, 4) INDIRECT (ram, 0x1d3330, 4) , (const, 0x3a, 4)
(stack, 0xffffffffffffffdc, 4) INDIRECT (stack, 0xffffffffffffffdc, 4) , (const, 0x3a, 4)
(unique, 0x10000059, 4) INT_ADD (register, 0x20, 4) , (const, 0xd0, 4)
(register, 0x24, 4) CAST (unique, 0x10000059, 4)
(register, 0x20, 4) CALL (ram, 0x13d54, 8) , (register, 0x20, 4) , (register, 0x24, 4) , (const, 0x400, 4)
(ram, 0x1d3330, 4) INDIRECT (ram, 0x1d3330, 4) , (const, 0x4c, 4)
(stack, 0xffffffffffffffdc, 4) INDIRECT (stack, 0xffffffffffffffdc, 4) , (const, 0x4c, 4)---  CALL (ram, 0x1216c, 8) , (register, 0x20, 4)

p-code的核心概念包括

地址空间(Address Space)

p-code的地址空间是RAM的泛化。简单的定义成可以被p-code操作读和写的可索引的字节序列。对于特定的字节,标记它的唯一索引是字节的地址。地址空间有一个名称用于识别它,一个大小表示空间中不同索引的数量,以及与之相关的endianess字节序表示整数或其他多字节的值如何编码到空间中。一个典型的处理器有一个RAM空间用于对可通过其主数据总线访问的内存进行建模,以及一个用于对处理器通用寄存器进行建模的寄存器空间(register space)。处理器操作的任何数据都必须在某个地址空间中。处理器的规范可以根据需要自由定义任意数量的地址空间。总是有一个特殊的地址空间,称为常量地址空间(const space),用于对p-code操作所需的任何常量值进行编码生成p-code的系统通常也使用专用的临时空间(temporary space),可以将其视为临时寄存器的无尽bottomless的源,这些地址空间用于在对指令行为建模时保存中间值

p-code的代码规范允许地址空间的可寻址单元大于一个字节。每个地址空间都有一个wordsize属性,可以设置该属性以指示一个单元中的字节数。大于1的wordsize对p-code的表示几乎没有影响。地址空间的所有偏移量仍在内部表示为字节偏移量。唯一的例外是 LOAD 和 STORE 操作,这些操作读取一个指针偏移量,当解引用指针时,该偏移量必须正确缩放以获得正确的字节偏移量。wordsize属性对任何其他 p-code操作都没有影响。

常见的地址空间包括CONST、RAM、UNIQUE、REGISTER、STACK,其定义在ghidra/program/model/address/AddressSpace.java

Varnode

varnode是寄存器或内存位置的概括,由三元组表示**<地址空间、偏移量、大小>**,直观地说,varnode是某个地址空间中的连续字节序列,可以被视为单个值。p-code的所有操作都发生在varnode上

Varnodes 本身只是一个连续的字节块,由地址和大小标识,没有类型。然而,p-code操作可以强制对 varnode 进行三种类型解释之一:整数、布尔值和浮点数。

  • 操作整数的操作总是使用与包含 varnode 的地址空间相关的字节序将 varnode 解释为二进制补码编码。
  • 用作布尔值的 varnode 被假定为单个字节,它只能取值 0,表示 false,1 表示 true。
  • 浮点运算使用被建模的处理器所期望的编码,这取决于 varnode 的大小。对于大多数处理器,这些编码由 IEEE 754 标准描述,但原则上其他编码也是可能的。

如果将 varnode 指定为常量地址空间的偏移量,则在使用该 varnode 的任何 p 代码操作中,该偏移量将被解释为常量或立即值。在这种情况下,varnode 的大小可以被视为可用于常量编码的大小或精度。与其他 varnode 一样,常量只有一种类型,由使用它们的 p 代码操作强制。

P-code操作(P-code Operation)

p 码操作类似于机器指令。所有 p 码操作在内部具有相同的基本格式。它们都将一个或多个 varnode 作为输入,并可选择生成单个输出 varnode。操作的动作由其操作码决定。对于几乎所有 p 代码操作,只有输出 varnode 可以修改其值;操作没有间接影响。唯一可能的例外是伪操作,参见“伪 P-CODE 操作”一节,当对指令行为的了解不完整时,有时需要使用伪操作。

所有 p 代码操作都与它们被翻译的原始处理器指令的地址相关联。对于单个指令,使用从零开始的加一计数器来枚举其翻译中涉及的多个 p 码操作。地址和计数器作为一对被称为 p 码操作的唯一序列号。 p 码操作的控制流通常遵循序列号顺序。当一条指令的所有p-code执行完成时,如果该指令具有fall-through语义,则p-code控制流从fall-through地址处的指令对应的顺序的第一个p-code操作开始。类似地,如果 p 代码操作导致控制流分支,则顺序中的第一个 p 代码操作在目标地址处执行。

可能的操作码列表类似于许多基于 RISC 的指令集。每个操作码的作用在后面的章节中有详细的描述,在“语法参考”一节中给出了一个参考表。通常,特定 p 码操作的大小或精度取决于 varnode 输入或输出的大小,而不是操作码。

HighFunction

HighFunction是反编译器生成的函数的特定信息的集合。HighFunction由下列对象组成:

  • 控制流表示基本块的基本功能
  • 数据流表示varnodes和p-code操作
  • 符号表函数访问的变量的符号表

HighSymbol

HighSymbol是反编译器恢复的显式符号之一,由名称和数据类型组成,可以描述为

  • 函数的参数
  • 函数的局部变量
  • 函数访问的全局变量

Varnodes

反编译器中的Varnode和p-code操作中的varnode不是一个东西。Varnode是反编译器的核心变量概念。Varnode表示反编译器生成的函数数据流表示中的各个结点。在分析的初始阶段,varnode仅表示特定的存储位置,这些位置由各个p-code操作按顺序访问。反编译器立即将p-code转换为基于图的数据流表示,称为静态单赋值形式SSA。在SSA中,varnode具有一些附加属性。

关于SSA可以参考南大《软件分析》课程IR章节
SSA,每个变量都有自己的唯一定义(def-use),有phi结点。
优点:唯一的变量名可以间接体现程序流信息,简化分析过程;def和use都是显式的
缺点:拆解出太多的变量和phi结点;转换回字节码存在性能问题,引入很多拷贝操作。

在SSA形式中,对存储未知的每次写入操作都会定义一个新的varnode。将代码中不同位置的操作写入同一个存储位置,仍然会产生不同的varnode。在这种情况下,每个varnode在函数内部都有一个生命周期或范围,开始于:

  • 定义了变量的(断句)p-code操作的(断句)输出varnode。
  • 如果varnode是函数的输入,则开始于函数起始位置

varnode的范围通过控制流扩展到读取了特定的varnode作为操作数的每个p-code操作定义p-code操作读取操作之间varnode的值不会改变。varnode的范围可以被认为是函数体中通过控制流连接的一组地址。定义了变量的p-code操作的地址称为varnode的first use point或first use offset

在高级语言比如C和java的反编译器输出中,一个varnode也具有范围,并且仅在代码的这个连通区域中表示高级语言中的变量。一组不相交的范围的varnode提供了对可以在函数多个位置写入的高级变量的完整描述。

HighVariable

HighVariable是一组varnodes,合在一起表示在反编译器输出的高级语言中整个变量的存储。每个varnode都描述了变量值在某些代码段中的存储位置。

HighVariables 和 HighSymbols 之间一般是一一对应的。 HighVariables 可以被认为是高级变量的详细存储描述,而 HighSymbol 提供了它的名称和数据类型。

HighVariable 总是描述函数中的指令对数据的显式操作。在某些情况下,HighVariable 可能只描述 HighSymbol 的部分存储。特别是对于结构化或复合数据类型,函数可能在代码的不同点对变量的不同部分进行操作,因此 HighVariable 可能只包含结构的一个字段。

一个符号可以在一个函数中被引用,但是这个符号的值可能没有被显式地操作。常量指针可以引用堆栈或主存储器中的变量,但变量的值在函数内既不读取也不写入。在这种情况下,HighSymbol 存在,但没有对应的 HighVariable。

merging

合并(merging)是分析过程的一部分,反编译器决定将哪些varnode组合在一起以在输出中创建最终的HighVariable。每个 varnode 的作用域(参见反编译器中 Varnodes 中的讨论)提供了对此过程的基本限制。如果两个 varnode 的作用域相交,则不能合并它们。但这在哪些 varnode 可以合并方面留下了很大的余地。

某些 varnode 必须合并;例如,如果它们使用相同的存储但在不同的控制流路径中,或者如果明确知道 varnodes 必须表示相同的变量。这称为强制合并。

反编译器还可以合并可以作为单独变量轻松存在的 varnode。这称为投机合并。除了 varnode 作用域上的交集条件外,反编译器仅推测性地合并共享相同数据类型的变量。除此之外,反编译器会优先考虑在同一指令中读取和写入的变量对,然后是函数控制流中彼此靠近的对。在有限的范围内,用户能够控制这种合并(请参阅拆分为新变量)。

Prototype Model

略。

参考

文档目录$ghidra_home/docs/languages/html/pcoderef.html
opcodes的子集可以出现在raw p-code中的被描述在P-Code Operation Reference(docs/languages/html/pcodedescription.html)和Pseudo P-CODE Operations(docs/languages/html/pseudo-ops.html)构成了本文档的大部分内容。
所有新的操作码都在Additional P-CODE Operations(docs/languages/html/additionalpcode.html)一节中进行了描述,这些操作码都不能在原始原始 p 代码转换中发生。

(Raw/High) P-Code Ghidra使用的中间表示语言相关推荐

  1. 用Visual Studio Code Debug世界上最好的语言(Mac篇)

    用Visual Studio Code Debug世界上最好的语言(Mac篇) 首先,你要有台Macbook Pro,接着才继续看这个教程. PS:Windows用户看这里用Visual Studio ...

  2. 如何在 VS Code 中编写、运行C语言程序 教程

    本篇目录 前言 1.下载.安装VS Code 2.安装VS code中2个插件 3.下载minGW64 4.配置系统的环境变量 5.C语言配置 6.编写一个测试程序 7.可能存在的问题 总结 前言 折 ...

  3. qstudio c语言中文网,再整理:Visual Studio Code(vscode)下的通用C语言环境搭建

    版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 主要流程: 1.vscode的下载与简单配置 2.MinGw的下载与安装 3.配置系统环境变量 4 ...

  4. Visual Studio Code设置中文包/配置中文语言

    打开vscode工具 使用快捷键组合[Ctrl+Shift+p],在搜索框中输入"configure display language",点击确定后: 修改locale.json文 ...

  5. exit code非0什么意思C语言,c++程序出现exit code -1073740940 (0xC0000374)

    一道动态规划的算法题. dp是我用new关键字分配的一个整形数组用来记录转移量,在程序51行使用"delete []dp;"去释放内存 出现exit code -107374094 ...

  6. 解决fortify扫描出的Code Correctness: Double-Checked Locking问题(java语言)

    现有java代码如下: ... if (fitz == null) {   synchronized (this) {     if (fitz == null) {       fitz = new ...

  7. VS Code中如何关闭保存Go语言文件时自动去除未引用包的行为

    在使用Visual Studio Code编写Go语言(Golang)程序代码的时候,有时候引用的包明明是正确引用了,但在保存的时候却会被自动删除掉,是被误认为未引用了.这时候,参照以下步骤就可以解决 ...

  8. 用Visual Studio Code Debug世界上最好的语言

    前言 这阵子因缘巧合接手了一个辣鸡项目,是用世界上最好的拍黄片写的,项目基本是另一个小伙伴在撸码,我就兼职打杂和发布做点运维的工作. 然后昨天项目上了测试版之后,一用起来Error满天飞了.让小伙伴查 ...

  9. C语言读取raw格式图像,求指导,如何用c语言实现读取*.raw格式图像

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 /* ** 这个程序是读取jpg图像的 ** 后续加上jpg图像打开和存放 */ #include #include #include #include ...

最新文章

  1. java 流 复制文件_【Java】使用字节流复制文件
  2. 网站设计之Flash简单动画入门介绍(一)字体闪烁及渐显
  3. java 俄文,俄文字体在word里面是什么
  4. net start mysql 发生系统错误 5。 拒绝访问。的解决方法
  5. 悲观锁和乐观锁的区别和应用场景
  6. 阶段3 1.Mybatis_12.Mybatis注解开发_1 mybatis注解开发的环境搭建
  7. 【图像处理】基于matlab GUI图像分水岭分割+灰度几何校正+运动图像复原【含Matlab源码 024期】
  8. 自定义的string类
  9. 金蝶k3服务器的操作系统,金蝶k3服务器配置工具
  10. excel手机版_excel仓库管理手机版导出软件
  11. 触摸板不小心卸载,触摸板重装,触摸板没有开关选项
  12. 【单片机仿真】(四)寻址方式 — 寄存器寻址与直接寻址
  13. cmd查看自己的CPU参数
  14. 一款很哇塞的csdn开发助手,你确定不来看看嘛
  15. 关于Tacotron2看这一篇就够了
  16. JavaScript节点操作、删除节点
  17. PMP之敏捷图表之燃起图和燃尽图、累积流量图
  18. Android中Kotlin面试问题讲解
  19. 【干货篇】调用其他系统http接口超时了,如何处理,方案汇总
  20. 攻防世界web新手区合集

热门文章

  1. Python 画图工具生成数据点图
  2. 前端登陆之cookie篇
  3. Nginx动静分离配置
  4. 深蓝算法反演AOD入门记录(一)
  5. Linux之恢复删除的数据
  6. 淘宝、京东电商的崛起,为什么如今越来越多的企业选择java商城?
  7. 图文结合带你搞懂InnoDB MVCC
  8. 海豚调度器初次使用 .......
  9. iOS14适配【解决iOS14下pop多层控制器至首页时,tabbar不显示问题】之问题分析篇
  10. 随手笔记--为对象增加新的属性,拼接多个对象