首页
社区
课程
招聘
ELF文件格式与got表hook简单实现
发表于: 2021-5-27 15:21 22457

ELF文件格式与got表hook简单实现

2021-5-27 15:21
22457

通过了解ELF文件格式,了解got表hook原理。

本文用到的简单demo以及编译后的so库名称为libtestLib.so

Executable and Linkable Format 可执行可链接文件,主要用在linux相关操作系统上,文件中存储了程序运行的信息

很多文件格式都是有固定的魔数信息,代表了文件属于哪一种格式。比如zip格式,tar.gz,exe等

elf文件也有固定魔数,我们通过hexdump看一下头部的信息

前四个字节就代表了elf文件的魔数,为什么是前四个字节?因为源码中就定义了魔数信息。

SELFMAG就是长度的意思,4个字节。"\177"是8进制,16进制就是7f。与hexdump呈现的16进制视图完全一致。

文件头包含魔数,还包含其他关键信息。

文件头的size是多少呢?其实armv8文件头是固定的长度,armv7文件头也是固定的长度。长度只与当前so库对应的平台相关。

比如apk中libs/armeabi-v7a/下面的所有so库都拥有一样长度的文件头。

使用ida工具打开一个arm64的so库,我们看看工具所解析的elf文件头包含的信息:

结合该图,再来看看linker的源码,增加大家对ELF文件头的印象

源码位置aosp7.1 bionic/linker/linker_phdr.cpp

这两个表大家要牢记,elf文件头包含了这两个表的信息。

图片描述

先啰嗦一下这个关键字:elf文件中,一个区域存储了很多个一摸一样的结构体,这个区域就可以视作表。比如got表,符号表,字符串表等等。这些表后边也会提到。

程序头表上面已经从ELF文件头信息中拿到了。通过循环遍历这个表,可以找到一个PT_DYNAMIC类型的程序头,这个程序头中存储了动态表的偏移大小等信息。我把demo中的so库用010editor这个工具解析出来贴了个图

大家可能有疑问,程序头表中有很多个程序头,为什么仅仅要拿到PT_DYNAMIC这个程序头,拿到动态表呢?

其实程序头表中的信息都很重要,比如图中的前两个程序头(loadable segment),这两个程序头包含了一些装载信息。

linker会用到装载信息。比如so库装载到内存中需要多大空间,内存中的属性(可读可写可执行等)。

既然提到了装载,那就简单说一下装载和链接吧。

so库包含了程序运行需要用的数据以及指令,这些数据以及指令需要加载到内存中,加载到内存的过程就可以简单理解为装载。

so库一般会使用到外部的一些符号,比如open,close,mmap,strlen等导入符号,这些符号的真实地址不在本so库,可能在系统的libc库等等。那么本so库要调用open这些函数的话,肯定需要一些特殊的方式拿到其真实地址。这些真实地址其实保存在so库的got表中。linker将so库装载后, 会将这些符号进行重新定位,重新定位简称为重定位。其实重定位不仅仅包含外部的一些符号,还包含本so库的一些符号。重定位修复的整个过程可以理解为链接。

上边提到了前两个程序头(loadable_segment)与装载有关系。那么链接过程需要用的重定位信息在哪里呢?寻找这个答案,就需要PT_DYNAMIC这个程序头, 程序头有一个字端为p_vaddr,值为0x2D28,这个地址就是动态节区,因为这个区域又是数组,后边就把这个节区称为动态表

动态表中的DT_JMPREL这个结构体,包含了重定位表的信息,继续用ida工具查看0x9f8->重定位表

重定位表包含了需要重定位的函数信息,包括__open_2函数。

前边提到了linker对so库链接的过程会进行符号重定位,重定位的信息就在重定位表中。

继续以__open_2这个重定位信息为例

Elf64_Rela<0x2F90, 0xc00000402, 0>, IDA已经解析出来了,这个结构体中0x2f90是个偏移,指向的地址就是got表, 0xc00000402这个数据其实是一个info,会解析出符号索引,通过这个索引拿到符号名(__open_2),也可以拿到这个重定位信息类型。

ELFE(R_TYPE)与ELFW(R_SYM)宏定义在libc/kernel/uapi/linux/elf.h中

刚才提到的0x2f90这个偏移也贴个图吧

linker重定位修复的数据就包括got表,比如0x2f90这个地方,使用8个字节存放了__open_2函数的真实地址(64位系统需要8个字节存放一个地址,这个地址的数据类型简单理解为void*)。

