Выяснить, вызывается ли функция в общей библиотеке
Я использовал утилиту elfhook Энтони Шоухихина для перенаправления некоторых вызовов функций в общей библиотеке.
В качестве подтверждения концепции я создал разделяемую библиотеку, которая вызывает различные функции из api сокета posix.
void TestAPI::work()
{
int fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
char buf[1024];
recv(fd, buf, sizeof(buf), 0);
listen(fd, 1);
}
Затем я подключил эти функции:
elf_hook(filename, base_address, "socket", hook_socket);
elf_hook(filename, base_address, "listen", hook_listen);
elf_hook(filename, base_address, "recv", hook_recv);
где перехваченная функция вызывает исходную функцию API, но также регистрирует происходящее, например:
int hook_socket(int domain, int type, int protocol)
{
int fd = socket(domain, type, protocol);
printf("fd=%d domain=%d type=%d protocol=%d\n", fd, domain, type, protocol);
return fd;
}
Это все работает нормально, пока я не попытаюсь подключить функцию, которая не вызывается в моем TestAPI
общая библиотека
elf_hook(filename, base_address, "bind", hook_bind);
elf_hook(filename, base_address, "connect", hook_connect);
Как только я это делаю, я получаю ошибку сегментации:
#0 elf_machine_fixup_plt (map=<optimized out>, t=<optimized out>, reloc=<optimized out>, value=139753823227104, reloc_addr=0x7f1afa15e188) at ../sysdeps/x86_64/dl-machine.h:235
#1 _dl_fixup (l=<optimized out>, reloc_arg=<optimized out>) at ../elf/dl-runtime.c:148
#2 0x00007f1afa176753 in _dl_runtime_resolve_avx () at ../sysdeps/x86_64/dl-trampoline.h:112
#3 0x0000000000561b20 in ?? ()
#4 0x00007f1afa16f8e0 in ?? () at dl-fini.c:105 from /lib64/ld-linux-x86-64.so.2
#5 0x00007f1afa16f5fb in call_init (env=0x7ffff0e3aae0, argv=0x4a7390 <_start>, argc=-253515440, l=<optimized out>) at dl-init.c:30
#6 _dl_init (main_map=0x0, argc=-253515440, argv=0x4a7390 <_start>, env=0x7ffff0e3aae0) at dl-init.c:120
#7 0x000000000000001c in ?? ()
#8 0x0000000000000001 in ?? ()
#9 0x00007ffff0e3c21f in ?? ()
#10 0x0000000000000000 in ?? ()
Я проверил это, перехватив функцию, запустив мое приложение, увидев его segfault, вызвав эту функцию в моей общей библиотеке, снова запустив и убедившись, что работа работает правильно.
Мои знания libdl
а также elf
не в силах узнать, что здесь происходит или как это предотвратить / поймать тот факт, что я пытался перехватить функцию, которая не вызывается.
Как я могу предотвратить это?
Редактировать:
По запросу, здесь вывод readelf
:
$ readelf -s -S --dyn-syms -r ./libtest_api.so
There are 36 section headers, starting at offset 0x14a208:
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .note.gnu.build-i NOTE 00000000000001c8 000001c8
0000000000000024 0000000000000000 A 0 0 4
[ 2] .gnu.hash GNU_HASH 00000000000001f0 000001f0
0000000000000044 0000000000000000 A 3 0 8
[ 3] .dynsym DYNSYM 0000000000000238 00000238
0000000000000240 0000000000000018 A 4 2 8
[ 4] .dynstr STRTAB 0000000000000478 00000478
00000000000001b4 0000000000000000 A 0 0 1
[ 5] .gnu.version VERSYM 000000000000062c 0000062c
0000000000000030 0000000000000002 A 3 0 2
[ 6] .gnu.version_r VERNEED 0000000000000660 00000660
0000000000000070 0000000000000000 A 4 3 8
[ 7] .rela.dyn RELA 00000000000006d0 000006d0
00000000000000f0 0000000000000018 A 3 0 8
[ 8] .rela.plt RELA 00000000000007c0 000007c0
00000000000000d8 0000000000000018 AI 3 22 8
[ 9] .init PROGBITS 0000000000000898 00000898
000000000000001a 0000000000000000 AX 0 0 4
[10] .plt PROGBITS 00000000000008c0 000008c0
00000000000000a0 0000000000000010 AX 0 0 16
[11] .plt.got PROGBITS 0000000000000960 00000960
0000000000000010 0000000000000000 AX 0 0 8
[12] .text PROGBITS 0000000000000970 00000970
0000000000000253 0000000000000000 AX 0 0 16
[13] .fini PROGBITS 0000000000000bc4 00000bc4
0000000000000009 0000000000000000 AX 0 0 4
[14] .rodata PROGBITS 0000000000000bd0 00000bd0
0000000000000105 0000000000000000 A 0 0 8
[15] .eh_frame_hdr PROGBITS 0000000000000cd8 00000cd8
0000000000000034 0000000000000000 A 0 0 4
[16] .eh_frame PROGBITS 0000000000000d10 00000d10
00000000000000cc 0000000000000000 A 0 0 8
[17] .init_array INIT_ARRAY 0000000000201dc0 00001dc0
0000000000000010 0000000000000000 WA 0 0 8
[18] .fini_array FINI_ARRAY 0000000000201dd0 00001dd0
0000000000000008 0000000000000000 WA 0 0 8
[19] .jcr PROGBITS 0000000000201dd8 00001dd8
0000000000000008 0000000000000000 WA 0 0 8
[20] .dynamic DYNAMIC 0000000000201de0 00001de0
00000000000001f0 0000000000000010 WA 4 0 8
[21] .got PROGBITS 0000000000201fd0 00001fd0
0000000000000030 0000000000000008 WA 0 0 8
[22] .got.plt PROGBITS 0000000000202000 00002000
0000000000000060 0000000000000008 WA 0 0 8
[23] .data PROGBITS 0000000000202060 00002060
0000000000000008 0000000000000000 WA 0 0 8
[24] .bss NOBITS 0000000000202068 00002068
0000000000000008 0000000000000000 WA 0 0 1
[25] .comment PROGBITS 0000000000000000 00002068
0000000000000034 0000000000000001 MS 0 0 1
[26] .debug_aranges PROGBITS 0000000000000000 0000209c
0000000000000040 0000000000000000 0 0 1
[27] .debug_info PROGBITS 0000000000000000 000020dc
0000000000007a3b 0000000000000000 0 0 1
[28] .debug_abbrev PROGBITS 0000000000000000 00009b17
00000000000009e1 0000000000000000 0 0 1
[29] .debug_line PROGBITS 0000000000000000 0000a4f8
00000000000052dd 0000000000000000 0 0 1
[30] .debug_str PROGBITS 0000000000000000 0000f7d5
000000000011cb84 0000000000000001 MS 0 0 1
[31] .debug_ranges PROGBITS 0000000000000000 0012c359
0000000000000030 0000000000000000 0 0 1
[32] .debug_macro PROGBITS 0000000000000000 0012c389
000000000001c8a8 0000000000000000 0 0 1
[33] .shstrtab STRTAB 0000000000000000 0014a0b4
0000000000000151 0000000000000000 0 0 1
[34] .symtab SYMTAB 0000000000000000 00148c38
0000000000000ba0 0000000000000018 35 102 8
[35] .strtab STRTAB 0000000000000000 001497d8
00000000000008dc 0000000000000000 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), l (large)
I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
Relocation section '.rela.dyn' at offset 0x6d0 contains 10 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000201dc0 000000000008 R_X86_64_RELATIVE a40
000000201dc8 000000000008 R_X86_64_RELATIVE ba2
000000201dd0 000000000008 R_X86_64_RELATIVE a00
000000202060 000000000008 R_X86_64_RELATIVE 202060
000000201fd0 000200000006 R_X86_64_GLOB_DAT 0000000000000000 __gmon_start__ + 0
000000201fd8 000300000006 R_X86_64_GLOB_DAT 0000000000000000 _Jv_RegisterClasses + 0
000000201fe0 000800000006 R_X86_64_GLOB_DAT 0000000000000000 _ZNSt8ios_base4InitD1E@GLIBCXX_3.4 + 0
000000201fe8 000900000006 R_X86_64_GLOB_DAT 0000000000000000 _ITM_deregisterTMClone + 0
000000201ff0 000a00000006 R_X86_64_GLOB_DAT 0000000000000000 _ITM_registerTMCloneTa + 0
000000201ff8 000c00000006 R_X86_64_GLOB_DAT 0000000000000000 __cxa_finalize@GLIBC_2.2.5 + 0
Relocation section '.rela.plt' at offset 0x7c0 contains 9 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000202018 000400000007 R_X86_64_JUMP_SLO 0000000000000000 puts@GLIBC_2.2.5 + 0
000000202020 000500000007 R_X86_64_JUMP_SLO 0000000000000000 _ZNSt8ios_base4InitC1E@GLIBCXX_3.4 + 0
000000202028 001600000007 R_X86_64_JUMP_SLO 0000000000000bb8 _ZN5boost6none_tC1ENS0 + 0
000000202030 000600000007 R_X86_64_JUMP_SLO 0000000000000000 recv@GLIBC_2.2.5 + 0
000000202038 000700000007 R_X86_64_JUMP_SLO 0000000000000000 __cxa_atexit@GLIBC_2.2.5 + 0
000000202040 000b00000007 R_X86_64_JUMP_SLO 0000000000000000 listen@GLIBC_2.2.5 + 0
000000202048 000d00000007 R_X86_64_JUMP_SLO 0000000000000000 socket@GLIBC_2.2.5 + 0
000000202050 000e00000007 R_X86_64_JUMP_SLO 0000000000000000 __stack_chk_fail@GLIBC_2.4 + 0
000000202058 000f00000007 R_X86_64_JUMP_SLO 0000000000000000 send@GLIBC_2.2.5 + 0
Symbol table '.dynsym' contains 24 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000898 0 SECTION LOCAL DEFAULT 9
2: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
3: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses
4: 0000000000000000 0 FUNC GLOBAL DEFAULT UND puts@GLIBC_2.2.5 (2)
5: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZNSt8ios_base4InitC1Ev@GLIBCXX_3.4 (3)
6: 0000000000000000 0 FUNC GLOBAL DEFAULT UND recv@GLIBC_2.2.5 (4)
7: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __cxa_atexit@GLIBC_2.2.5 (2)
8: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZNSt8ios_base4InitD1Ev@GLIBCXX_3.4 (3)
9: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTab
10: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable
11: 0000000000000000 0 FUNC GLOBAL DEFAULT UND listen@GLIBC_2.2.5 (2)
12: 0000000000000000 0 FUNC WEAK DEFAULT UND __cxa_finalize@GLIBC_2.2.5 (2)
13: 0000000000000000 0 FUNC GLOBAL DEFAULT UND socket@GLIBC_2.2.5 (2)
14: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __stack_chk_fail@GLIBC_2.4 (5)
15: 0000000000000000 0 FUNC GLOBAL DEFAULT UND send@GLIBC_2.2.5 (4)
16: 0000000000202070 0 NOTYPE GLOBAL DEFAULT 24 _end
17: 0000000000202068 0 NOTYPE GLOBAL DEFAULT 23 _edata
18: 0000000000000a70 172 FUNC GLOBAL DEFAULT 12 _ZN10ElfHookAPI4workEv
19: 0000000000202068 0 NOTYPE GLOBAL DEFAULT 24 __bss_start
20: 0000000000000898 0 FUNC GLOBAL DEFAULT 9 _init
21: 0000000000000bc4 0 FUNC GLOBAL DEFAULT 13 _fini
22: 0000000000000bb8 11 FUNC WEAK DEFAULT 12 _ZN5boost6none_tC1ENS0_8i
23: 0000000000000bb8 11 FUNC WEAK DEFAULT 12 _ZN5boost6none_tC2ENS0_8i
Symbol table '.symtab' contains 124 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000000001c8 0 SECTION LOCAL DEFAULT 1
2: 00000000000001f0 0 SECTION LOCAL DEFAULT 2
3: 0000000000000238 0 SECTION LOCAL DEFAULT 3
4: 0000000000000478 0 SECTION LOCAL DEFAULT 4
5: 000000000000062c 0 SECTION LOCAL DEFAULT 5
6: 0000000000000660 0 SECTION LOCAL DEFAULT 6
7: 00000000000006d0 0 SECTION LOCAL DEFAULT 7
8: 00000000000007c0 0 SECTION LOCAL DEFAULT 8
9: 0000000000000898 0 SECTION LOCAL DEFAULT 9
10: 00000000000008c0 0 SECTION LOCAL DEFAULT 10
11: 0000000000000960 0 SECTION LOCAL DEFAULT 11
12: 0000000000000970 0 SECTION LOCAL DEFAULT 12
13: 0000000000000bc4 0 SECTION LOCAL DEFAULT 13
14: 0000000000000bd0 0 SECTION LOCAL DEFAULT 14
15: 0000000000000cd8 0 SECTION LOCAL DEFAULT 15
16: 0000000000000d10 0 SECTION LOCAL DEFAULT 16
17: 0000000000201dc0 0 SECTION LOCAL DEFAULT 17
18: 0000000000201dd0 0 SECTION LOCAL DEFAULT 18
19: 0000000000201dd8 0 SECTION LOCAL DEFAULT 19
20: 0000000000201de0 0 SECTION LOCAL DEFAULT 20
21: 0000000000201fd0 0 SECTION LOCAL DEFAULT 21
22: 0000000000202000 0 SECTION LOCAL DEFAULT 22
23: 0000000000202060 0 SECTION LOCAL DEFAULT 23
24: 0000000000202068 0 SECTION LOCAL DEFAULT 24
25: 0000000000000000 0 SECTION LOCAL DEFAULT 25
26: 0000000000000000 0 SECTION LOCAL DEFAULT 26
27: 0000000000000000 0 SECTION LOCAL DEFAULT 27
28: 0000000000000000 0 SECTION LOCAL DEFAULT 28
29: 0000000000000000 0 SECTION LOCAL DEFAULT 29
30: 0000000000000000 0 SECTION LOCAL DEFAULT 30
31: 0000000000000000 0 SECTION LOCAL DEFAULT 31
32: 0000000000000000 0 SECTION LOCAL DEFAULT 32
33: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
34: 0000000000201dd8 0 OBJECT LOCAL DEFAULT 19 __JCR_LIST__
35: 0000000000000970 0 FUNC LOCAL DEFAULT 12 deregister_tm_clones
36: 00000000000009b0 0 FUNC LOCAL DEFAULT 12 register_tm_clones
37: 0000000000000a00 0 FUNC LOCAL DEFAULT 12 __do_global_dtors_aux
38: 0000000000202068 1 OBJECT LOCAL DEFAULT 24 completed.7585
39: 0000000000201dd0 0 OBJECT LOCAL DEFAULT 18 __do_global_dtors_aux_fin
40: 0000000000000a40 0 FUNC LOCAL DEFAULT 12 frame_dummy
41: 0000000000201dc0 0 OBJECT LOCAL DEFAULT 17 __frame_dummy_init_array_
42: 0000000000000000 0 FILE LOCAL DEFAULT ABS lib_elfhook.cpp
43: 0000000000000bd0 1 OBJECT LOCAL DEFAULT 14 _ZStL19piecewise_construc
44: 0000000000202069 1 OBJECT LOCAL DEFAULT 24 _ZStL8__ioinit
45: 0000000000000bd1 1 OBJECT LOCAL DEFAULT 14 _ZStL13allocator_arg
46: 0000000000000bd2 1 OBJECT LOCAL DEFAULT 14 _ZStL6ignore
47: 0000000000000bd3 1 OBJECT LOCAL DEFAULT 14 _ZStL10defer_lock
48: 0000000000000bd4 1 OBJECT LOCAL DEFAULT 14 _ZStL11try_to_lock
49: 0000000000000bd5 1 OBJECT LOCAL DEFAULT 14 _ZStL10adopt_lock
50: 0000000000000bd8 4 OBJECT LOCAL DEFAULT 14 _ZN9__gnu_cxxL21__default
51: 0000000000000bdc 4 OBJECT LOCAL DEFAULT 14 _ZN6google8protobuf8inter
52: 0000000000000be0 4 OBJECT LOCAL DEFAULT 14 _ZN6google8protobuf8inter
53: 0000000000000be4 4 OBJECT LOCAL DEFAULT 14 _ZN6google8protobufL9kint
54: 0000000000000be8 4 OBJECT LOCAL DEFAULT 14 _ZN6google8protobufL9kint
55: 0000000000000bf0 8 OBJECT LOCAL DEFAULT 14 _ZN6google8protobufL9kint
56: 0000000000000bf8 8 OBJECT LOCAL DEFAULT 14 _ZN6google8protobufL9kint
57: 0000000000000c00 4 OBJECT LOCAL DEFAULT 14 _ZN6google8protobufL10kui
58: 0000000000000c08 8 OBJECT LOCAL DEFAULT 14 _ZN6google8protobufL10kui
59: 0000000000000c10 4 OBJECT LOCAL DEFAULT 14 _ZN6google8protobuf8inter
60: 0000000000000c14 4 OBJECT LOCAL DEFAULT 14 _ZN3cay3logL9Level_MINE
61: 0000000000000c18 4 OBJECT LOCAL DEFAULT 14 _ZN3cay3logL9Level_MAXE
62: 0000000000000c1c 4 OBJECT LOCAL DEFAULT 14 _ZN3cay3logL15Level_ARRAY
63: 0000000000000c20 4 OBJECT LOCAL DEFAULT 14 _ZN3cay3logL13DEFAULT_LEV
64: 000000000020206a 1 OBJECT LOCAL DEFAULT 24 _ZN5boostL4noneE
65: 0000000000000c24 4 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL13days_per
66: 0000000000000c28 4 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL18days_per
67: 0000000000000c2c 4 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL16days_per
68: 0000000000000c30 4 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL18days_per
69: 0000000000000c34 4 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL18days_per
70: 0000000000000c38 8 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL12min_per_
71: 0000000000000c40 8 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL12sec_per_
72: 0000000000000c48 8 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL11ms_per_h
73: 0000000000000c50 8 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL11us_per_h
74: 0000000000000c58 8 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL11ns_per_h
75: 0000000000000c60 8 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL11sec_per_
76: 0000000000000c68 8 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL10ms_per_m
77: 0000000000000c70 8 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL10us_per_m
78: 0000000000000c78 8 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL10ns_per_m
79: 0000000000000c80 4 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL10ms_per_s
80: 0000000000000c84 4 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL10us_per_s
81: 0000000000000c88 4 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL10ns_per_s
82: 0000000000000c90 8 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL10sec_per_
83: 0000000000000c98 4 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL9us_per_ms
84: 0000000000000c9c 4 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL9ns_per_ms
85: 0000000000000ca0 8 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL10sec_per_
86: 0000000000000ca8 8 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL9ms_per_us
87: 0000000000000cb0 4 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL9ns_per_us
88: 0000000000000cb8 8 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL10sec_per_
89: 0000000000000cc0 8 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL9ms_per_ns
90: 0000000000000cc8 8 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL9us_per_ns
91: 0000000000000b1c 134 FUNC LOCAL DEFAULT 12 _Z41__static_initializati
92: 0000000000000ba2 21 FUNC LOCAL DEFAULT 12 _GLOBAL__sub_I_lib_elfhoo
93: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
94: 0000000000000dd8 0 OBJECT LOCAL DEFAULT 16 __FRAME_END__
95: 0000000000201dd8 0 OBJECT LOCAL DEFAULT 19 __JCR_END__
96: 0000000000000000 0 FILE LOCAL DEFAULT ABS
97: 0000000000000cd8 0 NOTYPE LOCAL DEFAULT 15 __GNU_EH_FRAME_HDR
98: 0000000000202000 0 OBJECT LOCAL DEFAULT 22 _GLOBAL_OFFSET_TABLE_
99: 0000000000202068 0 OBJECT LOCAL DEFAULT 23 __TMC_END__
100: 0000000000202060 0 OBJECT LOCAL DEFAULT 23 __dso_handle
101: 0000000000201de0 0 OBJECT LOCAL DEFAULT 20 _DYNAMIC
102: 0000000000000a70 172 FUNC GLOBAL DEFAULT 12 _ZN10ElfHookAPI4workEv
103: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
104: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses
105: 0000000000000000 0 FUNC GLOBAL DEFAULT UND puts@@GLIBC_2.2.5
106: 0000000000000bc4 0 FUNC GLOBAL DEFAULT 13 _fini
107: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZNSt8ios_base4InitC1Ev@@
108: 0000000000000bb8 11 FUNC WEAK DEFAULT 12 _ZN5boost6none_tC1ENS0_8i
109: 0000000000000000 0 FUNC GLOBAL DEFAULT UND recv@@GLIBC_2.2.5
110: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __cxa_atexit@@GLIBC_2.2.5
111: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZNSt8ios_base4InitD1Ev@@
112: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTab
113: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable
114: 0000000000000000 0 FUNC GLOBAL DEFAULT UND listen@@GLIBC_2.2.5
115: 0000000000000000 0 FUNC WEAK DEFAULT UND __cxa_finalize@@GLIBC_2.2
116: 0000000000000bb8 11 FUNC WEAK DEFAULT 12 _ZN5boost6none_tC2ENS0_8i
117: 0000000000000000 0 FUNC GLOBAL DEFAULT UND socket@@GLIBC_2.2.5
118: 0000000000202068 0 NOTYPE GLOBAL DEFAULT 24 __bss_start
119: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __stack_chk_fail@@GLIBC_2
120: 0000000000000000 0 FUNC GLOBAL DEFAULT UND send@@GLIBC_2.2.5
121: 0000000000202070 0 NOTYPE GLOBAL DEFAULT 24 _end
122: 0000000000202068 0 NOTYPE GLOBAL DEFAULT 23 _edata
123: 0000000000000898 0 FUNC GLOBAL DEFAULT 9 _init
1 ответ
Так что в основном его код делает, когда вы создаете общую библиотеку libtest.so
что вызывает libc.so
внутри него создаются следующие элементы в вашей библиотеке
- динамическая таблица символов (которая включает в себя данные всех функций, из которых вы вызываете
libc.so
) - таблица перемещений (список записей в вашем коде, которые вызывали функции внутри
libc.so
каждая запись в таблице перемещений говорит, что функция X, которая принадлежитlibc.so
был вызван вlibtest.so
в строках а, б, в...
Его код анализирует вашу общую библиотеку, тянет dynsymtable
и таблицу перемещений из нее и меняет символы к вашему запросу, вызывая elf_hook()
(увидеть elf_hook.c
строки 434 - 442).
Вы вызвали три функции из libc.so
API, который является ОГРОМНЫМ API, следовательно, dynsym
в вашей таблице должны содержать символы для socket()
listen()
а также recv()
Мы можем увидеть dyn-symbols
13 11 и 6 соответственно socket@GLIBC
, listen@GLIBC
а также recv@GLIBC
,
То, что делает таблица перемещения, в основном говорит, где в вашем АКТУАЛЬНОМ коде эти функции вызываются, и когда эти символы будут иметь разрешенный адрес, какие адреса необходимо будет заменить, чтобы ваш код вызывал реальные функции, как мы также можно увидеть на .rela.plt
Вы отправили в качестве вывода из readelf
По команде мы видим, что на 3 разных записях вы назвали эти символы. Это то, что нам нужно заменить.
Так что его код делает поиск индекса символа, который вы хотите заменить, проходит ВСЕ перемещения и проверяет, относятся ли они к индексу-символу. Если это так, это означает, что в месте, где эта запись о перемещении является релевантной, ее необходимо заменить на код, который вы хотите.
Вернемся к нашему предыдущему примеру. Допустим, вы хотите заменить socket()
с y()
в вашем libtest.so
, Его код находит индекс символа socket()
, находит, где в коде вы звонили socket()
и заменяет это адресом y()
вместо.
Попытка поймать символы, которые не существуют
Что может пойти не так, так это тот факт, что при попытке перехватить символы, которые не были вызваны, просто отсутствует запись о перемещении для этого символа И этот символ не существует, вы можете видеть, что, например, в записи нет dynsym
Таблица (readelf
выход) из bind()
,
Что ДОЛЖНО случиться, так это то, что он не найдет соответствующий символ и ничего не зацепит.
Честно говоря, я не прошел весь его код, но думаю, что там что-то пошло не так, и он не справился со случаем попытки перехватить символ, который не существует правильно...
Замечания:
Еще одна вещь, которую я заметил, которая кажется ужасно неправильной, - это rel.dyn
,
Он решил загрузить библиотеки в своем примере RTLD_LAZY
Это означает, что при каждом вызове функции DLL происходит переход к некоторой таблице смещений, которая указывает на ваш динамический компоновщик, и когда вызывается динамический компоновщик, он заменяет смещение, из которого он был вызван, фактическим смещением функция... это перемещение во время выполнения...
Насколько я знаю rel.dyn
обычно предназначен для перемещения во время загрузки, когда операционная система загружает исполняемый файл, она копирует свой код и просматривает все записи перемещения и заменяет их в коде....
Во время выполнения смещения rel.dyn
элементы таблицы, на которые указывают записи, будут находиться в пределах исполняемого раздела исполняемого образа, что означает, что они ДОЛЖНЫ иметь только разрешения ЧТЕНИЕ / ВЫПОЛНЕНИЕ, а не ЗАПИСАТЬ, поэтому попытка записи в них ДОЛЖНА вызвать некоторый segfault....
Подводя итог, это, вероятно, происходит потому, что его утилита не справилась с попыткой перехватить функцию API, которая не существует в таблице символов (не вызывается в вашем коде) правильно... надеюсь, я помог вам понять немного больше что случилось...
Кроме того, попробуйте прочитать это, это помогло мне узнать много нового о предмете ELF в прошлом:)