龙空技术网

当strace遇上printf,系统调用中二进制数据的获取和还原

极客小生活 44

前言:

现在看官们对“printf重定义linux”大概比较讲究,小伙伴们都想要了解一些“printf重定义linux”的相关知识。那么小编同时在网上汇集了一些有关“printf重定义linux””的相关资讯,希望咱们能喜欢,你们一起来学习一下吧!


我们知道,使用strace可以来确定程序使用的系统调用,而我们工作中经常希望得到read、write、send、recv这些系统调用具体读写的数据是什么。


对于可打印字符,我们可以直接复制strace的输出,比如

open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3


但是对于像下面这样的二进制数据,我们就不能直接复制了。

read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\20&\2\0\0\0\0\0@\0\0\0\0\0\0\0\200\323 \0\0\0\0\0\0\0\0\0@\0008\0\n\0@\0L\0K\0\6\0\0\0\5\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0000\2\0\0\0\0\0\0000\2\0\0\0\0\0\0\10\0\0\0\0\0\0\0\3\0\0\0\4\0\0\0\340\350\30\0\0\0\0\0\340\350\30\0\0\0\0\0\340\350\30\0\0\0\0\0\34\0\0\0\0\0\0\0\34\0\0\0\0\0\0\0\20\0\0\0\0\0\0\0\1\0\0\0\5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0p.\34\0\0\0\0\0p.\34\0\0\0\0\0\0\0 \0\0\0\0\0\1\0\0\0\6\0\0\0\0007\34\0\0\0\0\0\0007<\0\0\0\0\0\0007<\0\0\0\0\0\240Q\0\0\0\0\0\0\340\232\0\0\0\0\0\0\0\0 \0\0\0\0\0\2\0\0\0\6\0\0\0`k\34\0\0\0\0\0`k<\0\0\0\0\0`k<\0\0\0\0\0\360\1\0\0\0\0\0\0\360\1\0\0\0\0\0\0\10\0\0\0\0\0\0\0\4\0\0\0\4\0\0\0p\2\0\0\0\0\0\0p\2\0\0\0\0\0\0p\2\0\0\0\0\0\0D\0\0\0\0\0\0\0D\0\0\0\0\0\0\0\4\0\0\0\0\0\0\0\7\0\0\0\4\0\0\0\0007\34\0\0\0\0\0\0007<\0\0\0\0\0\0007<\0\0\0\0\0\20\0\0\0\0\0\0\0\240\0\0\0\0\0\0\0\20\0\0\0\0\0\0\0P\345td\4\0\0\0\374\350\30\0\0\0\0\0\374\350\30\0\0\0\0\0\374\350\30\0\0\0\0\0\314j\0\0\0\0\0\0\314j\0\0\0\0\0\0\4\0\0\0\0\0\0\0Q\345td\6\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\20\0\0\0\0\0\0\0R\345td\4\0\0\0\0007\34\0\0\0\0\0\0007<\0\0\0\0\0\0007<\0\0\0\0\0\0009\0\0\0\0\0\0\0009\0\0\0\0\0\0\1\0\0\0\0\0\0\0\4\0\0\0\24\0\0\0\3\0\0\0GNU\0009\211D\323,\361jg\257Q\6z2nl\f\301O\220\355\4\0\0\0\20\0\0\0\1\0\0\0GNU\0\0\0\0\0\2\0\0\0\6\0\0\0 \0\0\0\0\0\0\0\363\3\0\0\7\0\0\0\0\1\0\0\16\0\0\0\0000\20D\240 \2\1\210\3\346\220\305E\214\0\300\0\10\0\5\200\0`\300\200\0\r\212\f\0\4\20\0\210D2\10.@\210T<, \0162H&\204\300\214\4\10\0\2\2\16\241\254\32\4f\300\0\3002\0\300\0P\1 \201\10\204\v  ($\0\4 Z\0\20X\200\312DB(\0\6\200\20\30B\0 @\200\0\tP\0Q\212@\20\0\0\0\0\10\0\0\21\20", 832) = 832


为了还原上面这样的数据,我尝试过不同的方法,比如写一个程序对strace的输出做转换,这样的缺点引入了依赖,不够优雅。


最后我发现了一个简单有效的方法,我们注意到两件事。

1. printf特性。\xHH byte with hexadecimal value HH2. strace的一个参数。-xx   Print all strings in hexadecimal string format


我们来具体解释一下。

这里我们提到的printf指的是linux的命令,不是C语言的函数。具体用法可以通过man 1 printf查看。使用strace -xx时,我们将得到类似这样的输出

read(3, "\x7f\x45\x4c\x46\x02", 5) = 5。


可以看到,strace -xx输出的内容刚好适用于printf。于是,我们只需要在终端中使用

printf "\x7f\x45\x4c\x46\x02" > out.bin

这个命令, 就可以获取和还原read的二进制数据了。接下来我们还可以使用hexdump和xxd等工具去查看和编辑,这就是后话了。

标签: #printf重定义linux