关键的地方就在这里,既然linker通过重定位,将0x2f90这个地方的数据改了。那我们也仿照linker搞一个重定位的修复,将这个地方的数据改为我们的函数地址,是不是就可以实现hook了。答案是yes。

上述文件格式的分析,都是基于so库的静态分析。所有的偏移地址,都是一个相对地址,我们只要拿到so库在内存中加载的基址加上这个偏移,就可以了。

具体的代码百度一大堆,大家自行实现。这里简单的贴个图,看看maps文件

比如要hook的libtestLib.so库

base地址为77b61f6000,open_2在got表的偏移地址为0x2F90,我们通过将base + offset这个内存块的数据改为我们的函数地址就可以实现__open_2的hook了。

为什么是targetsdk<= 23,继续查看linker的源码

bionic/linker/linker.cpp

bionic/linker/linker.cpp

dlopen函数最终会调用到linker中的do_dlopen,do_dlopen的返回值为soinfo->to_handle()

void* soinfo::to_handle()这个函数中明确了targetsdk <= 23返回this(即so info),否则会通过get_handle返回一个随机值。

来看看soinfo结构体:

省略了很多,可以查看源码(bionic/linker/linker.h)

soinfo中可以拿到phdr*(程序头表), phnum(程序头个数), base(装载基址), size(装载所需空间)等等。

linker源码文件结构图,便于大家理解关键文件
图片描述

目前只简单实现了arch64的got表重定位hook。下面是一部分demo源码

__open_2_hook函数中特别的加上了一行log,打印了文件路径

__open_2_hook函数中打印的文件路径,其实是libtestLib.so访问的。运行程序后发现确实打印了相关日志:

 
static void testOpen(JNIEnv* env, jclass clazz, jstring jPath) {
 
    const char* cPath = env->GetStringUTFChars(jPath, JNI_FALSE);
    int fd = open(cPath, O_RDONLY);
    LOGD("open %s fd: %d", cPath, fd);
    if (fd > 0) close(fd);
    env->ReleaseStringUTFChars(jPath, cPath);
 
}
static void testOpen(JNIEnv* env, jclass clazz, jstring jPath) {
 
    const char* cPath = env->GetStringUTFChars(jPath, JNI_FALSE);
    int fd = open(cPath, O_RDONLY);
    LOGD("open %s fd: %d", cPath, fd);
    if (fd > 0) close(fd);
    env->ReleaseStringUTFChars(jPath, cPath);
 
}
 
