吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2749|回复: 41
上一主题 下一主题
收起左侧

[Android 原创] 过签名校验(2) -- MT 的 IO 重定向实践

  [复制链接]
跳转到指定楼层
楼主
2016976438 发表于 2023-1-5 23:46 回帖奖励
本帖最后由 2016976438 于 2023-1-6 00:13 编辑

过签名校验(2) -- MT 的 IO 重定向

本来是想照着敲一遍 MT 的 github 上面的代码 ,但个人c ++ 以及 arm 汇编 实在有点吃力。说白了就是个人水平不够。

所以砸门的目标就变成了.  

  1. 能看懂就行
  2. 可以编译 mt github源码 成 apk
  3. 复制 so 和 classX.dex 到我们要去签名的应用上

​     

运行 MT 的 去签名的 github 源码

  1. 先从github下下来

网络差的建议通过油猴转到网盘下载

  1. 导入到android studio

导入后您可以看到两个模块

app (测试demo)  killer(去签模块)

运行后 app 您应该能够得到

使用zip 解压 其中重要的就是

app-debug.apk/lib/  里面的 so hook 的 IO 重定向

classesXXX.dex   这个得看 KillerApplication 在哪里了

了解Killer 模块

我们主要目的是看 killer 去签的那个模块 , 先从 KillerApplication

public class KillerApplication extends Application {
   static {
        String packageName = "bin.mt.signature";
        killOpen(packageName);
    }

