• 安卓 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----------------------//
  • 相关阅读:
    【DOM】如何给div的placeholder传参
    【nvm】使用nvm将node升级到指定版本
    【Worktile】升级业务组件库后,http的数据返回整个response而不是data问题及解决方案
    js获取上传文件内容
    【正则】正则表达式-零宽断言(?=,?<=,?!,?<!)及常见报错
    【Angular】动态组件
    【扩展】div获取焦点或可编辑
    【CSS】position新增属性sticky
    thinkphp写接口返回固定的形式方法
    thinkphp5计算文件大小
  • 原文地址:https://www.cnblogs.com/gm-201705/p/9864105.html
Copyright © 2020-2023  润新知