This commit is contained in:
Pan Qiancheng 2025-04-08 20:29:35 +08:00
parent eb6316e8ec
commit 61a42adb2e
25 changed files with 6752 additions and 153 deletions

10
.vscode/settings.json vendored
View File

@ -11,6 +11,12 @@
"shm.h": "c",
"unistd.h": "c",
"logging.h": "c",
"fcntl.h": "c"
}
"fcntl.h": "c",
"exec_hook.h": "c",
"dlfcn.h": "c",
"signal.h": "c",
"stdio.h": "c",
"wait.h": "c"
},
"C_Cpp.errorSquiggles": "disabled"
}

View File

@ -1,28 +1,47 @@
CC = gcc
CFLAGS = -shared -fPIC -Wall -Wextra -Werror -O2 -fno-strict-aliasing -fPIC -fno-omit-frame-pointer -fno-stack-protector -Wl,-z,relro,-z,now
CFLAGS = -shared -fPIC -Wall -Wextra -Werror -fno-strict-aliasing -fPIC -fno-omit-frame-pointer -fno-stack-protector -Wl,-z,relro,-z,now
LDFLAGS = -ldl -ljson-c
HOOK_LDFLAGS = -ldl -pthread
TARGET_NAME = intercept.so
HOOK_NAME = hook_write.so
BUILD_DIR = build
SRC_DIR = src
SRC = $(wildcard $(SRC_DIR)/*.c)
SRC := $(filter-out $(SRC_DIR)/hook_write.c, $(SRC)) # 排除 hook_write.c
OBJ = $(patsubst $(SRC_DIR)/%.c,$(BUILD_DIR)/%.o,$(SRC))
TARGET = $(BUILD_DIR)/$(TARGET_NAME)
HOOK_SRC = $(SRC_DIR)/hook_write.c
HOOK_OBJ = $(BUILD_DIR)/hook_write.o
HOOK_TARGET = $(BUILD_DIR)/$(HOOK_NAME)
# 如果需要开启 debug只需执行 make DEBUG=1
ifeq ($(DEBUG),1)
CFLAGS += -DDEBUG -g # Add -g for debugging symbols
CFLAGS += -DDEBUG -g
endif
all: $(TARGET)
$(BUILD_DIR)/$(TARGET_NAME): $(OBJ)
@mkdir -p $(BUILD_DIR)
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
all: $(TARGET) $(HOOK_TARGET)
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c
@mkdir -p $(BUILD_DIR)
$(CC) $(CFLAGS) -c $< -o $@
$(TARGET): $(OBJ)
@mkdir -p $(BUILD_DIR)
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
$(HOOK_TARGET): $(HOOK_OBJ)
@mkdir -p $(BUILD_DIR)
$(CC) $(CFLAGS) -Wno-error=unused-result -o $@ $^ $(HOOK_LDFLAGS)
$(HOOK_OBJ): $(HOOK_SRC)
@mkdir -p $(BUILD_DIR)
$(CC) $(CFLAGS) -Wno-error=unused-result -c $< -o $@
clean:
rm -rf $(BUILD_DIR)
@ -30,4 +49,4 @@ debug:
rm -rf $(BUILD_DIR)
$(MAKE) DEBUG=1
rebuild: clean all
rebuild: clean all

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
build/hook_write.o Normal file

Binary file not shown.

BIN
build/hook_write.so Executable file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

5826
logs/execve.log Normal file

File diff suppressed because it is too large Load Diff

0
logs/execve_out.log Normal file
View File

231
output.txt Normal file
View File

@ -0,0 +1,231 @@
This is the parent process.
Enter something: This is the child process.
Enter something: 123
You entered: 123
This is a test output.
This is a test error output.
[DEBUG][PID 3285394] src/execve_interceptor.c:29:execve(): Intercepted execve for: /usr/bin/bash
[DEBUG][PID 3285394] src/execve_interceptor.c:30:execve(): argv[0] = bash
[DEBUG][PID 3285394] src/config.c:114:load_config_if_needed(): Creating shared memory for config data
[DEBUG][PID 3285394] src/config.c:127:load_config_if_needed(): Loading config file for the first time
[DEBUG][PID 3285394] src/config.c:17:load_config_to_shm(): Loading configuration from /tmp/exec_hook/config/execve_rules.json to shared memory
[DEBUG][PID 3285394] src/config.c:89:load_config_to_shm(): Loaded 3 rules to shared memory
[DEBUG][PID 3285394] src/execve_interceptor.c:43:execve(): Not a terminal shell, bypassing interception.
[DEBUG][PID 3285513] src/execve_interceptor.c:29:execve(): Intercepted execve for: /usr/bin/lesspipe
[DEBUG][PID 3285513] src/execve_interceptor.c:30:execve(): argv[0] = lesspipe
[DEBUG][PID 3285513] src/config.c:114:load_config_if_needed(): Creating shared memory for config data
[DEBUG][PID 3285513] src/config.c:127:load_config_if_needed(): Loading config file for the first time
[DEBUG][PID 3285513] src/config.c:17:load_config_to_shm(): Loading configuration from /tmp/exec_hook/config/execve_rules.json to shared memory
[DEBUG][PID 3285513] src/config.c:89:load_config_to_shm(): Loaded 3 rules to shared memory
[DEBUG][PID 3285513] src/execve_interceptor.c:48:execve(): Current Config rule count : 3
[DEBUG][PID 3285513] src/logging.c:21:write_log(): Writing exec log for command: /usr/bin/lesspipe
[DEBUG][PID 3285513] src/logging.c:154:duplicate_output_to_log(): Signal handler for SIGINT installed.
[DEBUG][PID 3285513] src/logging.c:236:duplicate_output_to_log(): Child process exited normally
[DEBUG][PID 3285513] src/init_cleanup.c:23:cleanup_shared_memory(): execve_intercept library unloaded.
[DEBUG][PID 3285513] src/init_cleanup.c:25:cleanup_shared_memory(): Log file: ./logs/execve.log
[DEBUG][PID 3285513] src/init_cleanup.c:26:cleanup_shared_memory(): Log out file: ./logs/execve_out.log
[DEBUG][PID 3285513] src/init_cleanup.c:27:cleanup_shared_memory(): Config file: /tmp/exec_hook/config/execve_rules.json
[DEBUG][PID 3285513] src/init_cleanup.c:28:cleanup_shared_memory(): Shared memory ID: 2
[DEBUG][PID 3285513] src/init_cleanup.c:30:cleanup_shared_memory(): Cleaning up shared memory.
/tmp/exec_hook/intercept.so(print_stacktrace+0x23)[0x7f78a48e21a5]
/tmp/exec_hook/intercept.so(cleanup_shared_memory+0x210)[0x7f78a48e29e0]
/lib64/ld-linux-x86-64.so.2(+0x624e)[0x7f78a48f024e]
/lib/x86_64-linux-gnu/libc.so.6(+0x45495)[0x7f78a46b8495]
/lib/x86_64-linux-gnu/libc.so.6(on_exit+0x0)[0x7f78a46b8610]
/tmp/exec_hook/intercept.so(duplicate_output_to_log+0x623)[0x7f78a48e334c]
/tmp/exec_hook/intercept.so(execve+0x5e4)[0x7f78a48e27a8]
bash(shell_execve+0x36)[0x60ac0270ba46]
bash(+0x5b8e7)[0x60ac027128e7]
bash(+0x4b993)[0x60ac02702993]
bash(execute_command_internal+0xf1d)[0x60ac02704b5d]
bash(parse_and_execute+0x6c8)[0x60ac027654e8]
bash(command_substitute+0xa98)[0x60ac0272d938]
bash(+0x780a2)[0x60ac0272f0a2]
bash(+0x81d58)[0x60ac02738d58]
bash(+0x83277)[0x60ac0273a277]
bash(+0x87df9)[0x60ac0273edf9]
bash(+0x4bf8f)[0x60ac02702f8f]
bash(execute_command_internal+0xf1d)[0x60ac02704b5d]
bash(execute_command+0xc8)[0x60ac027071b8]
bash(execute_command_internal+0x343b)[0x60ac0270707b]
bash(parse_and_execute+0x6c8)[0x60ac027654e8]
bash(+0xaf1c6)[0x60ac027661c6]
bash(maybe_execute_file+0x2e)[0x60ac0276659e]
bash(main+0x1a30)[0x60ac026e9db0]
/lib/x86_64-linux-gnu/libc.so.6(+0x29d90)[0x7f78a469cd90]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0x80)[0x7f78a469ce40]
bash(_start+0x25)[0x60ac026e9f15]
bash: eval: 行 31: 未预期的记号 "(" 附近有语法错误
bash: eval: 行 31: `[DEBUG][PID 3285514] src/logging.c:125:duplicate_output_to_log(): Child process 3285514: stdout is /dev/pts/6 '
[DEBUG][PID 3285518] src/execve_interceptor.c:29:execve(): Intercepted execve for: /usr/bin/dircolors
[DEBUG][PID 3285518] src/execve_interceptor.c:30:execve(): argv[0] = dircolors
[DEBUG][PID 3285518] src/config.c:114:load_config_if_needed(): Creating shared memory for config data
[DEBUG][PID 3285518] src/config.c:127:load_config_if_needed(): Loading config file for the first time
[DEBUG][PID 3285518] src/config.c:17:load_config_to_shm(): Loading configuration from /tmp/exec_hook/config/execve_rules.json to shared memory
[DEBUG][PID 3285518] src/config.c:89:load_config_to_shm(): Loaded 3 rules to shared memory
[DEBUG][PID 3285518] src/execve_interceptor.c:48:execve(): Current Config rule count : 3
[DEBUG][PID 3285518] src/logging.c:21:write_log(): Writing exec log for command: /usr/bin/dircolors
[DEBUG][PID 3285518] src/logging.c:154:duplicate_output_to_log(): Signal handler for SIGINT installed.
[DEBUG][PID 3285518] src/logging.c:236:duplicate_output_to_log(): Child process exited normally
[DEBUG][PID 3285518] src/init_cleanup.c:23:cleanup_shared_memory(): execve_intercept library unloaded.
[DEBUG][PID 3285518] src/init_cleanup.c:25:cleanup_shared_memory(): Log file: ./logs/execve.log
[DEBUG][PID 3285518] src/init_cleanup.c:26:cleanup_shared_memory(): Log out file: ./logs/execve_out.log
[DEBUG][PID 3285518] src/init_cleanup.c:27:cleanup_shared_memory(): Config file: /tmp/exec_hook/config/execve_rules.json
[DEBUG][PID 3285518] src/init_cleanup.c:28:cleanup_shared_memory(): Shared memory ID: 2
[DEBUG][PID 3285518] src/init_cleanup.c:30:cleanup_shared_memory(): Cleaning up shared memory.
/tmp/exec_hook/intercept.so(print_stacktrace+0x23)[0x7f78a48e21a5]
/tmp/exec_hook/intercept.so(cleanup_shared_memory+0x210)[0x7f78a48e29e0]
/lib64/ld-linux-x86-64.so.2(+0x624e)[0x7f78a48f024e]
/lib/x86_64-linux-gnu/libc.so.6(+0x45495)[0x7f78a46b8495]
/lib/x86_64-linux-gnu/libc.so.6(on_exit+0x0)[0x7f78a46b8610]
/tmp/exec_hook/intercept.so(duplicate_output_to_log+0x623)[0x7f78a48e334c]
/tmp/exec_hook/intercept.so(execve+0x5e4)[0x7f78a48e27a8]
bash(shell_execve+0x36)[0x60ac0270ba46]
bash(+0x5b8e7)[0x60ac027128e7]
bash(+0x4b993)[0x60ac02702993]
bash(execute_command_internal+0xf1d)[0x60ac02704b5d]
bash(parse_and_execute+0x6c8)[0x60ac027654e8]
bash(command_substitute+0xa98)[0x60ac0272d938]
bash(+0x780a2)[0x60ac0272f0a2]
bash(+0x81d58)[0x60ac02738d58]
bash(+0x83277)[0x60ac0273a277]
bash(+0x87df9)[0x60ac0273edf9]
bash(+0x4bf8f)[0x60ac02702f8f]
bash(execute_command_internal+0xf1d)[0x60ac02704b5d]
bash(execute_command+0xc8)[0x60ac027071b8]
bash(execute_command_internal+0x343b)[0x60ac0270707b]
bash(execute_command+0xc8)[0x60ac027071b8]
bash(execute_command_internal+0x1d8e)[0x60ac027059ce]
bash(execute_command+0xc8)[0x60ac027071b8]
bash(execute_command_internal+0x1d8e)[0x60ac027059ce]
bash(execute_command+0xc8)[0x60ac027071b8]
bash(execute_command_internal+0x1d8e)[0x60ac027059ce]
bash(execute_command+0xc8)[0x60ac027071b8]
bash(execute_command_internal+0x1d8e)[0x60ac027059ce]
bash(execute_command+0xc8)[0x60ac027071b8]
bash(execute_command_internal+0x108a)[0x60ac02704cca]
bash(parse_and_execute+0x6c8)[0x60ac027654e8]
bash(+0xaf1c6)[0x60ac027661c6]
bash(maybe_execute_file+0x2e)[0x60ac0276659e]
bash(main+0x1a30)[0x60ac026e9db0]
/lib/x86_64-linux-gnu/libc.so.6(+0x29d90)[0x7f78a469cd90]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0x80)[0x7f78a469ce40]
bash(_start+0x25)[0x60ac026e9f15]
bash: eval: 行 77: 未预期的记号 "(" 附近有语法错误
bash: eval: 行 77: `[DEBUG][PID 3285519] src/logging.c:125:duplicate_output_to_log(): Child process 3285519: stdout is /dev/pts/6 '
[?2004h]0;qcqcqc@qcqcqc-ThinkCentre-M710q-N000: ~/workspace/test_execveqcqcqc@qcqcqc-ThinkCentre-M710q-N000:~/workspace/test_execve$ You entered: exit
This is a test output.
This is a test error output.
[DEBUG][PID 3285395] src/execve_interceptor.c:29:execve(): Intercepted execve for: /usr/bin/bash
[DEBUG][PID 3285395] src/execve_interceptor.c:30:execve(): argv[0] = bash
[DEBUG][PID 3285395] src/config.c:114:load_config_if_needed(): Creating shared memory for config data
[DEBUG][PID 3285395] src/config.c:127:load_config_if_needed(): Loading config file for the first time
[DEBUG][PID 3285395] src/config.c:17:load_config_to_shm(): Loading configuration from /tmp/exec_hook/config/execve_rules.json to shared memory
[DEBUG][PID 3285395] src/config.c:89:load_config_to_shm(): Loaded 3 rules to shared memory
[DEBUG][PID 3285395] src/execve_interceptor.c:48:execve(): Current Config rule count : 3
[DEBUG][PID 3285395] src/logging.c:21:write_log(): Writing exec log for command: /usr/bin/bash
[DEBUG][PID 3285395] src/logging.c:154:duplicate_output_to_log(): Signal handler for SIGINT installed.
[DEBUG][PID 3286125] src/logging.c:125:duplicate_output_to_log(): Child process 3286125: stdout is /dev/pts/6
[DEBUG][PID 3286126] src/execve_interceptor.c:29:execve(): Intercepted execve for: /usr/bin/lesspipe
[DEBUG][PID 3286126] src/execve_interceptor.c:30:execve(): argv[0] = lesspipe
[DEBUG][PID 3286126] src/config.c:114:load_config_if_needed(): Creating shared memory for config data
[DEBUG][PID 3286126] src/config.c:127:load_config_if_needed(): Loading config file for the first time
[DEBUG][PID 3286126] src/config.c:17:load_config_to_shm(): Loading configuration from /tmp/exec_hook/config/execve_rules.json to shared memory
[DEBUG][PID 3286126] src/config.c:89:load_config_to_shm(): Loaded 3 rules to shared memory
[DEBUG][PID 3286126] src/execve_interceptor.c:48:execve(): Current Config rule count : 3
[DEBUG][PID 3286126] src/logging.c:21:write_log(): Writing exec log for command: /usr/bin/lesspipe
[DEBUG][PID 3286126] src/logging.c:154:duplicate_output_to_log(): Signal handler for SIGINT installed.
[DEBUG][PID 3286126] src/logging.c:236:duplicate_output_to_log(): Child process exited normally
[DEBUG][PID 3286126] src/init_cleanup.c:23:cleanup_shared_memory(): execve_intercept library unloaded.
[DEBUG][PID 3286126] src/init_cleanup.c:25:cleanup_shared_memory(): Log file: ./logs/execve.log
[DEBUG][PID 3286126] src/init_cleanup.c:26:cleanup_shared_memory(): Log out file: ./logs/execve_out.log
[DEBUG][PID 3286126] src/init_cleanup.c:27:cleanup_shared_memory(): Config file: /tmp/exec_hook/config/execve_rules.json
[DEBUG][PID 3286126] src/init_cleanup.c:28:cleanup_shared_memory(): Shared memory ID: 2
[DEBUG][PID 3286126] src/init_cleanup.c:30:cleanup_shared_memory(): Cleaning up shared memory.
/tmp/exec_hook/intercept.so(print_stacktrace+0x23)[0x73d8544b91a5]
/tmp/exec_hook/intercept.so(cleanup_shared_memory+0x210)[0x73d8544b99e0]
/lib64/ld-linux-x86-64.so.2(+0x624e)[0x73d8544c724e]
/lib/x86_64-linux-gnu/libc.so.6(+0x45495)[0x73d85428f495]
/lib/x86_64-linux-gnu/libc.so.6(on_exit+0x0)[0x73d85428f610]
/tmp/exec_hook/intercept.so(duplicate_output_to_log+0x623)[0x73d8544ba34c]
/tmp/exec_hook/intercept.so(execve+0x5e4)[0x73d8544b97a8]
bash(shell_execve+0x36)[0x5e60732eca46]
bash(+0x5b8e7)[0x5e60732f38e7]
bash(+0x4b993)[0x5e60732e3993]
bash(execute_command_internal+0xf1d)[0x5e60732e5b5d]
bash(parse_and_execute+0x6c8)[0x5e60733464e8]
bash(command_substitute+0xa98)[0x5e607330e938]
bash(+0x780a2)[0x5e60733100a2]
bash(+0x81d58)[0x5e6073319d58]
bash(+0x83277)[0x5e607331b277]
bash(+0x87df9)[0x5e607331fdf9]
bash(+0x4bf8f)[0x5e60732e3f8f]
bash(execute_command_internal+0xf1d)[0x5e60732e5b5d]
bash(execute_command+0xc8)[0x5e60732e81b8]
bash(execute_command_internal+0x343b)[0x5e60732e807b]
bash(parse_and_execute+0x6c8)[0x5e60733464e8]
bash(+0xaf1c6)[0x5e60733471c6]
bash(maybe_execute_file+0x2e)[0x5e607334759e]
bash(main+0x1a30)[0x5e60732cadb0]
/lib/x86_64-linux-gnu/libc.so.6(+0x29d90)[0x73d854273d90]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0x80)[0x73d854273e40]
bash(_start+0x25)[0x5e60732caf15]
bash: eval: 行 31: 未预期的记号 "(" 附近有语法错误
bash: eval: 行 31: `[DEBUG][PID 3286127] src/logging.c:125:duplicate_output_to_log(): Child process 3286127: stdout is /dev/pts/7 '
[DEBUG][PID 3286131] src/execve_interceptor.c:29:execve(): Intercepted execve for: /usr/bin/dircolors
[DEBUG][PID 3286131] src/execve_interceptor.c:30:execve(): argv[0] = dircolors
[DEBUG][PID 3286131] src/config.c:114:load_config_if_needed(): Creating shared memory for config data
[DEBUG][PID 3286131] src/config.c:127:load_config_if_needed(): Loading config file for the first time
[DEBUG][PID 3286131] src/config.c:17:load_config_to_shm(): Loading configuration from /tmp/exec_hook/config/execve_rules.json to shared memory
[DEBUG][PID 3286131] src/config.c:89:load_config_to_shm(): Loaded 3 rules to shared memory
[DEBUG][PID 3286131] src/execve_interceptor.c:48:execve(): Current Config rule count : 3
[DEBUG][PID 3286131] src/logging.c:21:write_log(): Writing exec log for command: /usr/bin/dircolors
[DEBUG][PID 3286131] src/logging.c:154:duplicate_output_to_log(): Signal handler for SIGINT installed.
[DEBUG][PID 3286131] src/logging.c:236:duplicate_output_to_log(): Child process exited normally
[DEBUG][PID 3286131] src/init_cleanup.c:23:cleanup_shared_memory(): execve_intercept library unloaded.
[DEBUG][PID 3286131] src/init_cleanup.c:25:cleanup_shared_memory(): Log file: ./logs/execve.log
[DEBUG][PID 3286131] src/init_cleanup.c:26:cleanup_shared_memory(): Log out file: ./logs/execve_out.log
[DEBUG][PID 3286131] src/init_cleanup.c:27:cleanup_shared_memory(): Config file: /tmp/exec_hook/config/execve_rules.json
[DEBUG][PID 3286131] src/init_cleanup.c:28:cleanup_shared_memory(): Shared memory ID: 2
[DEBUG][PID 3286131] src/init_cleanup.c:30:cleanup_shared_memory(): Cleaning up shared memory.
/tmp/exec_hook/intercept.so(print_stacktrace+0x23)[0x73d8544b91a5]
/tmp/exec_hook/intercept.so(cleanup_shared_memory+0x210)[0x73d8544b99e0]
/lib64/ld-linux-x86-64.so.2(+0x624e)[0x73d8544c724e]
/lib/x86_64-linux-gnu/libc.so.6(+0x45495)[0x73d85428f495]
/lib/x86_64-linux-gnu/libc.so.6(on_exit+0x0)[0x73d85428f610]
/tmp/exec_hook/intercept.so(duplicate_output_to_log+0x623)[0x73d8544ba34c]
/tmp/exec_hook/intercept.so(execve+0x5e4)[0x73d8544b97a8]
bash(shell_execve+0x36)[0x5e60732eca46]
bash(+0x5b8e7)[0x5e60732f38e7]
bash(+0x4b993)[0x5e60732e3993]
bash(execute_command_internal+0xf1d)[0x5e60732e5b5d]
bash(parse_and_execute+0x6c8)[0x5e60733464e8]
bash(command_substitute+0xa98)[0x5e607330e938]
bash(+0x780a2)[0x5e60733100a2]
bash(+0x81d58)[0x5e6073319d58]
bash(+0x83277)[0x5e607331b277]
bash(+0x87df9)[0x5e607331fdf9]
bash(+0x4bf8f)[0x5e60732e3f8f]
bash(execute_command_internal+0xf1d)[0x5e60732e5b5d]
bash(execute_command+0xc8)[0x5e60732e81b8]
bash(execute_command_internal+0x343b)[0x5e60732e807b]
bash(execute_command+0xc8)[0x5e60732e81b8]
bash(execute_command_internal+0x1d8e)[0x5e60732e69ce]
bash(execute_command+0xc8)[0x5e60732e81b8]
bash(execute_command_internal+0x1d8e)[0x5e60732e69ce]
bash(execute_command+0xc8)[0x5e60732e81b8]
bash(execute_command_internal+0x1d8e)[0x5e60732e69ce]
bash(execute_command+0xc8)[0x5e60732e81b8]
bash(execute_command_internal+0x1d8e)[0x5e60732e69ce]
bash(execute_command+0xc8)[0x5e60732e81b8]
bash(execute_command_internal+0x108a)[0x5e60732e5cca]
bash(parse_and_execute+0x6c8)[0x5e60733464e8]
bash(+0xaf1c6)[0x5e60733471c6]
bash(maybe_execute_file+0x2e)[0x5e607334759e]
bash(main+0x1a30)[0x5e60732cadb0]
/lib/x86_64-linux-gnu/libc.so.6(+0x29d90)[0x73d854273d90]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0x80)[0x73d854273e40]
bash(_start+0x25)[0x5e60732caf15]
bash: eval: 行 77: 未预期的记号 "(" 附近有语法错误
bash: eval: 行 77: `[DEBUG][PID 3286132] src/logging.c:125:duplicate_output_to_log(): Child process 3286132: stdout is /dev/pts/7 '
[?2004h]0;qcqcqc@qcqcqc-ThinkCentre-M710q-N000: ~/workspace/test_execveqcqcqc@qcqcqc-ThinkCentre-M710q-N000:~/workspace/test_execve$

View File

@ -18,12 +18,23 @@
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
#include "struct.h"
#define CONFIG_FILE "/tmp/exec_hook/config/execve_rules.json"
#define COMMAND_NOT_FOUND "/usr/lib/command-not-found"
#ifdef DEBUG //如果是debug模式在本地目录生成log方便debug
#define LOG_FILE "./logs/execve.log"
#define LOG_OUT_FILE "./logs/execve_out.log"
#else
#define LOG_FILE "/tmp/exec_hook/logs/execve.log"
#define LOG_OUT_FILE "/tmp/exec_hook/logs/execve_out.log"
#define COMMAND_NOT_FOUND "/usr/lib/command-not-found"
#endif
#define ANSI_COLOR_RED "\033[31m"
#define ANSI_COLOR_YELLOW "\033[33m"
@ -37,4 +48,4 @@ extern int shm_id;
extern time_t last_modified_time;
// extern int is_initialized;
#endif // EXEC_HOOK_H
#endif // EXEC_HOOK_H

View File

@ -23,84 +23,110 @@ time_t last_modified_time = 0;
orig_execve_type orig_execve = NULL;
int execve(const char *filename, char *const argv[], char *const envp[]) {
// if (!is_initialized) {
// initialize();
// }
DEBUG_LOG("Intercepted execve for: %s", filename);
DEBUG_LOG("argv[0] = %s", argv[0]);
// if (!is_initialized) {
// initialize();
// }
DEBUG_LOG("Intercepted execve for: %s", filename);
DEBUG_LOG("argv[0] = %s", argv[0]);
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);
}
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);
}
// Load configuration (only if needed)
load_config_if_needed();
// Load configuration (only if needed)
load_config_if_needed();
// Intercept only when execve is called from a shell terminal
if (!is_terminal_shell()) {
DEBUG_LOG("Not a terminal shell, bypassing interception.");
return orig_execve(filename, argv, envp);
}
// Intercept only when execve is called from a shell terminal
if (!is_terminal_shell()) {
DEBUG_LOG("Not a terminal shell, bypassing interception.");
return orig_execve(filename, argv, envp);
}
// Current configuration information
DEBUG_LOG("Current Config rule count : %d", shared_config->rule_count);
// Current configuration information
DEBUG_LOG("Current Config rule count : %d", shared_config->rule_count);
// If shared memory was not successfully loaded, execute directly
if (shared_config == NULL) {
DEBUG_LOG("Shared memory not initialized, bypassing interception.");
return orig_execve(filename, argv, envp);
}
// If shared memory was not successfully loaded, execute directly
if (shared_config == NULL) {
DEBUG_LOG("Shared memory not initialized, bypassing interception.");
return orig_execve(filename, argv, envp);
}
// If the feature is disabled, execute directly
if (!shared_config->enabled) {
DEBUG_LOG("Not enabled.");
return orig_execve(filename, argv, envp);
}
// If the feature is disabled, execute directly
if (!shared_config->enabled) {
DEBUG_LOG("Not enabled.");
return orig_execve(filename, argv, envp);
}
write_log(filename, argv);
write_log(filename, argv);
const char *basename = argv[0];
if (strcmp(filename, COMMAND_NOT_FOUND) == 0 && argv[2]) {
basename = argv[2];
}
const char *basename = argv[0];
if (strcmp(filename, COMMAND_NOT_FOUND) == 0 && argv[2]) {
basename = argv[2];
}
// Special handling for commands executed via shell.posix
// Execute directly, without rule matching and output redirection
if (argv[1] != NULL && strcmp(argv[1], "shell.posix") == 0) {
return orig_execve(filename, argv, envp);
}
// Special handling for commands executed via shell.posix
// Execute directly, without rule matching and output redirection
if (argv[1] != NULL && strcmp(argv[1], "shell.posix") == 0) {
return orig_execve(filename, argv, envp);
}
for (int i = 0; i < shared_config->rule_count; i++) {
if (strcmp(basename, shared_config->rules[i].cmd) == 0 &&
args_match(argv, &shared_config->rules[i])) {
DEBUG_LOG("Rule matched: %s (type: %s)",
shared_config->rules[i].cmd,
shared_config->rules[i].type);
if (strcmp(shared_config->rules[i].type, "warn") == 0) {
printf(ANSI_COLOR_YELLOW "[Warning] %s\n" ANSI_COLOR_RESET,
shared_config->rules[i].msg);
printf("按下 'Y' 继续执行, 或按任意键取消: ");
char input = getchar();
if (input != 'Y' && input != 'y') {
printf("\nExecution cancelled.\n");
exit(EXIT_FAILURE);
// return -1;
}
printf("\nContinuing execution...\n");
} else if (strcmp(shared_config->rules[i].type, "error") == 0) {
printf(ANSI_COLOR_RED "[Error] %s" ANSI_COLOR_RESET "\n",
shared_config->rules[i].msg);
exit(EXIT_FAILURE);
// return -1;
}
break;
}
}
for (int i = 0; i < shared_config->rule_count; i++) {
if (strcmp(basename, shared_config->rules[i].cmd) == 0 &&
args_match(argv, &shared_config->rules[i])) {
DEBUG_LOG("Rule matched: %s (type: %s)",
shared_config->rules[i].cmd,
shared_config->rules[i].type);
if (strcmp(shared_config->rules[i].type, "warn") == 0) {
printf(ANSI_COLOR_YELLOW "[Warning] %s\n" ANSI_COLOR_RESET,
shared_config->rules[i].msg);
printf("按下 'Y' 继续执行, 或按任意键取消: ");
char input = getchar();
if (input != 'Y' && input != 'y') {
printf("\nExecution cancelled.\n");
exit(EXIT_FAILURE);
// return -1;
}
printf("\nContinuing execution...\n");
} else if (strcmp(shared_config->rules[i].type, "error") == 0) {
printf(ANSI_COLOR_RED "[Error] %s" ANSI_COLOR_RESET "\n",
shared_config->rules[i].msg);
exit(EXIT_FAILURE);
// return -1;
}
break;
}
}
// Duplicate stdout and stderr to the log file
duplicate_output_to_log();
// Duplicate stdout and stderr to the log file
duplicate_output_to_log();
return orig_execve(filename, argv, envp);
// 移除LD_PRELOAD
// 计算原环境变量数量
size_t env_count = 0;
while (envp && envp[env_count]) {
env_count++;
}
// 分配新的环境变量数组(最多比原来少一个)
char **new_envp = malloc((env_count) * sizeof(char *));
if (!new_envp) {
perror("malloc");
return -1;
}
// 拷贝旧的 envp跳过 LD_PRELOAD
size_t i = 0;
for (size_t j = 0; j < env_count; j++) {
if (strncmp(envp[j], "LD_PRELOAD=", 11) != 0) {
new_envp[i++] = envp[j];
}
}
// 确保新数组末尾是 NULL
new_envp[i] = NULL;
return orig_execve(filename, argv, new_envp);
}

159
src/hook_write.c Normal file
View File

@ -0,0 +1,159 @@
#define _GNU_SOURCE
#include <dlfcn.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/uio.h>
#include "debug.h"
#include "exec_hook.h"
static int log_fd = -1;
// 原始函数指针
static ssize_t (*original_write)(int, const void *, size_t) = NULL;
static ssize_t (*orig_writev)(int, const struct iovec *, int) = NULL;
static size_t (*orig_fwrite)(const void *, size_t, size_t, FILE *) = NULL;
static int (*orig_fflush)(FILE *) = NULL;
static int (*orig_puts)(const char *) = NULL;
static int (*orig_printf)(const char *, ...) = NULL;
static int (*orig_vprintf)(const char *, va_list) = NULL;
static int (*orig_vfprintf)(FILE *, const char *, va_list) = NULL;
void init_hook() {
DEBUG_LOG("Initializing write hooks...");
original_write = dlsym(RTLD_NEXT, "write");
orig_writev = dlsym(RTLD_NEXT, "writev");
orig_fwrite = dlsym(RTLD_NEXT, "fwrite");
orig_fflush = dlsym(RTLD_NEXT, "fflush");
orig_puts = dlsym(RTLD_NEXT, "puts");
orig_printf = dlsym(RTLD_NEXT, "printf");
orig_vprintf = dlsym(RTLD_NEXT, "vprintf");
orig_vfprintf = dlsym(RTLD_NEXT, "vfprintf");
log_fd = open(LOG_OUT_FILE, O_WRONLY | O_CREAT | O_APPEND, 0644);
if (log_fd == -1) {
perror("Failed to open log file");
}
}
ssize_t write(int fd, const void *buf, size_t count) {
DEBUG_LOG("Intercepted write to fd %d", fd);
ssize_t result = original_write(fd, buf, count);
if (log_fd != -1 && (fd == STDOUT_FILENO || fd == STDERR_FILENO) && fd != log_fd) {
original_write(log_fd, buf, count);
}
return result;
}
ssize_t writev(int fd, const struct iovec *iov, int iovcnt) {
DEBUG_LOG("Intercepted writev to fd %d", fd);
ssize_t result = orig_writev(fd, iov, iovcnt);
if (log_fd != -1 && (fd == STDOUT_FILENO || fd == STDERR_FILENO) && fd != log_fd) {
for (int i = 0; i < iovcnt; ++i) {
write(log_fd, iov[i].iov_base, iov[i].iov_len);
}
}
return result;
}
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) {
DEBUG_LOG("Intercepted fwrite to stream %p", stream);
size_t result = orig_fwrite(ptr, size, nmemb, stream);
int fd = fileno(stream);
if (log_fd != -1 && (fd == STDOUT_FILENO || fd == STDERR_FILENO)) {
write(log_fd, ptr, size * nmemb);
}
return result;
}
int puts(const char *s) {
DEBUG_LOG("Intercepted puts: %s", s);
int result = orig_puts(s);
if (log_fd != -1) {
write(log_fd, s, strlen(s));
write(log_fd, "\n", 1);
}
return result;
}
int printf(const char *format, ...) {
DEBUG_LOG("Intercepted printf: %s", format);
va_list args;
va_start(args, format);
int result = orig_vprintf(format, args);
va_end(args);
// 再次获取 args 写入日志
va_start(args, format);
if (log_fd != -1) {
char buffer[4096];
int len = vsnprintf(buffer, sizeof(buffer), format, args);
if (len > 0) {
write(log_fd, buffer, len);
}
}
va_end(args);
return result;
}
int vprintf(const char *format, va_list args) {
DEBUG_LOG("Intercepted vprintf: %s", format);
int result = orig_vprintf(format, args);
if (log_fd != -1) {
char buffer[4096];
va_list args_copy;
va_copy(args_copy, args);
int len = vsnprintf(buffer, sizeof(buffer), format, args_copy);
va_end(args_copy);
if (len > 0) {
write(log_fd, buffer, len);
}
}
return result;
}
int vfprintf(FILE *stream, const char *format, va_list args) {
DEBUG_LOG("Intercepted vfprintf to stream %p: %s", stream, format);
int result = orig_vfprintf(stream, format, args);
int fd = fileno(stream);
if (log_fd != -1 && (fd == STDOUT_FILENO || fd == STDERR_FILENO)) {
va_list args_copy;
va_copy(args_copy, args);
char buffer[4096];
int len = vsnprintf(buffer, sizeof(buffer), format, args_copy);
va_end(args_copy);
if (len > 0) {
write(log_fd, buffer, len);
}
}
return result;
}
int fflush(FILE *stream) {
DEBUG_LOG("Intercepted fflush to stream %p", stream);
return orig_fflush(stream);
}
__attribute__((constructor)) void init() {
DEBUG_LOG("Write hook library loaded.");
init_hook();
}
__attribute__((destructor)) void cleanup() {
if (log_fd != -1) {
close(log_fd);
log_fd = -1;
}
DEBUG_LOG("Write hook library unloaded.");
}

View File

@ -35,9 +35,9 @@ __attribute__((destructor)) void cleanup_shared_memory() {
shared_config = NULL;
}
#ifdef DEBUG
print_stacktrace();
// print_stacktrace();
#endif
// Note: We don't delete the shared memory segment here, as it might be
// used by other processes. A separate mechanism would be needed to manage
// the lifecycle of the shared memory if deletion is required.
}
}

View File

@ -1,100 +1,262 @@
#include "logging.h"
#include "exec_hook.h"
#include "debug.h"
#include <fcntl.h>
#include <libgen.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <sys/select.h>
#include <sys/socket.h> // shutdown()
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#include "debug.h"
#include "exec_hook.h"
// Write log
void write_log(const char *filename, char *const argv[]) {
DEBUG_LOG("Writing exec log for command: %s", filename);
time_t now;
time(&now);
DEBUG_LOG("Writing exec log for command: %s", filename);
time_t now;
time(&now);
FILE *log = fopen(LOG_FILE, "a");
if (!log) return;
// Get the directory part of the log file path
char *log_file_path =
strdup(LOG_FILE); // Duplicate string as dirname might modify it
if (!log_file_path) {
perror("strdup failed");
return;
}
char *log_dir = dirname(log_file_path);
if (!log_dir) {
perror("dirname failed");
free(log_file_path);
return;
}
fprintf(log, "[%s] Command: %s\n", ctime(&now), filename);
// Check if the directory exists and is writable
if (access(log_dir, W_OK) != 0) {
if (errno == ENOENT) {
DEBUG_LOG("Log directory '%s' does not exist, creating it...",
log_dir);
// Create the directory with appropriate permissions (e.g., 0755)
if (mkdir(log_dir, 0755) == -1) {
perror("mkdir failed");
free(log_file_path);
return;
}
DEBUG_LOG("Log directory '%s' created successfully.", log_dir);
} else {
perror("access failed for log directory");
free(log_file_path);
return;
}
}
free(log_file_path); // Free the duplicated string
for (int i = 0; argv[i]; i++) {
fprintf(log, "arg[%d]: %s\n", i, argv[i]);
}
FILE *log = fopen(LOG_FILE, "a");
if (!log) {
perror("fopen failed for log file");
return;
}
fclose(log);
fprintf(log, "[%s] Command: %s\n", ctime(&now), filename);
for (int i = 0; argv[i]; i++) {
fprintf(log, "arg[%d]: %s\n", i, argv[i]);
}
fclose(log);
}
// Duplicate stdout/stderr to log file, while preserving terminal colors
// 全局变量记录子进程 PID
static pid_t g_child_pid = -1;
// 信号处理器:接收到 SIGINTCtrl+C将其转发给子进程
void handle_sigint(int sig) {
if (g_child_pid > 0) {
kill(g_child_pid, sig); // 向子进程发送 SIGINT
}
DEBUG_LOG("Received SIGINT, forwarded to child process %d", g_child_pid);
exit(EXIT_FAILURE);
// return -1;
}
/*
* hook execve()
* forkpty() fork
* execve()
* STDIN STDOUT
*/
void duplicate_output_to_log() {
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 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 master_fd;
// forkpty 创建伪终端并 fork 子进程
pid_t pid = forkpty(&master_fd, NULL, NULL, NULL);
if (pid < 0) {
perror("forkpty failed");
close(log_fd);
return;
}
int master_fd, slave_fd;
if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) == -1) {
perror("openpty failed");
close(log_fd);
return;
}
if (pid == 0) {
// 关闭 ECHO避免重复显示输入字符
struct termios ts;
if (tcgetattr(STDIN_FILENO, &ts) == 0) {
ts.c_lflag &= ~ECHO;
tcsetattr(STDIN_FILENO, TCSANOW, &ts);
}
pid_t pid = fork();
if (pid == -1) {
perror("fork failed");
close(log_fd);
close(master_fd);
close(slave_fd);
return;
}
return; // execve 之后替换为目标程序
}
if (pid == 0) { // Child process
close(master_fd);
// // 把父进程的输出改到/dev/null
// int dev_null_fd = open("/dev/null", O_WRONLY);
// if (dev_null_fd >= 0) {
// dup2(dev_null_fd, STDOUT_FILENO);
// dup2(dev_null_fd, STDERR_FILENO);
// if (dev_null_fd > STDERR_FILENO) close(dev_null_fd);
// }
// Connect slave_fd to standard input/output/error
dup2(slave_fd, STDIN_FILENO);
dup2(slave_fd, STDOUT_FILENO);
dup2(slave_fd, STDERR_FILENO);
close(slave_fd);
// 父进程
g_child_pid = pid;
// Child process does not output, only keeps the environment for execve
return; // Will be replaced by the original execve call
}
// 安装 SIGINT 处理器
struct sigaction sa;
sa.sa_handler = handle_sigint;
sa.sa_flags = 0;
sigemptyset(&sa.sa_mask);
if (sigaction(SIGINT, &sa, NULL) < 0) {
perror("sigaction failed");
close(log_fd);
close(master_fd);
return;
}
DEBUG_LOG("Signal handler for SIGINT installed.");
// Parent process (controller): read from master_fd and write to stdout + log
close(slave_fd);
// 父进程:负责 I/O 转发(日志记录与输出)
char buffer[1024];
ssize_t n;
fd_set read_fds;
int stdin_eof = 0; // 标识是否检测到 STDIN EOF
int status;
int max_fd = (master_fd > STDIN_FILENO) ? master_fd : STDIN_FILENO;
// Ignore child process exit signal
signal(SIGCHLD, SIG_IGN);
while (1) {
FD_ZERO(&read_fds);
FD_SET(master_fd, &read_fds);
if (!stdin_eof) {
FD_SET(STDIN_FILENO, &read_fds);
} else {
DEBUG_LOG("STDIN EOF detected, not monitoring STDIN");
}
char buffer[1024];
ssize_t n;
int has_error = 0;
int ret = select(max_fd + 1, &read_fds, NULL, NULL, NULL);
if (ret < 0) {
if (errno == EINTR) continue;
perror("select failed");
break;
}
while ((n = read(master_fd, buffer, sizeof(buffer))) > 0) {
// Check for errors
if (memmem(buffer, n, "error", 5) || memmem(buffer, n, "Error", 5) ||
memmem(buffer, n, "ERROR", 5)) {
has_error = 1;
}
// 若有用户输入,则转发到伪终端
if (!stdin_eof && FD_ISSET(STDIN_FILENO, &read_fds)) {
n = read(STDIN_FILENO, buffer, sizeof(buffer));
if (n > 0) {
if (write(master_fd, buffer, n) < 0) {
perror("Failed to write user input to pty");
}
} else if (n == 0) {
// 检测到 STDIN EOF关闭写端后续不再转发用户输入
stdin_eof = 1;
shutdown(master_fd, SHUT_WR);
}
}
// Write to log
if (write(log_fd, buffer, n) == -1) {
perror("Failed to write to log file");
}
}
// 若伪终端有输出,则转发到 STDOUT 并写入日志文件
if (FD_ISSET(master_fd, &read_fds)) {
// n = read(master_fd, buffer, sizeof(buffer));
// if (n > 0) {
// if (write(STDOUT_FILENO, buffer, n) < 0) {
// perror("Failed to write to stdout");
// }
// if (write(log_fd, buffer, n) < 0) {
// perror("Failed to write to log file");
// }
// } else if (n == 0) {
char *line_start = buffer;
ssize_t n = read(master_fd, buffer, sizeof(buffer) - 1);
if (n > 0) {
buffer[n] = '\0'; // 确保字符串结束
if (has_error) {
printf("\n检测到命令执行出错,已经上报北冥论坛~ \n");
fflush(stdout);
}
// 按行处理输出
while (line_start < buffer + n) {
char *line_end = strchr(line_start, '\n');
if (!line_end) {
line_end = buffer + n; // 最后一行可能没有换行符
} else {
line_end++; // 包含换行符
}
close(master_fd);
close(log_fd);
size_t line_len = line_end - line_start;
// 写入标准输出
if (write(STDOUT_FILENO, line_start, line_len) < 0) {
perror("Failed to write to stdout");
}
// 写入日志文件
if (write(log_fd, line_start, line_len) < 0) {
perror("Failed to write to log file");
}
line_start = line_end;
}
} else if (n == 0) {
/*
* 0
* waitpid(pid, , WNOHANG) 退
* bash 退
*/
pid_t ret_pid = waitpid(pid, &status, WNOHANG);
if (ret_pid == 0) {
continue;
} else {
break;
}
} else if (n < 0) {
if (errno == EIO) {
// 伪终端关闭,退出循环
break;
} else {
perror("Failed to read from pty");
break;
}
}
}
} // end while 循环
// 等待子进程完全退出,并报告异常状态(如果有)
if (waitpid(pid, &status, 0) < 0) {
perror("waitpid failed");
} else {
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
int status = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
DEBUG_LOG("Child process exited abnormally (status: %d)", status);
} else {
DEBUG_LOG("Child process exited normally");
}
}
close(master_fd);
close(log_fd);
exit(EXIT_SUCCESS);
}

