首页
社区
课程
招聘
[原创]LineageOS20+Pixel6 下的Fart8.0脱壳机迁移和编译流程
发表于: 2023-9-5 23:13 13168

[原创]LineageOS20+Pixel6 下的Fart8.0脱壳机迁移和编译流程

2023-9-5 23:13
13168

​ 之前将Fart8.0的代码编译到Android13下,运行发现在将Java的Method对象转换成C的ArtMethod对象时报错,没找到原因。再加上AOSP的系统太素了,就琢磨是否可以用LineageOS来编译,所以就有了这篇文章。

​ 先罗列一下我的环境吧,编译环境是Kali2022,用的r0ysue大佬的集成版,手机是Pixel6,选择的系统是LineageOS20版(基于AOSP13)的,原本想用基于AOSP10的Lineage17的,但是官网同步源码后发现缺少device blob,遂决定就用20版。

我的虚拟机设置了32G内存,8核CPU,500G的硬盘,实际下载编译完成占用了快300G空间。这里坑的地方在于同样的配置,我的AOSP能顺利编译完成,但在编译LineageOS时中途报错,检查原因发现是因为swap只有1G大小,在设置了swap为20G后,才编译成功。

安装好git和 platform-tools 并配置环境变量

创建源码所需目录(默认在kali root账户下)

安装repo命令行工具

将bin目录添加进环境变量。

​ 使用下面的命令打开~/.bashrc文件,

​ 在文件最后添加下面的代码:

配置git

查看git lfs是否安装

配置缓存,加快编译速度

可将其加入到~/.bashrc文件中,并在命令行执行下行

初始化LineageOS source repository

这里最好不要换成国内源,因为国内源同步出来的代码,我在编译时碰到浏览器app编译失败的问题,重新从官方源同步才解决,查看清华的issue发现有同样的问题,坑死了。

下载源码

上面的-j8是启动8个线程下载,可以不要,默认是4个线程。取决于你的虚拟机cpu内核数。由于网络问题,如果同步完成后报错,可根据提示,将线程数减为1,重新执行该命令即可。

下载设备内核代码

确保你在源码根目录下 ( <font color='red'>cd ~/android/lineage</font> )

下载源码整个过程根据网速会有1段时间,我自己搭建了科学上网的软路由,整个时间有3个小时左右。

下载完kernel源码后会报如下的错误,这是因为还没有下载device blob的缘故,暂时不用管,下载完device blob后再重新执行上面的命令即可

image-20230905183014828

这里是个大坑。我按照官方推荐的方式直接从已经安装了LineageOS的piexl6手机上提取blob,结果有几千个文件没有找到,害的我折腾了2天。总算使用官方镜像提取成功。下面是过程。

创建提取目录

下载官方镜像 LineageOS Downloads

image-20230905185252612

从zip文件中解压出 payload.bin文件

安装 python-protobuf

下载官方提供的导出脚本,然后用python运行脚本,注意脚本目录路径

成功运行后,应该能在system_dump目录下看到如下一些.img文件
image-20230905190110559

然后使用mout命令挂载这些img文件

进入<font color='red'>~/android/lineage/device/google/oriole</font>文件夹 运行如下命令 导出blob文件

重新执行如下命令

编译时间在2小时左右,尤其最后阶段编译kernel会持续50多分钟,这里即使我的内存设置到了32G,也不够用,需要设置swap,而且每次修改源码再编译 都会要重新编译这个kernel,很耗费时间,暂时没找到不重复编译的办法,在XDA上看到可以下载prebuild的内核,避免重复编译,实在懒折腾了,所以没尝试。

编译成功后会在/root/android/lineage/out/target/product/oriole目录下生成boot.img 和 lineage-20.0****.zip文件。按照官方文档替换官方镜像刷机即可。
image-20230905192434053

按照官方文档操作即可。实在懒翻译了

Install LineageOS on oriole | LineageOS Wiki

为了方便修改源码,减少报错,可以将源码中的Java代码导入AndroidStudio,C语言代码导入CLionAS导入Android源码

先成功编译一次,再使用以下方法导入

在ubuntu系统下,进入源码根目录,运行如下命令, 会在源码目录下的out/host/linux-x86/framework目录下生成了idegen.jar文件

