首页
社区
课程
招聘
[原创]我为Xpatch加把米
发表于: 2019-12-6 12:37 9207

[原创]我为Xpatch加把米

2019-12-6 12:37
9207

    源码

           Github:  https://github.com/skyun1314/haha


         前几天突然看到一个牛逼的工具Xpatch。由于Android 9.0以上手机不好root,不能装xposed 。虽然有一个太极可以免root加载xposed模块,但是里面的模块是有限制的,必须的上传到太极官网,审核通过才能使用 xposed模块。所以 平时 调试app在高版本手机上 兼容性的时候很麻烦。虽然可以重打包测试。但是遇到几百兆的app的时候就特别无力了。Xpatch确实是一个不错的选择,但是他不是app,为了使用方便我把它改成了app,并针对手机特性 结合Xposed代码做了一些优化。



         效果图:


   优化点:

       1、需要加载Xposed模块的app可以选择开启那些模块,而不需要自身开启读取sd卡权限,因为咱们使用了 ContentProvider!

       2、为了加快速度不反编译smali代码,使用dexlib2库查找manifest中定义的 application 最终父类 所在的dex。 并查看当前application中有没有静态代码块,

          同时使用 baksmali d 参数 只反编译一个smali文件从而插入入口代码。最后使用 DexMerger 库 合并dex。速度大大提升

       3、使用AXmlConverter 库修改manifest 二进制文件


  关键代码



使用ContentProvider 保存模块开启状态

public synchronized void updateModulesList(Context showToast) {
        try {

            String[] strings = {MODULES_LIST_FILE, ENABLED_MODULES_LIST_FILE};

            for (int i = 0; i < strings.length; i++) {
                File file = new File(strings[i]);
                if (!file.getParentFile().exists()) {
                    file.getParentFile().mkdirs();
                }
            }

            Cursor query = showToast.getContentResolver().query(StudentsProvider.CONTENT_URIstudents, null, null, null, null);


            if (query != null && query.getCount() > 0) {
                showToast.getContentResolver().delete(StudentsProvider.CONTENT_URIstudents, "_id>0", null);
            }


            PrintWriter modulesList = new PrintWriter(MODULES_LIST_FILE);
            PrintWriter enabledModulesList = new PrintWriter(ENABLED_MODULES_LIST_FILE);

            List<InstalledModule> enabledModules = getEnabledModules();
            for (InstalledModule module : enabledModules) {


                modulesList.println(module.app.sourceDir);
                try {
                    String installer = mPm.getInstallerPackageName(module.app.packageName);
                    if (!PLAY_STORE_PACKAGE.equals(installer)) {
                        enabledModulesList.println(module.app.packageName);


                        ContentValues values = new ContentValues();

                        values.put(StudentsProvider.NAME,
                                module.app.packageName);

                        values.put(StudentsProvider.GRADE,
                                module.app.sourceDir);


                        Uri uri = showToast.getContentResolver().insert(
                                StudentsProvider.CONTENT_URIstudents, values);


                    }
                } catch (IllegalArgumentException ignored) {
                    // In rare cases, the package might not be installed anymore at this point,
                    // so the PackageManager can't return its installer package name.
                }
            }
            modulesList.close();
            enabledModulesList.close();

            FileUtils.setPermissions(MODULES_LIST_FILE, 00664, -1, -1);
            FileUtils.setPermissions(ENABLED_MODULES_LIST_FILE, 00664, -1, -1);


        } catch (IOException e) {
            hahahaha.Log.e(e.toString());
        }
    }

 使用dexlib2 解析 class和method

 public static List<String> getClass(String input) {
        List<String>strings=new ArrayList<>();
        try {

            File file = new File(input);

            MultiDexContainer<? extends DexBackedDexFile> container = DexFileFactory.loadDexContainer(file, null);


            MultiDexContainer.DexEntry<? extends DexBackedDexFile> dexEntry = container.getEntry(container.getDexEntryNames().get(0));
            assert dexEntry != null;
            DexBackedDexFile dexFile = dexEntry.getDexFile();

            for (ClassDef classDef : dexFile.getClasses()) {
                strings.add(classDef.getType());
              //  System.out.println(classDef.getType());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return strings;

    }



    public static List<String> getMethods(String input) {
        List<String>strings=new ArrayList<>();
        try {

            File file = new File(input);

            MultiDexContainer<? extends DexBackedDexFile> container = DexFileFactory.loadDexContainer(file, null);


            MultiDexContainer.DexEntry<? extends DexBackedDexFile> dexEntry = container.getEntry(container.getDexEntryNames().get(0));
            assert dexEntry != null;
            DexBackedDexFile dexFile = dexEntry.getDexFile();


            for (Reference reference: dexFile.getReferences( ReferenceType.METHOD)) {
            //    System.out.println(ReferenceUtil.getReferenceString(reference));

                strings.add(ReferenceUtil.getReferenceString(reference));
            }


        } catch (Exception e) {
            e.printStackTrace();
        }
        return strings;

    }

  使用axml  修改 manifest

  // 修改app名称
                    @Override
                    public NodeVisitor visitChild(String ns, String name) {// manifest 下面的说有大标签

                        if ("application".equals(name)) {


                            return new NodeVisitor(super.visitChild(ns, name)) {


                                @Override
                                public void visitEnd() {
                                    NodeVisitor meta = super.visitChild("http://schemas.android.com/apk/res/android", "meta-data");
                                    meta.visitContentAttr("http://schemas.android.com/apk/res/android", "name", 16842755, 3, meta_data_key);
                                    meta.visitContentAttr("http://schemas.android.com/apk/res/android", "value", 16842788, 3, meta_data_value);
                                    if (!has_Application) {
                                        super.visitContentAttr("http://schemas.android.com/apk/res/android", "name", 16842755, 3, Application_name);
                                    }
                                    super.visitEnd();
                                }


                                @Override
                                public void visitContentAttr(String ns, String name, int resourceId, int type,//application 这一行
                                                             Object obj) {


                                    if ("name".equals(name)) {
                                        yuan_Application=obj.toString();
                                        if(obj.toString().startsWith(".")){
                                            yuan_Application=yuan_packageName+yuan_Application;
                                        }

                                        has_Application = true;
                                        hahahaha.Log.e("visitContentAttr:" + name + "  " + obj + "   " + ns + "   " + resourceId + "  " + type);
                                    }
                                    super.visitContentAttr(ns, name, resourceId, type, obj);
                                }

                                @Override
                                public NodeVisitor visitChild(String ns, String name) {//application 下面所有大标签


                                    return new NodeVisitor(super.visitChild(ns, name)) {


                                        @Override
                                        public void visitContentAttr(String ns, String name, int resourceId, int type, Object obj) {
                                            //     System.out.println("aaaa_visitChild:"+ns+"  "+name+"  "+resourceId+"  "+type+"  "+obj);
                                            super.visitContentAttr(ns, name, resourceId, type, obj);
                                        }

                                        @Override
                                        public NodeVisitor visitChild(String ns, String name) {
                                            // System.out.println("xxxx_visitChild:"+ns+"  "+name);
                                            return super.visitChild(ns, name);
                                        }
                                    };
                                }
                            };


                        }
                        return super.visitChild(ns, name);
                    }
                };
            }
        });


