浅谈Soot
这学期上了一门PG课COMP5111,它的PA要求用Soot来对Java字节码进行操作(主要插入一些自定义指令)。这样在没有源代码(which is mostly the case)的情况下也能做事情了。
Soot Model
https://noidsirius.medium.com/a-beginners-guide-to-static-program-analysis-using-soot-5aee14a878d
Scene
包含了所有soot加载的类,称为SootClass
。每个SootClass
中又有一些SootMethod
,每个SootMethod
中又有一个JimpleBody
。JimpleBody
中包含一些Jimple statements(Unit
s)。
可以用一张图表示:
Jimple
r0 := @this: FizzBuzz
i0 := @parameter0: int
$i1 = i0 % 15
if $i1 != 0 goto $i2 = i0 % 5
$r4 = <java.lang.System: java.io.PrintStream out>
virtualinvoke $r4.<java.io.PrintStream: void println(java.lang.String)>("FizzBuzz")
goto [?= return]
$i2 = i0 % 5
Jimple就是Java代码的一种简单表示。每一行代码叫做一个statement,或unit。
Setup
https://www.sable.mcgill.ca/soot/tutorial/usage/
主要是设定一些Soot参数,比如输入输出路径(-process-dir
,output-dir
)等等。
插入code (又称instrument)
插入功能是用Soot的“transform”功能来实现的。这个功能在一个叫“jtp”的包里面。
我们要定义的就是一个transform function然后Override internalTransform
方法,如下:
@Override
protected void internalTransform(Body body, String phase, Map options) {
SootMethod method = body.getMethod();
// we dont instrument constructor (<init>) and static initializer (<clinit>)
if (method.isConstructor() || method.isStaticInitializer()) {
return;
}
System.out.println("instrumenting method: " + method.getSignature());
Chain<Unit> units = body.getUnits();
// get a snapshot iterator of the unit since we are going to
// mutate the chain when iterating over it.
Iterator<?> stmtIt = units.snapshotIterator();
while (stmtIt.hasNext()) {
Stmt stmt = (Stmt) stmtIt.next();
if (stmt instanceof ReturnStmt || stmt instanceof ReturnVoidStmt) {
InvokeExpr incExpr = null;
if (method.isStatic()) {
incExpr = Jimple.v().newStaticInvokeExpr(
addStaticInvocationMethod.makeRef(), IntConstant.v(1));
} else {
incExpr = Jimple.v().newStaticInvokeExpr(
addInstanceInvocationMethod.makeRef(), IntConstant.v(1));
}
Stmt incStmt = Jimple.v().newInvokeStmt(incExpr);
units.insertBefore(incStmt, stmt);
}
}
}