本文共 3856 字,大约阅读时间需要 12 分钟。
要手动调用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中直接替换ExportMethodauto interface = FupkImpl::gUpkInterface;if (interface == nullptr) { FLOGE("Unable to found fupk interface"); return;}// Hook allinterface->ExportMethod = fupk_ExportMethod;
// 传递参数,然后直接调用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;}
上面dump下来的dex文件是非标准的,可能存在部分的class数据不合法,并且一些软件不认。所以需要一个写一个修复的server来跳过非法的数据。server主要修改了baksmali与smali的代码,自动跳过无法反编译的类。
Android加固发展到现在,经历了好几个大版本改动。最初的是dex整体加固,现在的是VMP加固,中间出了不少非常不错的脱壳机,其中最为经典的有2个:ZjDroid与dexHunter,这两个都是开源的,并且写得非常好,即使是放到今天来看,也具有相当的参考价值,想要学习脱壳的同学们可以拜读一下。另外,FUpk3是运行在dalvik上的,那么要在art下脱壳怎么办呢?道理还是一样的,只是art下会复杂很多, 跑解析的跑编译的都有,修复起来需要记录很多数据,这里由于某些原因就不公开art下的脱壳机了。
新手想要入门,需要什么?1. 一台谷歌亲儿子(nexus) 2. 一个Ubuntu系统 3. 一套完整的Android源码。平时有事没事可以多看看源码,刷刷机之类的。Android平台与Windows上的不同,到目前为止,Android上系统的优秀的教材实在是少,如果没人手把手地带入门的话,基本上就是在白做功,幸好大部分难点的解决方案答案都可以在源码里面找到,多熟悉一下总会有好处的。
转载地址:http://yvjvb.baihongyu.com/