记第一次使用ZjDroid dump内存中dex文件

操作步骤
1.设备 xiaomi 8SE 已root , Android 9.0通过解BL锁刷机
2.安装需要用到的工具,Xposed 不支持 Android 9.0,借助Magisk安装EdXposed

2.1下载TWRP app
2.2下载 twrp img (需要根据设备型号来选择,我的是 xiaomi 8 SE xmsirius)
2.3安装twrp app后授权root,选择TWRP flash 选择下载好的img 刷机

3.安装magisk app

选择最新的release包目前是25.2(2022-10-05)
打开magisk 授权root 查看“Ramdisk 是” 必须为是 ,点击安装 ->直接安装
安装完后会在主页提示 卸载magisk

screen.png

4.下载 riru 插件选择版本23

magisk-> 模块 本地安装 选择下载的文件,安装完成后重启手机

5.下载 EdXposedManager apk安装apk.

安装完成后即可创建xposed模块项目

6.下载ZjDroid project

原版没有维护,没有兼容art虚拟机因此无法使用,下载魔改版本

7.编译ZjDroid项目

mac OS Android studio(2021.2.1) 添加ndk-build命令 Preferences->Tools->External Tools -> add
name: ndk-build
program:$ModuleSdkPath$/ndk/21.4.7075529/build/ndk-build
Working directory:$ProjectFileDir$/app/src/main/jni
21.4.7075529为你安装的ndk版本

可能需要在elfinfo.cpp中加入依赖以免报错:

#include 

jni文件夹上点击右键 选择 external tools->ndk-build 编译生成so库,编译完成后引入.

sourceSets {
        main() {
            jniLibs.srcDirs = ['src/main/libs']
            jni.srcDirs = []
        }
    }
// 下面这个配置对于我的环境无效,所以替换为先打so包再引入进来
//    externalNativeBuild {
//        ndkBuild {
//            path 'src/main/jni/Android.mk'
//        }
//    }

编译成功后安装app,可能会遇到其他错误,需要根据实际情况修改.
最后在 EdXposedManager中启用模块并重启设备

8.dump 运行中app的dex文件

8.1先创建一个简单的app作为被dump app,简单起见没有对该应用做加固处理.
8.2打开app后使用adb获取pid

adb shell dumpsys activity top |grep packageName

可以另外起一个终端查看日志

adb shell 
logcat -s zidroid-shell-packageName

8.3根据日志获取的pid获取mCookie信息

am broadcast -a com.zjdroid.invoke --ei target **pid** --es cmd '{action:dump_dexinfo}'  

这里不知道是否因为root的原因,可以看到非常多的系统app的mCookie信息,查看ZjDroid源码

com.android.reverse.collecter.DexFileInfoCollecter

 private static HashMap dynLoadedDexInfo = new HashMap();

 public HashMap dumpDexFileInfo() {
    HashMap dexs = new HashMap(dynLoadedDexInfo);
    ...
}

发现是dynLoadedDexInfo赋值了所有系统app信息,修改:

HashMap dexs = new HashMap();

修改后重新编译安装ZjDroid app,再次执行dump_dexinfo,可以看到只有目标app的mCookie信息列表了.
8.4执行dump dex文件
根据获取的mCookie列表执行dump dex

am broadcast -a com.zjdroid.invoke --ei target **pid** --es cmd '{"action":"dump_dexfile","mCookie":" mCookieValue"}'

这里需要说明必须先进入adb shell 才能发送上面的广播命令,否则无法接收到该广播.
之后会发现报错:

java.io.FileNotFoundException: /data/user/0/com.miui.catcherpatch/xm_code_cache/xm_secondary-sos/libdvmnative.so (Permission denied)

看源码,libdvmnative.so会被拷贝到一个临时文件夹中但是这个文件夹被指向了com.miui.catcherpatch,看日志是因为在目标app开启后·com.miui.catcherpatch这个app触发了

com.android.reverse.mod.ReverseXposedModule
@Override
public void handleLoadPackage(LoadPackageParam lpparam) throws Throwable {
    APPINFO_DATA_DIR = lpparam.appInfo.dataDir;
    ...
}

之后APPINFO_DATA_DIR就指向了com.miui.catcherpatch.
修改移动到当前app的判断逻辑中:

else if (lpparam.isFirstApplication && !ZJDROID_PACKAGENAME.equals(lpparam.packageName)) {
     XMMultiDex.install(ReverseXposedModule.class.getClassLoader(),MODULE_PATH,lpparam.appInfo);
     APPINFO_DATA_DIR = lpparam.appInfo.dataDir;
...
}

这样只有目标app第一次运行的时候APPINFO_DATA_DIR才会赋值.
再次编译执行,这次能够正常打印出将dex文件保存的log了.

the dexfile data save to =/data/user/0/packageName/files/dexdump506910917696.odex

8.5解析dex转为jar包
使用IDA打开odex文件,会发现Magic number是cdex.001,在安卓9中为了减少内存的使用量,引入了cdex,这导致我们dump出来的dex不是一个正常的Dex结构,无法被jadx等反编译。
这里就需要我们将app删除重新安装,第一次安装运行的时候还没有优化为cdex格式(旧版本优化为odex格式),再次dump dex 查看Magic number显示为64 65 78 0A 30 33 37 00 (dex.037).
尝试用d2j-dex2jar转jar包

./d2j-dex2jar.sh dexdump.odex

报错

提示  com.googlecode.d2j.DexException: not support version.

原因是在源码中会判断版本号是否大于53,然后抛出异常.
使用IDA打开文件将Magic number version 改为53
64 65 78 0A 30 33 35 00 (dex.035)
操作路径
1.Edit->Patch program-> change byte
2.Edit->Patch program-> Apply patches to input file
保存文件后再次转jar成功了.

你可能感兴趣的:(记第一次使用ZjDroid dump内存中dex文件)