首页
论坛
专栏
课程

[原创]帮Xpatch添把柴

2019-8-23 09:48 1525

[原创]帮Xpatch添把柴

2019-8-23 09:48
1525

帮Xpatch添把柴

Xpatch是一个重打包工具,可以将自己的代码注入到第三方apk中。在使用的时候,遇到下面几个问题会导致打包失败:
1、原app没有Application
2、原app有自己的static代码块
3、原app有dex完整性校验

 

这篇 https://bbs.pediy.com/thread-251422.htm 文章对Xpatch流程梳理的很详细,实现上是在原app的Application入口位置添加static代码块,
抢在原app代码执行前注入自己代码。

 

但是选择这个注入点会有一些问题,如果原应用没有Application就会注入失败;或者原应用加壳了的,已经有 static 代码块,这个时候注入的代码执行时机也会有问题;
还有种情况,这样是修改了原应用的dex文件,如果应用对dex完整性做了检验,打包后也会失败。为了解决这些问题,想到了两种解决方式:
1、模拟加壳原理,将自己壳代码打包成dex文件,合并进原来apk中,并且将 AndroidManifest.xml 中应用入口改成壳的Application,通过壳将原app加载起来;
2、利用MutilDex机制,生成一个我们自己的Application类, 并且继承自 AndroidManifest.xml 中声明的Application, 重写 attachBaseContext 函数,
,在调用父类的 attachBaseContext 函数之前加入自己逻辑,打包成dex文件,修改 AndroidManifest.xml 中应用入口为我们自己的Application

 

综合下来,第一种方法显然麻烦很多,这里使用第二种方式。

 

代码很简单,分三部分:
1、自己写一个只包含 Application 的app,目的是为了取到dex
2、修改自定义的 Application 继承于原来 Application,如果原来没有 Application 就不用修改
3、修改 AndroidManifest.xml 入口为我们自定义的 Application

 

第一部分代码很简单

public class StubApplication extends Application {

    private static final String TAG = "StubApplication";

    @Override
    protected void attachBaseContext(Context base) {
        //这里可以写自己的代码逻辑,比如注入hook框架,过签名校验等操作
        super.attachBaseContext(base);
        Log.i(TAG, "StubApplication attachBaseContext...");
    }
}

第二部分代码也很简单,就是提取出第一部分生成的dex文件,转为smali之后修改继承的父类就可以了

private File modifyStubDex() throws Exception {

        //stub.apk就是我们第一步打包的apk
        File stubAppFile = new File(new File("apks"), "stub.apk");

        File stubDexSmaliDir = new File(new File("work"), "stubSmali");

        //将dex转为smali
        Util.decodeDex2Smali(stubAppFile, "classes.dex", stubDexSmaliDir);

        //遍历所有文件,找到StubApplication.smali文件
        Iterator<File> fileIterator = FileUtils.iterateFiles(stubDexSmaliDir, new String[]{"smali"}, true);

        File stubApplicationFile = null;
        while (fileIterator.hasNext()) {
            File next = fileIterator.next();
            if (StringUtils.containsIgnoreCase(next.getName(), "StubApplication")) {
                stubApplicationFile = next.getAbsoluteFile();
                break;
            }
        }

        if (Objects.isNull(stubApplicationFile)) {
            System.out.println("没找到StubApplication.smali文件");
            return null;
        }

        //找到之后,修改继承的父类
        List<String> lines = FileUtils.readLines(stubApplicationFile, Charsets.UTF_8);

        String originApplicationName = StringUtils.replace(applicationName, ".", "/");
        originApplicationName = StringUtils.prependIfMissing(originApplicationName, ".super L");
        originApplicationName = StringUtils.appendIfMissing(originApplicationName, ";");

        lines.set(1, originApplicationName);

        String invoke = "Landroid/app/Application;";
        for (int i = 0; i < lines.size(); i++) {
            if (StringUtils.containsIgnoreCase(lines.get(i).trim(), invoke)) {
                lines.set(i, StringUtils.replace(lines.get(i), "Landroid/app/Application;", StringUtils.remove(originApplicationName, ".super ")));
            }
        }


        //将修改完后的smali重打包成dex
        FileUtils.writeLines(stubApplicationFile, lines);

        File stubDexFile = new File(new File("work"), "stubDex.dex");
        SmaliBuilder.build(new ExtFile(stubDexSmaliDir), stubDexFile, Opcodes.getDefault().api);

        return stubDexFile;
    }