[课程]Android-CTF解题方法汇总!

最后于 2019-12-6 12:39 被skyun编辑 ,原因:
收藏
免费 5
支持
分享
最新回复 (27)
雪    币: 5
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
2
牛逼!厉害!大神就是大神!感谢大哥的分享
2019-12-6 12:57
0
雪    币: 342
活跃值: (759)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
AXmlConverter  和 DexMerger 开源库的地址有吗?
2019-12-6 14:08
0
雪    币: 2075
活跃值: (4447)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
感谢楼主 刚解答了我的疑问又发了新帖。我先上车试试
2019-12-6 14:15
0
雪    币:
活跃值: (102)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
学长大佬牛牛牛
2019-12-6 14:45
0
雪    币: 263
活跃值: (399)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
6
666
2019-12-6 14:45
0
雪    币: 2198
活跃值: (1351)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
厉害啊  6666
2019-12-6 15:02
0
雪    币: 2075
活跃值: (4447)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
逆向小学生 AXmlConverter 和 DexMerger 开源库的地址有吗?
有的 可以研究学习一波
2019-12-6 15:19
0
雪    币: 342
活跃值: (759)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
小黄鸭爱学习 有的 可以研究学习一波
老哥,AXmlConverter 和 DexMerger 开源库的地址在哪呢?我怎么没找到呀
2019-12-6 15:52
0
雪    币: 2075
活跃值: (4447)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
逆向小学生 老哥,AXmlConverter 和 DexMerger 开源库的地址在哪呢?我怎么没找到呀
就在项目里面啊 你搜索一下
2019-12-6 16:13
0
雪    币: 2075
活跃值: (4447)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
逆向小学生 老哥,AXmlConverter 和 DexMerger 开源库的地址在哪呢?我怎么没找到呀
最后于 2019-12-6 16:18 被小黄鸭爱学习编辑 ,原因:
2019-12-6 16:18
0
雪    币: 2075
活跃值: (4447)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
E/wodelog: runCMD:unzip /sdcard/360/multi/multi/com.multi.multi.apk classes*dex -o  -d  /sdcard/360/multi/multi/未命名文件夹/
E/wodelog: runCMD 执行出错了java.io.IOException: Cannot run program "unzip": error=13, Permission denied
求解
最后于 2019-12-6 16:52 被小黄鸭爱学习编辑 ,原因:
2019-12-6 16:51
0
雪    币: 723
活跃值: (1281)
能力值: ( LV9,RANK:160 )
在线值:
发帖
回帖
粉丝
13
小黄鸭爱学习 E/wodelog:&nbsp;runCMD:unzip&nbsp;/sdcard/360/multi/multi/com.multi.multi.apk&nbsp;class ...
啊。没权限吗? 你在 shell 里面执行一下试试
2019-12-6 17:12
0
雪    币: 2075
活跃值: (4447)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
skyun 啊。没权限吗? 你在 shell 里面执行一下试试
shell里面运行 错误
/system/bin/sh: unzip: not found
 好像没有unzip命令
