저는 AppArmor Complaint Mode와 같은 복잡한 도구를 사용하지 않을 것이며, 특정 프로그램에서 어떤 파일에 액세스하는지 알려주는 간단한 도구를 원합니다.
답변1
Chris Down에 따르면 다음 을 통해 strace -p
확인할 수 있습니다.이미 실행 중strace를 종료하거나 프로세스 자체가 완료될 때까지 지금부터 열려 있는 파일을 확인하는 프로세스입니다.
다음과 같이 보고 싶다면전체 기간처음부터 strace
실행 파일 이름과 함께 사용되는 프로세스 이름입니다. 추가하면 -f
분기된 하위 프로세스도 보고됩니다. 예
# strace -e open -f /bin/id
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libselinux.so.1", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libpcre.so.1", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
open("/proc/thread-self/attr/current", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/proc/self/task/1581/attr/current", O_RDONLY|O_CLOEXEC) = 3
open("/usr/share/locale/locale.alias", O_RDONLY|O_CLOEXEC) = 3
open("/usr/share/locale/en_US.UTF-8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en_US.utf8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en_US/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en.UTF-8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en.utf8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/etc/nsswitch.conf", O_RDONLY|O_CLOEXEC) = 3
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libnss_files.so.2", O_RDONLY|O_CLOEXEC) = 3
open("/etc/passwd", O_RDONLY|O_CLOEXEC) = 3
open("/etc/group", O_RDONLY|O_CLOEXEC) = 3
open("/etc/group", O_RDONLY|O_CLOEXEC) = 3
uid=0(root) gid=0(root) groups=0(root) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
+++ exited with 0 +++
#
lsof
프로세스에 어떤 파일이 있는지 확인하는 데 사용됩니다 .지금열려 있는
# lsof -p $(pidof NetworkManager)
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
NetworkMa 722 root cwd DIR 253,0 224 64 /
NetworkMa 722 root rtd DIR 253,0 224 64 /
NetworkMa 722 root txt REG 253,0 2618520 288243 /usr/sbin/NetworkManager
NetworkMa 722 root mem REG 253,0 27776 34560 /usr/lib64/libnss_dns-2.17.so
[...]
#
SystemTap이 있으면 전체 호스트에서 열린 파일을 모니터링할 수 있습니다.
[root@localhost tmp]# cat mon
#!/usr/bin/env stap
probe syscall.open { printf ("pid %d program %s opened %s\n", pid(), execname(), filename) }
# ./mon
pid 14813 program touch opened "/etc/ld.so.cache"
pid 14813 program touch opened "/lib64/libc.so.6"
pid 14813 program touch opened 0x7f7a8c6ec8d0
pid 14813 program touch opened "foo2"
[...]
#
답변2
opensnoop
내부적으로 eBPF를 사용하는 BCC에서 이를 사용할 수 있습니다 .
# ./opensnoop -p 1576
PID COMM FD ERR PATH
1576 snmpd 11 0 /proc/sys/net/ipv6/conf/lo/forwarding
1576 snmpd 11 0 /proc/sys/net/ipv6/neigh/lo/base_reachable_time_ms
1576 snmpd 9 0 /proc/diskstats
1576 snmpd 9 0 /proc/stat
1576 snmpd 9 0 /proc/vmstat
[...]
strace
이는 시스템 호출을 다시 시작 하지 않고도 kprobe를 사용하기 때문에 매우 효율적입니다 .
strace
(아마도 추적 프로세스의 하위 프로세스) 를 사용하여 이 작업을 수행할 수도 있지만 -f
이를 수행하는 방법에는 다음과 같이 시스템 호출을 다시 시작하는 것이 포함됩니다.길애플리케이션 속도가 약간 느려집니다.
# strace -e open -p 15735
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
open("/usr/lib/gconv/gconv-modules.cache", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/lib/gconv/gconv-modules", O_RDONLY|O_CLOEXEC) = 3
open("/usr/lib/python2.7/site-packages", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 4
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
open("/etc/localtime", O_RDONLY|O_CLOEXEC) = 8
[...]
strace [executable]
원하는 경우 또는 를 사용하여 이 방법으로 응용프로그램을 시작할 수도 있습니다 strace -f [executable]
.
답변3
응용 프로그램이 열리는 파일을 모니터링하기 위해 제가 가장 좋아하는 도구는 강력한 모니터링 프레임워크입니다 sysdig
.
다음 프로그램에서 열린 모든 열린 파일을 모니터링하는 데 사용됩니다 exe_file
.
sudo sysdig -p "proc.name=exe_file %12user.name %6proc.pid %12proc.name %3fd.num %fd.typechar %fd.name" evt.type=open
서버에 열려 있는 모든 파일을 모니터링합니다.
sudo sysdig -p "%12user.name %6proc.pid %12proc.name %3fd.num %fd.typechar %fd.name" evt.type=open
홈 디렉터리의 쓰기 이벤트만 포함하는 추적 파일을 만듭니다. (나중에 다음을 사용하여 검사할 수 있습니다 sysdig -r writetrace.scap.gz
.
sudo sysdig -p "%user.name %proc.name %fd.name" "evt.type=write and fd.name contains /home/" -z -w writetrace.scap.gz
다음 프로세스에 대한 시스템 호출 수준에서 exe_file
모든 것을 봅니다.
sudo sysdig proc.name=exe_file
Sysdig에는 많은 끌이 있습니다. 이를 통해 수행할 수 있는 더 흥미로운 작업을 확인하세요.
dtrace
또한 Linux에서는 많이 사용되지 않지만 *BSD 운영 체제에서는 여전히 많이 사용된다는 것을 알고 있습니다 .
# Files opened by process,
dtrace -n 'syscall::open*:entry { printf("%s %s",execname,copyinstr(arg0)); }'
sysdig
, strace
및 외에도 프로세스에서 호출/수신된 신호/동적 라이브러리/시스템 호출을 기록/가로채는 가 dtrace
있습니다 .ltrace
ltrace
종료될 때까지 지정된 명령만 실행하는 프로그램입니다. 실행 프로세스에서 호출한 동적 라이브러리 호출과 프로세스에서 수신한 신호를 가로채서 기록합니다. 또한 프로그램이 실행하는 시스템 호출을 가로채서 인쇄할 수도 있습니다.
$ltrace exe_file
_libc_start_main(0x400624, 1, 0x7ffcb7b6d7c8, 0x400710 <unfinished ...>
time(0) = 1508018406
srand(0x59e288e6, 0x7ffcb7b6d7c8, 0x7ffcb7b6d7d8, 0) = 0
sprintf("mkdir -p -- '/opt/sms/AU/mo'", "mkdir -p -- '%s'", "/opt/sms/AU/mo") = 28
system("mkdir -p -- '/opt/sms/AU/mo'" <no return ...>
--- SIGCHLD (Child exited) ---
<... system resumed> ) = 0
rand(2, 0x7ffcb7b6d480, 0, 0x7f9d6d4622b0) = 0x2d8ddbe1
sprintf("/opt/sms/AU/mo/tmp.XXXXXX", "%s/tmp.XXXXXX", "/opt/sms/AU/mo") = 29
mkstemp(0x7ffcb7b6d5c0, 0x40080b, 0x40081a, 0x7ffffff1) = 3
sprintf("/opt/sms/AU/mo/tmp.XXXXXX", "%s/tmp.XXXXXX", "/opt/sms/AU/mo") = 29
mkstemp(0x7ffcb7b6d5c0, 0x40080b, 0x40081a, 0x7ffffff1) = 4
+++ exited (status 0) +++
프로그램이 작다면 디스어셈블리 objdump -d exe_file
나 디스어셈블리/디컴파일을 사용하여 Hopper
프로그램이 처리하는 모든 파일을 확인하는 것도 고려해 볼 수 있습니다.
자세한 내용은 다음을 참조하세요.Linux 바이너리가 수행하는 작업 이해
첫 번째 접근 방식으로 다음과 같이 수행합니다.
strings exe_file
이는 저렴한 방법이며, 운이 좋다면 일부 파일 이름은 ASCII 모드의 바이너리에만 나타날 수도 있습니다.
관련 답변도 참조하세요진실은 왜 그렇게 거짓인가?
배포판이 바이너리/파일과 함께 제공되는 경우 배포판의 소스 저장소나 실제 유틸리티의 공식 저장소에서 소스 코드를 얻을 수도 있습니다.
최후의 수단으로 항상 다음과 같은 도구를 사용할 수 있습니다.데이터 베이스또는₩₩실시간으로 바이너리 디버깅.