Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Parsing 从程序集文件创建控制流图_Parsing_Assembly_Control Flow Graph - Fatal编程技术网

Parsing 从程序集文件创建控制流图

Parsing 从程序集文件创建控制流图,parsing,assembly,control-flow-graph,Parsing,Assembly,Control Flow Graph,我想用C语言从汇编文件创建控制流图(CFG)。我一直在思考,以下是我的想法: 1.创建块 -逐行处理程序集文件 -查找重要的指令,如函数名、块名、跳转指令、调用指令或leave/ret以及其他一些指令-是否可以使用正则表达式查找它们?但我还没有在Windows上找到C的正则表达式实现。 -在匹配上述指令之后,在匹配到某个结构之前保存指令,这是我的块 2.创建CFG -所以从块创建CFG,但我不知道 谁能给我一些建议怎么做?如果有更好的语言,如果你告诉我,我会很感激的。 谢谢你的时间和帮助 OP需

我想用C语言从汇编文件创建控制流图(CFG)。我一直在思考,以下是我的想法: 1.创建块 -逐行处理程序集文件 -查找重要的指令,如函数名、块名、跳转指令、调用指令或leave/ret以及其他一些指令-是否可以使用正则表达式查找它们?但我还没有在Windows上找到C的正则表达式实现。 -在匹配上述指令之后,在匹配到某个结构之前保存指令,这是我的块 2.创建CFG -所以从块创建CFG,但我不知道

谁能给我一些建议怎么做?如果有更好的语言,如果你告诉我,我会很感激的。

谢谢你的时间和帮助

OP需要一种严格的方法来完成这项任务

他需要一个好的汇编程序源解析器,所以他知道他有一个精确的表示。除了纯解析部分,他还有 完全模拟汇编程序,包括所有复杂的操作,如宏、条件块、多位置计数器、绝对/相对/外部符号等(仅依靠正则表达式构建一个好的解析器是行不通的)

然后,他需要通过检查机器指令和分支序列来计算控制流图的第一个估计值。 这可能比看起来更难做到;在大型、复杂的汇编代码中,人们滥用程序的入口点,因此有时很难分辨什么是指令,什么是数据

(以下是我在大型x86应用程序中使用的技巧。我想在许多地方向代码中添加健全性检查。健全性测试如下所示:

  <test for some sane condition>
  jf  location+3       ; this branchs to a breakpoint in the middle of the next instruction
  cmp  al, 0xCC        ; the immediate value is a BREAKPOINT opcode

JF位置+ 3;这个分支在下一个指令中间的断点。
cmp al,0xCC;立即值是断点操作码
它们很紧凑,当一些不好的情况发生时会出现断点。但是当分析这个程序的控制流时,“jmp false”有时会分支到指令的中间部分。OP将如何建模?)

下一个复杂问题是指向代码的指针。汇编代码通常生成指向其他指令的许多指针,然后将这些指针隐藏在不同的位置(调用指令将它们推送到x86的数据堆栈上),检索它们,然后执行“jmp间接”。如果您想知道jmp可能会去哪里,您需要跟踪内存位置可能包含的值,这意味着您需要进行数据流分析(值是如何到达的,从哪里来的)并结合调用图构造(无法到达该函数?好的,那么它去哪里不会影响此代码)计算一个合理的答案

通过特别的方法来做这些,最终会产生不准确(无用)的答案。OP需要找到一个框架来构建他的解析器,如果他希望得到一个好的结果,他需要实现分析算法的高质量点

C不是专门为支持此任务而设计的。它可以用足够多的额外精力来完成,但对于任何编程语言都是如此


(查看我的个人简历,了解这样一个框架。OP可以使用任何适合他的框架)。

一个更简单的方法是组装组装文件,然后将其反汇编。大多数解析问题都被消除了。反汇编将具有标签、操作码和操作数的固定列,因此不需要进行任何解析

使用拆解,执行两个过程。第一步是创建一个数据结构来表示每条指令,并收集所有跳转目标

第二步是创建表示(具有单个入口点和出口的代码块)的结构。将每个基本块链接到其后续块。一个基本块可以有零个、一个或两个后继(或者在跳转表的情况下有N个后继)。以RET结尾的基本块有零个后续块。以无条件跳转结束的基本块有一个后继块。一个有条件跳转的基本块有两个后继块——要么失败,要么跳转目标。没有前置的基本块要么是子例程入口点,要么是死(或无效)代码

跳转目标是基本块的开始,无条件跳转(应该是跳转目标或子程序入口点)后的指令也是如此

如果不运行程序(通过真正的硬件或模拟器),确定间接跳转的目标是不可行的。我建议支持两种简单的情况:1)跳转表,其中该表位于程序中;2)跳转全局内存位置,该位置用于链接到另一个可执行文件(反汇编程序列出目标是什么)。在第一种情况下,基本块可以有任意多个后继块。在第二种情况下,基本块有一个后续块

请注意,我故意在CFG中省略调用。当我实现CFG图示器时,我就是这么做的。我的图示器一次只显示一个函数。如果双击调用,则会显示子例程的CFG

但是,如果希望在单个CFG中包含整个子例程树,则调用将是基本块的结束,而调用后的指令将是基本块的开始。请注意,除了最简单的程序之外,很难查看程序的整个CFG

我省略了int和iret,因为我假设您正在处理用户模式的应用程序。如果没有,则将INT视为调用,将IRET视为RET。硬件中断服务例程(ISR)可以从启用中断的任何地方调用,因此(通常)不会直接调用ISR—它只是有点坐在一旁。如果你和kern打交道,更一般地说