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

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 10355|回复: 14
收起左侧

[Android 原创] CydiaSubtrateHook——Native注册混淆破解(更新版)

  [复制链接]
一夜梦惊人 发表于 2019-1-1 22:06
本帖最后由 一夜梦惊人 于 2019-1-3 21:39 编辑

前言:今天是2019年1月1号,首先祝大家新年快乐!然后前段时间我在看了姜维大佬的文章后,也觉得必须要搞个这样子的东西,于是就有了本文。
准备工具:海马玩模拟器、CydiaSubtrate(以下简称CS)、AS3.2
一、资金贫穷所以没有用真机,只能用模拟器。<请注意,模拟器必须用海马玩模拟器,其他的模拟器基本都是不可以的>,安装CS自行百度,想必对于各位都是So easy!
二、AS上编写Hook代码。首先下载CS的SDK,文件我会给出。打开AS新建一个project,由于我们不需要activity,所以就No Activity咯。在main目录下新建个jni目录,把SDK中的so和h文件复制到下面。
捕获.PNG
其中Android.mk的代码如下:
[Asm] 纯文本查看 复制代码
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    := CydiaHook.cy
LOCAL_SRC_FILES := CydiaNativeHook.cpp
LOCAL_LDLIBS += -L$(SYSROOT)/usr/lib -llog
LOCAL_LDLIBS += -L$(LOCAL_PATH) -lsubstrate-dvm -lsubstrate
include $(BUILD_SHARED_LIBRARY)

大家可以根据自己的不同进行修改,其中需要注意的是你写的CS代码必须要以.cy结尾。然后还要修改build.gradle。
捕获.PNG
由于我只在模拟器上进行运行,所以我只生成x86的。环境基本配置就是这样子了。
三、大家都知道Native注册函数是RegisterNatives,而
RegisterNatives方法在libdvm.so里面,实现代码则是jni.cpp
。而libdvm.so一般在system/lib下,但是请注意可能会有所不同,比如海马玩模拟器就有两个libdvm.so文件,经过我的查看,system/lib/arm下的才能使用。IDA打开libdvm.so,直接查找
RegisterNatives
。PS:未更新版中使用的AndroidRuntime:RegisterNativeMethod,但是当时查询的资料没有说明,这个方法是系统自带的服务的Native注册方法,而非系统服务APP调用的Native注册方法则是不同的。最后会给出资料给大家看。

捕获.PNG
但是呢很抱歉,没有。经过我的寻找,最终经过确认是sub_668c4方法。这个方法是没有EXPORT的,那么只能曲线救国,而我选用的就是Hook其他方法,然后计算偏移量转到Native注册方法sub_668c4方法就行。sub_668c4方法
的参数和返回值这些东西则是可以通过查看Android源码来得到。我选用的方法就是dexFileParse方法,而他的EXPORT则是_Z12dexFileParsePKhji(这里不讲解,给出的资料会说)

接下来我就贴上我写的代码吧!
[C++] 纯文本查看 复制代码
//
// Created by Poity on 2019/1/1.
//
#include <jni.h>
#include "substrate.h"
#include <android/log.h>
#include <unistd.h>
#include <dirent.h>

#define TAG "CydiaHook"

#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__)

MSConfig(MSFilterLibrary, "/system/lib/arm/libdvm.so");

void * get_base_of_lib_from_maps(const char *SoName)
{
    void * imagehandle = dlopen(SoName, RTLD_LOCAL | RTLD_LAZY);
    if (SoName == NULL)
        return NULL;
    if (imagehandle == NULL){
        return NULL;
    }
    uintptr_t * irc = NULL;
    FILE *f = NULL;
    char line[200] = {0};
    char *state = NULL;
    char *tok = NULL;
    char * baseAddr = NULL;
    if ((f = fopen("/proc/self/maps", "r")) == NULL)
        return NULL;
    while (fgets(line, 199, f) != NULL)
    {
        tok = strtok_r(line, "-", &state);
        baseAddr = tok;
        tok = strtok_r(NULL, "\t ", &state);
        tok = strtok_r(NULL, "\t ", &state); // "r-xp" field
        tok = strtok_r(NULL, "\t ", &state); // "0000000" field
        tok = strtok_r(NULL, "\t ", &state); // "01:02" field
        tok = strtok_r(NULL, "\t ", &state); // "133224" field
        tok = strtok_r(NULL, "\t ", &state); // path field

        if (tok != NULL) {
            int i;
            for (i = (int)strlen(tok)-1; i >= 0; --i) {
                if (!(tok[i] == ' ' || tok[i] == '\r' || tok[i] == '\n' || tok[i] == '\t'))
                    break;
                tok[i] = 0;
            }
            {
                size_t toklen = strlen(tok);
                size_t solen = strlen(SoName);
                if (toklen > 0) {
                    if (toklen >= solen && strcmp(tok + (toklen - solen), SoName) == 0) {
                        fclose(f);
                        return (uintptr_t*)strtoll(baseAddr,NULL,16);
                    }
                }
            }
        }
    }
    fclose(f);
    return NULL;
}