     private static void killOpen(String packageName) {
        try {
            //1.加载 so 层 hook
            System.loadLibrary("SignatureKiller");
        } catch (Throwable e) {
            System.err.println("Load SignatureKiller library failed");
            return;
        }
        //2. 通过 当前 /proc/self/maps 获取apk路径
        String apkPath = getApkPath(packageName);
        if (apkPath == null) {
            System.err.println("Get apk path failed");
            return;
        }
        //3. 获取的路径是 /data/app/{PackageName}-xxx/base.apk 这个是当前 apk文件
        File apkFile = new File(apkPath);
        //4.将当前 apk 中 origin.apk 文件提取出去 作为我们的 IO重定向文件
        File repFile = new File("/data/data/" + packageName + "/origin.apk");
        //5. 由于 apk实际是个 zip 所以我们可以解压缩 提取 origin.apk
        try (ZipFile zipFile = new ZipFile(apkFile)) {
            //6. apkFile  抽取 origin.apk  到 repFile变量 指定的位置
            String name = "assets/SignatureKiller/origin.apk";
            ZipEntry entry = zipFile.getEntry(name);
            if (entry == null) {
                System.err.println("Entry not found: " + name);
                return;
            }

            //7.把 /data/app/{PackageName}-xxx/base.apk/origin.apk 转换到 /data/data/packageName/origin.apk
            if (!repFile.exists() || repFile.length() != entry.getSize()) {
                try (InputStream is = zipFile.getInputStream(entry); OutputStream os = new FileOutputStream(repFile)) {
                    byte[] buf = new byte[102400];
                    int len;
                    while ((len = is.read(buf)) != -1) {
                        os.write(buf, 0, len);
                    }
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        //8. 传入到 底层 so hook
        hookApkPath(apkFile.getAbsolutePath(), repFile.getAbsolutePath());
    }

     private static native void hookApkPath(String apkPath, String repPath);

}    

KillerApplication  Java层 主要是 获取 当前 app 里面 我们放入的原始的  origin.apk 文件 , origin.apk 是没有改过签的正常 app

在我们编译的apk 的 :  app-debug.apk/assets/SignatureKiller/origin.apk

但是我们 android 安装后 路径会变成: /data/app/{包名}-XXX/ base.apk

获取apk 路径 通过 /proc/self/maps 获取 。

 # ps -ef|grep mt
 u0_a63        7864  1464 0 20:10:12 ?     00:00:00 bin.mt.signature

 # cat /proc/7864/maps | grep base.apk
 7ffff4080000-7ffff4082000 r--s 00009000 08:12 919883                     /data/app/bin.mt.signature-zJwiS40NJvMBt5AUPmgKRA==/base.apk
7ffff7a88000-7ffff7a89000 r--s 00019000 08:12 919883                     /data/app/bin.mt.signature-zJwiS40NJvMBt5AUPmgKRA==/base.apk

/data/app/bin.mt.signature-zJwiS40NJvMBt5AUPmgKRA==/base.apk 就是 安装包的路径了

为了方便, MT 将 base.apk 里面的 origin.apk 提取到  /data/data/包名 下面

# cd /data/data/包名
# ll
drwxrws--x 2 u0_a63 u0_a63_cache  4096 2023-01-04 19:36 cache
drwxrws--x 2 u0_a63 u0_a63_cache  4096 2023-01-04 19:36 code_cache
drwxrwxr-x 5 u0_a63 u0_a63        4096 2023-01-04 19:47 lldb
-rw------- 1 u0_a63 u0_a63       22989 2023-01-04 19:38 origin.apk

然后传到 hookApkPath 进行 HOOK

XHook 分析

xhook 是针对 so 层 拦截的一种框架。

github 在 :  

https://github.com/iqiyi/xHook/blob/master/README.zh-CN.md
//注册hook
xhook_register(".*\\.so$", "hook的函数", 到我们自定义的 ,  NULL);

//执行 hook!
xhook_refresh(1);

咋们只用看 mt_jni.c 就行了

``` c++

//1. 从 java 层传入的
// apkPath 是 原来的路径
const char apkPath__;
// repPath 要重定向的路径
const char
repPath__;

//2. hook open 函数
int (old_open)(const char , int, mode_t);
static int openImpl(const char *pathname, int flags, mode_t mode) {
//如果 打开是原路径 就替换成 repPath
if (strcmp(pathname, apkPath__) == 0){
return old_open(repPath__, flags, mode);
}
return old_open(pathname, flags, mode);
}

//3. hook openat 函数
int (old_openat)(int, const char, int, mode_t);
static int openatImpl(int fd, const char *pathname, int flags, mode_t mode) {
//如果 打开是原路径 就替换成 repPath
if (strcmp(pathname, apkPath__) == 0){
return old_openat(fd, repPath__, flags, mode);
}
return old_openat(fd, pathname, flags, mode);
}

JNIEXPORT void JNICALL
Java_bin_mt_signature_KillerApplication_hookApkPath(JNIEnv env, attribute((unused)) jclass clazz, jstring apkPath, jstring repPath) {
//4. 获取从 java传入来的 原路径和重定向路径
apkPath__ = (
env)->GetStringUTFChars(env, apkPath, 0);
repPath__ = (*env)->GetStringUTFChars(env, repPath, 0);

//5. 使用 xhook 进行 重定向 hook
xhook_register(".*\\.so$", "openat64", openat64Impl, (void **) &old_openat64);
xhook_register(".*\\.so$", "openat", openatImpl, (void **) &old_openat);
xhook_register(".*\\.so$", "open64", open64Impl, (void **) &old_open64);
xhook_register(".*\\.so$", "open", openImpl, (void **) &old_open);

xhook_refresh(0);

}


# 应用去签名

我就直接用 之前 有点遗憾的 七猫小说 做为这次的示例。

之前说过,但我们签名后,七猫就会显示网络异常











所以我们步骤如下:

1. 根据 mt 中 获取 原始包的路径, 我们在 **assets/SignatureKiller/** 创建我们的原始 apk

```java
 private static void killOpen(String packageName) {
      ....
        File repFile = new File("/data/data/" + packageName + "/origin.apk");
       //5. 由于 apk实际是个 zip 所以我们可以解压缩 提取 origin.apk
       try (ZipFile zipFile = new ZipFile(apkFile)) {
           //6. apkFile  抽取 origin.apk  到 repFile变量 指定的位置
           String name = "assets/SignatureKiller/origin.apk";
    ....    
 }

  1. 我们通过 jadx 看下 编译的 KillerApplication 在哪个 xxxx.dex 中,顺带用 mt 把 包名和签名都成 原始七猫的

  1. 移动到 七猫里面去

(注意还有个 lsposed 的 dex 依赖 也得弄进去,这个就交给你们自己找了)

  1. 看看 androidManifest.xml  文件 ,看看 application 在哪里

记住这个 SophixStubApplication 我们待会会用到

  1. 复制 so文件,先把 arm64 的删掉,咋们就留一份arm32,免得不兼容。

app-debug.apk/lib/armeabi-v7a 里面找到我们得so 复制到 七猫里面去

  1. com.km.sophix.SophixStubApplication 中加入我们的 KillerApplication

(在上篇 PM 过签中我是通过 static 代码块插入的) 但在 正己大佬 视频里 MT 一键是通过 继承的方式, 这种需要面向对象基础才能理解。 但这种更为简单,但是得一直找父类最上层 就如下图,最上层父类是 SophixApplication

可以看到这个继承 最终的 Application

咋们修改成 super  KillerApplication  让他继承我们过签名的 MT 的 application

转换成 java 看看

至此算是完毕了。

不过跟PM管理器一样,模拟器不行,但是 手机可以。

个人觉得应该是 hook 不支持 x86_64 android 内部的  hook 。 不让我实在不理解为啥,管他的,谁又会用模拟器看小说呢。

尾言

其实说这么多,也就是MT 一键过签的事情。不过实践一下感觉也不错,起码知道了思路,下次这一方法不行,来了个新家伙,砸门也可以尝试上手改改。不至于只能等待 工具的 更新

在大佬树下乘凉就是不错,168 直接开通 MT 会员 感觉也能接受了。

c++ 和 so 对我来说还是过于困难,感觉我的android  逆向之路会被这两座大山给拦住。

不过算了,要是什么都会,那还要大佬干什么,跟着大佬混饭吃也不错。

免费评分

参与人数 16威望 +2 吾爱币 +118 热心值 +16 收起 理由
hzr121792 + 1 + 1 谢谢@Thanks!
fengbolee + 2 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
allspark + 1 + 1 用心讨论,共获提升!
s757129 + 1 + 1 ggnb!
gaosld + 1 + 1 热心回复!
weixu + 1 + 1 谢谢@Thanks!
wbem5 + 1 感谢分享
wwb66668 + 1 + 1 我很赞同!
Li1y + 1 + 1 用心讨论,共获提升!
笙若 + 1 + 1 谢谢@Thanks!
正己 + 4 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
iifly + 1 + 1 谢谢@Thanks!
qtfreet00 + 2 + 100 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
莫问刀 + 1 + 1 谢谢@Thanks!
woyucheng + 1 + 1 谢谢@Thanks!
blackgrape + 1 + 1 谢谢@Thanks!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

推荐
 楼主| 2016976438 发表于 2023-1-6 22:50 |楼主
本帖最后由 2016976438 于 2023-1-6 23:11 编辑
Poorwood 发表于 2023-1-6 09:45
这个工具的原理,有大佬讲讲吗?我看,就是不停地替换dex和so文件?

排版太难了, 前面排版乱了 所以不太方便看

您可以下载 mt 开源的代码看看 里面有通过 openAt 获取签名的代码 不过 arm 汇编 和 c++ 个人水平有限




#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)

intptr_t openAt(intptr_t fd, const char *path, intptr_t flag) {
#if defined(__arm__)
    intptr_t r;
    asm volatile(
#ifndef OPTIMIZE_ASM
    "mov r0, %1\n\t"
    "mov r1, %2\n\t"
    "mov r2, %3\n\t"
#endif

    "mov ip, r7\n\t"
    ".cfi_register r7, ip\n\t"
    "mov r7, #" STR(__NR_openat) "\n\t"
    "svc #0\n\t"
    "mov r7, ip\n\t"
    ".cfi_restore r7\n\t"

#ifndef OPTIMIZE_ASM
    "mov %0, r0\n\t"
#endif
    : "=r" (r)
    : "r" (fd), "r" (path), "r" (flag));
    return r;
#elif defined(__aarch64__)
    intptr_t r;
    asm volatile(
#ifndef OPTIMIZE_ASM
    "mov x0, %1\n\t"
    "mov x1, %2\n\t"
    "mov x2, %3\n\t"
#endif

    "mov x8, #" STR(__NR_openat) "\n\t"
    "svc #0\n\t"

#ifndef OPTIMIZE_ASM
    "mov %0, x0\n\t"
#endif
    : "=r" (r)
    : "r" (fd), "r" (path), "r" (flag));
    return r;
#else
    return (intptr_t) syscall(__NR_openat, fd, path, flag);
#endif
}

JNIEXPORT jint JNICALL
Java_bin_mt_test_MainActivity_openAt(JNIEnv *env, __attribute__((unused)) jclass clazz, jstring path) {
    const char* p = (*env)->GetStringUTFChars(env, path, 0);
    __android_log_print(ANDROID_LOG_INFO, "openAt", "path=%s", p);
    intptr_t fd = openAt(AT_FDCWD, p, O_RDONLY);
    return fd;
}
推荐
正己 发表于 2023-1-7 15:23
2016976438 发表于 2023-1-6 22:51
算能 了理解 大佬的不容易 。 想写好看点真难, 加个图片 排版全乱了, 改来改去 吾爱给我限制 ip了...

是时候学一下md语法了,写帖子事半功倍
沙发
sopcast 发表于 2023-1-6 07:53
3#
aa2923821a 发表于 2023-1-6 08:45
感谢分享!!
4#
aonima 发表于 2023-1-6 08:54
不错,学习了
5#
lianquke 发表于 2023-1-6 08:56
感谢分享,其实mt的hook支持x86_64,用AS自带的虚拟机加上Bin的demo apk试试就行,应该是七猫不兼容,或者二者混合发生了奇怪反应。
6#
markdik31 发表于 2023-1-6 09:00
谢谢大神分享,小弟来学习学习
7#
大大连连 发表于 2023-1-6 09:02
这个教程实用,感谢感谢
8#
zkq970413 发表于 2023-1-6 09:04
感谢分享~我记得我买的时候MT永久会员还不是168,没想到现在这么贵了啊。
9#
yun520530 发表于 2023-1-6 09:11
谢谢分享,学习学习啦
10#
heng179 发表于 2023-1-6 09:22
谢谢分享
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2023-2-4 06:43

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表