在源码根目录下继续执行如下命令,会在根目录下生成android.iml和android.ipr两个文件,这两个文件是AndroidStudio的工程配置文件

安装并打开AndroidStudio,选择Open an existing Android Studio project,找到源码根目录,点击Android.ipr

具体参考:https://wuxiaolong.me/2018/08/15/AOSP3/

我在AOSP中成功导入了AS,但在LineageOS源码中在执行到第3步时长时间卡住,等了30个小时不动,没辙只好放弃。改用VSCode编辑java代码。

C/C++代码导入CLion

CMakeLists.txt会生成在out/development/ide/clion/art/runtime/libart-arm64-android/CMakeLists.txt

用Clion打开CMakeLists.txt

tools--->cmake-->Change Project Root

​ 选择aosp源码根路径,等解析完毕即可

Java代码可按上面导入的步骤,用AS编辑

修改LineageOS源码的/root/android/lineage/frameworks/base/core/java/android/app/ActivityThread.java文件,将Fart8.0对应文件中添加的部分复制到该文件中,并导入对应的包,为了防止加固厂商的检测,修改了函数名和日志输出。

在文件中的performLaunchActivity方法最后添加 wayneThread()方法的调用。

1693921584305

修改源码 /root/android/lineage/libcore/dalvik/src/main/java/dalvik/system/DexFile.java文件,将Fart8.0中添加的方法定义复制过来,并修改方法命名,

SO层的c\c++代码可按上面的步骤导入CLion编辑。

修改该文件最开始的art命名空间

在该文件最末尾添加saveMethodCode函数的函数名命名定义,<font color='red'>注意在上一行末尾添加逗号</font>
image-20230905220022645

编辑 /root/android/lineage/art/runtime/native/java_lang_reflect_Method.cc文件,添加上面用到的jobject2ArtMethod函数

编辑/root/android/lineage/art/runtime/art_method.cc文件,将Fart8.0源码同名文件中添加的代码复制到该代码中,并修改函数名和日志输出内容。

为了防止加固厂商的检测,修改了dex文件保存的目录,由原来的sdcard目录全部改为 "/data/data/%s/wayne/%d_classlist.txt",szProcName,size_int_);"

同时修改了invoke脱壳点的脱壳函数saveArtMethod和Execute脱壳点的脱壳函数saveDexFileByExeMethod中提示错误的部分,如下所列

打开文件添加O_CREATE方式
image-20230905224354735

修改文件是否存在的判断方式
image-20230905224447643

修改类型定义变化的出错
image-20230905224609024

image-20230905224648865

修改saveArtMethod函数中计算codeItem长度的方式
image-20230905224844797

在该文件最开始添加gettidv1()的宏定义

image-20230905224942005

导入需要的.h文件

在Invoke函数中添加对saveArtMethod函数的调用
image-20230905225136707

在该文件最前面的art命名空间添加脱壳函数的引入:

image-20230905225454188

刷机完毕,将待脱壳的apk安装后运行,等待一会,进入/data/data/包名/XXX目录下可看到脱壳下来的dex文件和方法的bin文件,copy到/sdcard目录
再使用adb pull命令拖到虚拟机中修复即可。 测试发现Execute脱壳点没有生效,需要进一步查找原因。

swapoff -a
dd if=/dev/zero of=/var/swapfile bs=1M count=20480
mkswap /var/swapfile
swapon /var/swapfile
free -m  --查看当前分区
swapoff -a
dd if=/dev/zero of=/var/swapfile bs=1M count=20480
mkswap /var/swapfile
swapon /var/swapfile
free -m  --查看当前分区
apt-get update
apt-get install bc bison build-essential ccache curl flex g++-multilib gcc-multilib git git-lfs gnupg gperf imagemagick
lib32ncurses5-dev lib32readline-dev lib32z1-dev libelf-dev liblz4-tool libncurses5 libncurses5-dev
libsdl1.2-dev libssl-dev libxml2 libxml2-utils lzop pngcrush rsync schedtool squashfs-tools xsltproc zip zlib1g-dev m4
apt-get update
apt-get install bc bison build-essential ccache curl flex g++-multilib gcc-multilib git git-lfs gnupg gperf imagemagick
lib32ncurses5-dev lib32readline-dev lib32z1-dev libelf-dev liblz4-tool libncurses5 libncurses5-dev
libsdl1.2-dev libssl-dev libxml2 libxml2-utils lzop pngcrush rsync schedtool squashfs-tools xsltproc zip zlib1g-dev m4
mkdir -p ~/bin
mkdir -p ~/android/lineage
mkdir -p ~/bin
mkdir -p ~/android/lineage
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
chmod a+x ~/bin/repo
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
chmod a+x ~/bin/repo
vim ~/.bashrc
vim ~/.bashrc
# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/bin" ] ; then
    PATH="$HOME/bin:$PATH"