BIN
tests/a.out Executable file

Binary file not shown.

BIN
tests/forkpty Executable file

Binary file not shown.

129
tests/forkpty.c Normal file
View File

@ -0,0 +1,129 @@
#define _GNU_SOURCE
#include <errno.h>
#include <fcntl.h>
#include <pty.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/prctl.h>
#include <sys/select.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
volatile sig_atomic_t terminate = 0;
void sig_handler(int sig) {
terminate = 1;
}
void createDup() {
int master_fd;
pid_t pid;
signal(SIGINT, sig_handler);
signal(SIGCHLD, sig_handler);
pid = forkpty(&master_fd, NULL, NULL, NULL);
if (pid < 0) {
perror("forkpty");
exit(EXIT_FAILURE);
}
if (pid == 0) {
// 子进程设置:如果父进程退出,自动收到 SIGTERM
prctl(PR_SET_PDEATHSIG, SIGTERM);
return;
} else {
char buffer[1024];
ssize_t num_read;
int output_fd = open("output.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (output_fd < 0) {
perror("open output.txt");
exit(EXIT_FAILURE);
}
fd_set read_fds;
int max_fd = (STDIN_FILENO > master_fd ? STDIN_FILENO : master_fd) + 1;
while (!terminate) {
FD_ZERO(&read_fds);
FD_SET(STDIN_FILENO, &read_fds);
FD_SET(master_fd, &read_fds);
int ret = select(max_fd, &read_fds, NULL, NULL, NULL);
if (ret < 0 && errno != EINTR) {
perror("select");
break;
}
if (terminate) break;
// 用户输入
if (FD_ISSET(STDIN_FILENO, &read_fds)) {
num_read = read(STDIN_FILENO, buffer, sizeof(buffer));
if (num_read <= 0) break;
write(master_fd, buffer, num_read);
}
// 子进程输出
if (FD_ISSET(master_fd, &read_fds)) {
num_read = read(master_fd, buffer, sizeof(buffer));
if (num_read <= 0) break;
write(STDOUT_FILENO, buffer, num_read);
write(output_fd, buffer, num_read);
}
}
kill(pid, SIGTERM); // 通知子进程退出
waitpid(pid, NULL, 0);
close(output_fd);
close(master_fd);
exit(EXIT_SUCCESS);
}
}
int main() {
createDup();
signal(SIGINT, sig_handler);
pid_t pid = fork();
if (pid < 0) {
perror("fork");
exit(EXIT_FAILURE);
} else if (pid == 0) {
// 子进程确保在父进程退出时自动结束
prctl(PR_SET_PDEATHSIG, SIGTERM);
printf("This is the child process.\n");
fflush(stdout);
} else {
printf("This is the parent process.\n");
fflush(stdout);
}
// 测试输入
char input[100];
printf("Enter something: ");
fflush(stdout);
if (fgets(input, sizeof(input), stdin) == NULL) exit(0);
printf("You entered: %s", input);
fflush(stdout);
// 测试输出
printf("This is a test output.\n");
fflush(stdout);
// 测试错误输出
fprintf(stderr, "This is a test error output.\n");
fflush(stderr);
char *const argv[] = {"bash", NULL, NULL};
extern char **environ;
execve("/usr/bin/bash", argv, environ);
return 0;
}

12
tests/output.txt Normal file
View File

@ -0,0 +1,12 @@
This is the parent process.
Enter something: This is the child process.
Enter something: 123
You entered: 123
This is a test output.
This is a test error output.
[?2004h]0;qcqcqc@qcqcqc-ThinkCentre-M710q-N000: ~/workspace/test_execve/testsqcqcqc@qcqcqc-ThinkCentre-M710q-N000:~/workspace/test_execve/tests$ You entered: ll
This is a test output.
This is a test error output.
[?2004h]0;qcqcqc@qcqcqc-ThinkCentre-M710q-N000: ~/workspace/test_execve/testsqcqcqc@qcqcqc-ThinkCentre-M710q-N000:~/workspace/test_execve/tests$ [?2004l
exit
[?2004l

18
tests/write.c Normal file
View File

@ -0,0 +1,18 @@
#include <stdio.h>
#include <unistd.h>
int main() {
const char *msg = "Hello, world!\n";
// 使用 write 系统调用向标准输出(文件描述符 1写入数据
ssize_t result = write(1, msg, 14);
if (result == -1) {
perror("write failed");
return 1;
}
printf("Successfully wrote %zd bytes.\n", result);
return 0;
}