记脱壳百度钱包app

记脱壳百度钱包app

获取百度钱包app的dex

  • apk中无原始dex,只有加载器,真正的dex在资源中加密
  • 在启动过程中存在反java层和c层调试,检测调试器(包括android_server),运行后则无
  • 考虑app启动时调用加载dex的api和每次搜索java类时解析DexFile的api ,编写cydia插件拦截dexFileParse得到4个文件dex,其中7M的为我们需要的dex,反编译失败;再次尝试dexFindClass获取内存dex,反编译失败
  • 研究dex结构发现内存dex的头部被擦除,另外类实现的字节码指针由局部偏移修改成超大地址,可知字节码被另外分配空间,需要还原内存dex
  • 遍历每个类结构,得到另外分配的地址范围,将这段数据dump出来,附加到原dex文件尾,修改偏移即可
  • 反编译dex,最后得到50M的smali

dexFindClass

if __name__=='__main__':
    pDexFile=0x75741828
    pOptHeader=Dword(pDexFile+0)
    pHeader=Dword(pDexFile+4)
    pStringIds=Dword(pDexFile+8)
    pTypeIds=Dword(pDexFile+12)
    pFieldIds=Dword(pDexFile+16)
    pMethodIds=Dword(pDexFile+20)
    pProtoIds=Dword(pDexFile+24)
    pClassDefs=Dword(pDexFile+28)
    pLinkData=Dword(pDexFile+32)
    pClassLookup=Dword(pDexFile+36)
    DexBase=Dword(pDexFile+44)

    print "DexBase=%08x ClassDefBase=%08x classDefsSize=%d"%(DexBase,pClassDefs,classDefsSize)
    classDefsSize=Dword(pHeader+0x60)
    
    
    minaddr=0xffffffff
    maxaddr=0
    for i in range(0,classDefsSize):
        off=pClassDefs+32*i
        classIdx=Dword(off)
        classDataOff=(Dword(off+24)+DexBase)&0xFFFFFFFF;
        if(classDataOff!=0x75f40028):
            if(classDataOff < minaddr):
                minaddr=classDataOff
            if(classDataOff > maxaddr):
                maxaddr=classDataOff
        print "%08x"%classDataOff
        #datastr=""
        #for j in range(0,16):
        #    datastr += "%02x"%(Byte(classDataOff+j))
        #print "classIdx=%04d,classDataOff=%08x,sig:%s"%(classIdx,classDataOff,datastr)
    print "min=%08x,max=%08x"%(minaddr,maxaddr)
#include <jni.h>
#include "substrate.h"
#include <android/log.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <string.h>
#include <sys/stat.h>

#define TAG "HOOKTEST"

#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__)

struct DexOptHeader
{
    char magic[8];
    u_int32_t dexOffset;
    u_int32_t dexLength;
    u_int32_t depsOffset;
    u_int32_t depsLength;
    u_int32_t optOffset;
    u_int32_t optLength;
    u_int32_t flags;
    u_int32_t checksum;
};

struct DexHeader
{
    char      magic[8];
    u_int32_t checksum;
    char      signature[20];
    u_int32_t  fileSize;
    u_int32_t  headerSize;
    u_int32_t  endianTag;
    u_int32_t  linkSize;
    u_int32_t  linkOff;
    u_int32_t  mapOff;
    u_int32_t  stringIdsSize;
    u_int32_t  stringIdsOff;
    u_int32_t  typeIdsSize;
    u_int32_t  typeIdsOff;
    u_int32_t  protoIdsSize;
    u_int32_t  protoIdsOff;
    u_int32_t  fieldIdsSize;
    u_int32_t  fieldIdsOff;
    u_int32_t  methodIdsSize;
    u_int32_t  methodIdsOff;
    u_int32_t  classDefsSize;
    u_int32_t  classDefsOff;
    u_int32_t  dataSize;
    u_int32_t  dataOff;
};

struct DexFile
{
    struct DexOptHeader* pOptHeader;
    struct DexHeader*    pHeader;
};


MSConfig(MSFilterLibrary, "libdvm.so"); // 要hook的so库,后缀名即可。

static int num=0;
void* new_dexFileParse(const unsigned char* data, size_t length, int flags);
void* (*old_dexFileParse)(const unsigned char* data, size_t length, int flags);

void* new_dexFindClass(DexFile* pDexFile, const char* descriptor);
void* (*old_dexFindClass)(DexFile* pDexFile, const char* descriptor);