第三步就是修改 AndroidManifest.xml 文件中的应用入口为我们自定义的 Application了。
修改 AndroidManifest.xml 可以直接在二进制层面改,也可以转为xml之后再修改,不过现在有些app做了对坑,直接转xml可能报错。
刚开始用的四哥的 AXMLEditor 进行二进制层面修改,修改的确成功了,但是重打包安装之后一启动就报错,看错误日志应该是没找到Application类,查了半天也没解决,
只能先暂时转为xml进行修改。

 private static File editManifest(File originApk) throws Exception {
        //使用 net.dongliu:apk-parser 对xml进行提取
        String originAPKManifestXml = ApkParsers.getManifestXml(originApk);
        Document document = loadDocument(new ByteArrayInputStream(originAPKManifestXml.getBytes(Charset.forName("utf-8"))));

        Element applicationElement = (Element) document.getElementsByTagName("application").item(0);

        applicationElement.setAttribute("android:name", stubAppApplicationName);

        File file = new File(new File("work"), "AndroidManifest.xml");
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();
        DOMSource source = new DOMSource(document);
        StreamResult streamResult = new StreamResult(file);
        transformer.transform(source, streamResult);
        return file;
}

上面就是所有的流程,做完后就是集成到Xpatch中了,Xpatch中每个步骤都是一个task,所以集成还是蛮方便的,只需要将上面步骤写到一个task中,再做如下修改,

    // 1. modify the apk dex file to make xposed can run in it
    //mXpatchTasks.add(new ApkModifyTask(showAllLogs, keepBuildFiles, unzipApkFilePath, applicationName, dexFileCount));
    mXpatchTasks.add(new ChangeApplicationTask(applicationName, dexFileCount, unzipApkFilePath));

这样就完事了。最后测试没有大规模测试,只做了业务需要的,基本是可以解决最开始遇到的几个问题。



[公告]安全服务和外包项目请将项目需求发到看雪企服平台:https://qifu.kanxue.com

最新回复 (5)
virjar 1 2019-8-23 10:38
2
0
1. “利用MutilDex机制,生成一个我们自己的Application类, 并且继承自 AndroidManifest.xml 中声明的Application, 重写 attachBaseContext 函数,
,在调用父类的 attachBaseContext 函数之前加入自己逻辑,打包成dex文件,修改 AndroidManifest.xml 中应用入口为我们自己的Application。”
有点小问题,继承方案假定了第一行代码是attachBaseContext,但是第一行代码是supperApplication的静态代码块。有不少apk都是这样的,这样你重写attachBaseContext,并不能保证你的代码最先执行。所以这里不能继承,而是构造另一个没有继承关系的application,然后这个application模拟调用这个apk的application的生命周期。可以参考instantRun的代码: https://android.googlesource.com/platform/tools/base/+/refs/tags/studio-2.3/instant-run/
virjar 1 2019-8-23 10:43
3
0
“修改 AndroidManifest.xml 可以直接在二进制层面改,也可以转为xml之后再修改,不过现在有些app做了对坑,直接转xml可能报错。
刚开始用的四哥的 AXMLEditor 进行二进制层面修改,修改的确成功了,但是重打包安装之后一启动就报错,看错误日志应该是没找到Application类,查了半天也没解决,”
四哥这个有点小问题,问题在于<application android:name="com.application.class"/> 这个"android:name"属性,在Android系统内是定义了特殊id的,四哥的处理是直接删除之前的android:name属性,然后重新添加adnroid:name属性。重新添加之后的id,其实是在AndroidManifiest.xml文件中定义,而不是android系统定义。我单步调试过Android pakagemanager的这部分代码,发现如果走四哥的那个代码。实际上Android的packageManager是找不到android:name的内容的,所以最终Android系统会认为是android.app.Application,也就是说,原来的application配置都丢了
virjar 1 2019-8-23 10:46
4
0
你可以修改四哥的AXMLEditor,或者有一个c++版本的实现。ele7enxxh大佬的  https://github.com/ele7enxxh/AmBinaryEditor 
tDasm 2019-8-23 11:10
5
0
virjar 你可以修改四哥的AXMLEditor,或者有一个c++版本的实现。ele7enxxh大佬的 https://github.com/ele7enxxh/AmBinaryEditor
你这个是Windows版吗?
virjar 1 2019-8-26 10:01
6
0
tDasm 你这个是Windows版吗?
我是修改了四哥的AXMLEditor,java版本
游客
登录 | 注册 方可回帖
返回