admin@C02D7132MD6R ~ % hexdump -C -n 20 ~/Downloads/libart.so                  
00000000  7f 45 4c 46 02 01 01 00  00 00 00 00 00 00 00 00  |.ELF............|
00000010  03 00 b7 00                                       |....|
00000014
admin@C02D7132MD6R ~ %
admin@C02D7132MD6R ~ % hexdump -C -n 20 ~/Downloads/libart.so                  
00000000  7f 45 4c 46 02 01 01 00  00 00 00 00 00 00 00 00  |.ELF............|
00000010  03 00 b7 00                                       |....|
00000014
admin@C02D7132MD6R ~ %
admin@C02D7132MD6R bionic % vim libc/kernel/uapi/linux/elf.h     
admin@C02D7132MD6R bionic %
admin@C02D7132MD6R bionic %
admin@C02D7132MD6R bionic % vim libc/kernel/uapi/linux/elf.h     
admin@C02D7132MD6R bionic %
admin@C02D7132MD6R bionic %
 
 
 
 
 
 
//通过pread64将文件头的内容读到内存header_中
bool ElfReader::ReadElfHeader() {
  ssize_t rc = TEMP_FAILURE_RETRY(pread64(fd_, &header_, sizeof(header_), file_offset_));
  if (rc < 0) {
    DL_ERR("can't read file \"%s\": %s", name_.c_str(), strerror(errno));
    return false;
  }
 
  if (rc != sizeof(header_)) {
    DL_ERR("\"%s\" is too small to be an ELF executable: only found %zd bytes", name_.c_str(),
           static_cast<size_t>(rc));
    return false;
  }
  return true;
}
//校验elf文件头
bool ElfReader::VerifyElfHeader() {
  //1.校验魔数信息
  if (memcmp(header_.e_ident, ELFMAG, SELFMAG) != 0) {
    DL_ERR("\"%s\" has bad ELF magic", name_.c_str());
    return false;
  }
 
  //2.校验文件类别,64位运行时只能加载64位so库,32位运行时只能加载32位so库
  // Try to give a clear diagnostic for ELF class mismatches, since they're
  // an easy mistake to make during the 32-bit/64-bit transition period.
  int elf_class = header_.e_ident[EI_CLASS];
#if defined(__LP64__)
  if (elf_class != ELFCLASS64) {
    if (elf_class == ELFCLASS32) {
      DL_ERR("\"%s\" is 32-bit instead of 64-bit", name_.c_str());
    } else {
      DL_ERR("\"%s\" has unknown ELF class: %d", name_.c_str(), elf_class);
    }
    return false;
  }
#else
  if (elf_class != ELFCLASS32) {
    if (elf_class == ELFCLASS64) {
      DL_ERR("\"%s\" is 64-bit instead of 32-bit", name_.c_str());
    } else {
      DL_ERR("\"%s\" has unknown ELF class: %d", name_.c_str(), elf_class);
    }
    return false;
  }
#endif
 
  //3.检验大小端对齐方式,目前安卓上为小端对齐
  if (header_.e_ident[EI_DATA] != ELFDATA2LSB) {
    DL_ERR("\"%s\" not little-endian: %d", name_.c_str(), header_.e_ident[EI_DATA]);
    return false;
  }
 
  //4.校验文件类型是否为动态库
  if (header_.e_type != ET_DYN) {
    DL_ERR("\"%s\" has unexpected e_type: %d", name_.c_str(), header_.e_type);
    return false;
  }
 
  //5.校验版本号,安卓上目前只能是EV_CURRENT
  if (header_.e_version != EV_CURRENT) {
    DL_ERR("\"%s\" has unexpected e_version: %d", name_.c_str(), header_.e_version);
    return false;
  }
 
  //6.校验machine
  if (header_.e_machine != GetTargetElfMachine()) {
    DL_ERR("\"%s\" has unexpected e_machine: %d", name_.c_str(), header_.e_machine);
    return false;
  }
 
  return true;
}
//通过pread64将文件头的内容读到内存header_中
bool ElfReader::ReadElfHeader() {
  ssize_t rc = TEMP_FAILURE_RETRY(pread64(fd_, &header_, sizeof(header_), file_offset_));
  if (rc < 0) {
    DL_ERR("can't read file \"%s\": %s", name_.c_str(), strerror(errno));
    return false;
  }
 
  if (rc != sizeof(header_)) {
    DL_ERR("\"%s\" is too small to be an ELF executable: only found %zd bytes", name_.c_str(),
           static_cast<size_t>(rc));
    return false;
  }
  return true;
}
//校验elf文件头
bool ElfReader::VerifyElfHeader() {
  //1.校验魔数信息
  if (memcmp(header_.e_ident, ELFMAG, SELFMAG) != 0) {
    DL_ERR("\"%s\" has bad ELF magic", name_.c_str());
    return false;
  }
 
  //2.校验文件类别,64位运行时只能加载64位so库,32位运行时只能加载32位so库
  // Try to give a clear diagnostic for ELF class mismatches, since they're
  // an easy mistake to make during the 32-bit/64-bit transition period.
  int elf_class = header_.e_ident[EI_CLASS];
#if defined(__LP64__)
  if (elf_class != ELFCLASS64) {
    if (elf_class == ELFCLASS32) {
      DL_ERR("\"%s\" is 32-bit instead of 64-bit", name_.c_str());
    } else {
      DL_ERR("\"%s\" has unknown ELF class: %d", name_.c_str(), elf_class);
    }
    return false;
  }
#else
  if (elf_class != ELFCLASS32) {
    if (elf_class == ELFCLASS64) {
      DL_ERR("\"%s\" is 64-bit instead of 32-bit", name_.c_str());
    } else {
      DL_ERR("\"%s\" has unknown ELF class: %d", name_.c_str(), elf_class);
    }
    return false;
  }
#endif
 
  //3.检验大小端对齐方式,目前安卓上为小端对齐
  if (header_.e_ident[EI_DATA] != ELFDATA2LSB) {
    DL_ERR("\"%s\" not little-endian: %d", name_.c_str(), header_.e_ident[EI_DATA]);
    return false;
  }
 
  //4.校验文件类型是否为动态库
  if (header_.e_type != ET_DYN) {
    DL_ERR("\"%s\" has unexpected e_type: %d", name_.c_str(), header_.e_type);
    return false;
  }
 
  //5.校验版本号,安卓上目前只能是EV_CURRENT
  if (header_.e_version != EV_CURRENT) {
    DL_ERR("\"%s\" has unexpected e_version: %d", name_.c_str(), header_.e_version);
    return false;
  }
 
  //6.校验machine
  if (header_.e_machine != GetTargetElfMachine()) {
    DL_ERR("\"%s\" has unexpected e_machine: %d", name_.c_str(), header_.e_machine);
    return false;
  }
 
  return true;
}
bool ElfReader::ReadProgramHeaders() {
  phdr_num_ = header_.e_phnum;
 
  // Like the kernel, we only accept program header tables that
  // are smaller than 64KiB.
  if (phdr_num_ < 1 || phdr_num_ > 65536/sizeof(ElfW(Phdr))) {
    DL_ERR("\"%s\" has invalid e_phnum: %zd", name_.c_str(), phdr_num_);
    return false;
  }
 
  // Boundary checks
  size_t size = phdr_num_ * sizeof(ElfW(Phdr));
  if (!CheckFileRange(header_.e_phoff, size, alignof(ElfW(Phdr)))) {
    DL_ERR_AND_LOG("\"%s\" has invalid phdr offset/size: %zu/%zu",
                   name_.c_str(),
                   static_cast<size_t>(header_.e_phoff),
                   size);
    return false;
  }
 
  //将elf文件的程序头表内容映射到内存中,程序头表的文件偏移为header_.e_phoff
  if (!phdr_fragment_.Map(fd_, file_offset_, header_.e_phoff, size)) {
    DL_ERR("\"%s\" phdr mmap failed: %s", name_.c_str(), strerror(errno));
    return false;
  }
 
  phdr_table_ = static_cast<ElfW(Phdr)*>(phdr_fragment_.data());
  return true;
}
bool ElfReader::ReadProgramHeaders() {
  phdr_num_ = header_.e_phnum;
 
  // Like the kernel, we only accept program header tables that
  // are smaller than 64KiB.
  if (phdr_num_ < 1 || phdr_num_ > 65536/sizeof(ElfW(Phdr))) {
    DL_ERR("\"%s\" has invalid e_phnum: %zd", name_.c_str(), phdr_num_);
    return false;
  }
 
  // Boundary checks
  size_t size = phdr_num_ * sizeof(ElfW(Phdr));
  if (!CheckFileRange(header_.e_phoff, size, alignof(ElfW(Phdr)))) {
    DL_ERR_AND_LOG("\"%s\" has invalid phdr offset/size: %zu/%zu",
                   name_.c_str(),
                   static_cast<size_t>(header_.e_phoff),
                   size);
    return false;
  }
 
  //将elf文件的程序头表内容映射到内存中,程序头表的文件偏移为header_.e_phoff
  if (!phdr_fragment_.Map(fd_, file_offset_, header_.e_phoff, size)) {
    DL_ERR("\"%s\" phdr mmap failed: %s", name_.c_str(), strerror(errno));
    return false;
  }
 
  phdr_table_ = static_cast<ElfW(Phdr)*>(phdr_fragment_.data());
  return true;
}
bool ElfReader::ReadSectionHeaders() {
  shdr_num_ = header_.e_shnum;
 
  if (shdr_num_ == 0) {
    DL_ERR_AND_LOG("\"%s\" has no section headers", name_.c_str());
    return false;
  }
 
  size_t size = shdr_num_ * sizeof(ElfW(Shdr));
  if (!CheckFileRange(header_.e_shoff, size, alignof(const ElfW(Shdr)))) {
    DL_ERR_AND_LOG("\"%s\" has invalid shdr offset/size: %zu/%zu",
                   name_.c_str(),
                   static_cast<size_t>(header_.e_shoff),
                   size);
    return false;
  }
 
  //将elf文件的节头表内容映射到内存中,节头表的文件偏移为header_.e_shoff
  if (!shdr_fragment_.Map(fd_, file_offset_, header_.e_shoff, size)) {
    DL_ERR("\"%s\" shdr mmap failed: %s", name_.c_str(), strerror(errno));
    return false;
  }
 
  shdr_table_ = static_cast<const ElfW(Shdr)*>(shdr_fragment_.data());
  return true;
}
bool ElfReader::ReadSectionHeaders() {
  shdr_num_ = header_.e_shnum;
 
  if (shdr_num_ == 0) {
    DL_ERR_AND_LOG("\"%s\" has no section headers", name_.c_str());
    return false;
  }
 
  size_t size = shdr_num_ * sizeof(ElfW(Shdr));
  if (!CheckFileRange(header_.e_shoff, size, alignof(const ElfW(Shdr)))) {
    DL_ERR_AND_LOG("\"%s\" has invalid shdr offset/size: %zu/%zu",
                   name_.c_str(),
                   static_cast<size_t>(header_.e_shoff),
                   size);
    return false;
  }
 
  //将elf文件的节头表内容映射到内存中,节头表的文件偏移为header_.e_shoff
  if (!shdr_fragment_.Map(fd_, file_offset_, header_.e_shoff, size)) {
    DL_ERR("\"%s\" shdr mmap failed: %s", name_.c_str(), strerror(errno));
    return false;
  }
 
  shdr_table_ = static_cast<const ElfW(Shdr)*>(shdr_fragment_.data());
  return true;
}
 
 
 
 
 
 
 
 
 
 
 
