Androidso文件分析「详细版」

原创 橙留香Park 2022-09-28 02:00

也许每个人出生的时候都以为这世界都是为他一个人而存在的,当他发现自己错的时候,他便开始长大

少走了弯路,也就错过了风景,无论如何,感谢经历


本篇文章遇到排版混乱的地方,可点击文末阅读原文或前往该地址:https://orangey.blog.csdn.net/article/details/126219819

更多关于Android安全的知识,可前往:https://blog.csdn.net/ananasorangey/category11955914.html



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文件格式分析-北京大学操作系统实验室.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

然后配置环境变量

cygwin64安装路径\bin
cygwin64安装路径\sbin
cygwin64安装路径\usr\sbin

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

$cygcheck.exe -c cygwin
Cygwin Package Information
Package Version Status
cygwin 3.3.2-1 OK

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

  • 查看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

  • 查看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

  • 查看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)
... ...(后面内容太多,此处省略)

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 --hex-dump= 以十六进制字节显示indecated section的内容。一个数字通过索引section表标识一个特定的section;任何其他string标识目标文件中具有该名称的所有section
-R --relocated-dump= 以十六进制字节显示indecated section的内容。一个数字通过索引section表标识一个特定的section;任何其他string标识目标文件中具有该名称的所有section,该section的内容将在显示之前重新定位。
-p --string-dump= 将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选项; 任何此类选项将以递归方式处理。

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;

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)的节区头是第几个

:这几个是比较重要的参数(修改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;

  • 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;

  • 字符串表(.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;

typedef struct {
Elf32_Addr r_offset;
Elf32_Word r_info;
Elf32_Word r_addend; //给出一个常量补齐,用来计算将被填充到可重定位字段的数值。
} Elf32_Rela;

对 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))

  • 常见的重定位表类型:

.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段,
从而实现运行时重定位

.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;

  • 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之ELF解析.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~default~OPENSEARCH~default-9.essearch_pc_relevant&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~OPENSEARCH~default-9.essearch_pc_relevant

http://www.choudan.net/2013/11/16/Linux进程地址空间再学习.html

http://www.choudan.net/2013/10/25/Linux进程地址空间学习(二).html

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


你以为你有很多路可以选择,其实你只有一条路可以走



