第14章 Android中的so加固原理

  • Android逆向之旅—基于对so中的section加密技术实现so加固

    http://www.520monkey.com/archives/565

  • Android逆向之旅—Android应用的汉化功能(修改SO中的字符串内容)

    http://www.520monkey.com/archives/561

  • 简单粗暴的so加解密实现

    https://bbs.pediy.com/thread-191649.htm

  • 至于ELF文件格式,下面给出64位ELF文件格式解析以及对比给出32位ELF文件格式解析

    i) readelf -h 查看64位so文件的header

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    
    ELF Header:
    Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
    Class:                             ELF64
    Data:                              2's complement, little endian
    Version:                           1 (current)
    OS/ABI:                            UNIX - System V
    ABI Version:                       0
    Type:                              DYN (Shared object file)
    Machine:                           AArch64
    Version:                           0x1
    Entry point address:               0xe5c0
    Start of program headers:          64 (bytes into file)
    Start of section headers:          221776 (bytes into file)
    Flags:                             0x0
    Size of this header:               64 (bytes)
    Size of program headers:           56 (bytes)
    Number of program headers:         8
    Size of section headers:           64 (bytes)
    Number of section headers:         24
    Section header string table index: 23
    

    对比查看32位so文件的header

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    
    ELF Header:
    Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
    Class:                             ELF32
    Data:                              2's complement, little endian
    Version:                           1 (current)
    OS/ABI:                            UNIX - System V
    ABI Version:                       0
    Type:                              DYN (Shared object file)
    Machine:                           ARM
    Version:                           0x1
    Entry point address:               0x0
    Start of program headers:          52 (bytes into file)
    Start of section headers:          103056 (bytes into file)
    Flags:                             0x5000200, Version5 EABI, soft-float ABI
    Size of this header:               52 (bytes)
    Size of program headers:           32 (bytes)
    Number of program headers:         8
    Size of section headers:           40 (bytes)
    Number of section headers:         26
    Section header string table index: 25
    

    可以看出一个很大的变化在于 Size of this headerSize of program headersSize of section headers

    ii) 下面给出64位ELF文件的section header的结构

    (来自 http://androidxref.com/8.1.0_r33/xref/external/syslinux/com32/include/sys/elf64.h

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    
    typedef struct elf64_shdr {
        Elf64_Word sh_name;
        Elf64_Word sh_type;
        Elf64_Xword sh_flags;
        Elf64_Addr sh_addr;
        Elf64_Off sh_offset;
        Elf64_Xword sh_size;
        Elf64_Word sh_link;
        Elf64_Word sh_info;
        Elf64_Xword sh_addralign;
        Elf64_Xword sh_entsize;
    } Elf64_Shdr;
    

    其中字段类型的typedef如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    typedef uint16_t Elf64_Half;
    typedef int16_t Elf64_SHalf;
    typedef uint32_t Elf64_Word;
    typedef int32_t Elf64_Sword;
    typedef uint64_t Elf64_Xword;
    typedef int64_t Elf64_Sxword;
    typedef uint64_t Elf64_Off;
    typedef uint64_t Elf64_Addr;
    typedef uint16_t Elf64_Section;
    

    对比给出32位ELF文件的section header的结构

    (来自 http://androidxref.com/8.1.0_r33/xref/external/syslinux/com32/include/sys/elf32.h

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    
    typedef struct elf32_shdr {
        Elf32_Word sh_name;
        Elf32_Word sh_type;
        Elf32_Word sh_flags;
        Elf32_Addr sh_addr;
        Elf32_Off sh_offset;
        Elf32_Word sh_size;
        Elf32_Word sh_link;
        Elf32_Word sh_info;
        Elf32_Word sh_addralign;
        Elf32_Word sh_entsize;
    } Elf32_Shdr;
    

    其中字段类型的typedef如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    typedef uint16_t Elf32_Half;
    typedef int16_t Elf32_SHalf;
    typedef uint32_t Elf32_Word;
    typedef int32_t Elf32_Sword;
    typedef uint64_t Elf32_Xword;
    typedef int64_t Elf32_Sxword;
    typedef uint32_t Elf32_Off;
    typedef uint32_t Elf32_Addr;
    typedef uint16_t Elf32_Section;
    

    由此可以简单计算出64位ELF文件section header共有

    len(Elf64_Word) + len(Elf64_Word) + len(Elf64_Xword) + len(Elf64_Addr) + len(Elf64_Off) + len(Elf64_Xword) + len(Elf64_Word) + len(Elf64_Word) + len(Elf64_Xword) + len(Elf64_Xword) = 4B + 4B + 8B + 8B + 8B + 8B + 4B + 4B + 8B + 8B = 64B

    32位ELF文件section header共有

    len(Elf32_Word) + len(Elf32_Word) + len(Elf32_Word) + len(Elf32_Addr) + len(Elf32_Off) + len(Elf32_Word) + len(Elf32_Word) + len(Elf32_Word) + len(Elf32_Word) + len(Elf32_Word) = 4B + 4B + 4B + 4B + 4B + 4B + 4B + 4B + 4B + 4B = 40B

    如有需要,可以查看elf.h(包含了elf32.h以及elf64.h)

  • 对于section header,存在Flg属性,在使用readelf -S命令查询时,会看到 Key to Flags :

    ```
    W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
    L (link order), O (extra OS processing required), G (group), T (TLS),
    C (compressed), x (unknown), o (OS specific), E (exclude),
    y (purecode), p (processor specific)
    ```
    
    在`section header`中对应每个`Flg`属性的二进制如下:
    
Flg 二进制
D D