fi
# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/bin" ] ; then
    PATH="$HOME/bin:$PATH"
fi
git config --global user.email "you@example.com"#替换成你的邮件 随便写
git config --global user.name "Your Name"  #替换成你的用户名 随便写
git config --global user.email "you@example.com"#替换成你的邮件 随便写
git config --global user.name "Your Name"  #替换成你的用户名 随便写
curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | sudo bash
apt-get install git-lfs
git lfs install #查看是否安装成功。
curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | sudo bash
apt-get install git-lfs
git lfs install #查看是否安装成功。
export USE_CCACHE=1
export CCACHE_EXEC=/usr/bin/ccache
export USE_CCACHE=1
export CCACHE_EXEC=/usr/bin/ccache
ccache -M 50G
ccache -M 50G
cd ~/android/lineage
repo init -u https://github.com/LineageOS/android.git -b lineage-20.0 --git-lfs
cd ~/android/lineage
repo init -u https://github.com/LineageOS/android.git -b lineage-20.0 --git-lfs
repo sync -j8
repo sync -j8
source build/envsetup.sh
breakfast oriole  #这里也可使用lunch 选择官方提供的机型  如果没有的你要的机型需要到git上搜索相应机型的kernel
source build/envsetup.sh
breakfast oriole  #这里也可使用lunch 选择官方提供的机型  如果没有的你要的机型需要到git上搜索相应机型的kernel
mkdir ~/android/system_dump/
cd ~/android/system_dump/
mkdir ~/android/system_dump/
cd ~/android/system_dump/
unzip /path/to/lineage-*.zip payload.bin
unzip /path/to/lineage-*.zip payload.bin
apt-get install python-protobuf
apt-get install python-protobuf
git clone https://github.com/LineageOS/scripts
python scripts/update-payload-extractor/extract.py payload.bin --output_dir ./
git clone https://github.com/LineageOS/scripts
python scripts/update-payload-extractor/extract.py payload.bin --output_dir ./
mkdir system/
sudo mount -o ro system.img system/
sudo mount -o ro vendor.img system/vendor/
sudo mount -o ro product.img system/product/
sudo mount -o ro system_ext.img system/system_ext/
mkdir system/
sudo mount -o ro system.img system/
sudo mount -o ro vendor.img system/vendor/
sudo mount -o ro product.img system/product/
sudo mount -o ro system_ext.img system/system_ext/
cd ~/android/lineage/device/google/oriole
./extract-files.sh ~/android/system_dump/
cd ~/android/lineage/device/google/oriole
./extract-files.sh ~/android/system_dump/
source build/envsetup.sh
breakfast oriole
source build/envsetup.sh
breakfast oriole
croot
brunch oriole
croot
brunch oriole
source build/envsetup.sh
 
mmm development/tools/idegen/
source build/envsetup.sh
 
