我在网上找了好久。但没有用。请帮助或尝试给出一些如何实现这一目标的想法。 而且这里有一个demo但是我看不懂。我想知道dexlib2是否可以用来写入或重写dex文件
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);
您有两种方法来重写 dex 文件。但在此之前,您需要了解一些基础知识。 首先,dex文件有类。每个类都有字段和方法。字段很简单。但方法有方法实现。这实际上是代码。该实现(代码)由指令组成。这些指令有多种类型。 例如,instruction21c 用于“const-string”。 您可以从以下对象的 dex 中读取其中的每一个 -
所以基本上你可以使用两个类来读取每个对象 - 一个是 Dexbacked,另一个是直接的。 区别在于 DexBackedObject 仅具有加载的 dex 文件上的指针。他们不保存任何数据。当调用这些对象的字段和方法时,它们会从 dex 文件中读取它们。否则它们是空的。 与它们不同的是,直接对象已经填充了数据。
然后来了-
这些都是MethodImplementation(代码)的一部分。例如
const-string v1, "hellow World"
这条指令是指令21c。 该指令的操作码是“const-string” 该指令的RegisterA = v1 该指令的 Reference 类型为 StringReference。
再举个例子-
调用静态 p0, Lmyclass;->myMethod(LmyParam1;LmyParam2;):LmyRetType;
这整行代码在方法实现中生成了一条指令。 该指令的引用是 MethodReference 类型。 我希望你明白 xxxxxReference 类的含义。
然后我们来到 ImmutableXXXXXXXXXX——这些是什么? 例如 - ImmutableClassDef、ImmutableMethod、ImmutableMethodReference 等。 好吧,它们与上面的相同,如果你想改变一些东西,你必须创建一个新的 ImmutableXXXXX。例如,如果我想更改
const-string v1,"hellow world" to const-string v1, "i am manoj"
那么我无法编辑现有指令。相反,我必须创建一个新指令,在其中我将从原始数据复制除“hellow world”之外的大部分数据。为了创建这个新指令,我将使用 ImmutableInstruction。在这种情况下 - 新的 ImmutableInstructions21c。
现在我们来回答你的问题。如何编辑它以及如何理解示例。
重写器接受方法作为接口。正如您所知,在 java 中,接口用于将方法作为参数传递。所以重写器接受一个方法作为参数。 在此方法中,方法参数是 classDef、Method、Field、Instruction 等。如果您不想更改,则可以返回原始对象。或者使用 ImmutableXXX 创建一个新对象,如果想要更改某些内容则返回它。 当您完成向重写器提供这些编辑方法后,您只需将 dex 文件提供给重写器即可。然后重写器将读取所有内容,即。 ClassDefs、方法、字段、指令、注释...并将它们扔给您的方法。 您定义的方法将编辑它们或按原样返回它们。从那里,它将使用它们编写一个新的 dex 文件。
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.
}
}
此示例代码适用于类型。这只是字符串。但如果您想编辑 .. 例如,可以说 .. .a 字段。那么你必须返回一个 ImmutableField 对象。
if(someCondition){
return new ImmutableField(value.definingClass,value.Type,value.name);
}
类似这样的事情。
第二种方法是使用dexPool。 dexPool 有很多池。如 stringPool、methodPool、fieldPool 等。 dexPool 使用其 intern() 方法读取类、方法等。 并收集其池中的所有中间项目。 所以在实习了整个dex文件之后,它的StringPool充满了在dex文件中找到的所有字符串..MethodPool充满了....等等。 然后它以 dex 文件格式重新排列所有这些池并写入 dex 文件。
所以如果你想编辑一些东西。首先列出原始 dex 文件的 ClassDef 列表。 然后选择一个你想要编辑的ClassDef。然后用新的 ImmutableClassDef 替换它
然后让 dexPool 内部化列表中的所有 classDef。并制作一个新的输出 dex 文件。
我已经使用这个 dexlib2 4 个月了。我希望我总结得很好。谢谢你。