未知网络服务分析之调试技巧(续2)
2021-04-09 00:59:00 Author: mp.weixin.qq.com(查看原文) 阅读量:140 收藏

若"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/30x43d7a8
   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.html

16 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",未必是你想设的断点,务必用其他手段检查断点设在哪里。有时你设的断点无命中,并不是灵异事件,要考虑前面介绍的场景。


文章来源: http://mp.weixin.qq.com/s?__biz=MzUzMjQyMDE3Ng==&mid=2247484630&idx=1&sn=d0ef9b7125113462d26e382457fe1c5f&chksm=fab2c7e9cdc54efffd69f5be34e20566eb3daa2dc7181682bba85ffc49fa4fbb34a4ae94ec35#rd
如有侵权请联系:admin#unsafe.sh