分析Dexhunter
来源:互联网 发布:金和网络 陈耀泉 编辑:程序博客网 时间:2024/05/24 06:05
—–我又回来csdn开始记流水账了
源码位置:https://github.com/zyq8709/DexHunter
配置工具:
4.4.3版本的nexus5手机
下载好的源码和编译环境
我们先谈用法:
置换源码中的dalvik\vm\native\dalvik_system_DexFile.cpp文件然后 make libdvm 编译 用生成的libdvm.so替换系统中的/system/lib/libdvm.so即可导入dexname文件 并push到data目录下 并chmod 777dexname里面写的是加载dex的位置 和输出脱壳的dex的位置
这是dexhunter里面改变的代码dalvik_system_DexFile.cpp
加入的第一段代码
#include <asm/siginfo.h>#include "libdex/DexClass.h"#include <sys/stat.h>#include <fcntl.h>#include <sys/mman.h>static char dexname[100]={0};static char dumppath[100]={0};static bool readable=true;static pthread_mutex_t read_mutex;static bool flag=true;static pthread_mutex_t mutex;static bool timer_flag=true;static timer_t timerId;struct arg{ DvmDex* pDvmDex; Object * loader;}param;void timer_thread(sigval_t){ timer_flag=false; timer_delete(timerId); ALOGI("GOT IT time up");}void* ReadThread(void *arg){ FILE *fp = NULL; while (dexname[0]==0||dumppath[0]==0) { fp=fopen("/data/dexname", "r"); if (fp==NULL) { sleep(1); continue; } fgets(dexname,99,fp); dexname[strlen(dexname)-1]=0; fgets(dumppath,99,fp); dumppath[strlen(dumppath)-1]=0; fclose(fp); fp=NULL; } struct sigevent sev; sev.sigev_notify=SIGEV_THREAD; sev.sigev_value.sival_ptr=&timerId; sev.sigev_notify_function=timer_thread; sev.sigev_notify_attributes = NULL; timer_create(CLOCK_REALTIME,&sev,&timerId); struct itimerspec ts; ts.it_value.tv_sec=5; ts.it_value.tv_nsec=0; ts.it_interval.tv_sec=0; ts.it_interval.tv_nsec=0; timer_settime(timerId,0,&ts,NULL); return NULL;}void ReadClassDataHeader(const uint8_t** pData, DexClassDataHeader *pHeader) { pHeader->staticFieldsSize = readUnsignedLeb128(pData); pHeader->instanceFieldsSize = readUnsignedLeb128(pData); pHeader->directMethodsSize = readUnsignedLeb128(pData); pHeader->virtualMethodsSize = readUnsignedLeb128(pData);}void ReadClassDataField(const uint8_t** pData, DexField* pField) { pField->fieldIdx = readUnsignedLeb128(pData); pField->accessFlags = readUnsignedLeb128(pData);}void ReadClassDataMethod(const uint8_t** pData, DexMethod* pMethod) { pMethod->methodIdx = readUnsignedLeb128(pData); pMethod->accessFlags = readUnsignedLeb128(pData); pMethod->codeOff = readUnsignedLeb128(pData);}DexClassData* ReadClassData(const uint8_t** pData) { DexClassDataHeader header; if (*pData == NULL) { return NULL; } ReadClassDataHeader(pData,&header); size_t resultSize = sizeof(DexClassData) + (header.staticFieldsSize * sizeof(DexField)) + (header.instanceFieldsSize * sizeof(DexField)) + (header.directMethodsSize * sizeof(DexMethod)) + (header.virtualMethodsSize * sizeof(DexMethod)); DexClassData* result = (DexClassData*) malloc(resultSize); if (result == NULL) { return NULL; } uint8_t* ptr = ((uint8_t*) result) + sizeof(DexClassData); result->header = header; if (header.staticFieldsSize != 0) { result->staticFields = (DexField*) ptr; ptr += header.staticFieldsSize * sizeof(DexField); } else { result->staticFields = NULL; } if (header.instanceFieldsSize != 0) { result->instanceFields = (DexField*) ptr; ptr += header.instanceFieldsSize * sizeof(DexField); } else { result->instanceFields = NULL; } if (header.directMethodsSize != 0) { result->directMethods = (DexMethod*) ptr; ptr += header.directMethodsSize * sizeof(DexMethod); } else { result->directMethods = NULL; } if (header.virtualMethodsSize != 0) { result->virtualMethods = (DexMethod*) ptr; } else { result->virtualMethods = NULL; } for (uint32_t i = 0; i < header.staticFieldsSize; i++) { ReadClassDataField(pData, &result->staticFields[i]); } for (uint32_t i = 0; i < header.instanceFieldsSize; i++) { ReadClassDataField(pData, &result->instanceFields[i]); } for (uint32_t i = 0; i < header.directMethodsSize; i++) { ReadClassDataMethod(pData, &result->directMethods[i]); } for (uint32_t i = 0; i < header.virtualMethodsSize; i++) { ReadClassDataMethod(pData, &result->virtualMethods[i]); } return result;}void writeLeb128(uint8_t ** ptr, uint32_t data){ while (true) { uint8_t out = data & 0x7f; if (out != data) { *(*ptr)++ = out | 0x80; data >>= 7; } else { *(*ptr)++ = out; break; } }}uint8_t* EncodeClassData(DexClassData *pData, int& len){ len=0; len+=unsignedLeb128Size(pData->header.staticFieldsSize); len+=unsignedLeb128Size(pData->header.instanceFieldsSize); len+=unsignedLeb128Size(pData->header.directMethodsSize); len+=unsignedLeb128Size(pData->header.virtualMethodsSize); if (pData->staticFields) { for (uint32_t i = 0; i < pData->header.staticFieldsSize; i++) { len+=unsignedLeb128Size(pData->staticFields[i].fieldIdx); len+=unsignedLeb128Size(pData->staticFields[i].accessFlags); } } if (pData->instanceFields) { for (uint32_t i = 0; i < pData->header.instanceFieldsSize; i++) { len+=unsignedLeb128Size(pData->instanceFields[i].fieldIdx); len+=unsignedLeb128Size(pData->instanceFields[i].accessFlags); } } if (pData->directMethods) { for (uint32_t i=0; i<pData->header.directMethodsSize; i++) { len+=unsignedLeb128Size(pData->directMethods[i].methodIdx); len+=unsignedLeb128Size(pData->directMethods[i].accessFlags); len+=unsignedLeb128Size(pData->directMethods[i].codeOff); } } if (pData->virtualMethods) { for (uint32_t i=0; i<pData->header.virtualMethodsSize; i++) { len+=unsignedLeb128Size(pData->virtualMethods[i].methodIdx); len+=unsignedLeb128Size(pData->virtualMethods[i].accessFlags); len+=unsignedLeb128Size(pData->virtualMethods[i].codeOff); } } uint8_t * store = (uint8_t *) malloc(len); if (!store) { return NULL; } uint8_t * result=store; writeLeb128(&store,pData->header.staticFieldsSize); writeLeb128(&store,pData->header.instanceFieldsSize); writeLeb128(&store,pData->header.directMethodsSize); writeLeb128(&store,pData->header.virtualMethodsSize); if (pData->staticFields) { for (uint32_t i = 0; i < pData->header.staticFieldsSize; i++) { writeLeb128(&store,pData->staticFields[i].fieldIdx); writeLeb128(&store,pData->staticFields[i].accessFlags); } } if (pData->instanceFields) { for (uint32_t i = 0; i < pData->header.instanceFieldsSize; i++) { writeLeb128(&store,pData->instanceFields[i].fieldIdx); writeLeb128(&store,pData->instanceFields[i].accessFlags); } } if (pData->directMethods) { for (uint32_t i=0; i<pData->header.directMethodsSize; i++) { writeLeb128(&store,pData->directMethods[i].methodIdx); writeLeb128(&store,pData->directMethods[i].accessFlags); writeLeb128(&store,pData->directMethods[i].codeOff); } } if (pData->virtualMethods) { for (uint32_t i=0; i<pData->header.virtualMethodsSize; i++) { writeLeb128(&store,pData->virtualMethods[i].methodIdx); writeLeb128(&store,pData->virtualMethods[i].accessFlags); writeLeb128(&store,pData->virtualMethods[i].codeOff); } } free(pData); return result;}uint8_t* codeitem_end(const u1** pData){ uint32_t num_of_list = readUnsignedLeb128(pData); for (;num_of_list>0;num_of_list--) { int32_t num_of_handlers=readSignedLeb128(pData); int num=num_of_handlers; if (num_of_handlers<=0) { num=-num_of_handlers; } for (; num > 0; num--) { readUnsignedLeb128(pData); readUnsignedLeb128(pData); } if (num_of_handlers<=0) { readUnsignedLeb128(pData); } } return (uint8_t*)(*pData);}void* DumpClass(void *parament){ while (timer_flag) { sleep(5); } DvmDex* pDvmDex=((struct arg*)parament)->pDvmDex; 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"); FILE *fp = fopen(path, "wb+"); strcpy(path,dumppath); strcat(path,"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; 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++) { 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); if (!clazz) { continue; } ALOGI("GOT IT class: %s",descriptor); if (!dvmIsClassInitialized(clazz)) { if(dvmInitClass(clazz)){ ALOGI("GOT IT init: %s",descriptor); } } if(pClassDef->classDataOff<start || pClassDef->classDataOff>end) { need_extra=true; } 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) { 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); strcpy(path,dumppath); strcat(path,"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 begin----------------------// int uid=getuid(); if (uid) { if (readable) { pthread_mutex_lock(&read_mutex); if (readable) { readable=false; pthread_mutex_unlock(&read_mutex); pthread_t read_thread; pthread_create(&read_thread, NULL, ReadThread, NULL); }else{ pthread_mutex_unlock(&read_mutex); } } } if(uid&&strcmp(dexname,"")){ char * res=strstr(pDexOrJar->fileName, dexname); if (res&&flag) { pthread_mutex_lock(&mutex); if (flag) { flag = false; pthread_mutex_unlock(&mutex); DexFile* pDexFile=pDvmDex->pDexFile; MemMapping * mem=&pDvmDex->memMap; char * temp=new char[100]; strcpy(temp,dumppath); strcat(temp,"part1"); FILE *fp = fopen(temp, "wb+"); const u1 *addr = (const u1*)mem->addr; int length=int(pDexFile->baseAddr+pDexFile->pHeader->classDefsOff-addr); fwrite(addr,1,length,fp); fflush(fp); fclose(fp); strcpy(temp,dumppath); strcat(temp,"data"); fp = fopen(temp, "wb+"); addr = pDexFile->baseAddr+pDexFile->pHeader->classDefsOff+sizeof(DexClassDef)*pDexFile->pHeader->classDefsSize; length=int((const u1*)mem->addr+mem->length-addr); fwrite(addr,1,length,fp); fflush(fp); fclose(fp); delete temp; param.loader=loader; param.pDvmDex=pDvmDex; pthread_t dumpthread; dvmCreateInternalThread(&dumpthread,"ClassDumper",DumpClass,(void*)¶m); }else{ pthread_mutex_unlock(&mutex); } } }//------------------------added end----------------------//
0 0
- 分析Dexhunter
- DexHunter脱壳神器分析
- DexHunter
- DexHunter的原理分析和使用说明(一)
- DexHunter的原理分析和使用说明(二)
- DexHunter--2
- DexHunter学习笔记记录
- DexHunter学习笔记记录2
- 分析
- 分析
- 分析
- 分析
- 分析
- 分析
- 分析
- 分析
- 分析
- 大家帮忙分析分析!
- SDK更新地址
- 10进制转16进制(不用函数)
- 仿《雷霆战机》飞行射击手游开发--新手引导
- 百练_2888字符串中的数字
- 使用sql语句创建数据库和表
- 分析Dexhunter
- jquery.tiptext.js 文本框、文本域文字提示工具
- Android使用每日必应美图作为启动页背景图片
- IOS开发学习笔记之数据存储
- ACM最短路问题
- iOS图片查看滚动放大缩小
- 深度学习(8):Supervised Learning
- 蓝桥杯 历届试题 PREV-12 危险系数 并查集找割点 Java
- 基于Highcharts的图表绘制