int (*old_execve)(char* name, char* argv, char* envp);
int new_execve(char* name, char* argv, char* envp);

bool getProcPackage(int pid, char* buf) {
    char filename[256];
    sprintf(filename,"/proc/%d/cmdline",pid);
    FILE *f = fopen(filename,"r");
    if (f)
    {
        fread(buf,256,1,f);
        fclose(f);
    }
}

char* whitelist[]=
{
        "meizu",
        "miui",
        "xiaomi",
        "android",
        "app_process",
        "system_server",
        "zygote",
};
#define arraysize(x) (sizeof(x)/sizeof(x[0]))

void* new_dexFileParse(const unsigned char* data, size_t length, int flags)
{
    LOGI("Enter dexFileParse!!!");
    char filename[256];
    char name[256];
    getProcPackage(getpid(),name);
    bool isinlist = false;

    if(name[0] == '\0')
        isinlist = true;
    for(int i=0;i<arraysize(whitelist) && !isinlist;i++)
    {
        if(strstr(name, whitelist[i]))
            isinlist = true;
    }
    if(!isinlist)
    {

        int len=strlen(name);
        for(int i=0;i<len;i++)
        {
            if (name[i] >= 'a' && name[i] <= 'z' || name[i] >= '0' && name[i] <= '9' ||
                    name[i] >= 'A' && name[i] <= 'Z' || name[i] == '.') {
            }
            else {
                name[i] = '_';
            }
        }

        sprintf(filename, "/data/local/tmp/unpatch-%s-%d-%d.odex", name, getpid(), num++);
        LOGI("patch %s",filename);
        FILE *fp = fopen(filename, "wb");
        if (!fp)
            LOGI("fopen failed!");
        else {
            fwrite((void *) data, length, 1, fp);
            fclose(fp);
        }
    }
    return old_dexFileParse(data, length, flags);
}


int count=0;
void* new_dexFindClass(DexFile* pDexFile, const char* descriptor)
{
    char name[128];
    getProcPackage(getpid(),name);

    void* pdata = old_dexFindClass(pDexFile, descriptor);
    if(0 != strstr(name, "com.baidu.wallet") && pdata && strstr(descriptor, "Lcom/baidu/wallet"))
    {
        LOGI("--------%s-%s-%x-%s-%x-------",name,descriptor,pdata,pDexFile->pOptHeader->magic,pDexFile);
        if(pdata && count < 2)
        {
            char buf[32];
            sprintf(buf,"/data/local/tmp/wallet-%s%d.odex",name,count++);
            if(0!=access(buf, F_OK))
            {
                FILE* fp = fopen(buf, "wb");
                if(fp != 0)
                {
                    fwrite(pDexFile->pOptHeader, pDexFile->pOptHeader->optOffset + pDexFile->pOptHeader->optLength, 1, fp);
                    LOGI("----------Dumped %s---------",buf);
                    fclose(fp);
                }
            }
        }
    }
    return pdata;
}

int new_execve(char* name, char* argv, char* envp)
{//从execve拦kill
    int ret = old_execve(name, argv, envp);
    LOGI("evec:%s %s",name,argv);
    return ret;
}

//Substrate entry point
MSInitialize{
    LOGI("Substrate initialized.");
    MSImageRef image;
    //image = MSGetImageByName("/system/lib/libdvm.so"); // 此处要绝对路径
    image = MSGetImageByName("/system/lib/libc.so"); // 此处要绝对路径
    if (image != NULL)
    {
        LOGI("dvm image: 0x%08X", (void*)image);
        //void * dvmload = MSFindSymbol(image, "_Z12dexFileParsePKhji");
        //void * dvmload = MSFindSymbol(image, "_Z12dexFindClassPK7DexFilePKc");
        void * dvmload = MSFindSymbol(image, "execve");
        if(dvmload == NULL)
        {
            //LOGI("error find dexFindClass.");
            LOGI("error find execve");
        }
        else
        {
            //MSHookFunction(dvmload,(void*)&new_dexFileParse,(void **)&old_dexFileParse);
           // MSHookFunction(dvmload,(void*)&new_dexFindClass, (void **)&old_dexFindClass);
           // LOGI("hook dexFindClasas sucess.");
            MSHookFunction(dvmload,(void*)&new_execve, (void **)&old_execve);
            LOGI("success hook execve");
        }
    }
    else{
        LOGI("can not find libdvm.");
    }
}