不知道你那是怎么运行成功的
最后于 2019-12-6 17:28 被小黄鸭爱学习编辑 ,原因:
2019-12-6 17:27
0
雪    币: 723
活跃值: (1281)
能力值: ( LV9,RANK:160 )
在线值:
发帖
回帖
粉丝
15
小黄鸭爱学习 skyun 啊。没权限吗? 你在 shell 里面执行一下试试 shell里面运行 错误/system/bin/sh:&nbsp;unzip:& ...
不应该啊。我这是 AndroidQ Pixel上测试的 
2019-12-6 18:56
0
雪    币: 723
活跃值: (1281)
能力值: ( LV9,RANK:160 )
在线值:
发帖
回帖
粉丝
16
skyun 不应该啊。我这是 AndroidQ Pixel上测试的
marlin:/ $ su
/system/bin/sh: su: inaccessible or not found
127|marlin:/ $ unzip
unzip: missing archive filename
2019-12-6 19:28
0
雪    币: 1867
活跃值: (3763)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
17
发现了可以抄的地方,太谢谢了
2019-12-6 19:35
0
雪    币: 723
活跃值: (1281)
能力值: ( LV9,RANK:160 )
在线值:
发帖
回帖
粉丝
18
virjar 发现了可以抄的地方,太谢谢了[em_13]
能够让大佬抄我的代码,真是 蓬荜生辉 。谢谢大佬
2019-12-6 19:37
0
雪    币: 1867
活跃值: (3763)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
19
skyun 能够让大佬抄我的代码,真是 蓬荜生辉 。谢谢大佬
emmm,随便说一句。contentProvider不一定稳。有些手机貌似第一次调调不动。所以得很多线路一起。包括存储卡,contentProvider,socket等
2019-12-6 19:56
0
雪    币: 723
活跃值: (1281)
能力值: ( LV9,RANK:160 )
在线值:
发帖
回帖
粉丝
20
哦哦哦
2019-12-6 20:25
0
雪    币: 409
活跃值: (17)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
厉害 老大
2019-12-6 20:59
0
雪    币: 268
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
22
有没有demo
2019-12-7 02:06
0
雪    币: 2075
活跃值: (4447)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
skyun marlin:/ $ su /system/bin/sh: su: inaccessible or not found 127|marlin:/ $ unzip unzip: missing a ...
我特意去借了台一加 AndroidQ 的确可以 adb shell  unzip
但是其他版本不行 android 9 都不行
2019-12-9 14:15
0
雪    币: 723
活跃值: (1281)
能力值: ( LV9,RANK:160 )
在线值:
发帖
回帖
粉丝
24
小黄鸭爱学习 我特意去借了台一加 AndroidQ 的确可以 adb shell unzip 但是其他版本不行 android 9 都不行
啊。那把解包方式全换成 baksmali就可以了
2019-12-9 15:36
0
雪    币: 723
活跃值: (1281)
能力值: ( LV9,RANK:160 )
在线值:
发帖
回帖
粉丝
25
华夏ei55s 有没有demo
你自己编译一下就OK
2019-12-9 15:36
0
游客
登录 | 注册 方可回帖
返回
//