FUPK原理图

要手动调用fupkInvokeMethod
在这里插入图片描述
在这里插入图片描述

bool DexDumper::fixMethodByDvm(DexSharedData &shared, DexMethod *dexMethod,
                               ClassDefBuilder* builder, u4 &lastIndex) {
    lastIndex = lastIndex + dexMethod->methodIdx;
    auto m = builder->getMethodMap(lastIndex);

    assert(m != nullptr && "Unable to fix MethodBy Dvm, this should happened");

    shared.mCurMethod = dexMethod;
    FupkImpl::fupkInvokeMethod(m);     /
    shared.mCurMethod = nullptr;
    return true;
}
/* @F8LEFT
 * This method is used to export some data for fupk3 to dump dex file.
 * Fupk3 will hook this method and get data from it.
 */
void fupkInvokeMethod(Method* meth) {
    // it is no need to init or link class, the code of the method will
    // not exec actually, so just ignore it
    // anyway, I should make sure this method has code to execute
    if (dvmIsMirandaMethod(meth) || dvmIsAbstractMethod(meth)) {
        return;
    }
    dvmInvokeMethod((Object*)0xF88FF88F, meth, NULL, NULL, NULL, true);
}

dvmInvokeMethod又会调用gFupk.ExportMethod

gFupk.ExportMethod在xposed的框架中加载so的过程中被设置为fupk_ExportMethod

也就是说,调用fixMethodByDvm 就会跳转到fupk_ExportMethod(void * thread,Method *method)

接口设计

c语言好像没有接口这种概念,作者整了个接口。

bool fupkExportMethod(Thread* self, const Method* method) {
    return false;
}

FupkInterface gFupk = {
    NULL, NULL, NULL, NULL, 
    fupkExportMethod
};

然后在xposed 的so中替换

// 在so中直接替换ExportMethod
auto interface = FupkImpl::gUpkInterface;
if (interface == nullptr) {
    FLOGE("Unable to found fupk interface");
    return;
}
// Hook all
interface->ExportMethod = fupk_ExportMethod;

dex重组

// 传递参数,然后直接调用
gUpkInterface->reserved0 = &shared;
shared.mCurMethod = dexMethod;
FupkImpl::fupkInvokeMethod(m);
shared.mCurMethod = nullptr;
// 在ExportMethod中直接提取CodeItem数据
bool fupk_ExportMethod(void *thread, Method *method) {
    DexSharedData* shared = (DexSharedData*)gUpkInterface->reserved0;
    DexMethod* dexMethod = shared->mCurMethod;
    u4 ac = (method->accessFlags) & mask;
    if (method->insns == nullptr || ac & ACC_NATIVE) {
        if (ac & ACC_ABSTRACT) {
            ac = ac & ~ACC_NATIVE;
        }
        dexMethod->accessFlags = ac;
        dexMethod->codeOff = 0;
        return false;
    }

    if (ac != dexMethod->accessFlags) {
        dexMethod->accessFlags = ac;
    }
    dexMethod->codeOff = shared->total_point;
    DexCode *code = (DexCode*)((const u1*) method->insns - 16);

    u1 *item = (u1*) code;
    int code_item_len = 0;
    if (code->triesSize) {
        const u1*handler_data = dexGetCatchHandlerData(code);
        const u1 **phandler = (const u1**) &handler_data;
        u1 *tail = codeitem_end(phandler);
        code_item_len = (int)(tail - item);
    } else {
        code_item_len = 16 + code->insnsSize * 2;
    }
    shared->extra.append((char*)item, code_item_len);
    shared->total_point += code_item_len;
    while(shared->total_point & 3) {
        shared->extra.push_back(shared->padding);
        shared->total_point++;
    }
    return true;
}

这样,所有加密的数据都提取出来了,直接进行组合,以加密的方式dump出来。

size_t myfwrite(const void* buffer, size_t size, size_t count, FILE* stream) {
    char *tmp = new char[size * count];
    mymemcpy(tmp, buffer, size * count);
    for (size_t i = 0; i < size * count; ++i) {
        tmp[i] ^= encryptKey;
    }
    size_t rel = fwrite(tmp, size, count, stream);
    delete []tmp;
    return rel;
}
  1. dex修复

上面dump下来的dex文件是非标准的,可能存在部分的class数据不合法,并且一些软件不认。所以需要一个写一个修复的server来跳过非法的数据。server主要修改了baksmali与smali的代码,自动跳过无法反编译的类。

  1. 其他

Android加固发展到现在,经历了好几个大版本改动。最初的是dex整体加固,现在的是VMP加固,中间出了不少非常不错的脱壳机,其中最为经典的有2个:ZjDroid与dexHunter,这两个都是开源的,并且写得非常好,即使是放到今天来看,也具有相当的参考价值,想要学习脱壳的同学们可以拜读一下。另外,FUpk3是运行在dalvik上的,那么要在art下脱壳怎么办呢?道理还是一样的,只是art下会复杂很多, 跑解析的跑编译的都有,修复起来需要记录很多数据,这里由于某些原因就不公开art下的脱壳机了。

  1. 写在最后

新手想要入门,需要什么?1. 一台谷歌亲儿子(nexus) 2. 一个Ubuntu系统 3. 一套完整的Android源码。平时有事没事可以多看看源码,刷刷机之类的。Android平台与Windows上的不同,到目前为止,Android上系统的优秀的教材实在是少,如果没人手把手地带入门的话,基本上就是在白做功,幸好大部分难点的解决方案答案都可以在源码里面找到,多熟悉一下总会有好处的。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值