zoukankan      html  css  js  c++  java
  • 利用Cydia Substrate进行Android HOOK(二)

       在前面关于Substrate的介绍中我们已经讲了用Substrate hook java代码,现在我们讲下怎么用它hook native代码。hook native代码我们需要编写Substrate extensions,它跟native库一样被视作标准的android包的一部分, 将作为一个共享库被编译 (使用复合扩展名.cy.so)。

    一、相关API

    (1)MSConfig
     
    名称 描述
    Filter:Executable 开发者试图hook的可执行文件的完整路径。一般为zygote, "/system/bin/app_process"。
    Filter:Library 开发者试图hook的lib库的名称,比如hook __android_log, 则指定 "liblog.so".
    如:
    MSConfig(MSFilterExecutable, "/system/bin/app_process")
    MSConfig(MSFilterLibrary, "liblog.so")

    (2)void MSHookFunction(void *symbol, void *hook, void **old);

    参数描述
    symbol   被替换代码的地址,一般是一个函数
    hook The address of an ABI-compatible replacement for the code at the address referenced by symbol.
    old 指向函数指针的指针,用来调用原函数的实现。如果不需要对原函数进行处理则为NULL
    示例:
     1 void *(*oldConnect)(int, const sockaddr *, socklen_t);
     2 
     3 void *newConnect(
     4     int socket, const sockaddr *address, socklen_t length
     5 ) {
     6     if (address->sa_family == AF_INET) {
     7         sockaddr_in *address_in = address;
     8         if (address_in->sin_port == htons(6667)) {
     9             sockaddr_in copy = *address_in;
    10             address_in->sin_port = htons(7001);
    11             return oldConnect(socket, &copy, length);
    12         }
    13     }
    14 
    15     return oldConnect(socket, address, length);
    16 }
    17 
    18 MSHookFunction(&connect, &newConnect, &oldConnect);

    (3)void *MSFindSymbol(MSImageRef image, const char *name);

    参数描述
    image 指定一个有效的image引用(通过调用MSGetImageByName返回的结果)。如果为NULL,则会搜索所有image
    name 待查找的原始镜像符号的名称。这并非如dlopen所加载的高级符号,它可能需要以下划线为前缀或其他特定平台的编码。
    return 符号的地址(调整为ARM/Thumb类型),如果不能定位符号则返回NULL
    示例:
    1 MSImageRef image;
    2 image = MSGetImageByName("/usr/lib/libSystem.B.dylib");
    3 
    4 void *(*palloc)(size_t);
    5 palloc = (void *(*)(size_t)) MSFindSymbol(image, "_malloc");
    6 
    7 void *data = (*palloc)(1024);
    8 free(data);

    (4)MSImageRef MSGetImageByName(const char *file);

    参数描述
    file 根据so或者动态库的完整路径加载image
    return 可以被其它API使用的image引用,如果image没有加载则为NULL
    示例:
    1 MSImageRef image;
    2 image = MSGetImageByName("/system/lib/libc.so");
    3 if (image != NULL)
    4     /* image is loaded */;

    二、使用示例

    下面以前一篇过签名验证的hook代码为例讲解native hook的代码编写过程:

    1.创建android native工程HookVerify,so层hook并不需要界面(作为Cydia Substrate的扩展模块),所以在新建工程时无需建activity。接下来在工程目录下新建jni文件夹,并将libsubstrate.so,libsubstrate-dvm.so,substrate.h三个文件拷贝至jni文件夹下。
    在jni目录下创建HookVerify.cy.cpp文件。


    2.配置Manifest文件
    需要添加权限:<uses-permission android:name="cydia.permission.SUBSTRATE"/>
    由于我们只使用native code,将android:hasCode设为false。
    3.Android.mk文件编写:
    LOCAL_PATH := $(call my-dir)
    include $(CLEAR_VARS) LOCAL_MODULE :
    = substrate LOCAL_SRC_FILES := libsubstrate.so include $(PREBUILT_SHARED_LIBRARY)
    include $(CLEAR_VARS) LOCAL_MODULE :
    = substrate-dvm LOCAL_SRC_FILES := libsubstrate-dvm.so include $(PREBUILT_SHARED_LIBRARY)
    include $(CLEAR_VARS) LOCAL_MODULE :
    = HookVerify #一定要有.cy作后缀 LOCAL_SRC_FILES := HookVerify.cy.cpp LOCAL_LDLIBS := -llog LOCAL_ARM_MODE := arm LOCAL_LDLIBS += -L$(LOCAL_PATH) -lsubstrate-dvm -lsubstrate include $(BUILD_SHARED_LIBRARY)
    4.HookVerify.cy.cpp代码:
     1 #include <jni.h>
     2 #include "substrate.h"
     3 #include <android/log.h>
     4 #include <unistd.h>
     5 #include <stdio.h>
     6 #include <fcntl.h>
     7 #include <sys/types.h>
     8 #include <string.h>
     9 #include <sys/stat.h>
    10 #define TAG "HOOKDEMO"
    11 #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__)
    12 #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__)
    13 char* AppName = NULL;
    14 //指定要hook的lib 库:
    15 MSConfig(MSFilterLibrary, "/system/lib/libdvm.so");
    16 //保留原来的地址:
    17 void *(*oldUnzOpen64)(const char* filepath);
    18 //替换的函数
    19 void *newUnzOpen64(const char* filepath){
    20     return oldUnzOpen64("/sdcard/myapk.apk");
    21 }
    22 //Hook dvmLoadNativeCode
    23 bool (*_dvmLoadNativeCode)(char* pathName, void* classLoader, char** detail);
    24 bool My_dvmLoadNativeCode(char* pathName, void* classLoader, char** detail){
    25     bool b_Result = _dvmLoadNativeCode(pathName,classLoader,detail);    //进行原来的调用,不影响程序运行
    26     //LOGD("dvmLoadNativeCode AppName:%s", AppName);
    27     if(strstr(pathName,"AppVerify") != NULL){
    28         LOGD("dvmLoadNativeCode Find Hook");
    29         MSImageRef image = MSGetImageByName(pathName);
    30             if(image != NULL){
    31                 void* mFun = MSFindSymbol(image, "unzOpen64");
    32                 //开始Hook fork
    33                 if(mFun != NULL){
    34                     LOGD("dvmLoadNativeCode Hook");
    35                     //MSHookFunction(mFun,(void*)&My_fork,(void**)&_fork);
    36             MSHookFunction(mFun, (void*)&newUnzOpen64, (void**)&oldUnzOpen64);
    37                 }
    38             }
    39     }
    40     return b_Result;
    41 }
    42 //在初始化的时候进行hook,具体如下:
    43 //Substrate entry point
    44 MSInitialize{
    45     __android_log_print(ANDROID_LOG_ERROR, TAG, "Substrate initialized.");
    46     MSImageRef image;
    47     image = MSGetImageByName("/system/lib/libdvm.so"); //载入lib
    48     if (image != NULL)
    49     {
    50         //注意这个是个c++函数,可以通过objdump来获取
    51         void * dvmload = MSFindSymbol(image, "_Z17dvmLoadNativeCodePKcP6ObjectPPc");
    52         if(dvmload == NULL)
    53         {
    54             LOGD("error find dvmLoadNativeCode ");
    55         }
    56         else{
    57             MSHookFunction(dvmload,(void*)&My_dvmLoadNativeCode,(void **)&_dvmLoadNativeCode);
    58         }
    59     }
    60     else{
    61         LOGD("ERROR FIND LIBDVM");
    62     }
    63 }

    这样就完成了hook代码的编写。安装运行就行了。

  • 相关阅读:
    ubuntu,day1基础命令,shutdown,man,touch,rm,mv,cp,stat,locale,apt,date,tzselect,cal,快捷方式,echo,查看文件
    day 7 编码
    NO.6 appium-网络设置
    NO.5 appium-滑动和点击
    NO.4 appium-定位
    NO.3 appium-退出/启动
    NO.2 appium-安装和卸载
    NO.1 appium-关于输入法
    Springboot框架搭建
    遍历Map的四种方法
  • 原文地址:https://www.cnblogs.com/goodhacker/p/4912904.html
Copyright © 2011-2022 走看看