mmm development/tools/idegen/
development/tools/idegen/idegen.sh
development/tools/idegen/idegen.sh
source build/envsetup.sh
#打开开关,编译时生成CMakeLists.txt
export SOONG_GEN_CMAKEFILES=1
export SOONG_GEN_CMAKEFILES_DEBUG=1
breakfast oriole
source build/envsetup.sh
#打开开关,编译时生成CMakeLists.txt
export SOONG_GEN_CMAKEFILES=1
export SOONG_GEN_CMAKEFILES_DEBUG=1
breakfast oriole
//add
 public static Field getClassField(ClassLoader classloader, String class_name,
                                     String filedName) {
 
       try {
           Class obj_class = classloader.loadClass(class_name);//Class.forName(class_name);
           Field field = obj_class.getDeclaredField(filedName);
           field.setAccessible(true);
           return field;
       } catch (SecurityException e) {
           e.printStackTrace();
       } catch (NoSuchFieldException e) {
           e.printStackTrace();
       } catch (IllegalArgumentException e) {
           e.printStackTrace();
       } catch (ClassNotFoundException e) {
           e.printStackTrace();
       }
       return null;
 
   }
 
   public static Object getClassFieldObject(ClassLoader classloader, String class_name, Object obj,
                                            String filedName) {
 
       try {
           Class obj_class = classloader.loadClass(class_name);//Class.forName(class_name);
           Field field = obj_class.getDeclaredField(filedName);
           field.setAccessible(true);
           Object result = null;
           result = field.get(obj);
           return result;
       } catch (SecurityException e) {
           e.printStackTrace();
       } catch (NoSuchFieldException e) {
           e.printStackTrace();
       } catch (IllegalArgumentException e) {
           e.printStackTrace();
       } catch (ClassNotFoundException e) {
           e.printStackTrace();
       } catch (IllegalAccessException e) {
           e.printStackTrace();
       }
       return null;
 
   }
 
   public static Object invokeStaticMethod(String class_name,
                                           String method_name, Class[] pareTyple, Object[] pareVaules) {
 
       try {
           Class obj_class = Class.forName(class_name);
           Method method = obj_class.getMethod(method_name, pareTyple);
           return method.invoke(null, pareVaules);
       } catch (SecurityException e) {
           e.printStackTrace();
       } catch (IllegalArgumentException e) {
           e.printStackTrace();
       } catch (IllegalAccessException e) {
           e.printStackTrace();
       } catch (NoSuchMethodException e) {
           e.printStackTrace();
       } catch (InvocationTargetException e) {
           e.printStackTrace();
       } catch (ClassNotFoundException e) {
           e.printStackTrace();
       }
       return null;
 
   }
 
   public static Object getFieldOjbect(String class_name, Object obj,
                                       String filedName) {
       try {
           Class obj_class = Class.forName(class_name);
           Field field = obj_class.getDeclaredField(filedName);
           field.setAccessible(true);
           return field.get(obj);
       } catch (SecurityException e) {
           e.printStackTrace();
       } catch (NoSuchFieldException e) {
           e.printStackTrace();
       } catch (IllegalArgumentException e) {
           e.printStackTrace();
       } catch (IllegalAccessException e) {
           e.printStackTrace();
       } catch (ClassNotFoundException e) {
           e.printStackTrace();
       } catch (NullPointerException e) {
           e.printStackTrace();
       }
       return null;
 
   }
 
   public static ClassLoader getClassloader() {
       ClassLoader resultClassloader = null;
       Object currentActivityThread = invokeStaticMethod(
               "android.app.ActivityThread", "currentActivityThread",
               new Class[]{}, new Object[]{});
       Object mBoundApplication = getFieldOjbect(
               "android.app.ActivityThread", currentActivityThread,
               "mBoundApplication");
       Application mInitialApplication = (Application) getFieldOjbect("android.app.ActivityThread",
               currentActivityThread, "mInitialApplication");
       Object loadedApkInfo = getFieldOjbect(
               "android.app.ActivityThread$AppBindData",
               mBoundApplication, "info");
       Application mApplication = (Application) getFieldOjbect("android.app.LoadedApk", loadedApkInfo, "mApplication");
       resultClassloader = mApplication.getClassLoader();
       return resultClassloader;
   }
   public static void loadClassAndCall(ClassLoader appClassloader, String eachclassname, Method saveMethodCode) {
       Class resultclass = null;
       Log.i("wayne", "go into loadClassAndCall->" + "classname:" + eachclassname);
       try {
           resultclass = appClassloader.loadClass(eachclassname);
       } catch (Exception e) {
           e.printStackTrace();
           return;
       } catch (Error e) {
           e.printStackTrace();
           return;
       }
       if (resultclass != null) {
           try {
               Constructor<?> cons[] = resultclass.getDeclaredConstructors();
               for (Constructor<?> constructor : cons) {
                   if (saveMethodCode != null) {
                       try {
                           saveMethodCode.invoke(null, constructor);
                       } catch (Exception e) {
                           e.printStackTrace();
                           continue;
                       } catch (Error e) {
                           e.printStackTrace();
                           continue;
                       }
                   } else {
                       Log.e("wayne", "saveMethodCode is null ");
                   }
 
               }
           } catch (Exception e) {
               e.printStackTrace();
           } catch (Error e) {
               e.printStackTrace();
           }
           try {
               Method[] methods = resultclass.getDeclaredMethods();
               if (methods != null) {
                   for (Method m : methods) {
                       if (saveMethodCode != null) {
                           try {
                               saveMethodCode.invoke(null, m);
                            } catch (Exception e) {
                               e.printStackTrace();
                               continue;
                           } catch (Error e) {
                               e.printStackTrace();
                               continue;
                           }
                       } else {
                           Log.e("wayne", "saveMethodCode is null ");
                       }
                   }
               }
           } catch (Exception e) {
               e.printStackTrace();
           } catch (Error e) {
               e.printStackTrace();
           }
       }
   }
   public static void wayne() {
       ClassLoader appClassloader = getClassloader();
       ClassLoader tmpClassloader=appClassloader;
       ClassLoader parentClassloader=appClassloader.getParent();
       if(appClassloader.toString().indexOf("java.lang.BootClassLoader")==-1)
       {
           wayneDoWithClassloader(appClassloader);
       }
       while(parentClassloader!=null){
           if(parentClassloader.toString().indexOf("java.lang.BootClassLoader")==-1)
           {
               wayneDoWithClassloader(parentClassloader);
           }
           tmpClassloader=parentClassloader;
           parentClassloader=parentClassloader.getParent();
       }
   }
   public static void wayneDoWithClassloader(ClassLoader appClassloader) {
       List<Object> dexFilesArray = new ArrayList<Object>();
       Field pathList_Field = (Field) getClassField(appClassloader, "dalvik.system.BaseDexClassLoader", "pathList");
       Object pathList_object = getFieldOjbect("dalvik.system.BaseDexClassLoader", appClassloader, "pathList");
       Object[] ElementsArray = (Object[]) getFieldOjbect("dalvik.system.DexPathList", pathList_object, "dexElements");
       Field dexFile_fileField = null;
       try {
           dexFile_fileField = (Field) getClassField(appClassloader, "dalvik.system.DexPathList$Element", "dexFile");
       } catch (Exception e) {
               e.printStackTrace();
           } catch (Error e) {
               e.printStackTrace();
           }
       Class DexFileClazz = null;
       try {
           DexFileClazz = appClassloader.loadClass("dalvik.system.DexFile");
       } catch (Exception e) {
               e.printStackTrace();
           } catch (Error e) {
               e.printStackTrace();
           }
       Method _getClassNameList = null;
       Method _saveMethodCode = null;
 
       for (Method field : DexFileClazz.getDeclaredMethods()) {
           if (field.getName().equals("getClassNameList")) {
               _getClassNameList = field;
               _getClassNameList.setAccessible(true);
           }
           if (field.getName().equals("saveMethodCode")) {
               _saveMethodCode = field;
               _saveMethodCode.setAccessible(true);
           }
       }
       Field mCookiefield = getClassField(appClassloader, "dalvik.system.DexFile", "mCookie");
       Log.e("wayne->methods", "dalvik.system.DexPathList.ElementsArray.length:" + ElementsArray.length);//5个
       for (int j = 0; j < ElementsArray.length; j++) {
           Object element = ElementsArray[j];
           Object dexfile = null;
           try {
               dexfile = (Object) dexFile_fileField.get(element);
           } catch (Exception e) {
               e.printStackTrace();
           } catch (Error e) {
               e.printStackTrace();
           }
           if (dexfile == null) {
               Log.e("ActivityThread", "dexfile is null");
               continue;
           }
           if (dexfile != null) {
               dexFilesArray.add(dexfile);
               Object mcookie = getClassFieldObject(appClassloader, "dalvik.system.DexFile", dexfile, "mCookie");
               if (mcookie == null) {
                   Object mInternalCookie = getClassFieldObject(appClassloader, "dalvik.system.DexFile", dexfile, "mInternalCookie");
                   if(mInternalCookie!=null)
                   {
                       mcookie=mInternalCookie;
                   }else{
                           Log.e("wayne->err", "get mInternalCookie is null");
                           continue;
                           }
                    
               }
               String[] classnames = null;
               try {
                   classnames = (String[]) _getClassNameList.invoke(dexfile, mcookie);
               } catch (Exception e) {
                   e.printStackTrace();
                   continue;
               } catch (Error e) {
                   e.printStackTrace();
                   continue;
               }
               if (classnames != null) {
                   for (String eachclassname : classnames) {
                       loadClassAndCall(appClassloader, eachclassname, _saveMethodCode);
                   }
               }
 
           }
       }
       return;
   }
   
   public static void wayneThread() {
       new Thread(new Runnable() {
 
           @Override
           public void run() {
               // TODO Auto-generated method stub
               try {
                   Log.e("wayne", "start sleep......");
                   Thread.sleep(1 * 60 * 1000);
               } catch (InterruptedException e) {
                   // TODO Auto-generated catch block
                   e.printStackTrace();
               }
               Log.e("wayne", "sleep over and start myshell");
               wayne();
               Log.e("wayne", "myshell run over");
 
           }
       }).start();
   }
 //add