ElfW(Word) type = ELFW(R_TYPE)(rel->r_info);//符号的类型
ElfW(Word) sym = ELFW(R_SYM)(rel->r_info);//符号的索引
ElfW(Word) type = ELFW(R_TYPE)(rel->r_info);//符号的类型
ElfW(Word) sym = ELFW(R_SYM)(rel->r_info);//符号的索引
#if defined(__LP64__)
#define ELFW(what) ELF64_ ## what
#else
#define ELFW(what) ELF32_ ## what
#endif
 
#define ELF32_R_SYM(x) ((x) >> 8)
#define ELF32_R_TYPE(x) ((x) & 0xff)
#define ELF64_R_SYM(i) ((i) >> 32)
#define ELF64_R_TYPE(i) ((i) & 0xffffffff)
#if defined(__LP64__)
#define ELFW(what) ELF64_ ## what
#else
#define ELFW(what) ELF32_ ## what
#endif
 
#define ELF32_R_SYM(x) ((x) >> 8)
#define ELF32_R_TYPE(x) ((x) & 0xff)
#define ELF64_R_SYM(i) ((i) >> 32)
#define ELF64_R_TYPE(i) ((i) & 0xffffffff)
 
 
template<typename ElfRelIteratorT>
bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& rel_iterator,
                      const soinfo_list_t& global_group, const soinfo_list_t& local_group) {
  for (size_t idx = 0; rel_iterator.has_next(); ++idx) {
    const auto rel = rel_iterator.next();
    if (rel == nullptr) {
      return false;
    }
 
    ElfW(Word) type = ELFW(R_TYPE)(rel->r_info);
    ElfW(Word) sym = ELFW(R_SYM)(rel->r_info);
 
    ElfW(Addr) reloc = static_cast<ElfW(Addr)>(rel->r_offset + load_bias);
    ElfW(Addr) sym_addr = 0;
    const char* sym_name = nullptr;
    ElfW(Addr) addend = get_addend(rel, reloc);
 
    DEBUG("Processing \"%s\" relocation at index %zd", get_realpath(), idx);
    if (type == R_GENERIC_NONE) {
      continue;
    }
 
    const ElfW(Sym)* s = nullptr;
    soinfo* lsi = nullptr;
 
    if (sym != 0) {
      sym_name = get_string(symtab_[sym].st_name);
      ...
      ...
    }
 
    switch (type) {
      //arch64的导入符号重定位就在这里,我们可以直接将linker的relocate源码拷贝过来,拿来所用
      case R_GENERIC_JUMP_SLOT:
        count_relocation(kRelocAbsolute);
        MARK(rel->r_offset);
        TRACE_TYPE(RELO, "RELO JMP_SLOT %16p <- %16p %s\n",
                   reinterpret_cast<void*>(reloc),
                   reinterpret_cast<void*>(sym_addr + addend), sym_name);
 
        *reinterpret_cast<ElfW(Addr)*>(reloc) = (sym_addr + addend);
        break;
      case R_GENERIC_GLOB_DAT:
        count_relocation(kRelocAbsolute);
        MARK(rel->r_offset);
        TRACE_TYPE(RELO, "RELO GLOB_DAT %16p <- %16p %s\n",
                   reinterpret_cast<void*>(reloc),
                   reinterpret_cast<void*>(sym_addr + addend), sym_name);
        *reinterpret_cast<ElfW(Addr)*>(reloc) = (sym_addr + addend);
        break;
      case R_GENERIC_RELATIVE:
        count_relocation(kRelocRelative);
        MARK(rel->r_offset);
        TRACE_TYPE(RELO, "RELO RELATIVE %16p <- %16p\n",
                   reinterpret_cast<void*>(reloc),
                   reinterpret_cast<void*>(load_bias + addend));
        *reinterpret_cast<ElfW(Addr)*>(reloc) = (load_bias + addend);
        break;
 
    }
template<typename ElfRelIteratorT>
bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& rel_iterator,
                      const soinfo_list_t& global_group, const soinfo_list_t& local_group) {
  for (size_t idx = 0; rel_iterator.has_next(); ++idx) {
    const auto rel = rel_iterator.next();
    if (rel == nullptr) {
      return false;
    }
 
    ElfW(Word) type = ELFW(R_TYPE)(rel->r_info);
    ElfW(Word) sym = ELFW(R_SYM)(rel->r_info);
 
    ElfW(Addr) reloc = static_cast<ElfW(Addr)>(rel->r_offset + load_bias);
    ElfW(Addr) sym_addr = 0;
    const char* sym_name = nullptr;
    ElfW(Addr) addend = get_addend(rel, reloc);
 
    DEBUG("Processing \"%s\" relocation at index %zd", get_realpath(), idx);
    if (type == R_GENERIC_NONE) {
      continue;
    }
 
    const ElfW(Sym)* s = nullptr;
    soinfo* lsi = nullptr;
 
    if (sym != 0) {
      sym_name = get_string(symtab_[sym].st_name);
      ...
      ...
    }
 
    switch (type) {
      //arch64的导入符号重定位就在这里,我们可以直接将linker的relocate源码拷贝过来,拿来所用
      case R_GENERIC_JUMP_SLOT:
        count_relocation(kRelocAbsolute);
        MARK(rel->r_offset);
        TRACE_TYPE(RELO, "RELO JMP_SLOT %16p <- %16p %s\n",
                   reinterpret_cast<void*>(reloc),
                   reinterpret_cast<void*>(sym_addr + addend), sym_name);
 
        *reinterpret_cast<ElfW(Addr)*>(reloc) = (sym_addr + addend);
        break;
      case R_GENERIC_GLOB_DAT:
        count_relocation(kRelocAbsolute);
        MARK(rel->r_offset);
        TRACE_TYPE(RELO, "RELO GLOB_DAT %16p <- %16p %s\n",
                   reinterpret_cast<void*>(reloc),
                   reinterpret_cast<void*>(sym_addr + addend), sym_name);
        *reinterpret_cast<ElfW(Addr)*>(reloc) = (sym_addr + addend);
        break;
      case R_GENERIC_RELATIVE:
        count_relocation(kRelocRelative);
        MARK(rel->r_offset);
        TRACE_TYPE(RELO, "RELO RELATIVE %16p <- %16p\n",
                   reinterpret_cast<void*>(reloc),
                   reinterpret_cast<void*>(load_bias + addend));
        *reinterpret_cast<ElfW(Addr)*>(reloc) = (load_bias + addend);
        break;
 
    }
admin@C02D7132MD6R bionic % adb shell
angler:/ $ ps |grep superhook
u0_a69    7680  540   1620436 71348 SyS_epoll_ 0000000000 S com.example.superhook
angler:/ $ su
angler:/ # cat /proc/7680/maps
12c00000-12e08000 rw-p 00000000 00:04 16462                              /dev/ashmem/dalvik-main space (deleted)
12e08000-13008000 rw-p 00208000 00:04 16462                              /dev/ashmem/dalvik-main space (deleted)
13008000-1ec00000 ---p 00408000 00:04 16462                              /dev/ashmem/dalvik-main space (deleted)
32c00000-32c01000 rw-p 00000000 00:04 16463                              /dev/ashmem/dalvik-main space 1 (deleted)
32c01000-3ec00000 ---p 00001000 00:04 16463                              /dev/ashmem/dalvik-main space 1 (deleted)
6f7b1000-6fa50000 rw-p 00000000 fd:00 278001                             /data/dalvik-cache/arm64/system@framework@boot.art
6fa50000-6fbcc000 rw-p 00000000 fd:00 278002                             /data/dalvik-cache/arm64/system@framework@boot-core-libart.art
6fbcc000-6fc01000 rw-p 00000000 fd:00 278003                             /data/dalvik-cache/arm64/system@framework@boot-conscrypt.art
6fc01000-6fc3a000 rw-p 00000000 fd:00 278004                             /data/dalvik-cache/arm64/system@framework@boot-okhttp.art
6fc3a000-6fc3d000 rw-p 00000000 fd:00 278005                             /data/dalvik-cache/arm64/system@framework@boot-core-junit.art
6fc3d000-6fc83000 rw-p 00000000 fd:00 278006                             /data/dalvik-cache/arm64/system@framework@boot-bouncycastle.art
6fc83000-6fcc5000 rw-p 00000000 fd:00 278007                             /data/dalvik-cache/arm64/system@framework@boot-ext.art
6fcc5000-70484000 rw-p 00000000 fd:00 278008                             /data/dalvik-cache/arm64/system@framework@boot-framework.art
70484000-70516000 rw-p 00000000 fd:00 278009                             /data/dalvik-cache/arm64/system@framework@boot-telephony-common.art
70516000-7051e000 rw-p 00000000 fd:00 278010                             /data/dalvik-cache/arm64/system@framework@boot-voip-common.art
7051e000-7052a000 rw-p 00000000 fd:00 278011                             /data/dalvik-cache/arm64/system@framework@boot-ims-common.art
7052a000-7054d000 rw-p 00000000 fd:00 278012                             /data/dalvik-cache/arm64/system@framework@boot-apache-xml.art
7054d000-70574000 rw-p 00000000 fd:00 278013                             /data/dalvik-cache/arm64/system@framework@boot-org.apache.http.legacy.boot.art
 
77b4a3c000-77b4a59000 r--s 00000000 103:0b 837                           /system/fonts/NotoNaskhArabicUI-Regular.ttf
77b4a59000-77b4aaa000 r--s 00000000 103:0b 949                           /system/fonts/Roboto-BoldItalic.ttf
77b4aaa000-77b4af5000 r--s 00000000 103:0b 948                           /system/fonts/Roboto-Bold.ttf
77b4af5000-77b4b46000 r--s 00000000 103:0b 947                           /system/fonts/Roboto-BlackItalic.ttf
77b4b46000-77b4b91000 r--s 00000000 103:0b 946                           /system/fonts/Roboto-Black.ttf
77b4b91000-77b4be2000 r--s 00000000 103:0b 954                           /system/fonts/Roboto-MediumItalic.ttf
77b4be2000-77b4c2d000 r--s 00000000 103:0b 953                           /system/fonts/Roboto-Medium.ttf
77b4c2d000-77b4c7e000 r--s 00000000 103:0b 950                           /system/fonts/Roboto-Italic.ttf
77b4c7e000-77b4cc9000 r--s 00000000 103:0b 955                           /system/fonts/Roboto-Regular.ttf
77b4cc9000-77b61f6000 r--s 00000000 103:0b 2205                          /system/usr/icu/icudt56l.dat
77b61f6000-77b61f8000 r-xp 00000000 fd:00 531594                         /data/app/com.example.superhook-1/lib/arm64/libtestLib.so
77b61f8000-77b61f9000 r--p 00001000 fd:00 531594                         /data/app/com.example.superhook-1/lib/arm64/libtestLib.so
77b61f9000-77b61fa000 rw-p 00002000 fd:00 531594                         /data/app/com.example.superhook-1/lib/arm64/libtestLib.so
77b6200000-77b6400000 rw-p 00000000 00:00 0                              [anon:libc_malloc]
77b6400000-77b6600000 rw-p 00000000 00:00 0                              [anon:libc_malloc]
77b6600000-77b6602000 r--s 00000000 103:0b 910                           /system/fonts/NotoSansRejang-Regular.ttf
77b6602000-77b660b000 r--s 00000000 103:0b 883                           /system/fonts/NotoSansKhmerUI-Bold.ttf
77b660b000-77b6619000 r--s 00000000 103:0b 894                           /system/fonts/NotoSansMalayalamUI-Bold.ttf
77b6619000-77b666b000 r--s 00000000 103:0b 952                           /system/fonts/Roboto-LightItalic.ttf
77b666b000-77b66b7000 r--s 00000000 103:0b 951                           /system/fonts/Roboto-Light.ttf
77b66b7000-77b66b8000 r--p 00000000 00:00 0                              [anon:linker_alloc]
77b66b8000-77b66d8000 rw-p 00000000 00:04 16053                          /dev/ashmem/dalvik-CompilerMetadata (deleted)
77b66d8000-77b66f8000 rw-p 00000000 00:04 16052                          /dev/ashmem/dalvik-CompilerMetadata (deleted)
admin@C02D7132MD6R bionic % adb shell
angler:/ $ ps |grep superhook
u0_a69    7680  540   1620436 71348 SyS_epoll_ 0000000000 S com.example.superhook
angler:/ $ su
angler:/ # cat /proc/7680/maps
12c00000-12e08000 rw-p 00000000 00:04 16462                              /dev/ashmem/dalvik-main space (deleted)
12e08000-13008000 rw-p 00208000 00:04 16462                              /dev/ashmem/dalvik-main space (deleted)
13008000-1ec00000 ---p 00408000 00:04 16462                              /dev/ashmem/dalvik-main space (deleted)
32c00000-32c01000 rw-p 00000000 00:04 16463                              /dev/ashmem/dalvik-main space 1 (deleted)
32c01000-3ec00000 ---p 00001000 00:04 16463                              /dev/ashmem/dalvik-main space 1 (deleted)
6f7b1000-6fa50000 rw-p 00000000 fd:00 278001                             /data/dalvik-cache/arm64/system@framework@boot.art
6fa50000-6fbcc000 rw-p 00000000 fd:00 278002                             /data/dalvik-cache/arm64/system@framework@boot-core-libart.art
6fbcc000-6fc01000 rw-p 00000000 fd:00 278003                             /data/dalvik-cache/arm64/system@framework@boot-conscrypt.art
6fc01000-6fc3a000 rw-p 00000000 fd:00 278004                             /data/dalvik-cache/arm64/system@framework@boot-okhttp.art
6fc3a000-6fc3d000 rw-p 00000000 fd:00 278005                             /data/dalvik-cache/arm64/system@framework@boot-core-junit.art
6fc3d000-6fc83000 rw-p 00000000 fd:00 278006                             /data/dalvik-cache/arm64/system@framework@boot-bouncycastle.art
6fc83000-6fcc5000 rw-p 00000000 fd:00 278007                             /data/dalvik-cache/arm64/system@framework@boot-ext.art

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2021-5-27 19:47 被whulzz编辑 ,原因: 添加丢失图片以及附加源码地址
收藏
免费 8
支持
分享
最新回复 (11)
雪    币: 5330
活跃值: (5464)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
2
赞赞赞!
2021-5-27 18:01
0
雪    币: 3836
活跃值: (4218)
能力值: ( LV9,RANK:180 )
在线值:
发帖
回帖
粉丝
3

配图良心。

另外,获取模块基址还可以用下面这个函数

       int dl_iterate_phdr(
                 int (*callback) (struct dl_phdr_info *info,
                                  size_t size, void *data),
                 void *data);


2021-5-27 22:14
0
雪    币: 550
活跃值: (2387)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
4
GitRoy 赞赞赞![em_63]
谢谢大牛来访
2021-5-27 22:42
0
雪    币: 550
活跃值: (2387)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
5
krash 配图良心。另外,获取模块基址还可以用下面这个函数&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&am ...
谢谢大牛来访哈,还留下了些代码
2021-5-27 22:43
0
雪    币: 70
活跃值: (2010)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
2021-5-28 16:17
0
雪    币: 2270
活跃值: (5537)
能力值: ( LV8,RANK:146 )
在线值:
发帖
回帖
粉丝
7
nnnb 怎么每次都有人跟我在做同样的事情,然后还比我更快出结果
2021-5-30 21:09
0
雪    币: 550
活跃值: (2387)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
8
Simp1er nnnb 怎么每次都有人跟我在做同样的事情,然后还比我更快出结果
大佬,下次早点发出来哈
2021-5-30 21:58
0
雪    币: 2270
活跃值: (5537)
能力值: ( LV8,RANK:146 )
在线值:
发帖
回帖
粉丝
9
whulzz 大佬,下次早点发出来哈[em_27]
还是大佬们强,我是准备做而已,我是垃圾
2021-5-31 08:45
0
雪    币: 92
活跃值: (209)
能力值: ( LV6,RANK:95 )
在线值:
发帖
回帖
粉丝
10
Simp1er nnnb 怎么每次都有人跟我在做同样的事情,然后还比我更快出结果
有libxhook呢
2021-6-4 15:44
0
雪    币: 2677
活跃值: (5340)
能力值: ( LV10,RANK:177 )
在线值:
发帖
回帖
粉丝
11
大佬,可以放下代码,学习学习嘛
2021-6-9 10:34
0
雪    币: 550
活跃值: (2387)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
12
YenKoc 大佬,可以放下代码,学习学习嘛
核心代码都贴出来了,hook原理都一样的,可以参考其他开原的,,比如xhook
2021-6-19 18:36
0
游客
登录 | 注册 方可回帖
返回
//