今天介绍的这个小工具叫做strings,它实现功能很简单,就是找出文件内容中的可打印字符串。所谓可打印字符串的涵义是,它的组成部分都是可打印字符,并且以null或者newline结尾。
对于普通文本文件来说,strings没有任何意义,因为文本文件中的任何内容实际都是可打印的字符串。strings最常用的场合就是列出动态库或者可执行程序等二进制文件中出现的字符串,结合grep即可实现查找。
strings的使用方法很简单,strings [文件]即可,它会默认输出长度大于4的字符串,每行一个。
此外它还有几个参数。
-n number 仅输出长度大于number的字符串
-t d/o/x 除了字符串之外,还额外输出字符串的位置(十进制/八进制/十六进制)
下面我用C语言写一个很简单的hello world程序:
#include int main() { printf("hello world "); return 0; }
编译过程中,hello world作为一个静态字符串会保存在全局数据区。使用strings查看,即可看到”hello world”这个字符串:
[leconte@localhost test]$ strings test /lib/ld-linux.so.2 __gmon_start__ libc.so.6 _IO_stdin_used puts __libc_start_main GLIBC_2.0 PTRh [^_] world world
除了hello world之外还有许多字符串,这些都是二进制文件test里包含的,它们都是编译,链接期间从glibc等动态库或其他地方引入的。
更为过分的是,我们可以用sed等编辑器对字符串进行修改:
[leconte@localhost test]$ gcc -g -o test a.c [leconte@localhost test]$ ./test hello world [leconte@localhost test]$ sed -i 's/hello world/linuxers.cn/g' test [leconte@localhost test]$ ./test linuxers.cn
可见我将hello world改成了linuxers.cn,执行test后输出已经变成了linuxers.cn,我们成功修改了可执行程序。但是这种修改必须很小心,通常字符串的长度在修改前后必须严格相等,否则很有可能产生段错误,因为毕竟我们修改的是数据而非代码逻辑。假如我像下面这样修改,执行后就会段错误:
[leconte@localhost test]$ sed -i 's/linuxers.cn/linux/g' test [leconte@localhost test]$ ./test 段错误