//http://androidxref.com/8.1.0_r33/xref/libcore/dalvik/src/main/java/dalvik/system/DexClassLoader.java
DexClassLoader->BaseDexClassLoader->ClassLoader->loadClassprotectedClass<?>loadClass(Stringname,booleanresolve)throwsClassNotFoundException{// First, check if the class has already been loaded
Class<?>c=findLoadedClass(name);if(c==null){try{if(parent!=null){c=parent.loadClass(name,false);}else{c=findBootstrapClassOrNull(name);}}catch(ClassNotFoundExceptione){// ClassNotFoundException thrown if class not found
// from the non-null parent class loader
}if(c==null){// If still not found, then invoke findClass in order
// to find the class.
c=findClass(name);}}returnc;}//如果没找到的话,就调用子类的findClass
//http://androidxref.com/8.1.0_r33/xref/libcore/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java
BaseDexClassLoader.findClass->pathList.findClass(name,suppressedExceptions)//http://androidxref.com/8.1.0_r33/xref/libcore/dalvik/src/main/java/dalvik/system/DexPathList.java
DexPathList.findClass->element.findClass->dexFile.loadClassBinaryName//http://androidxref.com/8.1.0_r33/xref/libcore/dalvik/src/main/java/dalvik/system/DexFile.java
DexFile.loadClassBinaryName->defineClass->defineClassNative//进入Native层
//http://androidxref.com/8.1.0_r33/xref/art/runtime/native/dalvik_system_DexFile.cc
defineClassNative->class_linker->DefineClass->LoadClass->LoadClassMembers->LoadMethod(constDexFile&dex_file,constClassDataItemIterator&it,Handle<mirror::Class>klass,ArtMethod*dst)//Native层凡出现DexFile的地方均可作为脱壳点
//Java层packagecom.example.luonative;importandroidx.appcompat.app.AppCompatActivity;importandroid.os.Bundle;importandroid.widget.TextView;importcom.example.luonative.databinding.ActivityMainBinding;publicclassMainActivityextendsAppCompatActivity{// Used to load the 'luonative' library on application startup.static{System.loadLibrary("luonative");}privateActivityMainBindingbinding;@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);binding=ActivityMainBinding.inflate(getLayoutInflater());setContentView(binding.getRoot());//方便IDA附加try{Thread.sleep(10*1000);}catch(InterruptedExceptione){e.printStackTrace();}LuoTst();// Example of a call to a native methodTextViewtv=binding.sampleText;tv.setText(stringFromJNI());}publicnativeStringstringFromJNI();publicnativevoidLuoTst();}
//调用栈
do_dlsymdlsym_impl//http://androidxref.com/8.1.0_r33/xref/art/runtime/java_vm_ext.cc
FindSymbol//以下函数返回值均为静态注册的函数地址
FindNativeMethodFindCodeForNativeMethodartFindNativeMethod//http://androidxref.com/8.1.0_r33/xref/art/runtime/entrypoints/jni/jni_entrypoints.cc
extern"C"constvoid*artFindNativeMethod(){Thread*self=Thread::Current();#else
extern"C"constvoid*artFindNativeMethod(Thread*self){DCHECK_EQ(self,Thread::Current());#endif
Locks::mutator_lock_->AssertNotHeld(self);// We come here as Native.
ScopedObjectAccesssoa(self);ArtMethod*method=self->GetCurrentMethod(nullptr);DCHECK(method!=nullptr);// Lookup symbol address for method, on failure we'll return null with an exception set,
// otherwise we return the address of the method we found.
void*native_code=soa.Vm()->FindCodeForNativeMethod(method);if(native_code==nullptr){self->AssertPendingException();returnnullptr;}// Register so that future calls don't come here
returnmethod->RegisterNative(native_code,false);}//从这里可以看到静态注册的函数也是调用了RegisterNative这个函数
functionfind_RegisterNatives(params){varsymbols=Module.enumerateSymbolsSync("libart.so");varaddrRegisterNatives=null;for(vari=0;i<symbols.length;i++){varsymbol=symbols[i];//_ZN3art3JNI15RegisterNativesEP7_JNIEnvP7_jclassPK15JNINativeMethodi
if(symbol.name.indexOf("art")>=0&&symbol.name.indexOf("JNI")>=0&&symbol.name.indexOf("RegisterNatives")>=0&&symbol.name.indexOf("CheckJNI")<0){addrRegisterNatives=symbol.address;console.log("RegisterNatives is at ",symbol.address,symbol.name);hook_RegisterNatives(addrRegisterNatives)}}}functionhook_RegisterNatives(addrRegisterNatives){if(addrRegisterNatives!=null){Interceptor.attach(addrRegisterNatives,{onEnter:function(args){console.log("[RegisterNatives] method_count:",args[3]);varenv=args[0];varjava_class=args[1];varclass_name=Java.vm.tryGetEnv().getClassName(java_class);//console.log(class_name);
varmethods_ptr=ptr(args[2]);varmethod_count=parseInt(args[3]);for(vari=0;i<method_count;i++){varname_ptr=Memory.readPointer(methods_ptr.add(i*Process.pointerSize*3));varsig_ptr=Memory.readPointer(methods_ptr.add(i*Process.pointerSize*3+Process.pointerSize));varfnPtr_ptr=Memory.readPointer(methods_ptr.add(i*Process.pointerSize*3+Process.pointerSize*2));varname=Memory.readCString(name_ptr);varsig=Memory.readCString(sig_ptr);varfind_module=Process.findModuleByAddress(fnPtr_ptr);console.log("[RegisterNatives] java_class:",class_name,"name:",name,"sig:",sig,"fnPtr:",fnPtr_ptr," fnOffset:",ptr(fnPtr_ptr).sub(find_module.base)," callee:",DebugSymbol.fromAddress(this.returnAddress));}}});}}setImmediate(find_RegisterNatives);
//Java层packagecom.example.luonative;importandroidx.appcompat.app.AppCompatActivity;importandroid.os.Bundle;importandroid.widget.TextView;importcom.example.luonative.databinding.ActivityMainBinding;publicclassMainActivityextendsAppCompatActivity{// Used to load the 'luonative' library on application startup.static{System.loadLibrary("luonative");}privateActivityMainBindingbinding;@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);binding=ActivityMainBinding.inflate(getLayoutInflater());setContentView(binding.getRoot());// Example of a call to a native methodTextViewtv=binding.sampleText;tv.setText(stringFromJNI());}publicnativeStringstringFromJNI();}
1
2
3
4
5
6
7
8
9
10
11
//Native层
#include<jni.h>#include<string>extern"C"JNIEXPORTjstringJNICALLJava_com_example_luonative_MainActivity_stringFromJNI(JNIEnv*env,jobjectthiz){std::stringhello="Hello from C++";returnenv->NewStringUTF(hello.c_str());}
functiongetclassload(){varactivityobj=Java.use("android.app.ActivityThread").currentActivityThread();varmInitialApplication=activityobj.mInitialApplication.value;varmLoadedApk=mInitialApplication.mLoadedApk.value;varmClassLoader=mLoadedApk.mClassLoader.value;returnmClassLoader;}functionmain(){Java.perform(function(){varmyshellclass=Java.use("com.sup.android.superb.MyWrapperProxyApplication");myshellclass.onCreate.implementation=function(){varresult=this.onCreate();varloader=getclassload();//切ClassLoader
// Java.classFactory.loader=loader;
varmyclass=Java.use("com.sup.android.superb.SplashActivity");myclass.onCreate.implementation=function(arg){console.log("i am from SplashActivity onCreate");returnthis.onCreate(arg);}console.log(myclass);returnresult;}})}setImmediate(main())
//Java层packagecom.example.luodst;importandroidx.appcompat.app.AppCompatActivity;importandroid.os.Bundle;importandroid.util.Log;importandroid.widget.TextView;importcom.example.luodst.databinding.ActivityMainBinding;importjava.util.Arrays;publicclassMainActivityextendsAppCompatActivity{privatestaticfinalStringTAG="LuoHun";// Used to load the 'luodst' library on application startup.static{System.loadLibrary("luodst");}privateActivityMainBindingbinding;@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);binding=ActivityMainBinding.inflate(getLayoutInflater());setContentView(binding.getRoot());// Example of a call to a native methodTextViewtv=binding.sampleText;tv.setText(stringFromJNI());}publicnativeStringstringFromJNI();publicstaticvoidfunc1(){mystaticstr="myfunc1";Log.e(TAG,"i am from my func1");}publicstaticintfunc2(inta){mystaticstr="myfunc2";Log.e(TAG,"i am from my func2");returna;}publicstaticStringfunc3(Stringa){mystaticstr="func3";Log.e(TAG,a);returna;}publicstaticbyte[]func4(byte[]a){mystaticstr="func4";Log.e(TAG,Arrays.toString(a));returna;}staticStringmystaticstr;}
//Native层
#include<jni.h>#include<string>#include"android/log.h"extern"C"JNIEXPORTjstringJNICALLJava_com_example_luodst_MainActivity_stringFromJNI(JNIEnv*env,jobject/* this */){std::stringhello="Hello from C++";jclassclsMainActivity=env->FindClass("com/example/luodst/MainActivity");jmethodIDmyfun1=env->GetStaticMethodID(clsMainActivity,"func1","()V");env->CallStaticVoidMethod(clsMainActivity,myfun1);jmethodIDmyfun2=env->GetStaticMethodID(clsMainActivity,"func2","(I)I");jintmyfun2re=env->CallStaticIntMethod(clsMainActivity,myfun2,58);__android_log_print(6,"LuoHun","%d",myfun2re);jmethodIDmyfun3=env->GetStaticMethodID(clsMainActivity,"func3","(Ljava/lang/String;)Ljava/lang/String;");jstringmystr=env->NewStringUTF("1231321321");jobjectmyfun3re=env->CallStaticObjectMethod(clsMainActivity,myfun3,mystr);constchar*myreturn=env->GetStringUTFChars(static_cast<jstring>(myfun3re),0);__android_log_print(6,"LuoHun","%s",myreturn);jmethodIDmyfun4=env->GetStaticMethodID(clsMainActivity,"func4","([B)[B");jbytemybytearray[5]={0x11,0x12,0x13,0x14,0x15};jbyteArraymybytearrt=env->NewByteArray(sizeof(mybytearray)/sizeof(jbyte));env->SetByteArrayRegion(mybytearrt,0,sizeof(mybytearray)/sizeof(jbyte),mybytearray);jbyteArraymyfun4ret=static_cast<jbyteArray>(env->CallStaticObjectMethod(clsMainActivity,myfun4,mybytearrt));jbyte*mylog=env->GetByteArrayElements(myfun4ret,0);for(inti=0;i<env->GetArrayLength(myfun4ret);i++)__android_log_print(6,"LuoHun","%x",*(mylog+i));jfieldIDmyfiled=env->GetStaticFieldID(clsMainActivity,"mystaticstr","Ljava/lang/String;");jstringmystaticstr=static_cast<jstring>(env->GetStaticObjectField(clsMainActivity,myfiled));__android_log_print(6,"LuoHun","%s",env->GetStringUTFChars(mystaticstr,0));returnenv->NewStringUTF(hello.c_str());}
//Java层packagecom.example.luonative;importandroidx.appcompat.app.AppCompatActivity;importandroid.os.Bundle;importandroid.widget.TextView;importcom.example.luonative.databinding.ActivityMainBinding;publicclassMainActivityextendsAppCompatActivity{// Used to load the 'luonative' library on application startup.static{System.loadLibrary("luonative");}privateActivityMainBindingbinding;@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);binding=ActivityMainBinding.inflate(getLayoutInflater());setContentView(binding.getRoot());// Example of a call to a native methodTextViewtv=binding.sampleText;tv.setText(stringFromJNI());}/**
* A native method that is implemented by the 'luonative' native library,
* which is packaged with this application.
*/publicnativeStringstringFromJNI();}