fdex2
原理:1. 通过loadClass得到一个Class对象。2. 通过 getDex得到Dex对象。3.通过getBytes得到
- frida版本构造原理:BaseDexClassLoader.findClass=>DexPathList.findClass=>DexFile.loadClassBinaryName=>DexFile.defineClass.最终会得到mCookie,而mCookie则指向Dex的首地址,即DexFile的指针。只要遍历mCookie即可。
var savepath = "/sdcard"
function savedexfile(dexfileptr){
try{
var dexfilebegin = ptr(dexfileptr).add(Process.pointerSize*1).readPointer();
var dexfilesize = ptr(dexfileptr).add(Process.pointerSize*2).readU32();
var dex = new File(savepath+"_"+dexfilesize+".dex","a");
if(dex!=null){
var content = ptr(dexfilebegin).readByteArray(dexfilesize);
dex.write(content);
dex.flush();
dex.close();
console.warn('[dump]dex'+savepath+"_"+dexfilesize+".dex")
}
}
catch(e){
}
}
function dump(){
Java.perform(function(){
var DexFileClass = Java.use('dalvik.system.DexFile')
Java.choose('dalvik.system.DexFile',{
onMatch:function(dexfile){
var mCookie = dexfile.mCookie.value;
var classlist = DexFileClass.getClassNameList(mCookie);
classlist.forEach(function(classname){
console.log(dexfile.mFileName.value+"->"+classname)
})
console.log(mCookie.$className)
var Array = Java.use('java.lang.reflect.Array');
var size = Array.getLength(mCookie);
var i=0;
for(i=0;i<size;i++){
console.log(i+'->'+Array.getLength(mCookie,i))
var longvalue = Array.getLong(mCookie,i);
var dexfileptr = ptr(longvalue + "")
savedexfile(dexfileptr)
}
},
onComplete:function(){
console.warn('search DexFile over!')
}
})
})
}
vmp的识别
vmp主要分2种形式,一种是数字壳,脱完壳之后对onCreate函数进行native化。另一种是onCreate函数中加载的是对各种相同签名的函数地址进行绑定。图中的A.V也是native函数,所以我们只能进行so层的逆向
对于这种vmp,我们可以hook RegisterNative函数对jni注册的函数进行查看。

1

2
当编译源码时,如果之前已经刷过源码,则只需要重新刷入system.img和system_other.img即可。下面的代码是通过frida来hook得到RegisterNative以及知道method_idx来得到索引。
var addrGetMethodNameByArtMethod = null;
var funcGetMethodNameByArtMethod = null;
var ArtMethodPrettyMethodaddr=null;
function readStdString(str) {
const isTiny = (str.readU8() & 1) == 0;
if (isTiny) {
return str.add(1).readUtf8String();
}
return str.add(2 * Process.pointerSize).readPointer().readUtf8String();
}
//arm32
function callprettymethod(artmethodptr) {
ArtMethodPrettyMethodaddr = Module.findExportByName("libart.so", "_ZN3art9ArtMethod12PrettyMethodEb");
var ArtMethodPrettyMethodfunc = new NativeFunction(ArtMethodPrettyMethodaddr, "pointer", ["pointer", "pointer", "pointer"]);
var strptr = Memory.alloc(64);
var ArtMethodName = null;
if (strptr != null) {
ArtMethodPrettyMethodfunc(ptr(strptr), ptr(artmethodptr), ptr(1));
ArtMethodName = readStdString(strptr);
return ArtMethodName;
}
return null;
}
function hooklibart() {
console.log("go into hooklibart," + "Process.arch:" + Process.arch);
var module_libext = null;
if (Process.arch === "arm64") {
module_libext = Module.load("/data/app/fart64.so");
} else if (Process.arch === "arm") {
module_libext = Module.load("/data/app/fart.so");
}
if (module_libext != null) {
addrGetMethodNameByArtMethod = module_libext.findExportByName("getMethodNameByArtMethod");
funcGetMethodNameByArtMethod = new NativeFunction(addrGetMethodNameByArtMethod, "pointer", ["pointer", "pointer"]);
}
ArtMethodPrettyMethodaddr = Module.findExportByName("libart.so", "_ZN3art9ArtMethod12PrettyMethodEb");
var libartmodule = Process.getModuleByName("libart.so");
var symbols = libartmodule.enumerateExports();
symbols.forEach(function (symbol) {
var symbolname = symbol.name;
if (symbolname != null) {
if (symbolname == '_ZN3art9ArtMethod14RegisterNativeEPKvb') {
console.log(symbol.name + "---" + symbol.address);
Interceptor.attach(symbol.address, {
onEnter: function (args) {
this.artmethod = args[0];
//method1
//var methodname = callprettymethod(ptr(this.artmethod));
//method2
var methodnameptr = funcGetMethodNameByArtMethod(ptr(ArtMethodPrettyMethodaddr), ptr(this.artmethod));
var methodname = ptr(methodnameptr).readCString();
var address = args[1];
this.dex_method_index_ = ptr(this.artmethod).add(12).readU32();
console.log("go into _ZN3art9ArtMethod14RegisterNativeEPKvb---" + "artmethodptr:" + ptr(this.artmethod) + "---methodidx:" + this.dex_method_index_ + "--addr:" + address + "----name:" + methodname);
}, onLeave: function (retval) {
}
})
}
}
});
}
function main() {
hooklibart();
}
setImmediate(main);
分析vmp的办法
jni trace
pip install jnitrace==3.0.3 指定安装的jnitrace为3.0.3
高级用法可以查看官网,比如正则匹配去trace