zoukankan      html  css  js  c++  java
  • drizzleDumper的原理分析和使用说明

    https://blog.csdn.net/qq1084283172/article/details/53561622
    版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/QQ1084283172/article/details/53561622

    本文博客地址:http://blog.csdn.net/qq1084283172/article/details/53561622

    在前面的博客中已经介绍了Android的脱壳工具DexExtractor的原理和使用说明,接下来就来分析一下另一个Android的脱壳工具drizzleDumper的原理和使用说明。drizzleDumper脱壳工具的作者是Drizzle.Risk,他是在strazzere大神的android-unpacker脱壳工具的基础上修改过来的drizzleDumper,他在完成drizzleDumper脱壳工具的时候,对某数字加固、ijiami、bangbang加固进行了脱壳测试,效果比较理想。drizzleDumper脱壳工具是一款基于内存特征搜索的dex文件dump脱壳工具。

     

    一、drizzleDumper脱壳工具的相关链接和讨论

    github地址:https://github.com/DrizzleRisk/drizzleDumper#drizzledumper

    freebuf地址:http://www.freebuf.com/sectool/105147.html

    看雪地址:http://bbs.pediy.com/showthread.php?goto=nextoldest&nojs=1&t=213174

    android-unpacker地址:https://github.com/strazzere/android-unpacker/tree/master/native-unpacker

     

    二、drizzleDumper脱壳工具的原理分析(见代码的注释):

    drizzleDumper工作的原理是root环境下,通过ptrace附加需要脱壳的apk进程,然后在脱壳的apk进程的内存中进行dex文件的特征搜索,当搜索到dex文件时,进行dex文件的内存dump

    drizzleDumper.h头文件

    1.  
      /*
    2.  
      * drizzleDumper Code By Drizzle.Risk
    3.  
      * file: drizzleDumper.h
    4.  
      */
    5.  
       
    6.  
      #include <stdlib.h>
    7.  
      #include <stdio.h>
    8.  
      #include <dirent.h>
    9.  
      #include <fcntl.h>
    10.  
      #include <unistd.h>
    11.  
      #include <stdarg.h>
    12.  
      #include <string.h>
    13.  
      #include <errno.h>
    14.  
      #include <sys/ptrace.h>
    15.  
      #include <sys/types.h>
    16.  
      #include <sys/wait.h>
    17.  
      #include <unistd.h>
    18.  
      #include <linux/user.h>
    19.  
       
    20.  
      #ifdef HAVE_STDINT_H
    21.  
      #include <stdint.h> /* C99 */
    22.  
      typedef uint8_t u1;
    23.  
      typedef uint16_t u2;
    24.  
      typedef uint32_t u4;
    25.  
      typedef uint64_t u8;
    26.  
      typedef int8_t s1;
    27.  
      typedef int16_t s2;
    28.  
      typedef int32_t s4;
    29.  
      typedef int64_t s8;
    30.  
      #else
    31.  
      typedef unsigned char u1;
    32.  
      typedef unsigned short u2;
    33.  
      typedef unsigned int u4;
    34.  
      typedef unsigned long long u8;
    35.  
      typedef signed char s1;
    36.  
      typedef signed short s2;
    37.  
      typedef signed int s4;
    38.  
      typedef signed long long s8;
    39.  
      #endif
    40.  
       
    41.  
      /*
    42.  
      * define kSHA1DigestLen
    43.  
      */
    44.  
      enum { kSHA1DigestLen = 20,
    45.  
      kSHA1DigestOutputLen = kSHA1DigestLen*2 +1 };
    46.  
       
    47.  
      /*
    48.  
      * define DexHeader
    49.  
      */
    50.  
      typedef struct DexHeader {
    51.  
      u1 magic[8]; /* includes version number */
    52.  
      u4 checksum; /* adler32 checksum */
    53.  
      u1 signature[kSHA1DigestLen]; /* SHA-1 hash */
    54.  
      u4 fileSize; /* length of entire file */
    55.  
      u4 headerSize; /* offset to start of next section */
    56.  
      u4 endianTag;
    57.  
      u4 linkSize;
    58.  
      u4 linkOff;
    59.  
      u4 mapOff;
    60.  
      u4 stringIdsSize;
    61.  
      u4 stringIdsOff;
    62.  
      u4 typeIdsSize;
    63.  
      u4 typeIdsOff;
    64.  
      u4 protoIdsSize;
    65.  
      u4 protoIdsOff;
    66.  
      u4 fieldIdsSize;
    67.  
      u4 fieldIdsOff;
    68.  
      u4 methodIdsSize;
    69.  
      u4 methodIdsOff;
    70.  
      u4 classDefsSize;
    71.  
      u4 classDefsOff;
    72.  
      u4 dataSize;
    73.  
      u4 dataOff;
    74.  
      } DexHeader;
    75.  
       
    76.  
      //#define ORIG_EAX 11
    77.  
      static const char* static_safe_location = "/data/local/tmp/";
    78.  
      static const char* suffix = "_dumped_";
    79.  
       
    80.  
      typedef struct {
    81.  
      uint32_t start;
    82.  
      uint32_t end;
    83.  
      } memory_region;
    84.  
       
    85.  
      uint32_t get_clone_pid(uint32_t service_pid);
    86.  
       
    87.  
      uint32_t get_process_pid(const char* target_package_name);
    88.  
       
    89.  
      char *determine_filter(uint32_t clone_pid, int memory_fd);
    90.  
       
    91.  
      int find_magic_memory(uint32_t clone_pid, int memory_fd, memory_region *memory ,const char* file_name);
    92.  
       
    93.  
      int peek_memory(int memory_file, uint32_t address);
    94.  
       
    95.  
      int dump_memory(const char *buffer , int len , char each_filename[]);
    96.  
       
    97.  
      int attach_get_memory(uint32_t pid);

    drizzleDumper.c实现文件
    1.  
      /*
    2.  
      * drizzleDumper Code By Drizzle.Risk
    3.  
      * file: drizzleDumper.c
    4.  
      */
    5.  
       
    6.  
      #include "drizzleDumper.h"
    7.  
       
    8.  
       
    9.  
      // 主函数main
    10.  
      int main(int argc, char *argv[]) {
    11.  
       
    12.  
      printf("[>>>] This is drizzleDumper [<<<] ");
    13.  
      printf("[>>>] code by Drizzle [<<<] ");
    14.  
      printf("[>>>] 2016.05 [<<<] ");
    15.  
       
    16.  
      // 脱壳工具drizzleDumper在工作的实收需要3个参数(需要脱壳的apk的package_name、脱壳等待的时间wait_times(s))
    17.  
      if(argc <= 1)
    18.  
      {
    19.  
      printf("[*] Useage : ./drizzleDumper package_name wait_times(s) [*] The wait_times(s) means how long between the two Scans, default 0s [*] if successed, you can find the dex file in /data/local/tmp [*] Good Luck! ");
    20.  
      return 0;
    21.  
      }
    22.  
       
    23.  
      // 由于脱壳的原理是基于进程的ptrace,需要有root权限
    24.  
      if(getuid() != 0)
    25.  
      {
    26.  
      printf("[*] Device Not root! ");
    27.  
      return -1;
    28.  
      }
    29.  
       
    30.  
      double wait_times = 0.01;
    31.  
      // 脱壳工具drizzleDumper在工作的实收需要3个参数(需要脱壳的apk的package_name、脱壳等待的时间wait_times(s))
    32.  
      if(argc >= 3)
    33.  
      {
    34.  
      // 获取加固脱壳的等待时间
    35.  
      wait_times = strtod(argv[2], NULL);
    36.  
      printf("[*] The wait_times is %ss ", argv[2]);
    37.  
      }
    38.  
       
    39.  
      // 获取需要被脱壳的加固apk的包名
    40.  
      char *package_name = argv[1];
    41.  
      printf("[*] Try to Find %s ", package_name);
    42.  
       
    43.  
      uint32_t pid = -1;
    44.  
       
    45.  
      int i = 0;
    46.  
      int mem_file;
    47.  
      uint32_t clone_pid;
    48.  
      char *extra_filter;
    49.  
      char *dumped_file_name;
    50.  
       
    51.  
      // 进入循环
    52.  
      while(1)
    53.  
      {
    54.  
      // 休眠等待一段时间
    55.  
      sleep(wait_times);
    56.  
       
    57.  
      pid = -1;
    58.  
      // 获取加固需要被脱壳的apk的进程pid
    59.  
      pid = get_process_pid(package_name);
    60.  
      // 判断获取的进程pid是否有效
    61.  
      if(pid < 1 || pid == -1)
    62.  
      {
    63.  
      continue;
    64.  
      }
    65.  
      printf("[*] pid is %d ", pid);
    66.  
       
    67.  
      // 获取进程pid的一个线程tid,方便后面进行ptrace附加
    68.  
      clone_pid = get_clone_pid(pid);
    69.  
      if(clone_pid <= 0)
    70.  
      {
    71.  
      continue;
    72.  
      }
    73.  
      printf("[*] clone pid is %d ", clone_pid);
    74.  
       
    75.  
      memory_region memory;
    76.  
      printf("[*] ptrace [clone_pid] %d ", clone_pid);
    77.  
       
    78.  
      // 对指定pid进程的克隆即tid进程ptrace附加,获取指定pid进程的内存模块基址
    79.  
      mem_file = attach_get_memory(clone_pid);
    80.  
      // 对获取到的内存有效数据的进行校验3次即最多进行3次脱壳尝试
    81.  
      if(mem_file == -10201)
    82.  
      {
    83.  
      continue;
    84.  
      }
    85.  
      else if(mem_file == -20402)
    86.  
      {
    87.  
      //continue;
    88.  
      }
    89.  
      else if(mem_file == -30903)
    90.  
      {
    91.  
      //continue
    92.  
      }
    93.  
       
    94.  
      /****
    95.  
      *static const char* static_safe_location = "/data/local/tmp/";
    96.  
      *static const char* suffix = "_dumped_";
    97.  
      ****/
    98.  
       
    99.  
      // 申请内存空间保存内存dump出来的dex文件的名称
    100.  
      dumped_file_name = malloc(strlen(static_safe_location) + strlen(package_name) + strlen(suffix));
    101.  
      // 格式化生成存dump出来的dex文件的名称
    102.  
      sprintf(dumped_file_name, "%s%s%s", static_safe_location, package_name, suffix);
    103.  
       
    104.  
      printf("[*] Scanning dex ... ");
    105.  
       
    106.  
      // 通过ptrace附件目标pid进程,在目标进程的pid中进行dex文件的搜索然后进行内存dump
    107.  
      if(find_magic_memory(clone_pid, mem_file, &memory, dumped_file_name) <= 0)
    108.  
      {
    109.  
      printf("[*] The magic was Not Found! ");
    110.  
      ptrace(PTRACE_DETACH, clone_pid, NULL, 0);
    111.  
      close(mem_file);
    112.  
      continue;
    113.  
      }
    114.  
      else
    115.  
      {
    116.  
      // dex的内存dump成功,跳出循环
    117.  
      close(mem_file);
    118.  
      ptrace(PTRACE_DETACH, clone_pid, NULL, 0);
    119.  
      break;
    120.  
      }
    121.  
      }
    122.  
       
    123.  
      printf("[*] Done. ");
    124.  
      return 1;
    125.  
      }
    126.  
       
    127.  
      // 获取指定进程的一个线程tid
    128.  
      uint32_t get_clone_pid(uint32_t service_pid)
    129.  
      {
    130.  
      DIR *service_pid_dir;
    131.  
      char service_pid_directory[1024];
    132.  
       
    133.  
      // 格式化字符串
    134.  
      sprintf(service_pid_directory, "/proc/%d/task/", service_pid);
    135.  
      // 查询指定进程的pid的线程TID的信息
    136.  
      if((service_pid_dir = opendir(service_pid_directory)) == NULL)
    137.  
      {
    138.  
      return -1;
    139.  
      }
    140.  
       
    141.  
      struct dirent* directory_entry = NULL;
    142.  
      struct dirent* last_entry = NULL;
    143.  
       
    144.  
      // 获取指定pid进程的线程TID
    145.  
      while((directory_entry = readdir(service_pid_dir)) != NULL)
    146.  
      {
    147.  
      last_entry = directory_entry;
    148.  
      }
    149.  
      if(last_entry == NULL)
    150.  
      return -1;
    151.  
       
    152.  
      closedir(service_pid_dir);
    153.  
       
    154.  
      // 返回获取到的指定pid的线程tid
    155.  
      return atoi(last_entry->d_name);
    156.  
      }
    157.  
       
    158.  
       
    159.  
      // 通过运行的apk的名称的获取进程的pid
    160.  
      uint32_t get_process_pid(const char *target_package_name)
    161.  
      {
    162.  
      char self_pid[10];
    163.  
      sprintf(self_pid, "%u", getpid());
    164.  
       
    165.  
      DIR *proc = NULL;
    166.  
       
    167.  
      if((proc = opendir("/proc")) == NULL)
    168.  
      return -1;
    169.  
       
    170.  
      struct dirent *directory_entry = NULL;
    171.  
      while((directory_entry = readdir(proc)) != NULL)
    172.  
      {
    173.  
       
    174.  
      if (directory_entry == NULL)
    175.  
      return -1;
    176.  
       
    177.  
      if (strcmp(directory_entry->d_name, "self") == 0 || strcmp(directory_entry->d_name, self_pid) == 0)
    178.  
      continue;
    179.  
       
    180.  
      char cmdline[1024];
    181.  
      snprintf(cmdline, sizeof(cmdline), "/proc/%s/cmdline", directory_entry->d_name);
    182.  
      FILE *cmdline_file = NULL;
    183.  
      if((cmdline_file = fopen(cmdline, "r")) == NULL)
    184.  
      continue;
    185.  
       
    186.  
      char process_name[1024];
    187.  
      fscanf(cmdline_file, "%s", process_name);
    188.  
      fclose(cmdline_file);
    189.  
       
    190.  
      if(strcmp(process_name, target_package_name) == 0)
    191.  
      {
    192.  
      closedir(proc);
    193.  
      return atoi(directory_entry->d_name);
    194.  
      }
    195.  
      }
    196.  
       
    197.  
      closedir(proc);
    198.  
      return -1;
    199.  
      }
    200.  
       
    201.  
      // 在目标进程的内存空间中进行dex文件的搜索
    202.  
      int find_magic_memory(uint32_t clone_pid, int memory_fd, memory_region *memory , const char *file_name) {
    203.  
       
    204.  
      int ret = 0;
    205.  
      char maps[2048];
    206.  
       
    207.  
      // 格式化字符串得到/proc/pid/maps
    208.  
      snprintf(maps, sizeof(maps), "/proc/%d/maps", clone_pid);
    209.  
       
    210.  
      FILE *maps_file = NULL;
    211.  
      // 打开文件/proc/pid/maps,获取指定pid进程的内存分布信息
    212.  
      if((maps_file = fopen(maps, "r")) == NULL)
    213.  
      {
    214.  
      printf(" [+] fopen %s Error " , maps);
    215.  
      return -1;
    216.  
      }
    217.  
       
    218.  
      char mem_line[1024];
    219.  
      // 循环读取文件/proc/pid/maps中的pid进程的每一条内存分布信息
    220.  
      while(fscanf(maps_file, "%[^ ] ", mem_line) >= 0)
    221.  
      {
    222.  
      char mem_address_start[10]={0};
    223.  
      char mem_address_end[10]={0};
    224.  
      char mem_info[1024]={0};
    225.  
       
    226.  
      // 解析pid进程的的内存分布信息--内存分布起始地址、内存分布结束地址等
    227.  
      sscanf(mem_line, "%8[^-]-%8[^ ]%*s%*s%*s%*s%s", mem_address_start, mem_address_end, mem_info);
    228.  
      memset(mem_line , 0 ,1024);
    229.  
       
    230.  
      // 获取内存分布起始地址的大小
    231.  
      uint32_t mem_start = strtoul(mem_address_start, NULL, 16);
    232.  
      memory->start = mem_start;
    233.  
      // 获取内存分布结束地址的大小
    234.  
      memory->end = strtoul(mem_address_end, NULL, 16);
    235.  
      // 获取实际的内存区间大小
    236.  
      int len = memory->end - memory->start;
    237.  
      // 过滤掉不符合条件的内存分布区间
    238.  
      if(len <= 10000)
    239.  
      {//too small
    240.  
      continue;
    241.  
      }
    242.  
      else if(len >= 150000000)
    243.  
      {//too big
    244.  
      continue;
    245.  
      }
    246.  
       
    247.  
      char each_filename[254] = {0};
    248.  
      char randstr[10] = {0};
    249.  
      sprintf(randstr ,"%d", rand()%9999);
    250.  
       
    251.  
      // 拼接字符串得到dump的dex文件的生成名称
    252.  
      strncpy(each_filename , file_name , 200); //防溢出
    253.  
      strncat(each_filename , randstr , 10);
    254.  
      strncat(each_filename , ".dex" , 4);
    255.  
       
    256.  
      // 先将pid进程内存文件句柄的指针置文件开头
    257.  
      lseek64(memory_fd , 0 , SEEK_SET);
    258.  
      // 设置pid进程内存文件句柄的指针为内存分布起始地址
    259.  
      off_t r1 = lseek64(memory_fd , memory->start , SEEK_SET);
    260.  
      if(r1 == -1)
    261.  
      {
    262.  
      //do nothing
    263.  
      }
    264.  
      else
    265.  
      {
    266.  
      // 根据内存分布区间的大小申请内存空间
    267.  
      char *buffer = malloc(len);
    268.  
      // 读取pid进程的指定区域的内存数据
    269.  
      ssize_t readlen = read(memory_fd, buffer, len);
    270.  
      printf("meminfo: %s ,len: %d ,readlen: %d, start: %x ", mem_info, len, readlen, memory->start);
    271.  
       
    272.  
      // 对读取的内存分布区域的数据进行dex文件的扫描和查找
    273.  
      if(buffer[1] == 'E' && buffer[2] == 'L' && buffer[3] == 'F')
    274.  
      {
    275.  
      free(buffer);
    276.  
       
    277.  
      continue;
    278.  
      }
    279.  
       
    280.  
      // 查找到dex文件所在的内存区域
    281.  
      if(buffer[0] == 'd' && buffer[1] == 'e' && buffer[2] == 'x' && buffer[3] == ' ' && buffer[4] == '0' && buffer[5] == '3')
    282.  
      {
    283.  
      printf(" [+] find dex, len : %d , info : %s " , readlen , mem_info);
    284.  
       
    285.  
      DexHeader header;
    286.  
      char real_lenstr[10]={0};
    287.  
       
    288.  
      // 获取内存区域中dex文件的文件头信息
    289.  
      memcpy(&header , buffer ,sizeof(DexHeader));
    290.  
      sprintf(real_lenstr , "%x" , header.fileSize);
    291.  
       
    292.  
      // 通过dex文件头信息,获取到整个dex文件的大小
    293.  
      long real_lennum = strtol(real_lenstr , NULL, 16);
    294.  
      printf(" [+] This dex's fileSize: %d ", real_lennum);
    295.  
       
    296.  
      // 对dex文件所在的内存区域进行内存dump
    297.  
      if(dump_memory(buffer , len , each_filename) == 1)
    298.  
      {
    299.  
      // 打印dump的dex文件的名称
    300.  
      printf(" [+] dex dump into %s ", each_filename);
    301.  
      free(buffer);
    302.  
      continue;
    303.  
      }
    304.  
      else
    305.  
      {
    306.  
      printf(" [+] dex dump error ");
    307.  
      }
    308.  
       
    309.  
      }
    310.  
       
    311.  
      free(buffer);
    312.  
      }
    313.  
       
    314.  
      // 前面的内存方法搜索没有查找dex文件的内存,尝试下面的内存+8位置进行搜索
    315.  
      // 具体什么原因没太明白??
    316.  
      lseek64(memory_fd , 0 , SEEK_SET); //保险,先归零
    317.  
      r1 = lseek64(memory_fd , memory->start + 8 , SEEK_SET); //不用 pread,因为pread用的是lseek
    318.  
      if(r1 == -1)
    319.  
      {
    320.  
      continue;
    321.  
      }
    322.  
      else
    323.  
      {
    324.  
      char *buffer = malloc(len);
    325.  
      ssize_t readlen = read(memory_fd, buffer, len);
    326.  
       
    327.  
      if(buffer[0] == 'd' && buffer[1] == 'e' && buffer[2] == 'x' && buffer[3] == ' ' && buffer[4] == '0' && buffer[5] == '3')
    328.  
      {
    329.  
      printf(" [+] Find dex! memory len : %d " , readlen);
    330.  
       
    331.  
      DexHeader header;
    332.  
      char real_lenstr[10]={0};
    333.  
       
    334.  
      // 获取内存dex文件的文件头信息
    335.  
      memcpy(&header , buffer ,sizeof(DexHeader));
    336.  
      sprintf(real_lenstr , "%x" , header.fileSize);
    337.  
       
    338.  
      // 通过dex文件头信息,获取到整个dex文件的大小
    339.  
      long real_lennum = strtol(real_lenstr , NULL, 16);
    340.  
      printf(" [+] This dex's fileSize: %d ", real_lennum);
    341.  
       
    342.  
      // 对dex文件所在的内存区域进行内存dump
    343.  
      if(dump_memory(buffer , len , each_filename) == 1)
    344.  
      {
    345.  
      printf(" [+] dex dump into %s ", each_filename);
    346.  
      free(buffer);
    347.  
      continue; //如果本次成功了,就不尝试其他方法了
    348.  
      }
    349.  
      else
    350.  
      {
    351.  
      printf(" [+] dex dump error ");
    352.  
      }
    353.  
      }
    354.  
       
    355.  
      free(buffer);
    356.  
      }
    357.  
      }
    358.  
      fclose(maps_file);
    359.  
       
    360.  
      return ret;
    361.  
      }
    362.  
       
    363.  
       
    364.  
      // 从内存中dump数据到文件中
    365.  
      int dump_memory(const char *buffer , int len , char each_filename[])
    366.  
      {
    367.  
      int ret = -1;
    368.  
       
    369.  
      // 创建文件
    370.  
      FILE *dump = fopen(each_filename, "wb");
    371.  
      // 将需要dump的内存数据写入到/data/local/tmp文件路径下
    372.  
      if(fwrite(buffer, len, 1, dump) != 1)
    373.  
      {
    374.  
      ret = -1;
    375.  
      }
    376.  
      else
    377.  
      {
    378.  
      ret = 1;
    379.  
      }
    380.  
       
    381.  
      fclose(dump);
    382.  
      return ret;
    383.  
      }
    384.  
       
    385.  
      // 获取指定附加pid进程的内存模块基址
    386.  
      int attach_get_memory(uint32_t pid) {
    387.  
       
    388.  
      char mem[1024];
    389.  
      bzero(mem,1024);
    390.  
       
    391.  
      // 格式化字符串得到字符串/proc/pid/mem
    392.  
      snprintf(mem, sizeof(mem), "/proc/%d/mem", pid);
    393.  
       
    394.  
      int ret = -1;
    395.  
      int mem_file;
    396.  
       
    397.  
      // 尝试ptrace附加目标pid进程
    398.  
      ret = ptrace(PTRACE_ATTACH, pid, NULL, NULL);
    399.  
      // 对ptrace附加目标pid进程的操作结果进行判断
    400.  
      if (0 != ret)
    401.  
      {
    402.  
      int err = errno; //这时获取errno
    403.  
      if(err == 1) //EPERM
    404.  
      {
    405.  
      return -30903; //代表已经被跟踪或无法跟踪
    406.  
      }
    407.  
      else
    408.  
      {
    409.  
      return -10201; //其他错误(进程不存在或非法操作)
    410.  
      }
    411.  
      }
    412.  
      else
    413.  
      {
    414.  
      // ptrace附加目标进程pid成功,获取指定pid进程的内存模块基址
    415.  
      // 获取其它进程的内存模块基址,需要root权限
    416.  
      if(!(mem_file = open(mem, O_RDONLY)))
    417.  
      {
    418.  
      return -20402; //打开错误
    419.  
      }
    420.  
      }
    421.  
       
    422.  
      return mem_file;
    423.  
      }

    drizzleDumper的编译配置文件Android.mk
    1.  
      LOCAL_PATH := $(call my-dir)
    2.  
       
    3.  
      TARGET_PIE := true
    4.  
      NDK_APP_PIE := true
    5.  
       
    6.  
      include $(CLEAR_VARS)
    7.  
       
    8.  
      # 需要编译的源码文件
    9.  
      LOCAL_SRC_FILES :=
    10.  
      drizzleDumper.c
    11.  
      LOCAL_C_INCLUDE :=
    12.  
      drizzleDumper.h
    13.  
      definitions.h
    14.  
       
    15.  
      LOCAL_MODULE := drizzleDumper
    16.  
      LOCAL_MODULE_TAGS := optional
    17.  
       
    18.  
      # Allow execution on android-16+
    19.  
      # 支持PIE
    20.  
      LOCAL_CFLAGS += -fPIE
    21.  
      LOCAL_LDFLAGS += -fPIE -pie
    22.  
       
    23.  
      # 编译生成可执行ELF文件
    24.  
      include $(BUILD_EXECUTABLE)
    25.  
       
    26.  
      include $(call all-makefiles-under,$(LOCAL_PATH))

    三、drizzleDumper的使用说明

    关于drizzleDumper的使用,作者已经在freebuf的文章中已经讲的很详细了,具体的修改的地方也指出来了。


     

    四、下面就使用nexcus 5的已经root的真机进行drizzleDumper的脱壳实战(以com.qihoo.freewifi为例)

    在cmd控制台的条件下,执行cd命令进入到存放drizzleDumper的文件夹,然后将drizzleDumper文件推送到android手机的/data/local/tmp文件夹下并赋予可执行权限,然后根据每种android加固的特点,选择需要脱壳的apk和drizzleDumper运行的先后顺序,调整能够脱壳成功的过程。这里使用的com.qihoo.freewifi为例,先运行com.qihoo.freewifi程序,然后adb shell条件下su提权执行drizzleDumper的脱壳操作,等待2秒。

    1.  
      cd xxxxx/drizzleDumper
    2.  
       
    3.  
      adb push drizzleDumper /data/local/tmp
    4.  
      adb shell chmod 0777 /data/local/tmp/drizzleDumper
    5.  
       
    6.  
      adb shell #进入androd系统的shell
    7.  
      su #获取root权限
    8.  
      ./data/local/tmp/drizzleDumper com.qihoo.freewifi 2 #执行脱壳操作

     



    说明:对脱壳是否成功,这个估计有一定的概率性,主要的目的是学习工具作者的脱壳思想和方法,自己去实践,不管怎样谢谢工具的作者Drizzle.Risk,代码中有理解错误的地方希望大牛不吝赐。

     

    编译好的drizzleDumper文件和代码的打包下载地址:http://download.csdn.net/detail/qq1084283172/9707768

     

    参考网址

    http://www.freebuf.com/sectool/105147.html

    https://github.com/DrizzleRisk/drizzleDumper

     

     

     

    jpg改rar 

  • 相关阅读:
    Average Score39届亚洲赛牡丹江站A题
    Average Score39届亚洲赛牡丹江站A题
    Building Fire Stations 39届亚洲赛牡丹江站B题
    Leetcode 155 Min Stack 小顶堆+栈,优先队列实现 难度:0
    pycharm 使用小结
    POJ 3020 Antenna Placement 匈牙利算法,最大流解法 难度:1
    POJ 3041 Asteroids 匈牙利算法,最大流解法,行列为点 难度:1
    POJ 1094 Sorting It All Out 拓扑排序 难度:0
    POJ 2240 && ZOJ 1082 Arbitrage 最短路,c++ stl pass g++ tle 难度:0
    POJ 1125 Stockbroker Grapevine 最短路 难度:0
  • 原文地址:https://www.cnblogs.com/kuangke/p/9524931.html
Copyright © 2011-2022 走看看