返回
从正在运行的进程中检查加载的共享库
Linux
2024-03-07 18:23:45
如何在运行时检查给定进程加载了哪些共享库?
问题陈述
获取正在运行进程加载的库信息是一个常见的任务。但是,使用传统工具(如readelf或ldd)可能会遗漏通过dlopen动态加载的库。本文将探索如何从正在运行的进程中提取此信息。
解决方案
有三种主要方法可以检查进程加载的共享库:
1. 使用procfs
procfs是一个伪文件系统,提供有关正在运行进程的信息。要使用procfs:
- 打开
/proc/[pid]/maps
文件。 此文件包含进程使用的所有内存映射。 - 查找包含"r-xp"标志的行。 这些行表示可执行代码段,通常对应于共享库。
- 提取"path"字段。 它包含加载的库的路径。
2. 使用ptrace
ptrace允许一个进程检查和控制另一个进程。要使用ptrace:
- 附加到目标进程。
- 获取目标进程的寄存器。
- 查找动态链接器寄存器。 它指向动态链接器结构。
- 解析动态链接器结构。 以获取有关加载的共享库的信息。
3. 使用系统工具
某些系统工具可以提供有关共享库的信息:
- lsof: 列出打开的文件和套接字。
- truss: 跟踪系统调用。
- dtruss: 仅跟踪动态链接库调用。
代码示例
使用procfs:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
int main(int argc, char *argv[]) {
if (argc != 2) {
fprintf(stderr, "Usage: %s <pid>\n", argv[0]);
return EXIT_FAILURE;
}
int pid = atoi(argv[1]);
char path[256];
snprintf(path, sizeof(path), "/proc/%d/maps", pid);
FILE *f = fopen(path, "r");
if (f == NULL) {
perror("fopen");
return EXIT_FAILURE;
}
char line[1024];
while (fgets(line, sizeof(line), f)) {
if (strstr(line, "r-xp") != NULL) {
char *path = strstr(line, "path: ");
if (path != NULL) {
printf("%s", path + 6);
}
}
}
fclose(f);
return EXIT_SUCCESS;
}
使用ptrace:
#include <stdio.h>
#include <stdlib.h>
#include <sys/ptrace.h>
#include <sys/user.h>
int main(int argc, char *argv[]) {
if (argc != 2) {
fprintf(stderr, "Usage: %s <pid>\n", argv[0]);
return EXIT_FAILURE;
}
int pid = atoi(argv[1]);
struct user_regs_struct regs;
if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) == -1) {
perror("ptrace");
return EXIT_FAILURE;
}
if (ptrace(PTRACE_GETREGS, pid, NULL, ®s) == -1) {
perror("ptrace");
return EXIT_FAILURE;
}
ElfW(Dyn) *dyn = (ElfW(Dyn) *)regs.r[PT_LD_0];
while (dyn->d_tag != DT_NULL) {
if (dyn->d_tag == DT_NEEDED) {
printf("%s\n", (char *)dyn->d_un.d_val);
}
dyn++;
}
if (ptrace(PTRACE_DETACH, pid, NULL, NULL) == -1) {
perror("ptrace");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
注意: 检查共享库可能需要root权限。
结论
本文介绍了三种检查正在运行的进程加载了哪些共享库的方法。这些方法提供了获取进程内存使用情况的宝贵见解,可以用于调试、安全分析和其他开发任务。
常见问题解答
1. 这些方法是否适用于所有平台?
这些方法主要适用于Linux和类Unix系统。其他平台可能有不同的机制来管理共享库。
2. 检查共享库的性能影响是什么?
procfs和ptrace方法可能对性能产生轻微影响。使用系统工具通常更快。
3. 我可以过滤特定库吗?
是的,可以使用grep或其他工具对输出进行过滤。例如:
cat /proc/[pid]/maps | grep 'lib.*\.so'
4. 这些方法可以用来检测恶意共享库吗?
是的,通过检查加载的库是否来自可信来源,可以帮助识别恶意共享库。
5. 我可以修改进程加载的共享库吗?
是的,可以使用dlopen和dlsym等函数动态加载和卸载共享库。