|
| 1 | +# cha-optimization |
| 2 | + |
| 3 | +## 实现&分析 |
| 4 | +在实际测试中发现,如果路径过长会出现neo4j查询不出来的情况,还需要对CHA进行进一步优化。优化方向有两个: |
| 5 | + |
| 6 | +1. 尽可能减少节点的数量 |
| 7 | +2. 尽可能减少环路的出现 |
| 8 | + |
| 9 | +目前采取的遍历算法,有点类似于从entry出发,进行广度优先遍历(bfs)。实际的节点表现可能是这样的 |
| 10 | + |
| 11 | + |
| 12 | + |
| 13 | +从这张图可以看出,有用的节点其实是标有颜色的那些节点,其中绿色表示entry,红色表示sink。但是在导入的时候其他节点也会被导入。 |
| 14 | + |
| 15 | +我们可以通过从sink向上回溯,筛选出那些能够到达sink的节点,就可以把这些有颜色的节点筛选出来。 |
| 16 | + |
| 17 | +定义SinkReachable(method:Method, sink:Method, step:number) 表示 method 经过 step步能调用到 sink 。 |
| 18 | + |
| 19 | +那么久可以根据CallGraph(insn, caller, callee) 一步步向上回溯了,具体规则见 |
| 20 | + |
| 21 | +```dl |
| 22 | +// 初始化 sink 到 sink 为 0 |
| 23 | +SinkReachable(sink, sink, 0) :- |
| 24 | + SinkMethod(sink). |
| 25 | +
|
| 26 | +// 如果caller 调用 了 callee |
| 27 | +// 且 callee n 步到 sink |
| 28 | +// 那么能够推导出 caller n+1 步 能到 sink |
| 29 | +SinkReachable(caller, sink, n+1) :- |
| 30 | + n < MAXSTEP, |
| 31 | + SinkReachable(callee, sink, n), |
| 32 | + CallGraph(_, caller, callee). |
| 33 | +``` |
| 34 | + |
| 35 | +更近一步我们还可以寻找从entry 到 sink 的最短路径 |
| 36 | + |
| 37 | +定义 ShortestPathToSink(caller:Method, sink:Method, step:number) 表示caller 经过最短step步 到达 sink |
| 38 | + |
| 39 | +```dl |
| 40 | +// 筛选出entry 到 sink 的 最短长度 n |
| 41 | +ShortestPathToSink(entry, sink, n) :- |
| 42 | + n = min step : {SinkReachable(entry, sink, step)}, |
| 43 | + SinkMethod(sink), |
| 44 | + EntryMethod(entry). |
| 45 | +
|
| 46 | +// 如果caller 到 sink 最短距离 为 n |
| 47 | +// 且 calle 到 sink 的距离为n-1 |
| 48 | +// 且 caller 调用 callee |
| 49 | +// 那么可以推导出 callee 到 sink 的 最短距离为 n-1 |
| 50 | +ShortestPathToSink(callee, sink, n-1) :- |
| 51 | + n < MAXSTEP + 1, |
| 52 | + ShortestPathToSink(caller, sink, n), |
| 53 | + SinkReachable(callee, sink, n-1), |
| 54 | + CallGraph(_, caller, callee). |
| 55 | +``` |
| 56 | + |
| 57 | +这里稍微解释一下 |
| 58 | + |
| 59 | +```dl |
| 60 | +ShortestPathToSink(entry, sink, n) :- |
| 61 | + n = min step : {SinkReachable(entry, sink, step)}, |
| 62 | + SinkMethod(sink), |
| 63 | + EntryMethod(entry). |
| 64 | +``` |
| 65 | + |
| 66 | +大概的执行顺序是 |
| 67 | + |
| 68 | +1. 先从EntryMethod 选出一个 entry |
| 69 | +2. 从SinkMethod 选出一个 sink |
| 70 | +3. 然后从SinkReachable 找出第一个值为entry 第二个值为sink的数据,从这些数据中选出最小的step |
| 71 | + |
| 72 | +这种就找到entry到sink的最短距离为n |
| 73 | + |
| 74 | +## 使用方法 |
| 75 | + |
| 76 | +通过宏定义 可以配置不同的优化级别 |
| 77 | + |
| 78 | +1. `#define CHAO 1` 返回的是所有能到sink的节点 |
| 79 | +2. `#define CHAO 2` 返回的是entry到sink最短路径上的节点 |
| 80 | +3. 如果没有 CHAO 宏定义 则 返回的是entry在MAXSTEP之内能到达的所有节点 |
| 81 | + |
| 82 | +使用样例 |
| 83 | + |
| 84 | +[ctf-buggyLoader.dl](../example/ctf-buggyLoader.dl) |
| 85 | + |
| 86 | +```dl |
| 87 | +#define MAXSTEP 5 |
| 88 | +#define CHAO 2 |
| 89 | +
|
| 90 | +#include "inputDeclaration.dl" |
| 91 | +#include "utils.dl" |
| 92 | +#include "cha.dl" |
| 93 | +
|
| 94 | +
|
| 95 | +.decl NonParamPublicMethod(method:Method, class:Class) |
| 96 | +.output NonParamPublicMethod |
| 97 | +
|
| 98 | +// 声明sink |
| 99 | +SinkDesc("exec", "java.lang.Runtime"). |
| 100 | +SinkDesc("<init>", "java.lang.ProcessBuilder"). |
| 101 | +SinkDesc("start", "java.lang.ProcessImpl"). |
| 102 | +SinkDesc("loadClass", "java.lang.ClassLoader"). |
| 103 | +SinkDesc("defineClass", "java.lang.ClassLoader"). |
| 104 | +SinkDesc("readObject", "java.io.ObjectInputStream"). |
| 105 | +SinkDesc("readExternal", "java.io.ObjectInputStream"). |
| 106 | +
|
| 107 | +// 声明入口方法 |
| 108 | +EntryMethod(method), |
| 109 | +Reachable(method, 0), |
| 110 | +NonParamPublicMethod(method, class) :- |
| 111 | + MethodInfo(method, simplename, _, class, _, _, arity), |
| 112 | + MethodModifier("public", method), |
| 113 | + simplename != "<init>", |
| 114 | + arity = 0, |
| 115 | + SubClass(class, "java.io.Serializable"). |
| 116 | +
|
| 117 | +.output SinkMethod |
| 118 | +``` |
| 119 | + |
| 120 | +## 优化效果 |
| 121 | + |
| 122 | +以ctf-buggyLoader为例 |
| 123 | + |
| 124 | +1. 无 CHAO 宏定义 |
| 125 | + - Nodes: 68561 |
| 126 | + - Relations: 1080201 |
| 127 | + - Time 1:39.87 s |
| 128 | +2. `#define CHAO 1` |
| 129 | + - Nodes: 3864 |
| 130 | + - Relations: 55736 |
| 131 | + - Time: 20.859 s |
| 132 | +3. `#define CHAO 2` |
| 133 | + - Nodes: 722 |
| 134 | + - Relations: 3672 |
| 135 | + - Time: 20.134 s |
| 136 | + |
| 137 | +优化效果还行,之所以优化之后的时间更短,我猜测可能是IO更浪费时间,因为不优化的CallNode.csv 和 CallEdge.csv 都上百M了 。 |
0 commit comments