从0开始实现一个简易的主动调用框架
本文为看雪论坛优秀文章
看雪论坛作者ID:r0ysue
总述
加载方案
https://bbs.pediy.com/thread-252630.htm
private void handleBindApplication(AppBindData data) { //step 1: 创建LoadedApk对象 data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo); ... //step 2: 创建ContextImpl对象; final ContextImpl appContext = ContextImpl.createAppContext(this, data.info); //step 3: 创建Instrumentation mInstrumentation = new Instrumentation(); //step 4: 创建Application对象;在makeApplication函数中调用了newApplication,在该函数中又调用了app.attach(context),在attach函数中调用了Application.attachBaseContext函数 Application app = data.info.makeApplication(data.restrictedBackupMode, null); mInitialApplication = app; //step 5: 安装providers List<ProviderInfo> providers = data.providers; installContentProviders(app, providers); //step 6: 执行Application.Create回调 mInstrumentation.callApplicationOnCreate(app);} public static void mycopy(String srcFileName, String trcFileName) { InputStream in = null; OutputStream out = null; try { // in = File.open(srcFileName); in = new FileInputStream(srcFileName); out = new FileOutputStream(trcFileName); byte[] bytes = new byte[1024]; int i; while ((i = in.read(bytes)) != -1) out.write(bytes, 0, i); } catch (IOException e) { e.printStackTrace(); } finally { try { if (in != null) in.close(); if (out != null){ out.flush(); out.close(); } } catch (IOException e) { e.printStackTrace(); } } }private void handleBindApplication(AppBindData data) {...... final ContextImpl appContext = ContextImpl.createAppContext(this, data.info); ContextImpl context = appContext; ActivityManager mAm = (ActivityManager) context.getSystemService("activity"); String activity_packageName = mAm.getRunningTasks(1).get(0).topActivity.getPackageName();//获得私有目录 if (activity_packageName.indexOf("com.android") < 0) {//不包括系统目录 String tagPath = "/data/data/" + activity_packageName + "/r0.so";//64位so的目录 String tagPath2 = "/data/data/" + activity_packageName + "/r032.so";//32位的so目录 File file1 = new File(tagPath); File file2 = new File(tagPath2); mycopy("/sdcard/r0.so", tagPath);//复制so到私有目录 mycopy("/sdcard/r032.so", tagPath2); int perm = FileUtils.S_IRWXU | FileUtils.S_IRWXG | FileUtils.S_IRWXO; FileUtils.setPermissions(tagPath, perm, -1, -1);//将权限改为777 FileUtils.setPermissions(tagPath2, perm, -1, -1);// com.android.systemui if (file1.exists()) { Log.e("r0ysue", System.getProperty("os.arch"));//判断是64位还是32位 if (System.getProperty("os.arch").indexOf("64") >= 0) { System.load(tagPath); file1.delete();//用完就删否则不会更新 } else { System.load(tagPath2); file2.delete(); } }}......}java函数调用方案
const char * getprocessname(JNIEnv* env){ jclass ActivityThread=env->FindClass("android/app/ActivityThread"); jmethodID currentProcessName=env->GetStaticMethodID(ActivityThread,"currentProcessName","()Ljava/lang/String;"); jstring name= static_cast<jstring>(env->CallStaticObjectMethod(ActivityThread,currentProcessName)); const char * name1=env->GetStringUTFChars(name,0); return name1; }JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *unused) { JNIEnv* env= nullptr; vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_4); const char* myname= getprocessname(env); __android_log_print(6,"r0ysue","i am from %s",myname); return JNI_VERSION_1_4;}unzip app-debug.apkcd lib/arm64-v8a/adb push libnative-lib.so /sdcard/r0.so调用Native函数
https://bbs.pediy.com/thread-269757.htm
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *unused) { mainfun("_ZN3art9ArtMethod14RegisterNativeEPKvb", "libart.so", reinterpret_cast<void *>(regist)); return JNI_VERSION_1_4; }void regist(void* a,void* b,int c){ const char* ds=getartmethod((unsigned int *)a);if(strstr(ds,"xxxxxx")){//过滤函数名 st=b; long* d= reinterpret_cast<long *>(myreplace);//替换的注册函数 __android_log_print(6,"r0ysue","%p",d); __asm__("str %[input_n], [X18,#0x28]\r\n"//修改registernative的第二个参数,我这里用x18传的调用栈 :[result_m] "=r" (d) :[input_n] "r" (d) ); __android_log_print(6,"r0ysue","register %s",ds);} } void* myreplace(void* a,void* b,int c,void* d){JNIEnv* env= static_cast<JNIEnv *>(a);jobject aa= static_cast<jobject>((docomm(st))(a, b, reinterpret_cast<void *>(c), d));//直接调用原函数if(aa!= nullptr) {//由于返回值是一个jstring判断一下 env->SetObjectArrayElement(static_cast<jobjectArray>(d), 2, env->NewStringUTF("4")); jobject opp= static_cast<jobject>((docomm(st))(a, b, reinterpret_cast<void *>(c), d));//调用将第2个字符串改为4之后的字符串 __android_log_print(6,"r0ysue"," 111111111111 %s",env->GetStringUTFChars( static_cast<jstring>(opp),0));//这个jobject数组是一个长度为5的字符串数组,就是说有5个字符串我随便改一个就好 const char *ss = getclassname(env,myclass); if(strstr(ss,"String")) {//由于返回值是一个jstring判断一下再打印printobjearry(env,(jobjectArray)d);//打印jobject数组 __android_log_print(6, "r0ysue", " ssssssss int:%x %s", c,env->GetStringUTFChars( static_cast<jstring>(aa), 0)); } } return aa;} void printobjearry (JNIEnv* env,jobjectArray a){//打印jobjet数组 int size=env->GetArrayLength(static_cast<jarray>(a)); for(int n=0;n<size;n++) { jobject ax=env->GetObjectArrayElement(static_cast<jobjectArray>(a), n); if(ax!=0) __android_log_print(6, "r0ysue", " ssssssss %d: %s",n, getclassname(env, ax)); }} const char * getartmethod(unsigned int *a1){//ArtMethod中的getName函数直接从ida复制过来的 __int64 v12; // x20 __int64 v13; // x0 _QWORD *v14; // x8 __int64 v15; // x9 char *v16; // x8 const char *result; // x0 unsigned int **v18; // x8 unsigned int *v19; // x9 unsigned int *v20; // x9 int v21; // w10 const char *v22; // x9 const char *v23; // x8 unsigned int **v24; // x20 __int64 v25; // x0 __int64 v26; // x0 unsigned int **v27; // x20 __int64 v28; // x0 __int64 v29; // x0 unsigned int *v30; // [xsp+48h] [xbp+18h] unsigned int *v31; // [xsp+48h] [xbp+18h] v12 = a1[3]; if ( (a1[1] & 0x40000) != 0 ) { // _ZN3art9ArtMethod19GetObsoleteDexCacheEvreturn "cxzcxzcxz"; } else v13 = *(unsigned int *)(*a1 + 0x10LL); v14 = *(_QWORD **)(v13 + 16); v15 = *(unsigned int *)(v14[12] + 8 * v12 + 4); if ( (_DWORD)v15 == -1 ) return 0LL; v16 = (char *)(v14[1] + *(unsigned int *)(v14[9] + 4 * v15)); result = v16 + 1; if ( (*v16 & 0x80000000) != 0 ) { if ( (v16[1] & 0x80000000) != 0 ) { if ( (v16[2] & 0x80000000) != 0 ) { v21 = v16[3]; v22 = v16 + 4; v23 = v16 + 5; if ( v21 >= 0 ) result = v22; else result = v23; } else { result = v16 + 3; } } else { result = v16 + 2; } } return result;}总结
参考资料
https://bbs.pediy.com/thread-266767.htm
https://bbs.pediy.com/thread-252630.htm
看雪ID:r0ysue
https://bbs.pediy.com/user-home-799845.htm
# 往期推荐
2.Android APP漏洞之战——权限安全和安全配置漏洞详解
4.Android APP漏洞之战——Activity漏洞挖掘详解
球分享
球点赞
球在看
点击“阅读原文”,了解更多!