橙留香Park 橙留香来自一位三流剑客之乡,担任威胁猎手,脑子不会转弯,属于安全特学脑。橙留香同学[小菜鸟],定期分享从零入门车联网安全(包括基础知识储备)技术。只为你呈现有价值的信息,专注于车联网安全领域之Android终端反入侵技术研究。
评论
  • 这篇内容主要讨论三个基本问题,硅电容是什么,为什么要使用硅电容,如何正确使用硅电容?1.  硅电容是什么首先我们需要了解电容是什么?物理学上电容的概念指的是给定电位差下自由电荷的储藏量,记为C,单位是F,指的是容纳电荷的能力,C=εS/d=ε0εrS/4πkd(真空)=Q/U。百度百科上电容器的概念指的是两个相互靠近的导体,中间夹一层不导电的绝缘介质。通过观察电容本身的定义公式中可以看到,在各个变量中比较能够改变的就是εr,S和d,也就是介质的介电常数,金属板有效相对面积以及距离。当前
    知白 2025-01-06 12:04 175浏览
  • 根据Global Info Research项目团队最新调研,预计2030年全球封闭式电机产值达到1425百万美元,2024-2030年期间年复合增长率CAGR为3.4%。 封闭式电机是一种电动机,其外壳设计为密闭结构,通常用于要求较高的防护等级的应用场合。封闭式电机可以有效防止外部灰尘、水分和其他污染物进入内部,从而保护电机的内部组件,延长其使用寿命。 环洋市场咨询机构出版的调研分析报告【全球封闭式电机行业总体规模、主要厂商及IPO上市调研报告,2025-2031】研究全球封闭式电机总体规
    GIRtina 2025-01-06 11:10 104浏览
  • By Toradex 秦海1). 简介嵌入式平台设备基于Yocto Linux 在开发后期量产前期,为了安全以及提高启动速度等考虑,希望将 ARM 处理器平台的 Debug Console 输出关闭,本文就基于 NXP i.MX8MP ARM 处理器平台来演示相关流程。 本文所示例的平台来自于 Toradex Verdin i.MX8MP 嵌入式平台。  2. 准备a). Verdin i.MX8MP ARM核心版配合Dahlia载板并
    hai.qin_651820742 2025-01-07 14:52 51浏览
  • 根据环洋市场咨询(Global Info Research)项目团队最新调研,预计2030年全球无人机锂电池产值达到2457百万美元,2024-2030年期间年复合增长率CAGR为9.6%。 无人机锂电池是无人机动力系统中存储并释放能量的部分。无人机使用的动力电池,大多数是锂聚合物电池,相较其他电池,锂聚合物电池具有较高的能量密度,较长寿命,同时也具有良好的放电特性和安全性。 全球无人机锂电池核心厂商有宁德新能源科技、欣旺达、鹏辉能源、深圳格瑞普和EaglePicher等,前五大厂商占有全球
    GIRtina 2025-01-07 11:02 74浏览
  • 村田是目前全球量产硅电容的领先企业,其在2016年收购了法国IPDiA头部硅电容器公司,并于2023年6月宣布投资约100亿日元将硅电容产能提升两倍。以下内容主要来自村田官网信息整理,村田高密度硅电容器采用半导体MOS工艺开发,并使用3D结构来大幅增加电极表面,因此在给定的占位面积内增加了静电容量。村田的硅技术以嵌入非结晶基板的单片结构为基础(单层MIM和多层MIM—MIM是指金属 / 绝缘体/ 金属) 村田硅电容采用先进3D拓扑结构在100um内,使开发的有效静电容量面积相当于80个
    知白 2025-01-07 15:02 76浏览
  • PLC组态方式主要有三种,每种都有其独特的特点和适用场景。下面来简单说说: 1. 硬件组态   定义:硬件组态指的是选择适合的PLC型号、I/O模块、通信模块等硬件组件,并按照实际需求进行连接和配置。    灵活性:这种方式允许用户根据项目需求自由搭配硬件组件,具有较高的灵活性。    成本:可能需要额外的硬件购买成本,适用于对系统性能和扩展性有较高要求的场合。 2. 软件组态   定义:软件组态主要是通过PLC
    丙丁先生 2025-01-06 09:23 85浏览
  • 每日可见的315MHz和433MHz遥控模块,你能分清楚吗?众所周知,一套遥控设备主要由发射部分和接收部分组成,发射器可以将控制者的控制按键经过编码,调制到射频信号上面,然后经天线发射出无线信号。而接收器是将天线接收到的无线信号进行解码,从而得到与控制按键相对应的信号,然后再去控制相应的设备工作。当前,常见的遥控设备主要分为红外遥控与无线电遥控两大类,其主要区别为所采用的载波频率及其应用场景不一致。红外遥控设备所采用的射频信号频率一般为38kHz,通常应用在电视、投影仪等设备中;而无线电遥控设备
    华普微HOPERF 2025-01-06 15:29 132浏览
  • 彼得·德鲁克被誉为“现代管理学之父”,他的管理思想影响了无数企业和管理者。然而,关于他的书籍分类,一种流行的说法令人感到困惑:德鲁克一生写了39本书,其中15本是关于管理的,而其中“专门写工商企业或为企业管理者写的”只有两本——《为成果而管理》和《创新与企业家精神》。这样的表述广为流传,但深入探讨后却发现并不完全准确。让我们一起重新审视这一说法,解析其中的矛盾与根源,进而重新认识德鲁克的管理思想及其著作的真正价值。从《创新与企业家精神》看德鲁克的视角《创新与企业家精神》通常被认为是一本专为企业管
    优思学院 2025-01-06 12:03 124浏览
  • 随着市场需求不断的变化,各行各业对CPU的要求越来越高,特别是近几年流行的 AIOT,为了有更好的用户体验,CPU的算力就要求更高了。今天为大家推荐由米尔基于瑞芯微RK3576处理器推出的MYC-LR3576核心板及开发板。关于RK3576处理器国产CPU,是这些年的骄傲,华为手机全国产化,国人一片呼声,再也不用卡脖子了。RK3576处理器,就是一款由国产是厂商瑞芯微,今年第二季推出的全新通用型的高性能SOC芯片,这款CPU到底有多么的高性能,下面看看它的几个特性:8核心6 TOPS超强算力双千
    米尔电子嵌入式 2025-01-03 17:04 55浏览
  • 在智能家居领域中,Wi-Fi、蓝牙、Zigbee、Thread与Z-Wave等无线通信协议是构建短距物联局域网的关键手段,它们常在实际应用中交叉运用,以满足智能家居生态系统多样化的功能需求。然而,这些协议之间并未遵循统一的互通标准,缺乏直接的互操作性,在进行组网时需要引入额外的网关作为“翻译桥梁”,极大地增加了系统的复杂性。 同时,Apple HomeKit、SamSung SmartThings、Amazon Alexa、Google Home等主流智能家居平台为了提升市占率与消费者
    华普微HOPERF 2025-01-06 17:23 146浏览
  •     为控制片内设备并且查询其工作状态,MCU内部总是有一组特殊功能寄存器(SFR,Special Function Register)。    使用Eclipse环境调试MCU程序时,可以利用 Peripheral Registers Viewer来查看SFR。这个小工具是怎样知道某个型号的MCU有怎样的寄存器定义呢?它使用一种描述性的文本文件——SVD文件。这个文件存储在下面红色字体的路径下。    例:南京沁恒  &n
    电子知识打边炉 2025-01-04 20:04 100浏览
  • 本文介绍Linux系统更换开机logo方法教程,通用RK3566、RK3568、RK3588、RK3576等开发板,触觉智能RK3562开发板演示,搭载4核A53处理器,主频高达2.0GHz;内置独立1Tops算力NPU,可应用于物联网网关、平板电脑、智能家居、教育电子、工业显示与控制等行业。制作图片开机logo图片制作注意事项(1)图片必须为bmp格式;(2)图片大小不能大于4MB;(3)BMP位深最大是32,建议设置为8;(4)图片名称为logo.bmp和logo_kernel.bmp;开机
    Industio_触觉智能 2025-01-06 10:43 87浏览
  • 大模型的赋能是指利用大型机器学习模型(如深度学习模型)来增强或改进各种应用和服务。这种技术在许多领域都显示出了巨大的潜力,包括但不限于以下几个方面: 1. 企业服务:大模型可以用于构建智能客服系统、知识库问答系统等,提升企业的服务质量和运营效率。 2. 教育服务:在教育领域,大模型被应用于个性化学习、智能辅导、作业批改等,帮助教师减轻工作负担,提高教学质量。 3. 工业智能化:大模型有助于解决工业领域的复杂性和不确定性问题,尽管在认知能力方面尚未完全具备专家级的复杂决策能力。 4. 消费
    丙丁先生 2025-01-07 09:25 83浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