//add
 public static Field getClassField(ClassLoader classloader, String class_name,
                                     String filedName) {
 
       try {
           Class obj_class = classloader.loadClass(class_name);//Class.forName(class_name);
           Field field = obj_class.getDeclaredField(filedName);
           field.setAccessible(true);
           return field;
       } catch (SecurityException e) {
           e.printStackTrace();
       } catch (NoSuchFieldException e) {
           e.printStackTrace();
       } catch (IllegalArgumentException e) {
           e.printStackTrace();
       } catch (ClassNotFoundException e) {
           e.printStackTrace();
       }
       return null;
 
   }
 
   public static Object getClassFieldObject(ClassLoader classloader, String class_name, Object obj,
                                            String filedName) {
 
       try {
           Class obj_class = classloader.loadClass(class_name);//Class.forName(class_name);
           Field field = obj_class.getDeclaredField(filedName);
           field.setAccessible(true);
           Object result = null;
           result = field.get(obj);
           return result;
       } catch (SecurityException e) {
           e.printStackTrace();
       } catch (NoSuchFieldException e) {
           e.printStackTrace();
       } catch (IllegalArgumentException e) {
           e.printStackTrace();
       } catch (ClassNotFoundException e) {
           e.printStackTrace();
       } catch (IllegalAccessException e) {
           e.printStackTrace();
       }
       return null;
 
   }
 
   public static Object invokeStaticMethod(String class_name,
                                           String method_name, Class[] pareTyple, Object[] pareVaules) {
 
       try {
           Class obj_class = Class.forName(class_name);
           Method method = obj_class.getMethod(method_name, pareTyple);
           return method.invoke(null, pareVaules);
       } catch (SecurityException e) {
           e.printStackTrace();
       } catch (IllegalArgumentException e) {
           e.printStackTrace();
       } catch (IllegalAccessException e) {
           e.printStackTrace();
       } catch (NoSuchMethodException e) {
           e.printStackTrace();
       } catch (InvocationTargetException e) {
           e.printStackTrace();
       } catch (ClassNotFoundException e) {
           e.printStackTrace();
       }
       return null;
 
   }
 
   public static Object getFieldOjbect(String class_name, Object obj,
                                       String filedName) {
       try {
           Class obj_class = Class.forName(class_name);
           Field field = obj_class.getDeclaredField(filedName);
           field.setAccessible(true);
           return field.get(obj);
       } catch (SecurityException e) {
           e.printStackTrace();
       } catch (NoSuchFieldException e) {
           e.printStackTrace();
       } catch (IllegalArgumentException e) {
           e.printStackTrace();
       } catch (IllegalAccessException e) {
           e.printStackTrace();
       } catch (ClassNotFoundException e) {
           e.printStackTrace();
       } catch (NullPointerException e) {
           e.printStackTrace();
       }
       return null;
 
   }
 
   public static ClassLoader getClassloader() {
       ClassLoader resultClassloader = null;
       Object currentActivityThread = invokeStaticMethod(
               "android.app.ActivityThread", "currentActivityThread",
               new Class[]{}, new Object[]{});
       Object mBoundApplication = getFieldOjbect(
               "android.app.ActivityThread", currentActivityThread,
               "mBoundApplication");
       Application mInitialApplication = (Application) getFieldOjbect("android.app.ActivityThread",
               currentActivityThread, "mInitialApplication");
       Object loadedApkInfo = getFieldOjbect(
               "android.app.ActivityThread$AppBindData",
               mBoundApplication, "info");
       Application mApplication = (Application) getFieldOjbect("android.app.LoadedApk", loadedApkInfo, "mApplication");
       resultClassloader = mApplication.getClassLoader();
       return resultClassloader;
   }
   public static void loadClassAndCall(ClassLoader appClassloader, String eachclassname, Method saveMethodCode) {
       Class resultclass = null;
       Log.i("wayne", "go into loadClassAndCall->" + "classname:" + eachclassname);
       try {
           resultclass = appClassloader.loadClass(eachclassname);
       } catch (Exception e) {
           e.printStackTrace();
           return;
       } catch (Error e) {
           e.printStackTrace();
           return;
       }
       if (resultclass != null) {
           try {
               Constructor<?> cons[] = resultclass.getDeclaredConstructors();
               for (Constructor<?> constructor : cons) {
                   if (saveMethodCode != null) {
                       try {
                           saveMethodCode.invoke(null, constructor);
                       } catch (Exception e) {
                           e.printStackTrace();
                           continue;
                       } catch (Error e) {
                           e.printStackTrace();
                           continue;
                       }
                   } else {
                       Log.e("wayne", "saveMethodCode is null ");
                   }
 
               }
           } catch (Exception e) {
               e.printStackTrace();
           } catch (Error e) {
               e.printStackTrace();
           }
           try {
               Method[] methods = resultclass.getDeclaredMethods();
               if (methods != null) {
                   for (Method m : methods) {
                       if (saveMethodCode != null) {
                           try {
                               saveMethodCode.invoke(null, m);
                            } catch (Exception e) {
                               e.printStackTrace();
                               continue;
                           } catch (Error e) {
                               e.printStackTrace();
                               continue;
                           }
                       } else {
                           Log.e("wayne", "saveMethodCode is null ");
                       }
                   }
               }
           } catch (Exception e) {
               e.printStackTrace();
           } catch (Error e) {
               e.printStackTrace();
           }
       }
   }
   public static void wayne() {
       ClassLoader appClassloader = getClassloader();
       ClassLoader tmpClassloader=appClassloader;
       ClassLoader parentClassloader=appClassloader.getParent();
       if(appClassloader.toString().indexOf("java.lang.BootClassLoader")==-1)
       {
           wayneDoWithClassloader(appClassloader);
       }
       while(parentClassloader!=null){
           if(parentClassloader.toString().indexOf("java.lang.BootClassLoader")==-1)
           {
               wayneDoWithClassloader(parentClassloader);
           }
           tmpClassloader=parentClassloader;
           parentClassloader=parentClassloader.getParent();
       }
   }
   public static void wayneDoWithClassloader(ClassLoader appClassloader) {
       List<Object> dexFilesArray = new ArrayList<Object>();
       Field pathList_Field = (Field) getClassField(appClassloader, "dalvik.system.BaseDexClassLoader", "pathList");
       Object pathList_object = getFieldOjbect("dalvik.system.BaseDexClassLoader", appClassloader, "pathList");
       Object[] ElementsArray = (Object[]) getFieldOjbect("dalvik.system.DexPathList", pathList_object, "dexElements");
       Field dexFile_fileField = null;
       try {
           dexFile_fileField = (Field) getClassField(appClassloader, "dalvik.system.DexPathList$Element", "dexFile");
       } catch (Exception e) {
               e.printStackTrace();
           } catch (Error e) {
               e.printStackTrace();
           }
       Class DexFileClazz = null;
       try {
           DexFileClazz = appClassloader.loadClass("dalvik.system.DexFile");
       } catch (Exception e) {
               e.printStackTrace();
           } catch (Error e) {
               e.printStackTrace();
           }
       Method _getClassNameList = null;
       Method _saveMethodCode = null;
 
       for (Method field : DexFileClazz.getDeclaredMethods()) {
           if (field.getName().equals("getClassNameList")) {
               _getClassNameList = field;
               _getClassNameList.setAccessible(true);
           }
           if (field.getName().equals("saveMethodCode")) {
               _saveMethodCode = field;
               _saveMethodCode.setAccessible(true);
           }
       }
       Field mCookiefield = getClassField(appClassloader, "dalvik.system.DexFile", "mCookie");
       Log.e("wayne->methods", "dalvik.system.DexPathList.ElementsArray.length:" + ElementsArray.length);//5个
       for (int j = 0; j < ElementsArray.length; j++) {
           Object element = ElementsArray[j];
           Object dexfile = null;
           try {
               dexfile = (Object) dexFile_fileField.get(element);
           } catch (Exception e) {
               e.printStackTrace();
           } catch (Error e) {
               e.printStackTrace();
           }
           if (dexfile == null) {
               Log.e("ActivityThread", "dexfile is null");
               continue;
           }
           if (dexfile != null) {
               dexFilesArray.add(dexfile);
               Object mcookie = getClassFieldObject(appClassloader, "dalvik.system.DexFile", dexfile, "mCookie");
               if (mcookie == null) {
                   Object mInternalCookie = getClassFieldObject(appClassloader, "dalvik.system.DexFile", dexfile, "mInternalCookie");
                   if(mInternalCookie!=null)
                   {
                       mcookie=mInternalCookie;
                   }else{
                           Log.e("wayne->err", "get mInternalCookie is null");
                           continue;
                           }
                    
               }
               String[] classnames = null;
               try {
                   classnames = (String[]) _getClassNameList.invoke(dexfile, mcookie);
               } catch (Exception e) {
                   e.printStackTrace();
                   continue;
               } catch (Error e) {
                   e.printStackTrace();
                   continue;
               }
               if (classnames != null) {
                   for (String eachclassname : classnames) {
                       loadClassAndCall(appClassloader, eachclassname, _saveMethodCode);
                   }
               }
 
           }
       }
       return;
   }
   
   public static void wayneThread() {
       new Thread(new Runnable() {
 
           @Override
           public void run() {
               // TODO Auto-generated method stub
               try {
                   Log.e("wayne", "start sleep......");
                   Thread.sleep(1 * 60 * 1000);
               } catch (InterruptedException e) {
                   // TODO Auto-generated catch block
                   e.printStackTrace();

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 8
支持
分享
最新回复 (8)
雪    币: 921
活跃值: (1712)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
排查出原因了吗? 为啥没有走Execute
2023-9-8 09:41
1
雪    币: 5782
活跃值: (3854)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
300G!几何倍数增长啊。
2023-9-8 09:55
0
雪    币: 3429
活跃值: (1566)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
求分享r0ysue大佬的集成版Kali2022
2023-9-13 08:52
1
雪    币: 3004
活跃值: (30866)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
感谢分享
2023-9-13 09:19
1
雪    币: 819
活跃值: (1650)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
Elice 求分享r0ysue大佬的集成版Kali2022
同求
2023-9-14 09:01
0
雪    币: 1681
活跃值: (1667)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
为什么最后编译成功了进去一直有factory data reset 可以请教一下这是什么原因引起的,,我是lineageos17.1 手机oneplus5
2023-9-16 20:23
0
雪    币: 1681
活跃值: (1667)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
execute问题是不是因为目录只能逐级建立
2023-9-16 20:26
0
雪    币: 1681
活跃值: (1667)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
wpfpzw 为什么最后编译成功了进去一直有factory data reset 可以请教一下这是什么原因引起的,,我是lineageos17.1 手机oneplus5
已解决
2023-9-17 15:33
0
游客
登录 | 注册 方可回帖
返回
//