jint (*old_RegiserNatives)(JNIEnv *env, jclass clazz, const JNINativeMethod* methods,jint nMethods) = NULL;
jint new_RegiserNatives(JNIEnv *env, jclass clazz, const JNINativeMethod* methods,jint nMethods){
    //传入你想Hookd的So文件的绝对地址
    void * Soaddress = get_base_of_lib_from_maps("");
    if (Soaddress != (void *) env){
//去掉你不想要的,如果有多个就自己修改把        LOGD("exclude So address %p",Soaddress);
        return old_RegiserNatives(env,clazz,methods,nMethods);
    }
    LOGD("------------------------------------------------");
    LOGD("env:%p,class:%p,methods:%p,methods_num:%d",env,clazz,methods,nMethods);
    LOGD("------------------------------------------------");
    for (int i = 0;i < nMethods;i++){
        LOGD("name:%s,sign:%s,address:%p",methods[i].name,methods[i].signature,methods[i].fnPtr);
    }
    LOGD("------------------------------------------------");
    return old_RegiserNatives(env,clazz,methods,nMethods);
}

void * Hook_Symbol(const char * LibraryName, const char * SymbolName){
    void * handle = dlopen(LibraryName,RTLD_GLOBAL | RTLD_NOW);
    if (handle != NULL){
        LOGD("Hook so %s success",LibraryName);
        void * symbol = dlsym(handle,SymbolName);
        if (symbol != NULL){
            LOGD("Hook function %s success",SymbolName);
            return symbol;
        } else{
            LOGD("error find functicon:%s",SymbolName);
            LOGD("dl error:%s",dlerror());
            return NULL;
        }
    } else{
        LOGD("error find so : %s",LibraryName);
        return NULL;
    }
}

MSInitialize{
    LOGD("CydiaHook MSinitialize.");
    MSImageRef image = MSGetImageByName("/system/lib/arm/libdvm.so");
    if (image != NULL){
        LOGD("Hook so libdvm.so success");
        void * function_address = MSFindSymbol(image,"_Z12dexFileParsePKhji");
        if (function_address != NULL){
            LOGD("get _Z12dexFileParsePKhji address success");
            LOGD("begin hook funvtion sub_668c4");
            void * RegiserNatives = (void *)((uint32_t)function_address - 0x43f0); //function_address:lib_base+0xc4990 差值:43f0
                    LOGD("RegiserNatives address:%p",RegiserNatives);
            MSHookFunction(RegiserNatives,(void*)&new_RegiserNatives, (void **)&old_RegiserNatives);
        } else{
            LOGD("error find functicon _Z12dexFileParsePKhji");
        }
    } else{
        LOGD("error find so : libdvm.so");
    }
}

代码中有个Hook_Symbol方法,这个方法看代码大家就知道其实跟MSGetImageByName和MSFindSymbol的方法是重复的,但是为什么我还会保留呢?因为其实大家Hook的可能Hook的时候还没有加载到进程空间里面,你用CS自带的是Hook不到的。所以为了方便大家我就保留下来了!代码大家自己看吧,我就不讲解了(还有一些需要改进,大家根据自己需求来改进吧)。
贴一下模拟器的log吧。
捕获.PNG
最后希望大家多多评分,谢谢!
资料链接:
1.https://www.52pojie.cn/thread-540077-1-1.htmlHook Android C代码(Cydia Substrate)
2.https://www.androidos.net.cn/android/4.2.2_r1/xref/dalvik/vm/Jni.cpp (Android 中jni.cpp代码)
3.https://www.androidos.net.cn/article/fmJJxVeqqg.html (Dalvik虚拟机JNI方法的注册过程分析)
4.https://www.52pojie.cn/thread-800279-1-1.htmlAndroid中-抖音火山视频的Native注册混淆函数获取方法
3.CS的SDK下载链接:http://asdk.cydiasubstrate.com/zips/cydia_substrate-r2.zip

免费评分

参与人数 6威望 +1 吾爱币 +14 热心值 +6 收起 理由
minighost + 1 + 1 我很赞同!
cherubines + 1 + 1 很厉害 目前能看懂一些java代码 还没有接触到jni,所以看不懂这篇文章。 .
fanfan491 + 1 + 1 我很赞同!
Anonymous、 + 1 + 1 我很赞同!
zhczf + 1 + 1 我很赞同!
qtfreet00 + 1 + 9 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

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

 楼主| 一夜梦惊人 发表于 2019-1-1 22:22
本文有些Bug。通过pid获取APP名字,但是pid是Android_runtime的,所以一旦用pid排除是不可能的。有大佬的说下解决思路。我将会重新编辑
新司机丶听雪 发表于 2019-1-1 23:47
wangxd 发表于 2019-1-2 05:00
a4531469 发表于 2019-1-2 11:48
这是什么原理??还是没说清楚呀
yidaozi 发表于 2019-1-2 13:36
一语惊醒梦中人
kanxue2018 发表于 2019-1-2 18:40
感谢分享技术
lulu6348055 发表于 2019-1-3 01:39

感谢分享技术,虽然我不明白
星煌 发表于 2019-1-3 10:47
不明觉厉
garen 发表于 2019-1-3 14:19
厉害啊 大神
您需要登录后才可以回帖 登录 | 注册[Register]

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

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

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

GMT+8, 2024-4-23 17:10

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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