对write也进行了hook,并且提供了初始化函数
This commit is contained in:
parent
e6568b3d81
commit
2256a6ce3b
|
|
@ -178,75 +178,34 @@ int is_ansi_escape_sequence(const char *str) {
|
||||||
return str[0] == '\033' && str[1] == '[';
|
return str[0] == '\033' && str[1] == '[';
|
||||||
}
|
}
|
||||||
|
|
||||||
// 复制标准输出和错误输出到日志文件
|
// 保存原始的 write 函数指针
|
||||||
void duplicate_output_to_log() {
|
static ssize_t (*original_write)(int fd, const void *buf, size_t count) = NULL;
|
||||||
DEBUG_LOG("Duplicating stdout/stderr to log file: %s", LOG_OUT_FILE);
|
|
||||||
int log_fd = open(LOG_OUT_FILE, O_WRONLY | O_CREAT | O_APPEND, 0644);
|
|
||||||
if (log_fd == -1) {
|
|
||||||
perror("Failed to open log file");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int pipe_fds[2];
|
// 保存日志文件描述符
|
||||||
if (pipe(pipe_fds) == -1) {
|
static int log_fd = -1;
|
||||||
perror("Failed to create pipe");
|
|
||||||
close(log_fd);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
pid_t pid = fork();
|
// 我们自己的 write 函数
|
||||||
if (pid == -1) {
|
ssize_t write(int fd, const void *buf, size_t count) {
|
||||||
perror("Failed to fork");
|
ssize_t result = -1;
|
||||||
close(log_fd);
|
|
||||||
close(pipe_fds[0]);
|
|
||||||
close(pipe_fds[1]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pid == 0) { // 子进程:读取 pipe,并写入日志
|
result = original_write(fd, buf, count);
|
||||||
close(pipe_fds[1]); // 关闭写端
|
// 如果原始 write 成功,则将相同的内容写入日志文件
|
||||||
char buffer[1024];
|
if (result > 0 && log_fd != -1) {
|
||||||
ssize_t n;
|
ssize_t log_result = original_write(log_fd, buf, count);
|
||||||
int has_error = 0;
|
if (log_result == -1) {
|
||||||
|
fprintf(stderr, "Error writing to log file: %s\n", strerror(errno));
|
||||||
while ((n = read(pipe_fds[0], buffer, sizeof(buffer))) > 0) {
|
// 注意:这里不应该影响原始 write 的返回值
|
||||||
// 检查buffer中是否包含错误信息
|
|
||||||
if (strstr(buffer, "error") || strstr(buffer, "Error") ||
|
|
||||||
strstr(buffer, "ERROR")) {
|
|
||||||
has_error = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 输出到终端时保留颜色
|
|
||||||
if (isatty(STDOUT_FILENO)) {
|
|
||||||
if (write(STDOUT_FILENO, buffer, n) == -1) {
|
|
||||||
perror("Failed to write to stdout");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (write(log_fd, buffer, n) == -1) {
|
return result;
|
||||||
perror("Failed to write to log file");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (has_error) {
|
|
||||||
printf("\n检测到命令执行出错,已经上报北冥论坛~ \n");
|
|
||||||
fflush(stdout); // 确保提示文字被输出
|
|
||||||
}
|
|
||||||
|
|
||||||
close(pipe_fds[0]);
|
|
||||||
close(log_fd);
|
|
||||||
_exit(0);
|
|
||||||
} else { // 父进程:写入 pipe
|
|
||||||
close(pipe_fds[0]); // 关闭读端
|
|
||||||
dup2(pipe_fds[1], STDOUT_FILENO);
|
|
||||||
dup2(pipe_fds[1], STDERR_FILENO);
|
|
||||||
close(pipe_fds[1]);
|
|
||||||
close(log_fd);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef int (*orig_execve_type)(const char *filename, char *const argv[],
|
typedef int (*orig_execve_type)(const char *filename, char *const argv[],
|
||||||
char *const envp[]);
|
char *const envp[]);
|
||||||
|
|
||||||
|
// 原始指针
|
||||||
|
static orig_execve_type orig_execve = NULL;
|
||||||
|
|
||||||
// 判断父进程是否为终端 shell (bash, zsh, fish 等)
|
// 判断父进程是否为终端 shell (bash, zsh, fish 等)
|
||||||
int is_terminal_shell() {
|
int is_terminal_shell() {
|
||||||
pid_t ppid = getppid();
|
pid_t ppid = getppid();
|
||||||
|
|
@ -326,8 +285,6 @@ int execve(const char *filename, char *const argv[], char *const envp[]) {
|
||||||
// 仅在 shell 终端调用 execve 时拦截
|
// 仅在 shell 终端调用 execve 时拦截
|
||||||
if (!is_terminal_shell()) {
|
if (!is_terminal_shell()) {
|
||||||
DEBUG_LOG("Not a terminal shell, bypassing interception.");
|
DEBUG_LOG("Not a terminal shell, bypassing interception.");
|
||||||
orig_execve_type orig_execve =
|
|
||||||
(orig_execve_type)dlsym(RTLD_NEXT, "execve");
|
|
||||||
return orig_execve(filename, argv, envp);
|
return orig_execve(filename, argv, envp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -340,16 +297,12 @@ int execve(const char *filename, char *const argv[], char *const envp[]) {
|
||||||
// 如果共享内存未成功加载,则直接执行
|
// 如果共享内存未成功加载,则直接执行
|
||||||
if (shared_config == NULL) {
|
if (shared_config == NULL) {
|
||||||
DEBUG_LOG("Shared memory not initialized, bypassing interception.");
|
DEBUG_LOG("Shared memory not initialized, bypassing interception.");
|
||||||
orig_execve_type orig_execve =
|
|
||||||
(orig_execve_type)dlsym(RTLD_NEXT, "execve");
|
|
||||||
return orig_execve(filename, argv, envp);
|
return orig_execve(filename, argv, envp);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果功能被禁用,则直接执行
|
// 如果功能被禁用,则直接执行
|
||||||
if (!shared_config->enabled) {
|
if (!shared_config->enabled) {
|
||||||
DEBUG_LOG("Not enabled.");
|
DEBUG_LOG("Not enabled.");
|
||||||
orig_execve_type orig_execve =
|
|
||||||
(orig_execve_type)dlsym(RTLD_NEXT, "execve");
|
|
||||||
return orig_execve(filename, argv, envp);
|
return orig_execve(filename, argv, envp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -363,8 +316,6 @@ int execve(const char *filename, char *const argv[], char *const envp[]) {
|
||||||
// 特殊处理以 shell.posix
|
// 特殊处理以 shell.posix
|
||||||
// 方式执行的命令,直接执行,不进行规则匹配和输出重定向
|
// 方式执行的命令,直接执行,不进行规则匹配和输出重定向
|
||||||
if (argv[1] != NULL && strcmp(argv[1], "shell.posix") == 0) {
|
if (argv[1] != NULL && strcmp(argv[1], "shell.posix") == 0) {
|
||||||
orig_execve_type orig_execve =
|
|
||||||
(orig_execve_type)dlsym(RTLD_NEXT, "execve");
|
|
||||||
return orig_execve(filename, argv, envp);
|
return orig_execve(filename, argv, envp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -394,12 +345,37 @@ int execve(const char *filename, char *const argv[], char *const envp[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 复制 stdout 和 stderr 到日志文件
|
// 复制 stdout 和 stderr 到日志文件
|
||||||
duplicate_output_to_log();
|
// duplicate_output_to_log();
|
||||||
|
|
||||||
orig_execve_type orig_execve = (orig_execve_type)dlsym(RTLD_NEXT, "execve");
|
|
||||||
return orig_execve(filename, argv, envp);
|
return orig_execve(filename, argv, envp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 构造函数,在库被加载时执行
|
||||||
|
__attribute__((constructor)) static void initialize() {
|
||||||
|
DEBUG_LOG("Initializing execve_intercept library.");
|
||||||
|
// 获取原始的 write 函数
|
||||||
|
original_write = dlsym(RTLD_NEXT, "write");
|
||||||
|
if (original_write == NULL) {
|
||||||
|
fprintf(stderr, "Error in dlsym(\"write\"): %s\n", dlerror());
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 打开日志文件,以追加模式打开,如果不存在则创建
|
||||||
|
log_fd = open(LOG_OUT_FILE, O_WRONLY | O_CREAT | O_APPEND, 0644);
|
||||||
|
if (log_fd == -1) {
|
||||||
|
fprintf(stderr, "Error opening log file \"%s\": %s\n", LOG_OUT_FILE,
|
||||||
|
strerror(errno));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
load_config_if_needed();
|
||||||
|
orig_execve = (orig_execve_type)dlsym(RTLD_NEXT, "execve");
|
||||||
|
if (orig_execve == NULL) {
|
||||||
|
fprintf(stderr, "Error in dlsym(\"execve\"): %s\n", dlerror());
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 在库卸载时分离和删除共享内存
|
// 在库卸载时分离和删除共享内存
|
||||||
__attribute__((destructor)) static void cleanup_shared_memory() {
|
__attribute__((destructor)) static void cleanup_shared_memory() {
|
||||||
DEBUG_LOG("Cleaning up shared memory.");
|
DEBUG_LOG("Cleaning up shared memory.");
|
||||||
|
|
@ -409,7 +385,20 @@ __attribute__((destructor)) static void cleanup_shared_memory() {
|
||||||
}
|
}
|
||||||
shared_config = NULL;
|
shared_config = NULL;
|
||||||
}
|
}
|
||||||
|
if (log_fd != -1) {
|
||||||
|
DEBUG_LOG("Closing log file descriptor.");
|
||||||
|
close(log_fd);
|
||||||
|
}
|
||||||
// 注意:这里不删除共享内存段,因为可能被其他进程使用。
|
// 注意:这里不删除共享内存段,因为可能被其他进程使用。
|
||||||
// 如果需要删除,需要一个明确的机制来判断是否是最后一个使用者。
|
// 如果需要删除,需要一个明确的机制来判断是否是最后一个使用者。
|
||||||
// 例如,可以创建一个单独的工具来管理共享内存的生命周期。
|
// 例如,可以创建一个单独的工具来管理共享内存的生命周期。
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__attribute__((destructor)) static void debug_log() {
|
||||||
|
DEBUG_LOG("execve_intercept library unloaded.");
|
||||||
|
// log输出路径
|
||||||
|
DEBUG_LOG("Log file: %s", LOG_FILE);
|
||||||
|
DEBUG_LOG("Log out file: %s", LOG_OUT_FILE);
|
||||||
|
DEBUG_LOG("Config file: %s", CONFIG_FILE);
|
||||||
|
DEBUG_LOG("Shared memory ID: %d", shm_id);
|
||||||
|
}
|
||||||
|
|
|
||||||
BIN
intercept.so
BIN
intercept.so
Binary file not shown.
Loading…
Reference in New Issue