您的位置:首页 > 其它

soot插桩关键点总结(三)

2016-05-18 11:11 246 查看

一 插入字段

给某个SootClass插入字段,关键API为new SootField(String,Type,int);

//向sootclass添加静态Intent intent_for_ipc字段
SootField intent_for_ipc = new SootField("intent_for_ipc", intentSootClass.getType(),Modifier.STATIC);
sootclass.addField(intent_for_ipc);
注意:一般是在wjtp下给某个SootClass插入字段

二 构造方法

1. 构造没有参数的方法

SootMethod sm = new SootMethod("getIntent", Arrays.asList(new Type[]{}), RefType.v("java.lang.String"), Modifier.PUBLIC);

2. 构造对象为参数的方法

SootClass intentSootClass = Scene.v().getSootClass("android.content.Intent");
SootMethod sm = new SootMethod("getIntent", Arrays.asList(new Type[]{}), intentSootClass.getType(),Modifier.PUBLIC);

3. 构造数组为参数的方法

method=new SootMethod("main",Arrays.asList(newType[]{ArrayType.v(RefType.v("java.lang.String"), 1)}),VoidType.v(),Modifier.PUBLIC|Modifier.STATIC);

4. 构造多个参数的方法

SootMethod smmm = new SootMethod("mulPara",Arrays.asList(new Type[]{RefType.v("java.lang.String"),intentSootClass.getType()}),VoidType.v(), Modifier.PUBLIC);


三 字段赋值

在(一)中给出了向某个SootClass插入字段的关键代码,那么针对字段该如何赋值呢?下面给出非静态字段赋值与静态字段赋值的方法

1. 静态字段赋值

关键API位:Jimple.v().newStaticFieldRef(intent_for_ipc_makeRef())和Jimple.v().newAssignStmt()
//保存参数
Local arg = Jimple.v().newLocal("l0", intentSootClass.getType());
helperBody.getLocals().add(arg);
IdentityStmt para = Jimple.v().newIdentityStmt(arg, Jimple.v().newParameterRef(intentSootClass.getType(), 0));
helperBody.getUnits().add(para);
//将arg赋值给字段
helperBody.getUnits().add(Jimple.v().newAssignStmt(Jimple.v().newStaticFieldRef(intent_for_ipc.makeRef()), arg));
helperBody.getUnits().add(Jimple.v().newReturnVoidStmt());

2. 非静态字段赋值

关键API为:Jimple.v().newInstanceFieldRef(Value, SootFieldRef),其中第一个参数为字段所在类的实例化对象

四 在确定位置插桩

soot实现Android Apps插桩(一)的完整代码中有一段代码:
while(iter.hasNext()){
final Unit unit = (Unit)iter.next();
unit.apply(new AbstractStmtSwitch(){

public void caseAssignStmt(AssignStmt stmt){
...

}

public void caseInvokeStmt(InvokeStmt stmt){
...
}

}

}




这是一种在确定位置插桩的方法,其中,还有另外一种方法,如下:
PatchingChain<Unit> units = body.getUnits();
for(Iterator iter = units.snapshotIterator();iter.hasNext();){
Unit u = (Unit)iter.next();
if(u instanceof InvokeStmt){
String methodName = ((InvokeStmt) u).getInvokeExpr().getMethod().getName();
System.out.println(methodName);
if(methodName.equals("add")){
Local local = Jimple.v().newLocal("lizhengqiao",RefType.v("java.lang.String"));
body.getLocals().add(local);
...
}

}
//if(u instance IdentityStmt)
//...
}
另:在Java中,可以采用另外一种插桩的方法:直接写一个需要插桩的Java代码,然后插桩调用该Java类中的方法即可。

经过我的测试:给某个确定的方法内插桩代码时,应该使用BodyTransformer,而插桩字段、方法则应该使用SceneTransformer;在向某个方法中插桩句子时,在使用SceneTransformer时,我没有成功;经过我的多次尝试,在Scene下插桩代码,很容易被soot优化掉,如:插桩一个local,但是没有对local进一步的操作,则会被soot优化掉,查看生成的代码中就没有该local,而在Body下插桩则不会出现这种情况。可能我的理解有误,有成功的希望能够分享一二。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: