首页
社区
课程
招聘
[原创]脱壳成长之路(2)-2代壳进阶(3)
发表于: 2020-2-4 22:05 6056

[原创]脱壳成长之路(2)-2代壳进阶(3)

2020-2-4 22:05
6056
样本:很老的x度加固

分析工具:ida、jeb、010、apktool

NativeHook:基于Substrate的Nativehook

Android系统: 4.4


上一篇我们已经初步修复了dex,然后这一篇也是最后一篇,把onCreate001修复。


修复onCreate001


先看Java层源代码

A.d和A.e 都是native函数,看到这里相信大家都已经有思路了,A.d肯定一定有对DexFile进行修复,把onCreate001的code_item变成正常的。A.e呢?经过一番测试(我分别dump调用A.e和不调用A.e进行对比),发现A.e是对修复的DexFile还原回错误的,为了防止我们直接dump修复后的dex。

那么这个时候,我个人思路,先防止它修复后还原,然后再指定时机进行Dump。注意这里指定时机,就是说一定要等到原程序调用A.d这个native函数之后,再进行dexFile的dump。

先通过nativehook,拦截A,e函数,下面直接上代码
jint new_JNI_OnLoad(JavaVM *vm, void *reserved) {

    vm->GetEnv((void **) &jniEnv, JNI_VERSION_1_4);
    //0x35c为RegisterNatives偏移地址
    elf_hook_Direct((void *) *(unsigned int *) ((*(unsigned int *) jniEnv) + 0x35C),
                    (void *) &myRegisterNatives, (void **) &oldRegisterNatives);
    return old_JNI_OnLoad(vm, reserved);
}


//修复函数
void new_d(JNIEnv *env, jclass c, jstring js) {
    log("%s",env->GetStringUTFChars(js, false));
    return old_d(env,c,js);
}

void (*old_e)(JNIEnv *env, jclass c,jstring js);

//还原函数
void new_e(JNIEnv *env, jclass c, jstring js) {
    //这里直接拦截它恢复
//    log("%s", "run new e");
//    log("%s",env->GetStringUTFChars(js, false));
//    return old_e(env,c,js);
}


void on_native_reg(JNIEnv *env, jclass c, const JNINativeMethod *m, jint n) {

    for (int i = 0; i < n; i++) {

        if (strcmp(m[i].name, "d") == 0) {
            elf_hook_Direct(m[i].fnPtr, (void *) &new_d, (void **) &old_d);
        }

        if (strcmp(m[i].name, "e") == 0) {
            elf_hook_Direct(m[i].fnPtr, (void *) &new_e, (void **) &old_e);
        }

    }

}

好的上面代码已经拦截了还原函数,那么下面我们就确认时机点了,我选择了Lcom/qsq/qianshengqian/LoginActivity这个时机点,确保SplashActivity已经onCreate了,然后再次dump DexFile,上代码

void *new_dexFindClass(const void *pDexFile, const char *descriptor) {
    DexFile *dexFile = (DexFile *) pDexFile;
    char *aim = "Lcom/qsq/qianshengqian/LoginActivity;";
    int cmp = strcmp(descriptor, aim);

    if (dexFile->pHeader->fileSize == 5573376 && a == 0 && cmp) {
        log("%s","start dump");
        a = 1;
        size_t size = dexFile->pHeader->fileSize;
        DexClassDef *pDef = dexFile->pClassDefs;
//        log("class def size is %d", dexFile->pHeader->classDefsSize);
        int classDefSize = dexFile->pHeader->classDefsSize;
        log("%d",classDefSize);
        //2.dex保留classdef。
        FILE *pFile = fopen("/data/data/com.qsq.qianshengqian/2.dex", "wb+");
        u4 currentLength =dexFile->pHeader->fileSize;
        for (int i = 0; i < classDefSize; ++i) {
            if (pDef->classDataOff != 0) {

                const u1 *start = dexGetClassData(dexFile, pDef);
                DexClassData *pData = ReadClassData(&start);

                int len = 0;
                u4 f_off = currentLength + len;
                uint8_t *string = EncodeClassData(pData, len);
                fwrite(string, 1, len, pFile);
                currentLength = currentLength + len;
                //重置偏移,
                if (i<4495) {
                    u4 *def_off = &(pDef->classDataOff);
                    *def_off = f_off;
                }
            }
            //重置annotation
            u4 *off = &(pDef->annotationsOff);
            *off = 0;
            pDef++;
        }
        log("%s","write compete");
        fclose(pFile);
        char *file_name = "/data/data/com.qsq.qianshengqian/1.dex";
        FILE *dex_file = fopen(file_name, "wb+");
        fwrite(dexFile->pHeader, dexFile->pHeader->fileSize, 1, dex_file);
        fclose(dex_file);

    }


    return old_findDex(pDexFile, descriptor);
}

同样我们这次dump好两个文件, 一个是修后后的dex,我们后面叫Fix_1.dex,另一个是修复后的class_data段,我们叫Fix_2.dex。然后再次拼接,上010看图。

Dump出来的文件有如下问题

1、header被处理了,膜(摩)数都没了。上面那个我自己加上去的

2、是一个相当不规则的文件,以至于baksmali都没办法转换。

不过我们可以先看看SplashActivity的CodeItem是不是修复了





OK,可以看到确实不一样了,那么下面我们要做的,就是把原dex进行修复(因为新dump出的dex太不规则了)。


这里我们先列一下,以免合并的时候懵逼了。

原dex:1.dex  这个是经过第一次修复后,onCreate001出问题的

原class_data段: 2.dex 这个是第一次dump出的class_data段

修复后的dex: Fix_1.dex

修复后的class_data段:Fix_2.dex 

然后我们就用1.dex与Fix_2.dex组合成一个新的dex,再将Fix_1.dex中的code_item覆盖到1.dex的code_item




可以看到已经修复成功了,到此为止 这个样本完成了。然后把样本以及代码资源奉上,谢谢大家的观看。



[课程]Android-CTF解题方法汇总!

最后于 2020-2-4 22:05 被GitRoy编辑 ,原因:
上传的附件:
收藏
免费 3
支持
分享
最新回复 (5)
雪    币: 1867
活跃值: (3763)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
2
2020-2-5 09:08
0
雪    币: 12502
活跃值: (3048)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
3
牛批,老哥要是能提供几个demo就更好了。
2020-2-5 10:17
0
雪    币: 1842
活跃值: (1164)
能力值: ( LV3,RANK:35 )
在线值:
发帖
回帖
粉丝
4
顶一个
2020-2-5 10:47
0
雪    币: 2510
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
5
感谢分享
2020-2-5 18:01
2
雪    币: 140
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
2020-2-9 15:56
0
游客
登录 | 注册 方可回帖
返回
//