安卓 dex 通用脱壳技术研究
Posted gm-201705
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了安卓 dex 通用脱壳技术研究相关的知识,希望对你有一定的参考价值。
/* 此为DexHunter实现的主要功能,进行内存dump,将class_def_items中dump出classdef和extra部分 */ void* DumpClass(void *parament) { while (timer_flag) { sleep(5); } DvmDex* pDvmDex=((struct arg*)parament)->pDvmDex; //pDvmDex代表一个dex文件 Object *loader=((struct arg*)parament)->loader; DexFile* pDexFile=pDvmDex->pDexFile; MemMapping * mem=&pDvmDex->memMap; u4 time=dvmGetRelativeTimeMsec(); ALOGI("GOT IT begin: %d ms",time); char *path = new char[100]; strcpy(path,dumppath); strcat(path,"classdef"); //构造classdef文件路径 FILE *fp = fopen(path, "wb+"); strcpy(path,dumppath); strcat(path,"extra"); //构造extra文件路径 FILE *fp1 = fopen(path,"wb+"); uint32_t mask=0x3ffff; char padding=0; const char* header="Landroid"; unsigned int num_class_defs=pDexFile->pHeader->classDefsSize; //dex文件的Header域,class_defs_size,标示了class_def域有几个class_def_item uint32_t total_pointer = mem->length-uint32_t(pDexFile->baseAddr-(const u1*)mem->addr); uint32_t rec=total_pointer; while (total_pointer&3) { total_pointer++; } int inc=total_pointer-rec; uint32_t start = pDexFile->pHeader->classDefsOff+sizeof(DexClassDef)*num_class_defs; uint32_t end = (uint32_t)((const u1*)mem->addr+mem->length-pDexFile->baseAddr); for (size_t i=0;i<num_class_defs;i++) //遍历所有class_def_item { bool need_extra=false; ClassObject * clazz=NULL; const u1* data=NULL; DexClassData* pData = NULL; bool pass=false; const DexClassDef *pClassDef = dexGetClassDef(pDvmDex->pDexFile, i); const char *descriptor = dexGetClassDescriptor(pDvmDex->pDexFile,pClassDef); if(!strncmp(header,descriptor,8)||!pClassDef->classDataOff) { pass=true; goto classdef; } clazz = dvmDefineClass(pDvmDex, descriptor, loader); //First Step:class加载 if (!clazz) { continue; } ALOGI("GOT IT class: %s",descriptor); if (!dvmIsClassInitialized(clazz)) { //Second Step:class初始化,遍历所有类进行初始化 if(dvmInitClass(clazz)){ //与dvmIsClassInitialized()函数共同完成初始化 ALOGI("GOT IT init: %s",descriptor); } } if(pClassDef->classDataOff<start || pClassDef->classDataOff>end) { need_extra=true; //是不是需要extra这一块,当存在class_data_off不在dex范围内时,就需要 } data=dexGetClassData(pDexFile, pClassDef); pData = ReadClassData(&data); if (!pData) { continue; } if (pData->directMethods) { for (uint32_t i=0; i<pData->header.directMethodsSize; i++) { Method *method = &(clazz->directMethods[i]); uint32_t ac = (method->accessFlags) & mask; ALOGI("GOT IT direct method name %s.%s",descriptor,method->name); if (!method->insns||ac&ACC_NATIVE) { if (pData->directMethods[i].codeOff) { need_extra = true; pData->directMethods[i].accessFlags=ac; pData->directMethods[i].codeOff=0; } continue; } u4 codeitem_off = u4((const u1*)method->insns-16-pDexFile->baseAddr); if (ac != pData->directMethods[i].accessFlags) { ALOGI("GOT IT method ac"); need_extra=true; pData->directMethods[i].accessFlags=ac; } if (codeitem_off!=pData->directMethods[i].codeOff&&((codeitem_off>=start&&codeitem_off<=end)||codeitem_off==0)) { ALOGI("GOT IT method code"); need_extra=true; pData->directMethods[i].codeOff=codeitem_off; } if ((codeitem_off<start || codeitem_off>end) && codeitem_off!=0) { //如果code_item_off不在dex文件范围内,则写入extra; fp1为extra的句柄 //这里使用的是slider.pptx,中的第二种方案,见p42 need_extra=true; pData->directMethods[i].codeOff = total_pointer; DexCode *code = (DexCode*)((const u1*)method->insns-16); uint8_t *item=(uint8_t *) code; int code_item_len = 0; if (code->triesSize) { const u1 * handler_data = dexGetCatchHandlerData(code); const u1** phandler=(const u1**)&handler_data; uint8_t * tail=codeitem_end(phandler); code_item_len = (int)(tail-item); }else{ code_item_len = 16+code->insnsSize*2; } ALOGI("GOT IT method code changed"); fwrite(item,1,code_item_len,fp1); fflush(fp1); total_pointer+=code_item_len; while (total_pointer&3) { fwrite(&padding,1,1,fp1); fflush(fp1); total_pointer++; } } } } if (pData->virtualMethods) { for (uint32_t i=0; i<pData->header.virtualMethodsSize; i++) { Method *method = &(clazz->virtualMethods[i]); uint32_t ac = (method->accessFlags) & mask; ALOGI("GOT IT virtual method name %s.%s",descriptor,method->name); if (!method->insns||ac&ACC_NATIVE) { if (pData->virtualMethods[i].codeOff) { need_extra = true; pData->virtualMethods[i].accessFlags=ac; pData->virtualMethods[i].codeOff=0; } continue; } u4 codeitem_off = u4((const u1 *)method->insns - 16 - pDexFile->baseAddr); if (ac != pData->virtualMethods[i].accessFlags) { ALOGI("GOT IT method ac"); need_extra=true; pData->virtualMethods[i].accessFlags=ac; } if (codeitem_off!=pData->virtualMethods[i].codeOff&&((codeitem_off>=start&&codeitem_off<=end)||codeitem_off==0)) { ALOGI("GOT IT method code"); need_extra=true; pData->virtualMethods[i].codeOff=codeitem_off; } if ((codeitem_off<start || codeitem_off>end)&&codeitem_off!=0) { need_extra=true; pData->virtualMethods[i].codeOff = total_pointer; DexCode *code = (DexCode*)((const u1*)method->insns-16); uint8_t *item=(uint8_t *) code; int code_item_len = 0; if (code->triesSize) { const u1 *handler_data = dexGetCatchHandlerData(code); const u1** phandler=(const u1**)&handler_data; uint8_t * tail=codeitem_end(phandler); code_item_len = (int)(tail-item); }else{ code_item_len = 16+code->insnsSize*2; } ALOGI("GOT IT method code changed"); fwrite(item,1,code_item_len,fp1); fflush(fp1); total_pointer+=code_item_len; while (total_pointer&3) { fwrite(&padding,1,1,fp1); fflush(fp1); total_pointer++; } } } } classdef: DexClassDef temp=*pClassDef; uint8_t *p = (uint8_t *)&temp; if (need_extra) { ALOGI("GOT IT classdata before"); int class_data_len = 0; uint8_t *out = EncodeClassData(pData,class_data_len); if (!out) { continue; } temp.classDataOff = total_pointer; fwrite(out,1,class_data_len,fp1); fflush(fp1); total_pointer+=class_data_len; while (total_pointer&3) { fwrite(&padding,1,1,fp1); fflush(fp1); total_pointer++; } free(out); ALOGI("GOT IT classdata written"); }else{ if (pData) { free(pData); } } if (pass) { temp.classDataOff=0; temp.annotationsOff=0; } ALOGI("GOT IT classdef"); fwrite(p, sizeof(DexClassDef), 1, fp); fflush(fp); } fclose(fp1); fclose(fp); //目前已经准备好了part1,classdef,data和extra 4部分文件 strcpy(path,dumppath); strcat(path,"whole.dex"); //组合4部分,并写入whole.dex fp = fopen(path,"wb+"); rewind(fp); int fd=-1; int r=-1; int len=0; char *addr=NULL; struct stat st; strcpy(path,dumppath); strcat(path,"part1"); fd=open(path,O_RDONLY,0666); if (fd==-1) { return NULL; } r=fstat(fd,&st); if(r==-1){ close(fd); return NULL; } len=st.st_size; addr=(char*)mmap(NULL,len,PROT_READ,MAP_PRIVATE,fd,0); fwrite(addr,1,len,fp); fflush(fp); munmap(addr,len); close(fd); strcpy(path,dumppath); strcat(path,"classdef"); fd=open(path,O_RDONLY,0666); if (fd==-1) { return NULL; } r=fstat(fd,&st); if(r==-1){ close(fd); return NULL; } len=st.st_size; addr=(char*)mmap(NULL,len,PROT_READ,MAP_PRIVATE,fd,0); fwrite(addr,1,len,fp); fflush(fp); munmap(addr,len); close(fd); strcpy(path,dumppath); strcat(path,"data"); fd=open(path,O_RDONLY,0666); if (fd==-1) { return NULL; } r=fstat(fd,&st); if(r==-1){ close(fd); return NULL; } len=st.st_size; addr=(char*)mmap(NULL,len,PROT_READ,MAP_PRIVATE,fd,0); fwrite(addr,1,len,fp); fflush(fp); munmap(addr,len); close(fd); while (inc>0) { fwrite(&padding,1,1,fp); fflush(fp); inc--; } strcpy(path,dumppath); strcat(path,"extra"); fd=open(path,O_RDONLY,0666); if (fd==-1) { return NULL; } r=fstat(fd,&st); if(r==-1){ close(fd); return NULL; } len=st.st_size; addr=(char*)mmap(NULL,len,PROT_READ,MAP_PRIVATE,fd,0); fwrite(addr,1,len,fp); fflush(fp); munmap(addr,len); close(fd); fclose(fp); delete path; time=dvmGetRelativeTimeMsec(); ALOGI("GOT IT end: %d ms",time); return NULL; } //------------------------added end----------------------//
以上是关于安卓 dex 通用脱壳技术研究的主要内容,如果未能解决你的问题,请参考以下文章