less than 1 minute read

这学期上了一门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中又有一个JimpleBodyJimpleBody中包含一些Jimple statements(Units)。

可以用一张图表示:

structure

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-diroutput-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);
        }
    }
}

Tags: ,

Categories:

Updated: