如何使用 Linux 审计来记录程序(比如 chrome)发出的所有系统调用?

如何使用 Linux 审计来记录程序(比如 chrome)发出的所有系统调用?

奥特拉斯可以通过运行程序来记录程序进行的系统调用。我想记录已经运行的程序的系统调用。可以通过查找进程id来完成,但是还有其他优雅的方法吗?哪个可能是使用chrome可执行文件作为参数来记录它生成的系统调用?

答案1

正如@Patrick 在评论中所述,您可以使用命令行工具strace来生成程序运行时所进行的系统调用的转储。

例子

这是显示正在运行的命令的示例echo hi

$ strace echo "hi"
execve("/usr/bin/echo", ["echo", "hi"], [/* 94 vars */]) = 0
brk(0)                                  = 0xf73000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f9996cf2000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=206010, ...}) = 0
mmap(NULL, 206010, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f9996cbf000
close(3)                                = 0
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\0P\34\242\213?\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=2108632, ...}) = 0
mmap(0x3f8ba00000, 3932768, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x3f8ba00000
mprotect(0x3f8bbb6000, 2097152, PROT_NONE) = 0
mmap(0x3f8bdb6000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1b6000) = 0x3f8bdb6000
mmap(0x3f8bdbc000, 16992, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x3f8bdbc000
close(3)                                = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f9996cbe000
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f9996cbc000
arch_prctl(ARCH_SET_FS, 0x7f9996cbc740) = 0
mprotect(0x606000, 4096, PROT_READ)     = 0
mprotect(0x3f8bdb6000, 16384, PROT_READ) = 0
mprotect(0x3f8b820000, 4096, PROT_READ) = 0
munmap(0x7f9996cbf000, 206010)          = 0
brk(0)                                  = 0xf73000
brk(0xf94000)                           = 0xf94000
brk(0)                                  = 0xf94000
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=106055264, ...}) = 0
mmap(NULL, 106055264, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f9990797000
close(3)                                = 0
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 2), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f9996cf1000
write(1, "hi\n", 3hi
)                     = 3
close(1)                                = 0
munmap(0x7f9996cf1000, 4096)            = 0
close(2)                                = 0
exit_group(0)                           = ?
+++ exited with 0 +++

您还可以通过包含选项来增加获取输出的详细信息-s <size>。我通常会使用-s 2000每次调用获取 2000 个字符的输出。此外,我还将包含一个开关-o <file>,用于将输出转储到文件中。事后查看此输出要容易得多。

例子

$ strace -s 2000 -o strace.log echo "hi" 
hi

这是文件:

$ cat strace.log 
execve("/usr/bin/echo", ["echo", "hi"], [/* 94 vars */]) = 0
brk(0)                                  = 0x1061000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f78bdab3000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=206010, ...}) = 0
mmap(NULL, 206010, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f78bda80000
close(3)                                = 0
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\0P\34\242\213?\0\0\0@\0\0\0\0\0\0\0\30\" \0\0\0\0\0\0\0\0\0@\0008\0\n\0@\0+\0*\0\6\0\0\0\5\0\0\0@\0\0\0\0\0\0\0@\0\240\213?\0\0\0@\0\240\213?\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\360\26\30\0\0\0\0\0\360\26\270\213?\0\0\0\360\26\270\213?\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\240\213?\0\0\0\0\0\240\213?\0\0\0\344W\33\0\0\0\0\0\344W\33\0\0\0\0\0\0\0 \0\0\0\0\0\1\0\0\0\6\0\0\0 g\33\0\0\0\0\0 g\333\213?\0\0\0 g\333\213?\0\0\0\240Q\0\0\0\0\0\0@\233\0\0\0\0\0\0\0\0 \0\0\0\0\0\2\0\0\0\6\0\0\0\200\233\33\0\0\0\0\0\200\233\333\213?\0\0\0\200\233\333\213?\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\240\213?\0\0\0p\2\240\213?\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 g\33\0\0\0\0\0 g\333\213?\0\0\0 g\333\213?\0\0\0\20\0\0\0\0\0\0\0\220\0\0\0\0\0\0\0\20\0\0\0\0\0\0\0P\345td\4\0\0\0\f\27\30\0\0\0\0\0\f\27\270\213?\0\0\0\f\27\270\213?\0\0\0\\h\0\0\0\0\0\0\\h\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 g\33\0\0\0\0\0 g\333\213?\0\0\0 g\333\213?\0\0\0\3408\0\0\0\0\0\0\3408\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\0\206\353)\243\237\22p\240\253\216F\316.Tkn\303R\312\10\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\t\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.@\210P<, \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 P\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
fstat(3, {st_mode=S_IFREG|0755, st_size=2108632, ...}) = 0
mmap(0x3f8ba00000, 3932768, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x3f8ba00000
mprotect(0x3f8bbb6000, 2097152, PROT_NONE) = 0
mmap(0x3f8bdb6000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1b6000) = 0x3f8bdb6000
mmap(0x3f8bdbc000, 16992, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x3f8bdbc000
close(3)                                = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f78bda7f000
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f78bda7d000
arch_prctl(ARCH_SET_FS, 0x7f78bda7d740) = 0
mprotect(0x606000, 4096, PROT_READ)     = 0
mprotect(0x3f8bdb6000, 16384, PROT_READ) = 0
mprotect(0x3f8b820000, 4096, PROT_READ) = 0
munmap(0x7f78bda80000, 206010)          = 0
brk(0)                                  = 0x1061000
brk(0x1082000)                          = 0x1082000
brk(0)                                  = 0x1082000
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=106055264, ...}) = 0
mmap(NULL, 106055264, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f78b7558000
close(3)                                = 0
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 2), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f78bdab2000
write(1, "hi\n", 3)                     = 3
close(1)                                = 0
munmap(0x7f78bdab2000, 4096)            = 0
close(2)                                = 0
exit_group(0)                           = ?
+++ exited with 0 +++

您可以包含通常可以在 shell 中运行的任何程序或命令作为 的参数strace。在深入了解可执行文件如何在系统中工作方面,它可能是 Linux 中包含的最有用的工具。

我在这里只是触及了表面,您strace也可以指示仅显示系统调用或信号。查看该man strace页面以获取更多信息。

答案2

解决问题:

我想记录已经运行的程序的系统调用。

strace开始一个程序的名称,但对于“已经运行的程序”,您必须(如autrace)引用进程 ID。

给定的可执行文件可以有多个与其关联的进程。您可以制作一个脚本来检查exe下的所有链接/proc,例如,

/proc/*/exe

查看哪个与您感兴趣的可执行文件匹配,并且(因为中间目录名称进程 ID)使strace每个进程运行。

对于您所执行的任何流程跟踪,exe链接是可执行文件的路径名。您的脚本将读取路径名(使用readlink),如果匹配,则strace使用-p相应进程 ID 的选项运行。当然,您可以在后台运行它们,以便能够处理多个进程。

将它们收集到一个连贯的日志文件中可能是(也可能不是)您接下来想要做的。您的脚本可以将结果通过管道传输到straceto logger,从而使结果成为一个大日志文件。

进一步阅读:

以及手册页:

相关内容