过签名校验(2) -- MT 的 IO 重定向实践
本帖最后由 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下下来
网络差的建议通过油猴转到网盘下载
2. 导入到android studio
导入后您可以看到两个模块
**app (测试demo)killer(去签模块)**
运行后 app 您应该能够得到
使用zip 解压 其中重要的就是
**app-debug.apk/lib/**里面的 so hook 的 IO 重定向
**classesXXX.dex** 这个得看 **KillerApplication** 在哪里了
# 了解Killer 模块
我们主要目的是看 **killer** 去签的那个模块 , 先从 **KillerApplication** 看
``` java
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;
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** 获取 。
```cmake
# ps -ef|grep mt
u0_a63 78641464 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_cache4096 2023-01-04 19:36 cache
drwxrws--x 2 u0_a63 u0_a63_cache4096 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
```
```cpp
//注册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";
....
}
```
2.我们通过 **jadx** 看下 编译的 **KillerApplication** 在哪个 **xxxx.dex** 中,顺带用 **mt** 把 包名和签名都成 原始七猫的
3. 移动到 七猫里面去
(注意还有个 lsposed 的 dex 依赖 也得弄进去,这个就交给你们自己找了)
4. 看看 **androidManifest.xml**文件 ,看看 **application** 在哪里
记住这个 **SophixStubApplication** 我们待会会用到
5. 复制 so文件,先把 arm64 的删掉,咋们就留一份arm32,免得不兼容。
在 **app-debug.apk/lib/armeabi-v7a** 里面找到我们得so 复制到 七猫里面去
6. 在 **com.km.sophix.SophixStubApplication** 中加入我们的 **KillerApplication**
(在上篇 PM 过签中我是通过 **static** 代码块插入的) 但在 **正己大佬** 视频里 **MT 一键**是通过 继承的方式, 这种需要面向对象基础才能理解。 但这种更为简单,但是得一直找父类最上层 就如下图,最上层父类是 **SophixApplication**
可以看到这个继承 最终的 **Application**
咋们修改成 **superKillerApplication**让他继承我们过签名的 **MT 的 application**
转换成 java 看看
至此算是完毕了。
**不过跟PM管理器一样,模拟器不行,但是 手机可以。**
个人觉得应该是 hook 不支持 x86_64 android 内部的hook 。 不让我实在不理解为啥,管他的,谁又会用模拟器看小说呢。
#尾言
其实说这么多,也就是MT 一键过签的事情。不过实践一下感觉也不错,起码知道了思路,下次这一方法不行,来了个新家伙,砸门也可以尝试上手改改。不至于只能等待 工具的 更新
在大佬树下乘凉就是不错,168 直接开通 MT 会员 感觉也能接受了。
c++ 和 so 对我来说还是过于困难,感觉我的android逆向之路会被这两座大山给拦住。
不过算了,要是什么都会,那还要大佬干什么,跟着大佬混饭吃也不错。 谢谢分享,学习学习啦 这个工具的原理,有大佬讲讲吗?我看,就是不停地替换dex和so文件? 小学徒来学习了 感谢分析学习了 感谢分享!! 不错,学习了 感谢分享,其实mt的hook支持x86_64,用AS自带的虚拟机加上Bin的demo apk试试就行,应该是七猫不兼容,或者二者混合发生了奇怪反应。 谢谢大神分享,小弟来学习学习 感谢分享~我记得我买的时候MT永久会员还不是168,没想到现在这么贵了啊。