美文网首页
尝试修改mmap函数dump dex

尝试修改mmap函数dump dex

作者: 修符道人 | 来源:发表于2020-01-03 11:04 被阅读0次

https://www.jianshu.com/p/feecde9a9aee这篇文章里,我讲到了如何成功dump出360的dex方法,但是没有dump出壳内真正apk的dex文件。网上有一种说法是从mmap函数入手,我尝试了一下,但是失败了,过程记录一下:

mmap.cpp文件

所在目录:bionic/libc/bionic/mmap.cpp
编译目录:bionic/libc/

ALOGE使用不了

在DvmDex.cpp里,可以直接调用ALOGE打印android日志,但是到了mmap.cpp却没法直接使用。网上百度了各种办法都不行,编译虽然通过,系统跑不起来,大概是https://blog.csdn.net/flydream0/article/details/7344730里的方案的综合,有的是教怎么在JNI的cpp里如何打印android日志,有的虽然是教源码里cpp如何打印android日志。可能是不同的模块修改Android.mk的方式不一样。

最终,我参照DvmDex.cpp所在模块的Android.mk,依葫芦画瓢找到了答案:

bionic/libc/Android.mk的 libc_common.a处增加libcutils和liblog依赖,在mmap.cpp里增加#include <cutils/log.h>即可。

image.png
  • 依葫芦画瓢的过程:
    首先看DvmDex.cpp的include的.h文件,
#include "Dalvik.h"
#include <sys/mman.h>

先去DvmDex.cpp的当前目录下找这两个文件,发现Dalvik.h有一个

#include "Common.h"

在Common.h里发现

#include "cutils/log.h"

然而,在当前目录发现找不到cutils/log.h这个文件,为何?(关于这个问题,我研究发现要单独成文,想要知道libxxx.so xxx.a这些共享库、静态库都是怎么生成的,请转至:)
看先去DvmDex.cpp编译模块的Android.mk文件:

image.png
然后文章开头,我照样将libcutils、liblog两个静态库添加到bionic/libc/Android.mk中。
网上的很多的做法都是将libcutils添加到LOCAL_SHARED_LIBRARIES的后面,把静态库添加到共享库变量里,我不知道编译为啥还成功了,但是系统跑不起来(Nexus出现Google页面2次后卡在感叹号机器人页面)。

有了ALOG,就等于有了眼睛,等于我们离底层又更进了一步。

mmap函数研究

void* mmap(void* addr, size_t size, int prot, int flags, int fd, off_t offset)
我的目的还是希望通过addr和size来dump出dex的内存,但是mmap会被频繁的调用到。
我在https://www.jianshu.com/p/feecde9a9aee这篇文章提到过,DvmDex.cpp文件中的dvmDexFileOpenPartial的调用时机问题我已经解决了。但是mmap函数,我如何确定是360壳内部的应用的dex加载时调用了呢?我想到了几种解决方案:
1)利用Dex文件结构

image.png
了解Dex文件结构的都知道Dex文件开头的7个字节始终是固定的:64 65 78 0A 30 33 35,对应的字符串是dex.035。那么是否可以通过addr和size来判断呢?

我操作星(result+x)判断字节,编译直接报错。void星指针不能直接拿来运算

我写了下面的这些的几行代码,发现系统起不来,出现2次Google页面后卡在感叹号机器人页面。


image.png

原来mmap函数的参数void* addr,addr可能是任意的类型,直接强转成int星肯定会报错。但是我发现void*可以强转成unsiged char *,
看与mmap.cpp同级的目录的memcmp.c文件,google官方就是这么干的。


image.png

所以对代码再一次做了优化:


image.png

这次是卡在android字样页面。
将下面这行代码注释掉,系统起来了。

//ALOGE("CZLog mmap find dex035");

为什么限制了条件之后打Log反而打不出来呢?不光限制条件,就在条件里进行变量的运算,自增、自减运算,系统也会起不来。

memcmp函数研究

这篇https://www.52pojie.cn/thread-648311-1-1.html博客解释了360没有使用 系统的dvmDexFileOpenPartial函数,而是模仿了系统的解析dex的方法:DexFile.c中的dexFileParse方法,然后使用了memcmp函数(系统方法,我们找的就是系统方法。),所以mmap行不通,尝试修改这个函数。
关于博客里有2个常量:DEX_OPT_MAGIC和DEX_OPT_MAGIC_VERS,请看https://blog.csdn.net/yhtppp/article/details/44829449?locationNum=12,位于/dalvik/libdex/DexFile.h 文件中。

<u> memcmp.c一引入了cutil/log,然后bionic/libc/Android.mk增加libcutil、liblog,就会导致整个make都无法使用,报错如下:
没有规则可以创建“out/host/linux-x86/obj/SHARED_LIBRARIES/libdvm_intermediates/import_includes”需要的目标“out/host/linux-x86/obj/SHARED_LIBRARIES/libcutils_intermediates/export_includes”。 停止
在memcmp.c可以直接使用ALOGE,也不用引入cutil/log头文件,不知道是什么个原理。</u>
上面这段奇遇,可能是由于什么缓存,或者源码的某个文件不小心删除造成的。后来重新下载源码重新走流程就没有什么问题。但是,memcmp.c里的android日志没有输出。
首先我怀疑360可能根本没有调用这个方法,为了证明我的猜想,我写了一个JNI程序,调用了C的memcmp方法,memcmp.c里的android日志仍然没有输出。

重新研究bionic/libc/Android.mk发现端倪

在Android.mk里搜索memcmp.c,发现只有一处引用:


image.png

Android.mk文件里的关键变量:

TARGET_ARCH: 目标 CPU平台的名字, 和android 开放源码中指定的那样。如果是
arm,表示要生成 ARM 兼容的指令,与 CPU架构的修订版无关。

memcmp.c编译mips架构的组件时才会被依赖。
使用

adb shell
cat /proc/cpuinfo

发现我的调试设备的架构是armv7,所以memcmp.c不会被我的设备调用,更别谈打印日志了。

  • 看看arm架构的依赖:
    有一个wmemcmp.c和memcmp.c长得很像。


    image.png

    定位到文件


    image.png
    加上日志
#include <cutils/log.h>
int
wmemcmp(const wchar_t *s1, const wchar_t *s2, size_t n)
{
    size_t i;
    ALOGE("CZLog3333333333"); 
    for (i = 0; i < n; i++) {
        if (*s1 != *s2) {
            /* wchar might be unsigned */
            return *s1 > *s2 ? 1 : -1; 
        }
        s1++;
        s2++;
    }
    
    return 0;
}

android日志TM还是没有输出,气死人了。

Android源码与NDK的关系

在上面,我写了个JNI,调用memcmp()方法,以为就是调用的源码里的bionic/libc/upstream-freebsd/lib/libc/string/wmemcmp.c的wmemcmp方法。
其实,这里我有个很大的误区:JNI调用的库<string.h>并非Android源码里的<string.h>,而且NDK里的库。而NDK是独立于Android系统的,是一个开发工具集,有着很多和Android源码里相似的库,但是它不属于Android系统本身的一部分。

相关文章

网友评论

      本文标题:尝试修改mmap函数dump dex

      本文链接:https://www.haomeiwen.com/subject/jrzcoctx.html