若"catch syscall read"因BUG无法命中,就只能对库函数read()或其他封装函数设断,此时有个新坑需要注意。
(gdb) info functions ^read$
All functions matching regular expression "^read$":Non-debugging symbols:
0x000000000043d7a8 read // read@plt in some
0x00007f4bbbec7800 read // read in libpthread
0x00007f4bbb8d1818 read // read@plt in libcrypto
0x00007f4bbafc3e88 read // read@plt in librt
0x00007f4bbadab668 read // read@plt in libresolv
0x00007f4bba8ec760 read // read in libc
0x00007f4bbc0ed550 read // read in ld-linux-x86-64.so
0x00007f4bba2ff6e8 read // read@plt in libkrb5
0x00007f4bb9eb9f70 read // read@plt in libk5crypto
0x00007f4bb988e1f8 read // read@plt in libselinux
有很多地址对应符号read
(gdb) show multiple-symbols
How the debugger handles ambiguities in expressions is "all".
multiple-symbols缺省就是all,但"b *read"并未在所有动态库提供的read()上同时设断,只用了其中一个:
(gdb) b *read
Breakpoint 1 at 0x7f4bbbec7800(gdb) info symbol 0x7f4bbbec7800
read in section .text of /lib64/libpthread.so.0
(gdb) info symbol read
read in section .text of /lib64/libpthread.so.0
(gdb) info address read
Symbol "read" is at 0x7f4bbbec7800 in a file compiled without debugging.
本例"b *read"用了libpthread提供的read(),而非libc提供的read()。
How to detect which shared libraries a binary is actually using - Igor Skochinsky [2020-05-02]
https://reverseengineering.stackexchange.com/questions/24885/how-to-detect-which-shared-libraries-a-binary-is-actually-using
提问者问了一个问题,如果liba.so/libb.so都提供了符号c,如何知道some用的是哪个c?Igor Skochinsky在回答中指出
ELF model doesn't bind symbols to a specific library, so the first module providing a specific symbol is used. You can try to check into which address range the symbol's value falls.
意思是,some使用了c,但并未限定由谁提供c,谁先来就用谁。前面"b *read"正是这种情况,libpthread先于libc提供了read()。
检查目标进程some的PLT[]、GOT[]:
(gdb) info address read@plt
Symbol "read@plt" is at 0x43d7a8 in a file compiled without debugging.(gdb) x/3i 0x43d7a8
0x43d7a8 <read@plt>: jmp QWORD PTR [rip+0x50c16a] # 0x949918 <[email protected]>
0x43d7ae <read@plt+6>: push 0x182
0x43d7b3 <read@plt+11>: jmp 0x43bf78
(gdb) info address read@got.plt
Symbol "[email protected]" is at 0x949918 in a file compiled without debugging.
(gdb) x/1gx 0x949918
0x949918 <read@got.plt>: 0x00007f4bbbec7800
(gdb) info symbol *(void**)0x949918
read in section .text of /lib64/libpthread.so.0
some中调用read(),一般去调read@plt,而[email protected]会被重定位,上例重定位到libpthread提供的read()。
顺便说一下,IDA反汇编.got.plt section时有特殊处理。在Segments(Shift-F7)最后几行有个extern,实际不存在,是IDA歪歪出来的,它只是方便IDA在.got.plt中填写一些可读性较好的符号,再直白点,IDA"假装"完成了GOT[]的重定位处理。
gdb doesn't show symbol from a shared library when another library has the same symbol - [2019-08-04]
https://stackoverflow.com/questions/57342963/gdb-doesnt-show-symbol-from-a-shared-library-when-another-library-has-the-same
提问者想让"info address read"显示所有的read地址,这是不可能的。"info address read"只会显示被填到[email protected]中的那个read地址,也就是"b *read"所用的地址。但前面我演示过,"info functions ^read$"可以显示所有的read地址。
回答者提到
under normal symbol resolution rules, and assuming the symbol is global, all references to Journal will bind to the same symbol, so the fact that the symbol is also present in another library is irrelevant.
意思是,如果some已经使用了liba.so提供的c,libb.so提供的c不会被用到。
windbg可以用"module!func"的形式限定某模块提供的函数,gdb没有类似语法。为了在libc!read()上设断,只能用16进制地址,"b *0x7f4bba8ec760"。但在本节上下文里,这样做没有意义,libc提供的read()永远不会被用到。
关于gdb的符号处理,还可以参看:
10.2 Ambiguous Expressions
https://sourceware.org/gdb/onlinedocs/gdb/Ambiguous-Expressions.html16 Examining the Symbol Table
https://sourceware.org/gdb/current/onlinedocs/gdb/Symbols.html
https://ftp.gnu.org/old-gnu/Manuals/gdb/html_node/gdb_109.html
前面想强调的是,你在"b *read",未必是你想设的断点,务必用其他手段检查断点设在哪里。有时你设的断点无命中,并不是灵异事件,要考虑前面介绍的场景。