• [免费专栏] Android安全之Android的so文件分析



    欢迎新同学的光临
    … …
    人若无名,便可专心练剑


    我不是一条咸鱼,而是一条死鱼啊!


    0x01 前言

    开发Android应用时,有时候Java层的编码不能满足实现需求,就需要到C/C++实现后生成SO文件,再用System.loadLibrary()加载进行调用,成为JNI层的实现。常见的场景如:加解密算法,音视频编解码等。在生成SO文件时,需要考虑适配市面上不同手机CPU架构,而生成支持不同平台的SO文件进行兼容。目前Android共支持七种不同类型的CPU架构,分别是:ARMv5,ARMv7 (从2010年起),x86 (从2011年起),MIPS (从2012年起),ARMv8,MIPS64和x86_64 (从2014年起)

    so库一般是程序里面核心代码块,通过Android提供的NDK技术将核心代码用安全性更高的C/C++语言实现并提供给Java层调用来保证程序核心代码的安全。

    高性能的代码一般都会采取C/C++实现,通过Android的NDK技术来让Java层直接使用。其安全性相对于Java会高很多,相对于Java代码来说其反编译难度要大很多,但对于经验丰富的破解者来说,仍然是很容易的事,可以通过暴力破解或国外高价工具来将其破解。应用的关键性功能或算法,都会在so中实现,如果so被逆向,应用的关键性代码和算法都将会暴露

    :elf 文件是 linux 底下二进制文件,可以理解为 windows 下的PE文件,在 Android 中可以比作dll,方便函数的移植,在常用于保护 Android 软件,增加逆向难度。

    • 解析 elf 文件有啥子用?
      1、so 加固
      2、用于 frida(xposed) 的检测

    0x02 ELF文件格式解析

    可执行和可链接格式(Executable and Linkable Format,缩写为ELF),常被称为ELF格式,在计算机科学中,是一种用于执行档、目的档、共享库和核心转储的标准文件格式

    so 文件大体上可分为四部分,一般来说从上往下是ELF头部->Pargarm头部->节区(Section)->节区头,其中,除了ELF头部在文件位置固定不变外,其余三部分的位置都不固定。整体结构图可以参考非虫大佬的那张图,图片如下:

    在这里插入图片描述

    https://github.com/qintangtao/android.cracking.doc/blob/master/ELF%E6%96%87%E4%BB%B6%E6%A0%BC%E5%BC%8F%E5%88%86%E6%9E%90-%E5%8C%97%E4%BA%AC%E5%A4%A7%E5%AD%A6%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E5%AE%9E%E9%AA%8C%E5%AE%A4.pdf

    2.1 ultraedit工具

    地址:http://www.ultraedit.cn

    2.2 ELF文件主四种类型

    • 可重定位文件(Relocatable File) 包含适合于与其他目标文件链接来创建可执行文件或者共享目标文件的代码和数据
    • 可执行文件(Executable File) 包含适合于执行的一个程序,此文件规定了 exec() 如何创建一个程序的进程映像
    • 共享目标文件(Shared Object File) 包含可在两种上下文中链接的代码和数据。首先链接编辑器可以将它和其它可重定位文件和共享目标文件一起处理,生成另外一个目标文件。其次,动态链接器(Dynamic Linker)可能将它与某个可执行文件以及其它共享目标一起组合,创建进程映像

    Android中so文件就是ELF文件,所以我们需要了解ELF文件的格式。如何详细了解ELF文件?最好的方法就是手动写一个工具类来解析一个ELF文件

    2.3 cygwin安装教程

    Windows ELF文件解析工具:https://cygwin.com

    安装如下工具包:

    binutils:		// 工具集,用于编译 c
    gcc-core:		// 编译 c
    gcc-g++			// 编译 c++
    gcc-mingw-core:	// windows 编译 c(不一定需要)
    gdb:			// 调试
    make:			// makefile
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这里插入图片描述

    在这里插入图片描述

    然后配置环境变量

    cygwin64安装路径\bin
    cygwin64安装路径\sbin
    cygwin64安装路径\usr\sbin
    
    
    • 1
    • 2
    • 3
    • 4

    然后运行一下查看是否安装成功

    $cygcheck.exe -c cygwin
    Cygwin Package Information
    Package              Version        Status
    cygwin               3.3.2-1        OK
    
    • 1
    • 2
    • 3
    • 4

    0x03 Linux 下的readelf命令

    • 查看so文件的头部信息
    $ readelf -h libsqlite.so
    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:                           Intel 80386
      Version:                           0x1
      Entry point address:               0x0
      Start of program headers:          52 (bytes into file)
      Start of section headers:          651124 (bytes into file)
      Flags:                             0x0
      Size of this header:               52 (bytes)
      Size of program headers:           32 (bytes)
      Number of program headers:         7
      Size of section headers:           40 (bytes)
      Number of section headers:         23
      Section header string table index: 22
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 查看so文件的节(Section)头的信息
    $ readelf -s libsqlite.so
    Symbol table '.dynsym' contains 262 entries:
       Num:    Value  Size Type    Bind   Vis      Ndx Name
         0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
         1: 00000000     0 FUNC    GLOBAL DEFAULT  UND __cxa_finalize
         2: 00000000     0 FUNC    GLOBAL DEFAULT  UND __cxa_atexit
         3: 00000000     0 FUNC    GLOBAL DEFAULT  UND __stack_chk_fail
         4: 00008ab0    35 FUNC    GLOBAL DEFAULT    7 sqlite3_compileoption_get
         5: 00008b80    39 FUNC    GLOBAL DEFAULT    7 sqlite3_mutex_free
         6: 00008bb0    39 FUNC    GLOBAL DEFAULT    7 sqlite3_mutex_enter
         7: 00008be0    41 FUNC    GLOBAL DEFAULT    7 sqlite3_mutex_try
         8: 00008c10    39 FUNC    GLOBAL DEFAULT    7 sqlite3_mutex_leave
         9: 00008c40    78 FUNC    GLOBAL DEFAULT    7 sqlite3_vfs_unregister
        10: 00008d20     3 FUNC    GLOBAL DEFAULT    7 sqlite3_release_memory
        11: 00008e20    40 FUNC    GLOBAL DEFAULT    7 sqlite3_msize
        12: 00009000   168 FUNC    GLOBAL DEFAULT    7 sqlite3_stricmp
        13: 000090b0   159 FUNC    GLOBAL DEFAULT    7 sqlite3_strnicmp
        14: 00009150   230 FUNC    GLOBAL DEFAULT    7 sqlite3_compileoption_use
        15: 0007f26c   381 FUNC    GLOBAL DEFAULT    7 __moddi3
        16: 0007f106   358 FUNC    GLOBAL DEFAULT    7 __divdi3
        17: 00000000     0 OBJECT  GLOBAL DEFAULT  UND __stack_chk_guard
        18: 0000b2b0     8 FUNC    GLOBAL DEFAULT    7 sqlite3_backup_remaining
        19: 0000b2c0     8 FUNC    GLOBAL DEFAULT    7 sqlite3_backup_pagecount
        20: 0000b3a0    27 FUNC    GLOBAL DEFAULT    7 sqlite3_sql
        21: 0000b3c0    31 FUNC    GLOBAL DEFAULT    7 sqlite3_value_type
        22: 0000b3e0    11 FUNC    GLOBAL DEFAULT    7 sqlite3_user_data
        23: 0000b3f0    10 FUNC    GLOBAL DEFAULT    7 sqlite3_context_db_handle
        24: 0000b400    59 FUNC    GLOBAL DEFAULT    7 sqlite3_get_auxdata
        25: 0000b440    19 FUNC    GLOBAL DEFAULT    7 sqlite3_column_count
        26: 0000b460    27 FUNC    GLOBAL DEFAULT    7 sqlite3_data_count
        27: 0000b480    19 FUNC    GLOBAL DEFAULT    7 sqlite3_bind_parameter_co
        28: 0000b4a0    35 FUNC    GLOBAL DEFAULT    7 sqlite3_bind_parameter_na
        29: 0000b4d0    19 FUNC    GLOBAL DEFAULT    7 sqlite3_db_handle
        30: 0000b4f0    30 FUNC    GLOBAL DEFAULT    7 sqlite3_stmt_readonly
        31: 0000b510    33 FUNC    GLOBAL DEFAULT    7 sqlite3_stmt_busy
        32: 0000b540    77 FUNC    GLOBAL DEFAULT    7 sqlite3_next_stmt
        33: 0000b590    34 FUNC    GLOBAL DEFAULT    7 sqlite3_stmt_status
        34: 0000b6d0    27 FUNC    GLOBAL DEFAULT    7 sqlite3_blob_bytes
        35: 0000bb50    95 FUNC    GLOBAL DEFAULT    7 sqlite3_set_authorizer
        36: 0000c510    60 FUNC    GLOBAL DEFAULT    7 sqlite3_strglob
        37: 0000c6d0   182 FUNC    GLOBAL DEFAULT    7 sqlite3_cancel_auto_exten
        38: 0000ca80    28 FUNC    GLOBAL DEFAULT    7 sqlite3_vtab_on_conflict
        39: 0000cfe0   899 FUNC    GLOBAL DEFAULT    7 sqlite3_complete
        40: 0000d370    18 FUNC    GLOBAL DEFAULT    7 sqlite3_libversion
        41: 00087c00     9 OBJECT  GLOBAL DEFAULT    8 sqlite3_version
        42: 0000d390    18 FUNC    GLOBAL DEFAULT    7 sqlite3_sourceid
        43: 0000d3b0     6 FUNC    GLOBAL DEFAULT    7 sqlite3_libversion_number
        44: 0000d3c0     6 FUNC    GLOBAL DEFAULT    7 sqlite3_threadsafe
        45: 0000d3d0     8 FUNC    GLOBAL DEFAULT    7 sqlite3_db_mutex
        46: 0000d3e0   115 FUNC    GLOBAL DEFAULT    7 sqlite3_db_release_memory
        47: 0000d4b0    11 FUNC    GLOBAL DEFAULT    7 sqlite3_last_insert_rowid
        48: 0000d4c0     8 FUNC    GLOBAL DEFAULT    7 sqlite3_changes
        49: 0000d4d0     8 FUNC    GLOBAL DEFAULT    7 sqlite3_total_changes
        50: 0000d560    92 FUNC    GLOBAL DEFAULT    7 sqlite3_busy_handler
        51: 0000d5c0    15 FUNC    GLOBAL DEFAULT    7 sqlite3_interrupt
        52: 0000d5d0    80 FUNC    GLOBAL DEFAULT    7 sqlite3_trace
        53: 0000d620    80 FUNC    GLOBAL DEFAULT    7 sqlite3_profile
        54: 0000d670    80 FUNC    GLOBAL DEFAULT    7 sqlite3_commit_hook
        55: 0000d6c0    80 FUNC    GLOBAL DEFAULT    7 sqlite3_update_hook
        56: 0000d710    80 FUNC    GLOBAL DEFAULT    7 sqlite3_rollback_hook
        57: 0000d760    80 FUNC    GLOBAL DEFAULT    7 sqlite3_wal_hook
        58: 0000d7b0    71 FUNC    GLOBAL DEFAULT    7 sqlite3_limit
        59: 0000d800    82 FUNC    GLOBAL DEFAULT    7 sqlite3_collation_needed
        60: 0000d860    82 FUNC    GLOBAL DEFAULT    7 sqlite3_collation_needed1
        61: 0000d8c0     9 FUNC    GLOBAL DEFAULT    7 sqlite3_get_autocommit
        62: 0000d8d0    70 FUNC    GLOBAL DEFAULT    7 sqlite3_extended_result_c
        63: 0000d9d0   143 FUNC    GLOBAL DEFAULT    7 sqlite3_file_control
        64: 0000da60    68 FUNC    GLOBAL DEFAULT    7 sqlite3_db_filename
        65: 0000dab0    43 FUNC    GLOBAL DEFAULT    7 sqlite3_db_readonly
        66: 00000000     0 FUNC    GLOBAL DEFAULT  UND memset
        67: 00000000     0 FUNC    GLOBAL DEFAULT  UND memcpy
        68: 00000000     0 FUNC    GLOBAL DEFAULT  UND strcmp
        69: 0000e970   256 FUNC    GLOBAL DEFAULT    7 sqlite3_uri_parameter
        70: 00000000     0 FUNC    GLOBAL DEFAULT  UND pthread_mutex_unlock
        71: 00000000     0 FUNC    GLOBAL DEFAULT  UND pthread_mutex_trylock
        72: 00000000     0 FUNC    GLOBAL DEFAULT  UND pthread_mutex_lock
        73: 00000000     0 FUNC    GLOBAL DEFAULT  UND sysconf
        74: 00000000     0 FUNC    GLOBAL DEFAULT  UND geteuid
        75: 00000000     0 FUNC    GLOBAL DEFAULT  UND fchown
        76: 00000000     0 FUNC    GLOBAL DEFAULT  UND __errno
        77: 00000000     0 FUNC    GLOBAL DEFAULT  UND open
        78: 00000000     0 FUNC    GLOBAL DEFAULT  UND lseek64
        79: 00000000     0 FUNC    GLOBAL DEFAULT  UND gettimeofday
        80: 00000000     0 FUNC    GLOBAL DEFAULT  UND sleep
        81: 00000000     0 FUNC    GLOBAL DEFAULT  UND dlclose
        82: 00000000     0 FUNC    GLOBAL DEFAULT  UND dlsym
        83: 00000000     0 FUNC    GLOBAL DEFAULT  UND dlopen
        84: 00000000     0 FUNC    GLOBAL DEFAULT  UND memcmp
        85: 00000000     0 FUNC    GLOBAL DEFAULT  UND strncmp
        86: 0000f700    75 FUNC    GLOBAL DEFAULT    7 sqlite3_bind_parameter_in
        87: 00000000     0 FUNC    GLOBAL DEFAULT  UND free
        88: 000108e0   122 FUNC    GLOBAL DEFAULT    7 sqlite3_free
        89: 00011190    92 FUNC    GLOBAL DEFAULT    7 sqlite3_free_table
        90: 00000000     0 FUNC    GLOBAL DEFAULT  UND pthread_mutex_destroy
        91: 00011e60    17 FUNC    GLOBAL DEFAULT    7 sqlite3_result_double
        92: 00011ec0    55 FUNC    GLOBAL DEFAULT    7 sqlite3_result_int
        93: 00011f80    55 FUNC    GLOBAL DEFAULT    7 sqlite3_result_int64
        94: 00012000    29 FUNC    GLOBAL DEFAULT    7 sqlite3_result_null
        95: 00012020    65 FUNC    GLOBAL DEFAULT    7 sqlite3_result_error_nome
        96: 000120d0   141 FUNC    GLOBAL DEFAULT    7 sqlite3_clear_bindings
        97: 00012160    63 FUNC    GLOBAL DEFAULT    7 sqlite3_result_zeroblob
        98: 00014aa0    18 FUNC    GLOBAL DEFAULT    7 sqlite3_value_int
        99: 00014ac0     9 FUNC    GLOBAL DEFAULT    7 sqlite3_value_int64
       100: 00014c20    28 FUNC    GLOBAL DEFAULT    7 sqlite3_value_double
       101: 00014ce0    72 FUNC    GLOBAL DEFAULT    7 sqlite3_value_numeric_typ
       102: 00016df0   238 FUNC    GLOBAL DEFAULT    7 sqlite3_db_config
       103: 00016f90    39 FUNC    GLOBAL DEFAULT    7 sqlite3_errstr
       104: 00017000   106 FUNC    GLOBAL DEFAULT    7 sqlite3_busy_timeout
       105: 00017070   100 FUNC    GLOBAL DEFAULT    7 sqlite3_wal_autocheckpoin
       106: 000176d0   211 FUNC    GLOBAL DEFAULT    7 sqlite3_set_auxdata
       107: 00018510    62 FUNC    GLOBAL DEFAULT    7 sqlite3_column_double
       108: 00018550    60 FUNC    GLOBAL DEFAULT    7 sqlite3_column_int
       109: 00018590    70 FUNC    GLOBAL DEFAULT    7 sqlite3_column_int64
       110: 000185e0    58 FUNC    GLOBAL DEFAULT    7 sqlite3_column_value
       111: 00018620    60 FUNC    GLOBAL DEFAULT    7 sqlite3_column_type
       112: 00018e50    91 FUNC    GLOBAL DEFAULT    7 sqlite3_uri_int64
       113: 0001a190    79 FUNC    GLOBAL DEFAULT    7 sqlite3_uri_boolean
       114: 00000000     0 FUNC    GLOBAL DEFAULT  UND pthread_mutexattr_init
       115: 00000000     0 FUNC    GLOBAL DEFAULT  UND pthread_mutexattr_settype
       116: 00000000     0 FUNC    GLOBAL DEFAULT  UND pthread_mutex_init
       117: 00000000     0 FUNC    GLOBAL DEFAULT  UND pthread_mutexattr_destroy
       118: 0001afe0    34 FUNC    GLOBAL DEFAULT    7 sqlite3_column_name16
       119: 00028310    14 FUNC    GLOBAL DEFAULT    7 sqlite3_value_text16
       120: 0001b010    34 FUNC    GLOBAL DEFAULT    7 sqlite3_column_name
       121: 000264a0    14 FUNC    GLOBAL DEFAULT    7 sqlite3_value_text
       122: 00000000     0 FUNC    GLOBAL DEFAULT  UND utimes
       123: 0001d8e0   982 FUNC    GLOBAL DEFAULT    7 sqlite3_db_status
       124: 0001f1c0     3 FUNC    GLOBAL DEFAULT    7 sqlite3_os_end
       125: 0001f1d0    81 FUNC    GLOBAL DEFAULT    7 sqlite3_enable_load_exten
       126: 0001f230  1174 FUNC    GLOBAL DEFAULT    7 sqlite3_config
       127: 0001f6d0  1404 FUNC    GLOBAL DEFAULT    7 sqlite3_initialize
       128: 0001ff10    65 FUNC    GLOBAL DEFAULT    7 sqlite3_malloc
       129: 0001fdd0   111 FUNC    GLOBAL DEFAULT    7 sqlite3_os_init
       130: 0001fc50   155 FUNC    GLOBAL DEFAULT    7 sqlite3_vfs_find
       131: 0001fcf0    77 FUNC    GLOBAL DEFAULT    7 sqlite3_sleep
       132: 0001fd40   137 FUNC    GLOBAL DEFAULT    7 sqlite3_vfs_register
       133: 0001fe40    89 FUNC    GLOBAL DEFAULT    7 sqlite3_mutex_alloc
       134: 00020060    54 FUNC    GLOBAL DEFAULT    7 sqlite3_malloc64
       135: 000200a0    70 FUNC    GLOBAL DEFAULT    7 sqlite3_realloc
       136: 000200f0    75 FUNC    GLOBAL DEFAULT    7 sqlite3_realloc64
       137: 00020490    36 FUNC    GLOBAL DEFAULT    7 sqlite3_aggregate_context
       138: 00000000     0 FUNC    GLOBAL DEFAULT  UND memmove
       139: 00020cc0    50 FUNC    GLOBAL DEFAULT    7 sqlite3_result_error
       140: 00000000     0 FUNC    GLOBAL DEFAULT  UND localtime
       141: 00021170    50 FUNC    GLOBAL DEFAULT    7 sqlite3_result_error16
       142: 000211b0   105 FUNC    GLOBAL DEFAULT    7 sqlite3_result_error_code
       143: 00021220    73 FUNC    GLOBAL DEFAULT    7 sqlite3_result_error_toob
       144: 000213f0    39 FUNC    GLOBAL DEFAULT    7 sqlite3_result_blob
       145: 000214f0    39 FUNC    GLOBAL DEFAULT    7 sqlite3_result_text
       146: 00021710    39 FUNC    GLOBAL DEFAULT    7 sqlite3_result_text16
       147: 00021740    39 FUNC    GLOBAL DEFAULT    7 sqlite3_result_text16be
       148: 00021770    39 FUNC    GLOBAL DEFAULT    7 sqlite3_result_text16le
       149: 000217a0    68 FUNC    GLOBAL DEFAULT    7 sqlite3_result_blob64
       150: 000217f0   117 FUNC    GLOBAL DEFAULT    7 sqlite3_result_text64
       151: 000221e0    15 FUNC    GLOBAL DEFAULT    7 sqlite3_result_value
       152: 0007f4fc   317 FUNC    GLOBAL DEFAULT    7 __umoddi3
       153: 0007f3e9   275 FUNC    GLOBAL DEFAULT    7 __udivdi3
       154: 00026090    99 FUNC    GLOBAL DEFAULT    7 sqlite3_vsnprintf
       155: 00026100    58 FUNC    GLOBAL DEFAULT    7 sqlite3_snprintf
       156: 00000000     0 FUNC    GLOBAL DEFAULT  UND dlerror
       157: 00026400    14 FUNC    GLOBAL DEFAULT    7 sqlite3_value_bytes
       158: 00026410    60 FUNC    GLOBAL DEFAULT    7 sqlite3_column_bytes
       159: 00026450    14 FUNC    GLOBAL DEFAULT    7 sqlite3_value_bytes16
       160: 00026460    60 FUNC    GLOBAL DEFAULT    7 sqlite3_column_bytes16
       161: 000264f0    79 FUNC    GLOBAL DEFAULT    7 sqlite3_value_blob
       162: 00026600    60 FUNC    GLOBAL DEFAULT    7 sqlite3_column_blob
       163: 00026860    60 FUNC    GLOBAL DEFAULT    7 sqlite3_column_text
       164: 00028320    60 FUNC    GLOBAL DEFAULT    7 sqlite3_column_text16
       165: 00028360    14 FUNC    GLOBAL DEFAULT    7 sqlite3_value_text16be
       166: 00028370    14 FUNC    GLOBAL DEFAULT    7 sqlite3_value_text16le
       167: 00029970   199 FUNC    GLOBAL DEFAULT    7 sqlite3_log
       168: 00029a90   178 FUNC    GLOBAL DEFAULT    7 sqlite3_status64
       169: 00029b50    82 FUNC    GLOBAL DEFAULT    7 sqlite3_status
       170: 00029bb0    67 FUNC    GLOBAL DEFAULT    7 sqlite3_memory_used
       171: 00029c00    67 FUNC    GLOBAL DEFAULT    7 sqlite3_memory_highwater
       172: 00029d90    39 FUNC    GLOBAL DEFAULT    7 sqlite3_create_module
       173: 00029dc0    39 FUNC    GLOBAL DEFAULT    7 sqlite3_create_module_v2
       174: 00029df0   134 FUNC    GLOBAL DEFAULT    7 sqlite3_vtab_config
       175: 00000000     0 FUNC    GLOBAL DEFAULT  UND strlen
       176: 00000000     0 FUNC    GLOBAL DEFAULT  UND getpid
       177: 00000000     0 FUNC    GLOBAL DEFAULT  UND time
       178: 00000000     0 FUNC    GLOBAL DEFAULT  UND fsync
       179: 0002d430    79 FUNC    GLOBAL DEFAULT    7 sqlite3_errcode
       180: 0002d480    79 FUNC    GLOBAL DEFAULT    7 sqlite3_extended_errcode
       181: 0002d4d0   200 FUNC    GLOBAL DEFAULT    7 sqlite3_errmsg
       182: 00000000     0 FUNC    GLOBAL DEFAULT  UND realloc
       183: 00000000     0 FUNC    GLOBAL DEFAULT  UND malloc
       184: 0002d9d0    49 FUNC    GLOBAL DEFAULT    7 sqlite3_bind_blob
       185: 0002da10    83 FUNC    GLOBAL DEFAULT    7 sqlite3_bind_blob64
       186: 0002da70    49 FUNC    GLOBAL DEFAULT    7 sqlite3_bind_text
       187: 0002dab0   130 FUNC    GLOBAL DEFAULT    7 sqlite3_bind_text64
       188: 0002db40    49 FUNC    GLOBAL DEFAULT    7 sqlite3_bind_text16
       189: 0002db80   100 FUNC    GLOBAL DEFAULT    7 sqlite3_bind_double
       190: 0002dbf0   126 FUNC    GLOBAL DEFAULT    7 sqlite3_bind_int64
       191: 0002dc70    57 FUNC    GLOBAL DEFAULT    7 sqlite3_bind_int
       192: 0002dcb0    64 FUNC    GLOBAL DEFAULT    7 sqlite3_bind_null
       193: 0002dcf0   126 FUNC    GLOBAL DEFAULT    7 sqlite3_bind_zeroblob
       194: 0002dd70   329 FUNC    GLOBAL DEFAULT    7 sqlite3_bind_value
       195: 0002e300   331 FUNC    GLOBAL DEFAULT    7 sqlite3_create_function_v
       196: 0002e450    98 FUNC    GLOBAL DEFAULT    7 sqlite3_create_function
       197: 0002e4c0   162 FUNC    GLOBAL DEFAULT    7 sqlite3_create_function16
       198: 0002e570   230 FUNC    GLOBAL DEFAULT    7 sqlite3_overload_function
       199: 0002e820   108 FUNC    GLOBAL DEFAULT    7 sqlite3_create_collation_
       200: 0002e890    74 FUNC    GLOBAL DEFAULT    7 sqlite3_create_collation
       201: 0002e8e0   145 FUNC    GLOBAL DEFAULT    7 sqlite3_create_collation1
       202: 0002e980   210 FUNC    GLOBAL DEFAULT    7 sqlite3_errmsg16
       203: 0003ac00   228 FUNC    GLOBAL DEFAULT    7 sqlite3_soft_heap_limit64
       204: 0003acf0    48 FUNC    GLOBAL DEFAULT    7 sqlite3_soft_heap_limit
       205: 0003ad20   168 FUNC    GLOBAL DEFAULT    7 sqlite3_vmprintf
       206: 0003add0    55 FUNC    GLOBAL DEFAULT    7 sqlite3_mprintf
       207: 0003b600  1427 FUNC    GLOBAL DEFAULT    7 sqlite3_load_extension
       208: 0003c0c0   576 FUNC    GLOBAL DEFAULT    7 sqlite3_randomness
       209: 0009fe64     4 OBJECT  GLOBAL DEFAULT   19 sqlite3_temp_directory
       210: 00000000     0 FUNC    GLOBAL DEFAULT  UND getenv
       211: 0004a020  1917 FUNC    GLOBAL DEFAULT    7 sqlite3_backup_step
       212: 0004c4f0   320 FUNC    GLOBAL DEFAULT    7 sqlite3_backup_init
       213: 0005bb30   219 FUNC    GLOBAL DEFAULT    7 sqlite3_backup_finish
       214: 0005bd60    11 FUNC    GLOBAL DEFAULT    7 sqlite3_close
       215: 0005bd70    14 FUNC    GLOBAL DEFAULT    7 sqlite3_close_v2
       216: 0005c430   240 FUNC    GLOBAL DEFAULT    7 sqlite3_wal_checkpoint_v2
       217: 0005c520    66 FUNC    GLOBAL DEFAULT    7 sqlite3_wal_checkpoint
       218: 0005d2f0   135 FUNC    GLOBAL DEFAULT    7 sqlite3_finalize
       219: 0005d380    87 FUNC    GLOBAL DEFAULT    7 sqlite3_blob_close
       220: 0005d530    54 FUNC    GLOBAL DEFAULT    7 sqlite3_blob_read
       221: 0005d570    54 FUNC    GLOBAL DEFAULT    7 sqlite3_blob_write
       222: 0005d5b0   152 FUNC    GLOBAL DEFAULT    7 sqlite3_reset
       223: 000677f0  1022 FUNC    GLOBAL DEFAULT    7 sqlite3_exec
       224: 000666b0  3816 FUNC    GLOBAL DEFAULT    7 sqlite3_step
       225: 00067710   219 FUNC    GLOBAL DEFAULT    7 sqlite3_blob_reopen
       226: 00079d10    39 FUNC    GLOBAL DEFAULT    7 sqlite3_prepare_v2
       227: 0006e700  1720 FUNC    GLOBAL DEFAULT    7 sqlite3_blob_open
       228: 00079ab0    39 FUNC    GLOBAL DEFAULT    7 sqlite3_prepare
       229: 00079ec0    49 FUNC    GLOBAL DEFAULT    7 sqlite3_prepare16
       230: 00079f00    49 FUNC    GLOBAL DEFAULT    7 sqlite3_prepare16_v2
       231: 0007d360   442 FUNC    GLOBAL DEFAULT    7 sqlite3_declare_vtab
       232: 0007da70   756 FUNC    GLOBAL DEFAULT    7 sqlite3_table_column_meta
       233: 0007dd70   527 FUNC    GLOBAL DEFAULT    7 sqlite3_get_table
       234: 0007e150  1349 FUNC    GLOBAL DEFAULT    7 sqlite3_test_control
       235: 0007e6a0   211 FUNC    GLOBAL DEFAULT    7 sqlite3_auto_extension
       236: 0007e780   113 FUNC    GLOBAL DEFAULT    7 sqlite3_reset_auto_extens
       237: 0007e800   233 FUNC    GLOBAL DEFAULT    7 sqlite3_shutdown
       238: 0009fe60     4 OBJECT  GLOBAL DEFAULT   19 sqlite3_data_directory
       239: 0007e8f0   134 FUNC    GLOBAL DEFAULT    7 sqlite3_complete16
       240: 0007eff0    29 FUNC    GLOBAL DEFAULT    7 sqlite3_open
       241: 0007f010    29 FUNC    GLOBAL DEFAULT    7 sqlite3_open_v2
       242: 0007f030   210 FUNC    GLOBAL DEFAULT    7 sqlite3_open16
       243: 00000000     0 FUNC    GLOBAL DEFAULT  UND close
       244: 00000000     0 FUNC    GLOBAL DEFAULT  UND access
       245: 00000000     0 FUNC    GLOBAL DEFAULT  UND getcwd
       246: 00000000     0 FUNC    GLOBAL DEFAULT  UND stat
       247: 00000000     0 FUNC    GLOBAL DEFAULT  UND fstat
       248: 00000000     0 FUNC    GLOBAL DEFAULT  UND ftruncate
       249: 00000000     0 FUNC    GLOBAL DEFAULT  UND fcntl
       250: 00000000     0 FUNC    GLOBAL DEFAULT  UND read
       251: 00000000     0 FUNC    GLOBAL DEFAULT  UND write
       252: 00000000     0 FUNC    GLOBAL DEFAULT  UND fchmod
       253: 00000000     0 FUNC    GLOBAL DEFAULT  UND unlink
       254: 00000000     0 FUNC    GLOBAL DEFAULT  UND mkdir
       255: 00000000     0 FUNC    GLOBAL DEFAULT  UND rmdir
       256: 00000000     0 FUNC    GLOBAL DEFAULT  UND mmap
       257: 00000000     0 FUNC    GLOBAL DEFAULT  UND munmap
       258: 00000000     0 FUNC    GLOBAL DEFAULT  UND mremap
       259: 0009fe4c     0 NOTYPE  GLOBAL DEFAULT  ABS _edata
       260: 0009fe4c     0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
       261: 000a025c     0 NOTYPE  GLOBAL DEFAULT  ABS _end
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 查看so文件的程序段头信息(Program)
    $ readelf -l libsqlite.so
    
    Elf file type is DYN (Shared object file)
    Entry point 0x0
    There are 7 program headers, starting at offset 52
    
    Program Headers:
      Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
      PHDR           0x000034 0x00000034 0x00000034 0x000e0 0x000e0 R   0x4
      LOAD           0x000000 0x00000000 0x00000000 0x9c610 0x9c610 R E 0x1000
      LOAD           0x09d060 0x0009e060 0x0009e060 0x01dec 0x021fc RW  0x1000
      DYNAMIC        0x09ddf4 0x0009edf4 0x0009edf4 0x000f8 0x000f8 RW  0x4
      GNU_EH_FRAME   0x09a32c 0x0009a32c 0x0009a32c 0x022e4 0x022e4 R   0x4
      GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0
      GNU_RELRO      0x09d060 0x0009e060 0x0009e060 0x00fa0 0x00fa0 RW  0x20
    
     Section to Segment mapping:
      Segment Sections...
       00     
       01     .dynsym .dynstr .hash .rel.dyn .rel.plt .plt .text .rodata .eh_frame .eh_frame_hdr 
       02     .data.rel.ro.local .fini_array .data.rel.ro .init_array .dynamic .got .got.plt .data .bss 
       03     .dynamic 
       04     .eh_frame_hdr 
       05     
       06     .data.rel.ro.local .fini_array .data.rel.ro .init_array .dynamic .got .got.plt
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 查看so文件的全部内容
    $ readelf -a libsqlite.so
    
    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:                           Intel 80386
      Version:                           0x1
      Entry point address:               0x0
      Start of program headers:          52 (bytes into file)
      Start of section headers:          651124 (bytes into file)
      Flags:                             0x0
      Size of this header:               52 (bytes)
      Size of program headers:           32 (bytes)
      Number of program headers:         7
      Size of section headers:           40 (bytes)
      Number of section headers:         23
      Section header string table index: 22
    
    Section Headers:
      [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
      [ 0]                   NULL            00000000 000000 000000 00      0   0  0
      [ 1] .dynsym           DYNSYM          00000114 000114 001060 10   A  2   1  4
      [ 2] .dynstr           STRTAB          00001174 001174 00126c 00   A  0   0  1
      [ 3] .hash             HASH            000023e0 0023e0 000734 04   A  1   0  4
      [ 4] .rel.dyn          REL             00002b14 002b14 001b10 08   A  1   0  4
      [ 5] .rel.plt          REL             00004624 004624 0001b8 08  AI  1  17  4
      [ 6] .plt              PROGBITS        000047e0 0047e0 000380 04  AX  0   0 16
      [ 7] .text             PROGBITS        00004b60 004b60 07cae1 00  AX  0   0 16
      [ 8] .rodata           PROGBITS        00081660 081660 008cc0 00   A  0   0 32
      [ 9] .eh_frame         PROGBITS        0008a320 08a320 01000c 00   A  0   0  4
      [10] .eh_frame_hdr     PROGBITS        0009a32c 09a32c 0022e4 00   A  0   0  4
      [11] .data.rel.ro.loca PROGBITS        0009e060 09d060 000a58 00  WA  0   0 32
      [12] .fini_array       FINI_ARRAY      0009eab8 09dab8 000008 04  WA  0   0  4
      [13] .data.rel.ro      PROGBITS        0009eac0 09dac0 000330 00  WA  0   0 32
      [14] .init_array       INIT_ARRAY      0009edf0 09ddf0 000004 04  WA  0   0  1
      [15] .dynamic          DYNAMIC         0009edf4 09ddf4 0000f8 08  WA  2   0  4
      [16] .got              PROGBITS        0009eeec 09deec 00001c 00  WA  0   0  4
      [17] .got.plt          PROGBITS        0009ef08 09df08 0000e8 00  WA  0   0  4
      [18] .data             PROGBITS        0009f000 09e000 000e4c 00  WA  0   0 32
      [19] .bss              NOBITS          0009fe60 09ee4c 0003fc 00  WA  0   0 32
      [20] .comment          PROGBITS        00000000 09ee4c 000035 01  MS  0   0  1
      [21] .note.gnu.gold-ve NOTE            00000000 09ee84 00001c 00      0   0  4
      [22] .shstrtab         STRTAB          00000000 09eea0 0000d3 00      0   0  1
    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),
      p (processor specific)
    ... ...(后面内容太多,此处省略)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54

    3.1 readelf常用命令

    -a --all 相当于指定--file-header --program-headers --sections --symbols --relocs --dynamic --notes和--version-info
    -h --file-header 显示文件开头的ELF头中包含的信息
    -l --program-headers --segments 显示文件的segment头中包含的信息(如果有)
    -S --sections --section-headers 显示文件的section头中包含的信息(如果有)
    -g --section-groups 显示文件的section group中包含的信息(如果有)
    -t --section-details 显示详细的section信息。意味着-S
    -s --symbols --syms 显示文件的symbol table section中的条目(如果有)
    -e --headers 显示文件中的所有headers。相当于-h -l -S
    -n --notes 显示NOTE segment(/)section的内容(如果有)
    -r --relocs 显示文件relocation section的内容(如果有)
    -u --unwind 显示文件的unwind section的内容(如果有)。目前仅支持IA64 ELF文件的unwind section
    -d --dynamic 显示文件dynamic section的内容(如果有)
    -V --version-info 显示文件中version section的内容,如果存在
    -A --arch-specific 显示文件中特定于体系结构的信息(如果有)
    -D --use-dynamic 显示符号时,此选项使readelf使用文件dynamic section中的符号表,而不是symbol section中的符号表
    -x <number or name> --hex-dump=<number or name> 以十六进制字节显示indecated section的内容。一个数字通过索引section表标识一个特定的section;任何其他string标识目标文件中具有该名称的所有section
    -R <number or name> --relocated-dump=<number or name> 以十六进制字节显示indecated section的内容。一个数字通过索引section表标识一个特定的section;任何其他string标识目标文件中具有该名称的所有section,该section的内容将在显示之前重新定位。
    -p <number or name> --string-dump=<number or name> 将indicated section的内容显示为可打印字符串。一个数字通过索引section表标识一个特定的section;任何其他string标识目标文件中具有该名称的所有section
    -c --archive-index 显示二进制归档的header部分中包含的文件符号索引信息。对ar执行与t命令相同的功能,但不使用BFD库
    -w[lLiaprmfFsoR] --debug-dump[=rawline,=decodedline,=info,=abbrev,=pubnames,=aranges,=macro,=frames,=frames-interp,=str,=loc,=Ranges] 显示文件中debug section的内容(如果存在)。 如果后面有一个可选的字母或单词,则只会转储在这些特定部分中找到的数据
    注意:=codedline选项将显示.debug_line section解释后的内容,而=rawline选项将以原始格式转储内容
    -I --histogram 显示符号表的内容时,显示桶列表长度的直方图。
    -v --version 显示readelf的版本号
    -W --wide 不破坏输出线以适应80列。 默认情况下,readelf会断开64位ELF文件的section header和segment 列表行,以便它们适合80列。 此选项使readelf打印每个节标题resp。 每个segment只有一行,在80列以上的终端上可读性更高
    -H --help 显示readelf理解的命令行选项。
    @file
    从文件中读取命令行选项。读取的选项将替换原始@file选项。 如果文件不存在或无法读取,则该选项将按字面处理,而不会被删除。
    文件中的选项由空格分隔。通过用单引号或双引号括起整个选项,可以在选项中包含空格字符。可以通过在字符前加上反斜杠来包含任何字符(包括反斜杠)。该文件本身可能包含其他@file选项; 任何此类选项将以递归方式处理。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    0x04 分析ELF文件

    分析一个so文件,该文件是xx.apk的

    ELF文件头结构定义在“/usr/include/elf.h”头文件下,ELF文件有32位版本和64位版本,故其头文件结构也有32位结构和64位结构,分别定义为Elf32_Ehdr和Elf64_Ehdr。两种版本文件内容一样,只是有些成员的大小不一样。

    4.1 ELF Header的结构体

    #define EI_NIDENT	16
    typedef struct elf32_hdr{
      unsigned char	e_ident[EI_NIDENT];
      Elf32_Half	e_type;
      Elf32_Half	e_machine;
      Elf32_Word	e_version;
      Elf32_Addr	e_entry;  /* Entry point */
      Elf32_Off	e_phoff;
      Elf32_Off	e_shoff;
      Elf32_Word	e_flags;
      Elf32_Half	e_ehsize;
      Elf32_Half	e_phentsize;
      Elf32_Half	e_phnum;
      Elf32_Half	e_shentsize;
      Elf32_Half	e_shnum;
      Elf32_Half	e_shstrndx;
    } Elf32_Ehdr;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    4.1.1 字段意思

    e_ident 数组:前4个字节为.ELF,是 elf 标志头,第 5 个字节为该文件标志符,为 1 代表这是一个 32 位的 elf 文件,后面几个字节代表版本等信息
    e_type 字段:表示是可执行文件还是链接文件等,安卓上的 so 文件就是分享文件,一般该字段为 3
    e_machine 字段:该字段标志该文件运行在什么机器架构上,例如 ARM
    e_version 字段:该字段表示当前 so 文件的版本信息,一般为 1
    e_entry 字段:该字段是一个偏移地址,为程序启动的地址
    e_phoff 字段:该字段也是一个偏移地址,指向程序头 (Pargram Header) 的起始地址
    e_shoff 字段:该字段是一个偏移地址,指向节区头 (Section Header) 的起始地址
    e_flags 字段:该字段表示该文件的权限,常见的值有 1、2、4,分别代表 read、write、exec
    e_ehsize 字段:该字段表示 elf 文件头部大小,一般固定为 52
    e_phentsize 字段:该字段表示程序头 (Program Header) 大小,一般固定为 32
    e_phnum 字段:该字段表示文件中有几个程序头
    e_shentsize: 该字段表示节区头 (Section Header) 大小,一般固定为 40
    e_shnum 字段:该字段表示文件中有几个节区头
    e_shstrndx 字段:该字段是一个数字,这个表明了.shstrtab 节区(这个节区存储着所有节区的名字,例如.text)的节区头是第几个
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    :这几个是比较重要的参数(修改so文件时会用到):e_phoff、e_shoff、e_phnum、e_shstrndx

    在这里插入图片描述

    或者使用010Editor的ELF模板也可以看到ELF Header结构

    下载地址:https://www.sweetscape.com/010editor/

    在这里插入图片描述

    • e_ident

    e_ident是一个16字节的数组,这个数组按位置从左到右都是有特定含义,每个数组元素的下标在标准中还存在别称,如byte0的下标0别名为EI_MAG0,如下:

    名称元素下标值含义
    EI_MAG00文件标识
    EI_MAG11文件标识
    EI_MAG22文件标识
    EI_MAG33文件标识
    EI_CLASS4文件类
    EI_DATA5数据编码
    EI_VERSION6文件版本
    EI_PAD7补齐字节开始处
    EI_NIDENT16e_ident[]大小

    e_ident[EI_MAG0]e_ident[EI_MAG3]即e_ident[0]e_ident[3]被称为魔数(Magic Number),其值一般为0x7f,‘E’,‘L’,‘F’。

    e_ident[EI_CLASS](即e_ident[4])识别目标文件运行在目标机器的类别,取值可为三种值:ELFCLASSNONE(0)非法类别;ELFCLASS32(1)32位目标;ELFCLASS64(2)64位目标。

    e_ident[EI_DATA](即e_ident[5]):给出处理器特定数据的数据编码方式。即大端还是小端方式。取值可为3种:ELFDATANONE(0)非法数据编码;ELFDATA2LSB(1)高位在前;ELFDATA2MSB(2)低位在前。

    • e_type

    e_type表示elf文件的类型,如下:

    名称取值含义
    ET_NONE0未知目标文件格式
    ET_REL1可重定位文件
    ET_EXEC2可执行文件
    ET_DYN3共享目标文件
    ET_CORE4Core 文件(转储格式)
    ET_LOPROC0xff00特定处理器文件
    ET_HIPROC0xffff特定处理器文件
    ET_LOPROC~ET_HIPROC0xff00~0xffff特定处理器文件
    • e_machine

    e_machine表示目标体系结构类型:

    名称取值含义
    EM_NONE0未指定
    EM_M321AT&T WE 32100
    EM_SPARC2SPARC
    EM_3863Intel 80386
    EM_68K4Motorola 68000
    EM_88K5Motorola 88000
    EM_8607Intel 80860
    EM_MIPS8MIPS RS3000
    others9~预留
    • e_entry

    e_entry表示程序入口地址
    这 个sum.o的进入点是0x0(e_entry),这表面Relocatable objects不会有程序进入点。所谓程序进入点是指当程序真正执行起来的时候,其第一条要运行的指令的运行时地址。因为Relocatable objects file只是供再链接而已,所以它不存在进入点。而可执行文件test和动态库.so都存在所谓的进入点,且可执行文件的e_entry指向C库中的_start,而动态库.so中的进入点指向 call_gmon_start。
    如上图中e_entry = 0xD8B0,我们用ida打开该文件看到确实是_start()函数的地址

    图片xxx

    4.2 解析ELF文件的头部信息

    一个ELF文件中到底有哪些具体的 sections,由包含在这个ELF文件中的 section head table(SHT)决定。在SHT中,针对每一个section,都设置有一个条目(entry),用来描述对应的这个section,其内容主要包括该 section 的名称、类型、大小以及在整个ELF文件中的字节偏移位置等等。我们也可以在TISCv1.2规范中找到SHT表中条目的C结构定义:

    typedef struct{
        Elf32_Word sh_name;   //节区名,是节区头部字符串表节区(Section Header String Table Section)的索引。名字是一个 NULL 结尾的字符串。
        Elf32_Word sh_type;    //为节区类型
        Elf32_Word sh_flags;    //节区标志
        Elf32_Addr sh_addr;    //如果节区将出现在进程的内存映像中,此成员给出节区的第一个字节应处的位置。否则,此字段为 0。
        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;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • sh_type

    sh_type的取值如下:

    名称取值说明
    SHT_NULL0此值标志节区头部是非活动的,没有对应的节区。此节区头部中的其他成员取值无意义
    SHT_PROGBITS1此节区包含程序定义的信息,其格式和含义都由程序来解释
    SHT_SYMTAB2此节区包含一个符号表。目前目标文件对每种类型的节区都只能包含一个,不过这个限制将来可能发生变化。一般,SHT_SYMTAB 节区提供用于链接编辑(指 ld 而言)的符号,尽管也可用来实现动态链接
    SHT_STRTAB3此节区包含字符串表。目标文件可能包含多个字符串表节区
    SHT_RELA4此节区包含重定位表项,其中可能会有补齐内容(addend),例如 32 位目标文件中的 Elf32_Rela 类型。目标文件可能拥有多个重定位节区
    SHT_HASH5此节区包含符号哈希表。所有参与动态链接的目标都必须包含一个符号哈希表。目前,一个目标文件只能包含一个哈希表,不过此限制将来可能会解除
    SHT_DYNAMIC6此节区包含动态链接的信息。目前一个目标文件中只能包含一个动态节区,将来可能会取消这一限制
    SHT_NOTE7此节区包含以某种方式来标记文件的信息
    SHT_NOBITS8这 种 类 型 的 节 区 不 占 用 文 件 中 的 空 间 , 其 他 方 面 和SHT_PROGBITS 相似。尽管此节区不包含任何字节,成员sh_offset 中还是会包含概念性的文件偏移
    SHT_REL9此节区包含重定位表项,其中没有补齐(addends),例如 32 位目标文件中的 Elf32_rel 类型。目标文件中可以拥有多个重定位节区
    SHT_SHLIB10此节区被保留,不过其语义是未规定的。包含此类型节区的程序与 ABI 不兼容
    SHT_DYNSYM11作为一个完整的符号表,它可能包含很多对动态链接而言不必要的符号。因此,目标文件也可以包含一个 SHT_DYNSYM 节区,其中保存动态链接符号的一个最小集合,以节省空间
    SHT_LOPROC0X70000000这一段(包括两个边界),是保留给处理器专用语义的
    SHT_HIPROCOX7FFFFFFF这一段(包括两个边界),是保留给处理器专用语义的
    SHT_LOUSER0X80000000此值给出保留给应用程序的索引下界
    SHT_HIUSER0X8FFFFFFF此值给出保留给应用程序的索引上界
    • sh_flag

    sh_flag标志着此节区是否可以修改,是否可以执行,如下定义:

    名称取值含义
    SHF_WRITE0x1节区包含进程执行过程中将可写的数据
    SHF_ALLOC0x2此节区在进程执行过程中占用内存。某些控制节区并不出现于目标文件的内存映像中,对于那些节区,此位应设置为 0
    SHF_EXECINSTR0x4节区包含可执行的机器指令
    SHF_MASKPROC0xF0000000所有包含于此掩码中的四位都用于处理器专用的语义
    • sh_link 和 sh_info 字段

    sh_link和sh_info字段的具体含义依赖于sh_type的值:

    sh_typesh_linksh_info
    SHT_DYNAMIC此节区中条目所用到的字符串表格的节区头部索引0
    SHT_HASH此哈希表所适用的符号表的节区头部索引0
    SHT_REL
    SHT_RELA相关符号表的节区头部索引重定位所适用的节区的节区头部索引
    SHT_SYMTAB
    SHT_DYNSYM相关联的字符串表的节区头部索引最后一个局部符号(绑定 STB_LOCAL)的符号表索引值加一
    其它SHN_UNDEF0

    4.2.1 Section

    有些节区是系统预订的,一般以点开头号,因此,我们有必要了解一些常用到的系统节区

    名称类型属性含义
    .bssSHT_NOBITSSHF_ALLOC + SHF_WRITE包含将出现在程序的内存映像中的为初始化数据。根据定义,当程序开始执行,系统将把这些数据初始化为 0。此节区不占用文件空间
    .commentSHT_PROGBITS-包含版本控制信息
    .dataSHT_PROGBITSSHF_ALLOC + SHF_WRITE这些节区包含初始化了的数据,将出现在程序的内存映像中
    .data1SHT_PROGBITSSHF_ALLOC + SHF_WRITE这些节区包含初始化了的数据,将出现在程序的内存映像中
    .debugSHT_PROGBITS-此节区包含用于符号调试的信息
    .dynamicSHT_DYNAMIC-此节区包含动态链接信息。节区的属性将包含 SHF_ALLOC 位。是否 SHF_WRITE 位被设置取决于处理器
    .dynstrSHT_STRTABSHF_ALLOC此节区包含用于动态链接的字符串,大多数情况下这些字符串代表了与符号表项相关的名称
    .dynsymSHT_DYNSYMSHF_ALLOC此节区包含了动态链接符号表
    .finiSHT_PROGBITSSHF_ALLOC + SHF_EXECINSTR此节区包含了可执行的指令,是进程终止代码的一部分。程序正常退出时,系统将安排执行这里的代码
    .gotSHT_PROGBITS-此节区包含全局偏移表
    .hashSHT_HASHSHF_ALLOC此节区包含了一个符号哈希表
    .initSHT_PROGBITSSHF_ALLOC + SHF_EXECINSTR此节区包含了可执行指令,是进程初始化代码的一部分。当程序开始执行时,系统要在开始调用主程序入口之前(通常指 C 语言的 main 函数)执行这些代码
    .interpSHT_PROGBITS-此节区包含程序解释器的路径名。如果程序包含一个可加载的段,段中包含此节区,那么节区的属性将包含 SHF_ALLOC 位,否则该位为 0
    .lineSHT_PROGBITS-此节区包含符号调试的行号信息,其中描述了源程序与机器指令之间的对应关系。其内容是未定义的
    .noteSHT_NOTE-此节区中包含注释信息,有独立的格式
    .pltSHT_PROGBITS-此节区包含过程链接表(procedure linkage table)
    .relname和.relanameSHT_REL和SHT_RELA-这些节区中包含了重定位信息。如果文件中包含可加载的段,段中有重定位内容,节区的属性将包含 SHF_ALLOC 位,否则该位置 0。传统上 name 根据重定位所适用的节区给定。例如 .text 节区的重定位节区名字将是:.rel.text 或者 .rela.text
    .rodata和.rodata1SHT_PROGBITS和SHF_ALLOC-这些节区包含只读数据,这些数据通常参与进程映像的不可写段
    .shstrtabSHT_STRTAB-此节区包含节区名称
    .strtabSHT_STRTAB-此节区包含字符串,通常是代表与符号表项相关的名称。如果文件拥有一个可加载的段,段中包含符号串表,节区的属性将包含SHF_ALLOC 位,否则该位为 0
    .symtabSHT_SYMTAB-此节区包含一个符号表。如果文件中包含一个可加载的段,并且该段中包含符号表,那么节区的属性中包含SHF_ALLOC 位,否则该位置为 0
    .textSHT_PROGBITSSHF_ALLOC + SHF_EXECINSTR此节区包含程序的可执行指令

    下面我们分析一些so文件中重要的Section,包括
    符号表、重定位表、GOT表等。

    • 符号表(.dynsym)

    符号表包含用来定位、重定位程序中符号定义和引用的信息,简单的理解就是符号表记录了该文件中的所有符号,所谓的符号就是经过修饰了的函数名或者变量名,不同的编译器有不同的修饰规则。例如符号_ZL15global_static_a,就是由global_static_a变量名经过修饰而来。

    符号表项的格式如下:

    typedef struct {  
         Elf32_Word st_name;      //符号表项名称。如果该值非0,则表示符号名的字符串表索引(offset),否则符号表项没有名称。
         Elf32_Addr st_value;       //符号的取值。依赖于具体的上下文,可能是一个绝对值、一个地址等等。
         Elf32_Word st_size;         //符号的尺寸大小。例如一个数据对象的大小是对象中包含的字节数。
         unsigned char st_info;    //符号的类型和绑定属性。
         unsigned char st_other;  //该成员当前包含 0,其含义没有定义。
         Elf32_Half st_shndx;        //每个符号表项都以和其他节区的关系的方式给出定义。此成员给出相关的节区头部表索引。
    } Elf32_sym;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 字符串表(.dynstr)

    符号表的st_name是符号名的字符串表中的索引,那么字符串表中肯定存放着所有符号的名称字符串

    • 重定位表

    重定位表在ELF文件中扮演很重要的角色,首先我们得理解重定位的概念,程序从代码到可执行文件这个过程中,要经历编译器,汇编器和链接器对代码的处理。然而编译器和汇编器通常为每个文件创建程序地址从0开始的目标代码,但是几乎没有计算机会允许从地址0加载你的程序。如果一个程序是由多个子程序组成的,那么所有的子程序必需要加载到互不重叠的地址上。_重定位就是为程序不同部分分配加载地址,调整程序中的数据和代码以反映所分配地址的过程。_简单的言之,则是将程序中的各个部分映射到合理的地址上来。
    换句话来说,重定位是将符号引用与符号定义进行连接的过程。例如,当程序调用了一个函数时,相关的调用指令必须把控制传输到适当的目标执行地址。
    具体来说,就是把符号的value进行重新定位。

    可重定位文件必须包含如何修改其节区内容的信息,从而允许可执行文件和共享目标文件保存进程的程序映象的正确信息。这就是重定位表项做的工作。重定位表项的格式如下:

    typedef struct {  
        Elf32_Addr r_offset;     //重定位动作所适用的位置(受影响的存储单位的第一个字节的偏移或者虚拟地址)
        Elf32_Word r_info;       //要进行重定位的符号表索引,以及将实施的重定位类型(哪些位需要修改,以及如何计算它们的取值)
                                             //其中 .rel.dyn 重定位类型一般为R_386_GLOB_DAT和R_386_COPY;.rel.plt为R_386_JUMP_SLOT
    } Elf32_Rel; 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    typedef struct {  
       Elf32_Addr r_offset;  
       Elf32_Word r_info;  
       Elf32_Word r_addend;    //给出一个常量补齐,用来计算将被填充到可重定位字段的数值。
    } Elf32_Rela;
    
    • 1
    • 2
    • 3
    • 4
    • 5

    对 r_info 成员使用 ELF32_R_TYPE 宏运算可得到重定位类型,使用 ELF32_R_SYM 宏运算可得到符号在符号表里的索引值。 三种宏的具体定义如下:

    #define ELF32_R_SYM(i) ((i)>>8)
    #define ELF32_R_TYPE(i) ((unsigned char)(i))
    #define ELF32_R_INFO(s, t) (((s)<<8) + (unsigned char)(t))
    
    • 1
    • 2
    • 3
    • 常见的重定位表类型:

    .rel.text:重定位的地方在.text段内,以offset指定具体要定位位置。在链接时候由链接器完成。.rel.text属于普通重定位辅助段 ,他由编译器编译产生,存在于obj文件内。连接器连接时,他用于最终可执行文件或者动态库的重定位。通过它修改原obj文件的.text段后,合并到最终可执行文件或者动态文件的.text段。其类型一般为R_386_32和R_386_PC32。

    .rel.dyn:重定位的地方在.got段内。主要是针对外部数据变量符号。例如全局数据。重定位在程序运行时定位,一般是在.init段内。定位过程:获得符号对应value后,根据rel.dyn表中对应的offset,修改.got表对应位置的value。另外,.rel.dyn 含义是指和dyn有关,一般是指在程序运行时候,动态加载。区别于rel.plt,rel.plt是指和plt相关,具体是指在某个函数被调用时候加载。我个人理解这个Section的作用是,在重定位过程中,动态链接器根据r_offset找到.got对应表项,来完成对.got表项值的修改。

    .rel.dyn和.rel.plt是动态定位辅助段。
    由连接器产生,存在于可执行文件或者动态库文件内。
    借助这两个辅助段可以动态修改对应.got和.got.plt段,
    从而实现运行时重定位
    
    • 1
    • 2
    • 3
    • 4

    .rel.plt:重定位的地方在.got.plt段内(注意也是.got内,具体区分而已)。 主要是针对外部函数符号。一般是函数首次被调用时候重定位。首次调用时会重定位函数地址,把最终函数地址放到.got内,以后读取该.got就直接得到最终函数地址。我个人理解这个Section的作用是,在重定位过程中,动态链接器根据r_offset找到.got对应表项,来完成对.got表项值的修改。

    .plt段(过程链接表):所有外部函数调用都是经过一个对应桩函数,这些桩函数都在.plt段内。具体调用外部函数过程是:
    调用对应桩函数—>桩函数取出.got表表内地址—>然后跳转到这个地址.如果是第一次,这个跳转地址默认是桩函数本身跳转处地址的下一个指令地址(目的是通过桩函数统一集中取地址和加载地址),后续接着把对应函数的真实地址加载进来放到.got表对应处,同时跳转执行该地址指令.以后桩函数从.got取得地址都是真实函数地址了。

    .got(全局偏移表)

    4.2.2 Program Header Table

    程序头部(Program Header)描述与程序执行直接相关的目标文件结构信息。用来在文件中定位各个段的映像。同时包含其他一些用来为程序创建映像所必须的信息。
    可执行文件或者共享目标文件的程序头部是一个结构数组,每个结构描述了一个段或者系统准备程序执行所必须的其他信息。目标文件的“段”包含一个或者多个“节区”,也就是“段内容(Segment Contents)”。程序头部仅对可执行文件和共享目标文件有意义。

    程序头部的数据结构如下:

    typedef struct {  
        Elf32_Word p_type;           //此数组元素描述的段的类型,或者如何解释此数组元素的信息。 
        Elf32_Off  p_offset;           //此成员给出从文件头到该段第一个字节的偏移
        Elf32_Addr p_vaddr;         //此成员给出段的第一个字节将被放到内存中的虚拟地址
        Elf32_Addr p_paddr;        //此成员仅用于与物理地址相关的系统中。System V忽略所有应用程序的物理地址信息。
        Elf32_Word p_filesz;         //此成员给出段在文件映像中所占的字节数。可以为0。
        Elf32_Word p_memsz;     //此成员给出段在内存映像中占用的字节数。可以为0。
        Elf32_Word p_flags;         //此成员给出与段相关的标志。
        Elf32_Word p_align;        //此成员给出段在文件中和内存中如何对齐。
    } Elf32_phdr;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • p_type
    名称取值说明
    PT_NULL0此数组元素未用。结构中其他成员都是未定义的
    PT_LOAD1此数组元素给出一个可加载的段,段的大小由 p_filesz 和 p_memsz描述。文件中的字节被映射到内存段开始处。如果 p_memsz 大于p_filesz,“剩余”的字节要清零。p_filesz 不能大于 p_memsz。可加载的段在程序头部表格中根据 p_vaddr 成员按升序排列
    PT_DYNAMIC2数组元素给出动态链接信息
    PT_INTERP3数组元素给出一个 NULL 结尾的字符串的位置和长度,该字符串将被当作解释器调用。这种段类型仅对与可执行文件有意义(尽管也可能在共享目标文件上发生)。在一个文件中不能出现一次以上。如果存在这种类型的段,它必须在所有可加载段项目的前面
    PT_NOTE4此数组元素给出附加信息的位置和大小
    PT_SHLIB5此段类型被保留,不过语义未指定。包含这种类型的段的程序与 ABI不符
    PT_PHDR6此类型的数组元素如果存在,则给出了程序头部表自身的大小和位置,既包括在文件中也包括在内存中的信息。此类型的段在文件中不能出现一次以上。并且只有程序头部表是程序的内存映像的一部分时才起作用。如果存在此类型段,则必须在所有可加载段项目的前面
    PT_LOPROC~PT_HIPROC0x70000000~0x7fffffff此范围的类型保留给处理器专用语义

    上面如果看的太复杂,那就记点简单点:

    • 文件的最开始几个字节给出如何解释文件的提示信息。这些信息独立于处理器,也独立于文件中的其余内容

      • e_phoff:是程序头(Program Header)内容在整个文件的偏移值,可以用这个偏移值来定位程序头的开始位置,用于解析程序头信息
      • e_shoff:是段头(Section Header)内容在这个文件的偏移值,可以用这个偏移值来定位段头的开始位置,用于解析段头信息
      • e_phnum:是程序头的个数
      • e_shnum:是段头的个数
      • e_shstrndx:是String段在整个段列表中的索引值,用于后面定位String段的位置
    • 解析程序头信息

      • 可执行文件或者共享目标文件的程序头部是一个结构数组,每个结构描述了一个段或者系统准备程序执行所必需的其他信息。目标文件的“段”包含一个或者多个“节区”,也就是“段内容”(SegmentContents)。程序头部仅对可执行文件和共享目标文件有意义。可执行目标文件在ELF头部的e_phentsize和e_phnum成员中给出其自身程序头部的大小。

    补充点:https://mp.weixin.qq.com/s?src=11×tamp=1637745305&ver=3456&signature=5gUPAnPavLW8c3xT0FUO0JZqSPyWStpYdj9KLSItDiW0ILpbAPRcbnJAqc6HvvgcDaY8QKfzGTiSjWgSdgAuZQMSdsmre376If-qas9DpeuxhltD6qx7oE0bfNzc-Z&new=1。 信安之路的so文件解析详解

    基础实践了解:https://github.com/s0wr0b1ndef/pwn2exploit/blob/master/PWN%E4%B9%8BELF%E8%A7%A3%E6%9E%90.md

    0x05 编写so解析类

    待补充

    参考链接

    https://www.jianshu.com/p/8cf24df30dba

    https://blog.csdn.net/mergerly/article/details/94585901?spm=1001.2101.3001.6650.8&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EOPENSEARCH%7Edefault-9.essearch_pc_relevant&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EOPENSEARCH%7Edefault-9.essearch_pc_relevant

    http://www.choudan.net/2013/11/16/Linux%E8%BF%9B%E7%A8%8B%E5%9C%B0%E5%9D%80%E7%A9%BA%E9%97%B4%E5%86%8D%E5%AD%A6%E4%B9%A0.html

    http://www.choudan.net/2013/10/25/Linux%E8%BF%9B%E7%A8%8B%E5%9C%B0%E5%9D%80%E7%A9%BA%E9%97%B4%E5%AD%A6%E4%B9%A0%28%E4%BA%8C%29.html

    http://blog.chinaunix.net/uid-52437-id-3029374.html


    我自横刀向天笑,去留肝胆两昆仑


  • 相关阅读:
    逍遥自在学C语言 | 多级指针探秘
    只会Excel想做图表可视化,让数据动起来?可以,快来围观啦(附大量模板下载)
    WOL唤醒配置(以太网、PHY、MAC)
    分布式概念:编码一个简单分布式系统
    信息学一本通 1213:八皇后问题
    Nacos学习服务发现(二)之服务注册
    Mybatis-Plus(插件篇 ==> 分页插件
    设计模式-抽象工厂模式
    Java技术学习|消息队列|初级RabbitMQ
    SSM框架整合详细教程
  • 原文地址:https://blog.csdn.net/Ananas_Orangey/article/details/126219819