Reputation: 21
I am searching for a long time on net. But no use. Please help or try to give some ideas how to achieve this. And there is a demo here but I can't understand.I want to know whether dexlib2 can be used to write or rewrite the dex file
DexRewriter rewriter = new DexRewriter(new RewriterModule() {
public Rewriter<String> getTypeRewriter(Rewriters rewriters) {
return new Rewriter<String>() {
public String rewrite(String value) {
if (value.equals("Lorg/blah/MyBlah;")) {
return "Lorg/blah/YourBlah;";
}
return value;
}
};
}
});
DexFile rewrittenDexFile = rewriter.rewriteDexFile(dexFile);
Upvotes: 2
Views: 2550
Reputation: 497
you have two ways to rewrite dex file. but before, you need to understand some basics. first of all, dex file has classes. each class has fields and methods. fields are simple. but methods has method implementation. which is actually the code. that implementation(code) is made of instructions. these instructions are of many types. for example instruction21c is for "const-string". you can read each of these from dex in the following objects-
So basically you can read each object using two classes- one is Dexbacked and another is direct. the difference is- DexBackedObject has only pointers on the loaded dex file. they do not hold a single data. when fields and methods of these Objects are called, that time they read them from dex file. otherwise they are empty. unlike them, direct Objects are already filled with data.
then there comes-
these all are part of MethodImplementation(code). for example
const-string v1, "hellow World"
this instruction is instruction21c. this instruction's opcode is "const-string" this instruction's RegisterA = v1 this instruction's Reference is type of StringReference.
lets take another example-
invoke-static p0, Lmyclass;->myMethod(LmyParam1;LmyParam2;):LmyRetType;
this whole line makes a single instructions in a method implementation. this instruction's reference is type of MethodReference. i hope you understand what is meaning of xxxxxReference classes.
then we comes to ImmutableXXXXXXXXXX- what are these?
for example- ImmutableClassDef, ImmutableMethod, ImmutableMethodReference etc..
ok, they are same thing as above, if you want to change something you have to create a new ImmutableXXXXX. for example if i want to change the const-string v1,"hellow world" to const-string v1, "i am manoj"
then i cannot edit existing instruction. instead i have to create a new instruction in which i will copy most of data from orignal except the "hellow world".. to create this new instruction , i will use ImmutableInstruction. in this case- new ImmutableInstructions21c.
now we comes to your question. how to edit it and how to understand the examples.
rewriter accept a method as interface. as you already know, in java, interfaces are used to pass a method as parameter. so rewriter accepts a method as parameter. in this method, method argument is the classDef,Method,Field,Instruction etc. you either return orignal object if you dont want to change. or make a new object using ImmutableXXX and return it if want to change something. when you finished providing these editingMethods to rewriter, you just need to feed the dex file to rewriter. then rewriter will read each and everything ie. ClassDefs,Methods,Fields,Instructions,Annotations.. and throw them to your methods. your defined methods will either edit them or return them as is. from there, it will use them to write a new dex file.
DexRewriter rewriter = new DexRewriter // the DexRewriter which will do the actual reading and writing of dex file. but its only parameter is a 'middleMan' method.
new RewriterModule() {} // this is our middle man
public Rewriter<String> getTypeRewriter(Rewriters rewriters) {} // this is our first worker which works under this middle man boss. this worker is expert in throwing found Types (like Lbla/bla/bla;) and getting modified ones from you.
// there can be many workers expert in different things. such as StringRewriter, MethodRewriters etc. you can also add them below it using @override.
//for example, MethodRewriter will throw all found methods at you and collect them as you modify or return as is.
public String rewrite(String value) {} //write code that edits throwed objects under this method.
//for example i want to replace Lmybla; to Lyourbla; everywhere in dex file- so i will write following code-
public String rewrite(String value) {
if(value.equals("Lmybla;"){
return "Lyourbla;"; //return edited.
}else{
return value; //dont touch, return as it.
}
}
this example code was for types. which are just strings. but if you want to edit a .. for example lets say.. .a field. then you have to return a ImmutableField object.
if(someCondition){
return new ImmutableField(value.definingClass,value.Type,value.name);
}
something like this.
second method is to use dexPool. dexPool has many pools. such as stringPool, methodPool, fieldPool etc. dexPool reads classes, methods etc using its intern() method. and it collects all interend items in its pools. so after interning a whole dex file, its StringPool is full of all strings found all over the dex file..MethodPool is full of.... and so on. then it rearrange all these pools in dex file format and write a dex file.
so if you want to edit something. first make a list of ClassDefs of orignal dex file. then pick up a ClassDef you want to edit. then replace it with new ImmutableClassDef
then make dexPool intern all classDefs of list. and make a new output dex file.
i am working with this dexlib2 for 4 months now. i hope i summarize it well. thank you.
Upvotes: 0