【安卓 dex 通用脱壳技术研究】亦余心之所善兮,虽九死其犹未悔。这篇文章主要讲述安卓 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=https://www.songbingjia.com/android/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=https://www.songbingjia.com/android/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----------------------//
推荐阅读
- H5页面关于android软键盘弹出顶起底部元素的解决方案
- Android Studio NDK开发环境搭建
- Android驱动中的remap_pfn_range()校验漏洞(CVE-2013-2596)
- Win 8系统下怎样打开/关闭Bing联机搜索?【图文详细教程】
- 如何处理Win8系统打开页面时提示未响应问题?
- Win8系统下打开应用商店提示脱机的3种处理技巧
- 笔记本Win8系统弹出“文字换转出错”提示怎样办
- win8系统文件失去该如何找到?
- 笔记本win8系统关闭鼠标单击锁定技巧的办法