main.cpp
g++ -Wall -fPIC -shared -o net_ip_hook.so main.cpp -ldl sudo gedit /etc/environment #LD_LIBRARY_PATH #LD_PRELOAD LD_PRELOAD="/home/dongl/code/safe_test/hook.so" #LD_PRELOAD="/home/dongl/code/safe_test/net_ip_hook.so"
This commit is contained in:
commit
64452a7aa7
7
CMakeLists.txt
Normal file
7
CMakeLists.txt
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.25)
|
||||||
|
project(ko_open)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
|
||||||
|
#add_executable(ko_open main.cpp)
|
||||||
|
add_executable(ko_open hook.bin.cpp)
|
273
hook.bin.cpp
Normal file
273
hook.bin.cpp
Normal file
@ -0,0 +1,273 @@
|
|||||||
|
//
|
||||||
|
// Created by dongl on 23-7-10.
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <cstring>
|
||||||
|
#include <string>
|
||||||
|
#include <set>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#define ACCEPT 9999
|
||||||
|
#define CONNECT 19999
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 定义指向原始open函数的函数指针
|
||||||
|
typedef int (*file_open_func_t)(const char *pathname, int flags, ...);
|
||||||
|
static file_open_func_t original_file_open = nullptr;
|
||||||
|
static file_open_func_t file_open = nullptr;
|
||||||
|
//read
|
||||||
|
typedef ssize_t (*file_read_func_t)(int fd, void *buf, size_t nbytes);
|
||||||
|
static file_read_func_t original_file_read = nullptr;
|
||||||
|
static file_read_func_t file_read = nullptr;
|
||||||
|
// connect
|
||||||
|
typedef int (*ip_connect_fun_t)(int, const struct sockaddr *, socklen_t);
|
||||||
|
static ip_connect_fun_t original_file_connect = nullptr;
|
||||||
|
static ip_connect_fun_t file_connect = nullptr;
|
||||||
|
// accept
|
||||||
|
typedef int (*ip_accept_fun_t)(int, struct sockaddr *, socklen_t *);
|
||||||
|
static ip_accept_fun_t original_file_accept = nullptr;
|
||||||
|
static ip_accept_fun_t file_accept = nullptr;
|
||||||
|
|
||||||
|
|
||||||
|
// 定义原始的do_sys_open()函数指针
|
||||||
|
//static long (*real_do_sys_open)(int dfd, const char __user *filename, int flags, umode_t mode) = nullptr;
|
||||||
|
|
||||||
|
// 定义日志文件路径和配置文件路径的环境变量
|
||||||
|
const char *LOG_FILE_PATH = "/home/dongl/code/safe_test/log";
|
||||||
|
const char *CONFIG_FILE_PATH = "/home/dongl/code/safe_test/config.txt";
|
||||||
|
const char *LOG_NET_IP_PATH = "/home/dongl/code/safe_test/net-log";
|
||||||
|
const char *CONFIG_NET_IP_PATH = "/home/dongl/code/safe_test/net-config.txt";
|
||||||
|
|
||||||
|
// 将时间戳转换为字符串
|
||||||
|
std::string Time_t2String(time_t t) {
|
||||||
|
char tmp[64] = {0};
|
||||||
|
strftime(tmp, sizeof(tmp), "%Y-%m-%d %H:%M:%S", localtime(&t));
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取当前进程的可执行文件路径和名称
|
||||||
|
size_t get_executable_path(char *processdir, char *processname, size_t len) {
|
||||||
|
char *path_end;
|
||||||
|
if (readlink("/proc/self/exe", processdir, len) <= 0)
|
||||||
|
return -1;
|
||||||
|
path_end = strrchr(processdir, '/');
|
||||||
|
if (path_end == nullptr)
|
||||||
|
return -1;
|
||||||
|
++path_end;
|
||||||
|
strcpy(processname, path_end);
|
||||||
|
*path_end = '\0';
|
||||||
|
return (size_t) (path_end - processdir);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 读取配置文件并填充文件和进程集合
|
||||||
|
void read_config_file(std::set<std::string>& file_set, std::set<std::string>& process_set, const char* config_name) {
|
||||||
|
// 打开配置文件
|
||||||
|
int config_fd = original_file_open(config_name, O_RDONLY);
|
||||||
|
if (config_fd < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// 读取配置文件
|
||||||
|
char buff[4096];
|
||||||
|
std::string data;
|
||||||
|
bool state = true;
|
||||||
|
while (original_file_read(config_fd, buff, sizeof(buff)) > 0) {
|
||||||
|
for (const auto &item: buff) {
|
||||||
|
if (item != '\n') {
|
||||||
|
data.push_back(item);
|
||||||
|
} else if (item == '\n') {
|
||||||
|
// 检查行是文件部分还是进程部分
|
||||||
|
std::string temp = config_name == CONFIG_FILE_PATH ? "[safe_file]" : "[black_ip]";
|
||||||
|
if (data == temp) {
|
||||||
|
state = true;
|
||||||
|
data.clear();
|
||||||
|
continue;
|
||||||
|
} else if (data == "[safe_process]") {
|
||||||
|
state = false;
|
||||||
|
data.clear();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将文件或进程添加到相应的集合中
|
||||||
|
if (state) {
|
||||||
|
file_set.insert(data);
|
||||||
|
data.clear();
|
||||||
|
} else {
|
||||||
|
process_set.insert(data);
|
||||||
|
data.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭配置文件
|
||||||
|
close(config_fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将文件访问日志写入日志文件
|
||||||
|
void write_log(const std::string &pathname, int mode, const std::string &result, const char* log_name) {
|
||||||
|
char run_path[40960] = {0};
|
||||||
|
char process_name[10240] = {0};
|
||||||
|
get_executable_path(run_path, process_name, sizeof(run_path));
|
||||||
|
|
||||||
|
std::string access_mode;
|
||||||
|
if (mode == O_RDONLY)
|
||||||
|
access_mode = "读取";
|
||||||
|
else if (mode == ACCEPT)
|
||||||
|
access_mode = "ACCEPT";
|
||||||
|
else if (mode == CONNECT)
|
||||||
|
access_mode = "CONNECT";
|
||||||
|
else if (mode == O_WRONLY)
|
||||||
|
access_mode = "写入";
|
||||||
|
else if (mode == O_RDWR)
|
||||||
|
access_mode = "读写";
|
||||||
|
else if (mode == (O_WRONLY | O_APPEND))
|
||||||
|
access_mode = "追加";
|
||||||
|
|
||||||
|
std::string log = "[" + Time_t2String(time(nullptr)) + "] " +
|
||||||
|
"<" + pathname + "> " + access_mode + " {" + process_name + ":" + run_path + "} " + result + "\n";
|
||||||
|
int log_fd = original_file_open(log_name, O_WRONLY | O_CREAT | O_APPEND, 0644);
|
||||||
|
if (log_fd > 0) {
|
||||||
|
write(log_fd, log.c_str(), log.size());
|
||||||
|
close(log_fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
ssize_t read(int fd, void *buf, size_t nbytes) {
|
||||||
|
std::set<std::string> file_set;
|
||||||
|
std::set<std::string> process_set;
|
||||||
|
read_config_file(file_set, process_set, CONFIG_FILE_PATH);
|
||||||
|
// 查进程名 及 运行路径
|
||||||
|
char run_path[4096] = {0};
|
||||||
|
char process_name[1024] = {0};
|
||||||
|
get_executable_path(run_path, process_name, sizeof(run_path));
|
||||||
|
// 根据fd取文件名
|
||||||
|
char file_name[4096] = {'\0'};
|
||||||
|
char file_path[4096] = {'\0'};
|
||||||
|
snprintf(file_name, sizeof(file_name), "/proc/%d/fd/%d", getpid(), fd);
|
||||||
|
ssize_t ret = readlink(file_name, file_path, sizeof(file_path) - 1);
|
||||||
|
if (ret == -1) {
|
||||||
|
return original_file_read(fd, buf, nbytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查
|
||||||
|
auto safe_file = file_set.find(file_path);
|
||||||
|
auto safe_process = process_set.find(process_name);
|
||||||
|
|
||||||
|
// 校验
|
||||||
|
if (safe_file != file_set.end()) {
|
||||||
|
if (safe_process != process_set.end()) {
|
||||||
|
write_log(file_path, O_RDONLY, "正常访问", LOG_FILE_PATH);
|
||||||
|
} else {
|
||||||
|
write_log(file_path, O_RDONLY, "拒绝访问", LOG_FILE_PATH);
|
||||||
|
errno = EACCES;
|
||||||
|
return original_file_read(fd, buf, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return original_file_read(fd, buf, nbytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断接入的网络是否为过滤IP,如果是则提前返回
|
||||||
|
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
|
||||||
|
// 获取链接ip
|
||||||
|
char ip[128];
|
||||||
|
memset(ip, 0, sizeof(ip)); // ip地址
|
||||||
|
int port = -1; // 端口号
|
||||||
|
if (AF_INET == addr->sa_family) {
|
||||||
|
auto *sa4 = (struct sockaddr_in *) addr;
|
||||||
|
inet_ntop(AF_INET, (void *) (struct sockaddr *) &sa4->sin_addr, ip, sizeof(ip));
|
||||||
|
port = ntohs(sa4->sin_port);
|
||||||
|
printf("\nAF_INET IP===%s:%d\n", ip, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查进程名 及 运行路径
|
||||||
|
char run_path[4096] = {0};
|
||||||
|
char process_name[1024] = {0};
|
||||||
|
get_executable_path(run_path, process_name, sizeof(run_path));
|
||||||
|
|
||||||
|
// 获取黑名单ip
|
||||||
|
std::set<std::string> ip_set;
|
||||||
|
std::set<std::string> process_set;
|
||||||
|
read_config_file(ip_set, process_set, CONFIG_NET_IP_PATH);
|
||||||
|
auto black_ip = ip_set.find(ip);
|
||||||
|
auto safe_process = process_set.find(process_name);
|
||||||
|
|
||||||
|
// 比较IP 是黑名单ip
|
||||||
|
if (black_ip != ip_set.end()) {
|
||||||
|
// log ip
|
||||||
|
std::string temp;
|
||||||
|
temp.append(ip);
|
||||||
|
temp.append(":"+std::to_string(port)+"<"+std::to_string(sockfd)+">");
|
||||||
|
|
||||||
|
if (safe_process != process_set.end()) {
|
||||||
|
write_log(temp, CONNECT, "允许访问", LOG_NET_IP_PATH);
|
||||||
|
return original_file_connect(sockfd, addr, addrlen);
|
||||||
|
} else {
|
||||||
|
write_log(temp, CONNECT, "拒绝访问", LOG_NET_IP_PATH);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return original_file_connect(sockfd, addr, addrlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) {
|
||||||
|
// 获取链接ip
|
||||||
|
char ip[128];
|
||||||
|
memset(ip, 0, sizeof(ip)); // ip地址
|
||||||
|
int port = -1; // 端口号
|
||||||
|
if (AF_INET == addr->sa_family) {
|
||||||
|
auto *sa4 = (struct sockaddr_in *) addr;
|
||||||
|
inet_ntop(AF_INET, (void *) (struct sockaddr *) &sa4->sin_addr, ip, sizeof(ip));
|
||||||
|
port = ntohs(sa4->sin_port);
|
||||||
|
printf("\nAF_INET IP===%s:%d\n", ip, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查进程名 及 运行路径
|
||||||
|
char run_path[4096] = {0};
|
||||||
|
char process_name[1024] = {0};
|
||||||
|
get_executable_path(run_path, process_name, sizeof(run_path));
|
||||||
|
|
||||||
|
// 获取黑名单ip
|
||||||
|
std::set<std::string> ip_set;
|
||||||
|
std::set<std::string> process_set;
|
||||||
|
read_config_file(ip_set, process_set, CONFIG_NET_IP_PATH);
|
||||||
|
auto black_ip = ip_set.find(ip);
|
||||||
|
auto safe_process = process_set.find(process_name);
|
||||||
|
|
||||||
|
// log ip
|
||||||
|
std::string temp;
|
||||||
|
temp.append(ip);
|
||||||
|
temp.append(":"+std::to_string(port)+"<"+std::to_string(sockfd)+">");
|
||||||
|
|
||||||
|
// 比较IP 是黑名单ip
|
||||||
|
if (black_ip != ip_set.end()) {
|
||||||
|
if (safe_process != process_set.end()) {
|
||||||
|
write_log(temp, ACCEPT, "允许访问",LOG_NET_IP_PATH);
|
||||||
|
return original_file_accept(sockfd, addr, addrlen);
|
||||||
|
} else {
|
||||||
|
write_log(temp, ACCEPT, "拒绝访问", LOG_NET_IP_PATH);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 放行
|
||||||
|
return original_file_accept(sockfd, addr, addrlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 初始化函数,获取原始文件访问函数的地址并替换为拦截函数
|
||||||
|
int main() {
|
||||||
|
original_file_open = (file_open_func_t) dlsym(RTLD_NEXT, "open");
|
||||||
|
original_file_read = (file_read_func_t) dlsym(RTLD_NEXT, "read");
|
||||||
|
original_file_connect = (ip_connect_fun_t) dlsym(RTLD_NEXT, "connect");
|
||||||
|
original_file_accept = (ip_accept_fun_t) dlsym(RTLD_NEXT, "accept");
|
||||||
|
}
|
270
main.cpp
Normal file
270
main.cpp
Normal file
@ -0,0 +1,270 @@
|
|||||||
|
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <cstring>
|
||||||
|
#include <string>
|
||||||
|
#include <set>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#define ACCEPT 9999
|
||||||
|
#define CONNECT 19999
|
||||||
|
|
||||||
|
|
||||||
|
// 定义指向原始文件访问函数的函数指针
|
||||||
|
typedef int (*file_access_func_t)(const char *pathname, int mode, ...);
|
||||||
|
static file_access_func_t original_file_access = nullptr;
|
||||||
|
// 定义指向原始open函数的函数指针
|
||||||
|
typedef int (*file_open_func_t)(const char *pathname, int flags, ...);
|
||||||
|
static file_open_func_t original_file_open = nullptr;
|
||||||
|
// 定义指向原始creat函数的函数指针
|
||||||
|
typedef int (*file_creat_func_t)(const char *pathname, mode_t mode);
|
||||||
|
static file_creat_func_t original_file_creat = nullptr;
|
||||||
|
//read
|
||||||
|
typedef ssize_t (*file_read_func_t)(int fd, void *buf, size_t nbytes);
|
||||||
|
static file_read_func_t original_file_read = nullptr;
|
||||||
|
// connect
|
||||||
|
typedef int (*ip_connect_fun_t)(int, const struct sockaddr *, socklen_t);
|
||||||
|
static ip_connect_fun_t original_file_connect = nullptr;
|
||||||
|
// accept
|
||||||
|
typedef int (*ip_accept_fun_t)(int, struct sockaddr *, socklen_t *);
|
||||||
|
static ip_accept_fun_t original_file_accept = nullptr;
|
||||||
|
|
||||||
|
|
||||||
|
// 定义原始的do_sys_open()函数指针
|
||||||
|
//static long (*real_do_sys_open)(int dfd, const char __user *filename, int flags, umode_t mode) = nullptr;
|
||||||
|
|
||||||
|
// 定义日志文件路径和配置文件路径的环境变量
|
||||||
|
const char *LOG_FILE_PATH = "/home/dongl/code/safe_test/log";
|
||||||
|
const char *CONFIG_FILE_PATH = "/home/dongl/code/safe_test/config.txt";
|
||||||
|
const char *LOG_NET_IP_PATH = "/home/dongl/code/safe_test/net-log";
|
||||||
|
const char *CONFIG_NET_IP_PATH = "/home/dongl/code/safe_test/net-config.txt";
|
||||||
|
|
||||||
|
// 将时间戳转换为字符串
|
||||||
|
std::string Time_t2String(time_t t) {
|
||||||
|
char tmp[64] = {0};
|
||||||
|
strftime(tmp, sizeof(tmp), "%Y-%m-%d %H:%M:%S", localtime(&t));
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取当前进程的可执行文件路径和名称
|
||||||
|
size_t get_executable_path(char *processdir, char *processname, size_t len) {
|
||||||
|
char *path_end;
|
||||||
|
if (readlink("/proc/self/exe", processdir, len) <= 0)
|
||||||
|
return -1;
|
||||||
|
path_end = strrchr(processdir, '/');
|
||||||
|
if (path_end == nullptr)
|
||||||
|
return -1;
|
||||||
|
++path_end;
|
||||||
|
strcpy(processname, path_end);
|
||||||
|
*path_end = '\0';
|
||||||
|
return (size_t) (path_end - processdir);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 读取配置文件并填充文件和进程集合
|
||||||
|
void read_config_file(std::set<std::string>& file_set, std::set<std::string>& process_set, const char* config_name) {
|
||||||
|
// 打开配置文件
|
||||||
|
int config_fd = original_file_open(config_name, O_RDONLY);
|
||||||
|
if (config_fd < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// 读取配置文件
|
||||||
|
char buff[4096];
|
||||||
|
std::string data;
|
||||||
|
bool state = true;
|
||||||
|
while (original_file_read(config_fd, buff, sizeof(buff)) > 0) {
|
||||||
|
for (const auto &item: buff) {
|
||||||
|
if (item != '\n') {
|
||||||
|
data.push_back(item);
|
||||||
|
} else if (item == '\n') {
|
||||||
|
// 检查行是文件部分还是进程部分
|
||||||
|
std::string temp = config_name == CONFIG_FILE_PATH ? "[safe_file]" : "[black_ip]";
|
||||||
|
if (data == temp) {
|
||||||
|
state = true;
|
||||||
|
data.clear();
|
||||||
|
continue;
|
||||||
|
} else if (data == "[safe_process]") {
|
||||||
|
state = false;
|
||||||
|
data.clear();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将文件或进程添加到相应的集合中
|
||||||
|
if (state) {
|
||||||
|
file_set.insert(data);
|
||||||
|
data.clear();
|
||||||
|
} else {
|
||||||
|
process_set.insert(data);
|
||||||
|
data.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭配置文件
|
||||||
|
close(config_fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将文件访问日志写入日志文件
|
||||||
|
void write_log(const std::string &pathname, int mode, const std::string &result, const char* log_name) {
|
||||||
|
char run_path[40960] = {0};
|
||||||
|
char process_name[10240] = {0};
|
||||||
|
get_executable_path(run_path, process_name, sizeof(run_path));
|
||||||
|
|
||||||
|
std::string access_mode;
|
||||||
|
if (mode == O_RDONLY)
|
||||||
|
access_mode = "读取";
|
||||||
|
else if (mode == ACCEPT)
|
||||||
|
access_mode = "ACCEPT";
|
||||||
|
else if (mode == CONNECT)
|
||||||
|
access_mode = "CONNECT";
|
||||||
|
else if (mode == O_WRONLY)
|
||||||
|
access_mode = "写入";
|
||||||
|
else if (mode == O_RDWR)
|
||||||
|
access_mode = "读写";
|
||||||
|
else if (mode == (O_WRONLY | O_APPEND))
|
||||||
|
access_mode = "追加";
|
||||||
|
|
||||||
|
std::string log = "[" + Time_t2String(time(nullptr)) + "] " +
|
||||||
|
"<" + pathname + "> " + access_mode + " {" + process_name + ":" + run_path + "} " + result + "\n";
|
||||||
|
int log_fd = original_file_open(log_name, O_WRONLY | O_CREAT | O_APPEND, 0644);
|
||||||
|
if (log_fd > 0) {
|
||||||
|
write(log_fd, log.c_str(), log.size());
|
||||||
|
close(log_fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
ssize_t read(int fd, void *buf, size_t nbytes) {
|
||||||
|
std::set<std::string> file_set;
|
||||||
|
std::set<std::string> process_set;
|
||||||
|
read_config_file(file_set, process_set, CONFIG_FILE_PATH);
|
||||||
|
// 查进程名 及 运行路径
|
||||||
|
char run_path[4096] = {0};
|
||||||
|
char process_name[1024] = {0};
|
||||||
|
get_executable_path(run_path, process_name, sizeof(run_path));
|
||||||
|
// 根据fd取文件名
|
||||||
|
char file_name[4096] = {'\0'};
|
||||||
|
char file_path[4096] = {'\0'};
|
||||||
|
snprintf(file_name, sizeof(file_name), "/proc/%d/fd/%d", getpid(), fd);
|
||||||
|
ssize_t ret = readlink(file_name, file_path, sizeof(file_path) - 1);
|
||||||
|
if (ret == -1) {
|
||||||
|
return original_file_read(fd, buf, nbytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查
|
||||||
|
auto safe_file = file_set.find(file_path);
|
||||||
|
auto safe_process = process_set.find(process_name);
|
||||||
|
|
||||||
|
// 校验
|
||||||
|
if (safe_file != file_set.end()) {
|
||||||
|
if (safe_process != process_set.end()) {
|
||||||
|
write_log(file_path, O_RDONLY, "正常访问", LOG_FILE_PATH);
|
||||||
|
} else {
|
||||||
|
write_log(file_path, O_RDONLY, "拒绝访问", LOG_FILE_PATH);
|
||||||
|
errno = EACCES;
|
||||||
|
return original_file_read(fd, buf, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return original_file_read(fd, buf, nbytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断接入的网络是否为过滤IP,如果是则提前返回
|
||||||
|
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
|
||||||
|
// 获取链接ip
|
||||||
|
char ip[128];
|
||||||
|
memset(ip, 0, sizeof(ip)); // ip地址
|
||||||
|
int port = -1; // 端口号
|
||||||
|
if (AF_INET == addr->sa_family) {
|
||||||
|
auto *sa4 = (struct sockaddr_in *) addr;
|
||||||
|
inet_ntop(AF_INET, (void *) (struct sockaddr *) &sa4->sin_addr, ip, sizeof(ip));
|
||||||
|
port = ntohs(sa4->sin_port);
|
||||||
|
printf("\nAF_INET IP===%s:%d\n", ip, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查进程名 及 运行路径
|
||||||
|
char run_path[4096] = {0};
|
||||||
|
char process_name[1024] = {0};
|
||||||
|
get_executable_path(run_path, process_name, sizeof(run_path));
|
||||||
|
|
||||||
|
// 获取黑名单ip
|
||||||
|
std::set<std::string> ip_set;
|
||||||
|
std::set<std::string> process_set;
|
||||||
|
read_config_file(ip_set, process_set, CONFIG_NET_IP_PATH);
|
||||||
|
auto black_ip = ip_set.find(ip);
|
||||||
|
auto safe_process = process_set.find(process_name);
|
||||||
|
|
||||||
|
// 比较IP 是黑名单ip
|
||||||
|
if (black_ip != ip_set.end()) {
|
||||||
|
// log ip
|
||||||
|
std::string temp;
|
||||||
|
temp.append(ip);
|
||||||
|
temp.append(":"+std::to_string(port)+"<"+std::to_string(sockfd)+">");
|
||||||
|
|
||||||
|
if (safe_process != process_set.end()) {
|
||||||
|
write_log(temp, CONNECT, "允许访问", LOG_NET_IP_PATH);
|
||||||
|
return original_file_connect(sockfd, addr, addrlen);
|
||||||
|
} else {
|
||||||
|
write_log(temp, CONNECT, "拒绝访问", LOG_NET_IP_PATH);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return original_file_connect(sockfd, addr, addrlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) {
|
||||||
|
// 获取链接ip
|
||||||
|
char ip[128];
|
||||||
|
memset(ip, 0, sizeof(ip)); // ip地址
|
||||||
|
int port = -1; // 端口号
|
||||||
|
if (AF_INET == addr->sa_family) {
|
||||||
|
auto *sa4 = (struct sockaddr_in *) addr;
|
||||||
|
inet_ntop(AF_INET, (void *) (struct sockaddr *) &sa4->sin_addr, ip, sizeof(ip));
|
||||||
|
port = ntohs(sa4->sin_port);
|
||||||
|
printf("\nAF_INET IP===%s:%d\n", ip, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查进程名 及 运行路径
|
||||||
|
char run_path[4096] = {0};
|
||||||
|
char process_name[1024] = {0};
|
||||||
|
get_executable_path(run_path, process_name, sizeof(run_path));
|
||||||
|
|
||||||
|
// 获取黑名单ip
|
||||||
|
std::set<std::string> ip_set;
|
||||||
|
std::set<std::string> process_set;
|
||||||
|
read_config_file(ip_set, process_set, CONFIG_NET_IP_PATH);
|
||||||
|
auto black_ip = ip_set.find(ip);
|
||||||
|
auto safe_process = process_set.find(process_name);
|
||||||
|
|
||||||
|
// log ip
|
||||||
|
std::string temp;
|
||||||
|
temp.append(ip);
|
||||||
|
temp.append(":"+std::to_string(port)+"<"+std::to_string(sockfd)+">");
|
||||||
|
|
||||||
|
// 比较IP 是黑名单ip
|
||||||
|
if (black_ip != ip_set.end()) {
|
||||||
|
if (safe_process != process_set.end()) {
|
||||||
|
write_log(temp, ACCEPT, "允许访问",LOG_NET_IP_PATH);
|
||||||
|
return original_file_accept(sockfd, addr, addrlen);
|
||||||
|
} else {
|
||||||
|
write_log(temp, ACCEPT, "拒绝访问", LOG_NET_IP_PATH);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 放行
|
||||||
|
return original_file_accept(sockfd, addr, addrlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 初始化函数,获取原始文件访问函数的地址并替换为拦截函数
|
||||||
|
__attribute__((constructor)) void init() {
|
||||||
|
original_file_access = (file_access_func_t) dlsym(RTLD_NEXT, "access");
|
||||||
|
original_file_open = (file_open_func_t) dlsym(RTLD_NEXT, "open");
|
||||||
|
original_file_creat = (file_creat_func_t) dlsym(RTLD_NEXT, "creat");
|
||||||
|
original_file_read = (file_read_func_t) dlsym(RTLD_NEXT, "read");
|
||||||
|
original_file_connect = (ip_connect_fun_t) dlsym(RTLD_NEXT, "connect");
|
||||||
|
original_file_accept = (ip_accept_fun_t) dlsym(RTLD_NEXT, "accept");
|
||||||
|
}
|
270
old.cpp
Normal file
270
old.cpp
Normal file
@ -0,0 +1,270 @@
|
|||||||
|
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <cstring>
|
||||||
|
#include <string>
|
||||||
|
#include <set>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#define ACCEPT 9999
|
||||||
|
#define CONNECT 19999
|
||||||
|
|
||||||
|
|
||||||
|
// 定义指向原始文件访问函数的函数指针
|
||||||
|
typedef int (*file_access_func_t)(const char *pathname, int mode, ...);
|
||||||
|
static file_access_func_t original_file_access = nullptr;
|
||||||
|
// 定义指向原始open函数的函数指针
|
||||||
|
typedef int (*file_open_func_t)(const char *pathname, int flags, ...);
|
||||||
|
static file_open_func_t original_file_open = nullptr;
|
||||||
|
// 定义指向原始creat函数的函数指针
|
||||||
|
typedef int (*file_creat_func_t)(const char *pathname, mode_t mode);
|
||||||
|
static file_creat_func_t original_file_creat = nullptr;
|
||||||
|
//read
|
||||||
|
typedef ssize_t (*file_read_func_t)(int fd, void *buf, size_t nbytes);
|
||||||
|
static file_read_func_t original_file_read = nullptr;
|
||||||
|
// connect
|
||||||
|
typedef int (*ip_connect_fun_t)(int, const struct sockaddr *, socklen_t);
|
||||||
|
static ip_connect_fun_t original_file_connect = nullptr;
|
||||||
|
// accept
|
||||||
|
typedef int (*ip_accept_fun_t)(int, struct sockaddr *, socklen_t *);
|
||||||
|
static ip_accept_fun_t original_file_accept = nullptr;
|
||||||
|
|
||||||
|
|
||||||
|
// 定义原始的do_sys_open()函数指针
|
||||||
|
//static long (*real_do_sys_open)(int dfd, const char __user *filename, int flags, umode_t mode) = nullptr;
|
||||||
|
|
||||||
|
// 定义日志文件路径和配置文件路径的环境变量
|
||||||
|
const char *LOG_FILE_PATH = "/home/dongl/code/safe_test/log";
|
||||||
|
const char *CONFIG_FILE_PATH = "/home/dongl/code/safe_test/config.txt";
|
||||||
|
const char *LOG_NET_IP_PATH = "/home/dongl/code/safe_test/net-log";
|
||||||
|
const char *CONFIG_NET_IP_PATH = "/home/dongl/code/safe_test/net-config.txt";
|
||||||
|
|
||||||
|
// 将时间戳转换为字符串
|
||||||
|
std::string Time_t2String(time_t t) {
|
||||||
|
char tmp[64] = {0};
|
||||||
|
strftime(tmp, sizeof(tmp), "%Y-%m-%d %H:%M:%S", localtime(&t));
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取当前进程的可执行文件路径和名称
|
||||||
|
size_t get_executable_path(char *processdir, char *processname, size_t len) {
|
||||||
|
char *path_end;
|
||||||
|
if (readlink("/proc/self/exe", processdir, len) <= 0)
|
||||||
|
return -1;
|
||||||
|
path_end = strrchr(processdir, '/');
|
||||||
|
if (path_end == nullptr)
|
||||||
|
return -1;
|
||||||
|
++path_end;
|
||||||
|
strcpy(processname, path_end);
|
||||||
|
*path_end = '\0';
|
||||||
|
return (size_t) (path_end - processdir);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 读取配置文件并填充文件和进程集合
|
||||||
|
void read_config_file(std::set<std::string>& file_set, std::set<std::string>& process_set, const char* config_name) {
|
||||||
|
// 打开配置文件
|
||||||
|
int config_fd = original_file_open(config_name, O_RDONLY);
|
||||||
|
if (config_fd < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// 读取配置文件
|
||||||
|
char buff[4096];
|
||||||
|
std::string data;
|
||||||
|
bool state = true;
|
||||||
|
while (original_file_read(config_fd, buff, sizeof(buff)) > 0) {
|
||||||
|
for (const auto &item: buff) {
|
||||||
|
if (item != '\n') {
|
||||||
|
data.push_back(item);
|
||||||
|
} else if (item == '\n') {
|
||||||
|
// 检查行是文件部分还是进程部分
|
||||||
|
std::string temp = config_name == CONFIG_FILE_PATH ? "[safe_file]" : "[black_ip]";
|
||||||
|
if (data == temp) {
|
||||||
|
state = true;
|
||||||
|
data.clear();
|
||||||
|
continue;
|
||||||
|
} else if (data == "[safe_process]") {
|
||||||
|
state = false;
|
||||||
|
data.clear();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将文件或进程添加到相应的集合中
|
||||||
|
if (state) {
|
||||||
|
file_set.insert(data);
|
||||||
|
data.clear();
|
||||||
|
} else {
|
||||||
|
process_set.insert(data);
|
||||||
|
data.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭配置文件
|
||||||
|
close(config_fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将文件访问日志写入日志文件
|
||||||
|
void write_log(const std::string &pathname, int mode, const std::string &result, const char* log_name) {
|
||||||
|
char run_path[40960] = {0};
|
||||||
|
char process_name[10240] = {0};
|
||||||
|
get_executable_path(run_path, process_name, sizeof(run_path));
|
||||||
|
|
||||||
|
std::string access_mode;
|
||||||
|
if (mode == O_RDONLY)
|
||||||
|
access_mode = "读取";
|
||||||
|
else if (mode == ACCEPT)
|
||||||
|
access_mode = "ACCEPT";
|
||||||
|
else if (mode == CONNECT)
|
||||||
|
access_mode = "CONNECT";
|
||||||
|
else if (mode == O_WRONLY)
|
||||||
|
access_mode = "写入";
|
||||||
|
else if (mode == O_RDWR)
|
||||||
|
access_mode = "读写";
|
||||||
|
else if (mode == (O_WRONLY | O_APPEND))
|
||||||
|
access_mode = "追加";
|
||||||
|
|
||||||
|
std::string log = "[" + Time_t2String(time(nullptr)) + "] " +
|
||||||
|
"<" + pathname + "> " + access_mode + " {" + process_name + ":" + run_path + "} " + result + "\n";
|
||||||
|
int log_fd = original_file_open(log_name, O_WRONLY | O_CREAT | O_APPEND, 0644);
|
||||||
|
if (log_fd > 0) {
|
||||||
|
write(log_fd, log.c_str(), log.size());
|
||||||
|
close(log_fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
ssize_t read(int fd, void *buf, size_t nbytes) {
|
||||||
|
std::set<std::string> file_set;
|
||||||
|
std::set<std::string> process_set;
|
||||||
|
read_config_file(file_set, process_set, CONFIG_FILE_PATH);
|
||||||
|
// 查进程名 及 运行路径
|
||||||
|
char run_path[4096] = {0};
|
||||||
|
char process_name[1024] = {0};
|
||||||
|
get_executable_path(run_path, process_name, sizeof(run_path));
|
||||||
|
// 根据fd取文件名
|
||||||
|
char file_name[4096] = {'\0'};
|
||||||
|
char file_path[4096] = {'\0'};
|
||||||
|
snprintf(file_name, sizeof(file_name), "/proc/%d/fd/%d", getpid(), fd);
|
||||||
|
ssize_t ret = readlink(file_name, file_path, sizeof(file_path) - 1);
|
||||||
|
if (ret == -1) {
|
||||||
|
return original_file_read(fd, buf, nbytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查
|
||||||
|
auto safe_file = file_set.find(file_path);
|
||||||
|
auto safe_process = process_set.find(process_name);
|
||||||
|
|
||||||
|
// 校验
|
||||||
|
if (safe_file != file_set.end()) {
|
||||||
|
if (safe_process != process_set.end()) {
|
||||||
|
write_log(file_path, O_RDONLY, "正常访问", LOG_FILE_PATH);
|
||||||
|
} else {
|
||||||
|
write_log(file_path, O_RDONLY, "拒绝访问", LOG_FILE_PATH);
|
||||||
|
errno = EACCES;
|
||||||
|
return original_file_read(fd, buf, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return original_file_read(fd, buf, nbytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断接入的网络是否为过滤IP,如果是则提前返回
|
||||||
|
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
|
||||||
|
// 获取链接ip
|
||||||
|
char ip[128];
|
||||||
|
memset(ip, 0, sizeof(ip)); // ip地址
|
||||||
|
int port = -1; // 端口号
|
||||||
|
if (AF_INET == addr->sa_family) {
|
||||||
|
auto *sa4 = (struct sockaddr_in *) addr;
|
||||||
|
inet_ntop(AF_INET, (void *) (struct sockaddr *) &sa4->sin_addr, ip, sizeof(ip));
|
||||||
|
port = ntohs(sa4->sin_port);
|
||||||
|
printf("\nAF_INET IP===%s:%d\n", ip, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查进程名 及 运行路径
|
||||||
|
char run_path[4096] = {0};
|
||||||
|
char process_name[1024] = {0};
|
||||||
|
get_executable_path(run_path, process_name, sizeof(run_path));
|
||||||
|
|
||||||
|
// 获取黑名单ip
|
||||||
|
std::set<std::string> ip_set;
|
||||||
|
std::set<std::string> process_set;
|
||||||
|
read_config_file(ip_set, process_set, CONFIG_NET_IP_PATH);
|
||||||
|
auto black_ip = ip_set.find(ip);
|
||||||
|
auto safe_process = process_set.find(process_name);
|
||||||
|
|
||||||
|
// 比较IP 是黑名单ip
|
||||||
|
if (black_ip != ip_set.end()) {
|
||||||
|
// log ip
|
||||||
|
std::string temp;
|
||||||
|
temp.append(ip);
|
||||||
|
temp.append(":"+std::to_string(port)+"<"+std::to_string(sockfd)+">");
|
||||||
|
|
||||||
|
if (safe_process != process_set.end()) {
|
||||||
|
write_log(temp, CONNECT, "允许访问", LOG_NET_IP_PATH);
|
||||||
|
return original_file_connect(sockfd, addr, addrlen);
|
||||||
|
} else {
|
||||||
|
write_log(temp, CONNECT, "拒绝访问", LOG_NET_IP_PATH);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return original_file_connect(sockfd, addr, addrlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) {
|
||||||
|
// 获取链接ip
|
||||||
|
char ip[128];
|
||||||
|
memset(ip, 0, sizeof(ip)); // ip地址
|
||||||
|
int port = -1; // 端口号
|
||||||
|
if (AF_INET == addr->sa_family) {
|
||||||
|
auto *sa4 = (struct sockaddr_in *) addr;
|
||||||
|
inet_ntop(AF_INET, (void *) (struct sockaddr *) &sa4->sin_addr, ip, sizeof(ip));
|
||||||
|
port = ntohs(sa4->sin_port);
|
||||||
|
printf("\nAF_INET IP===%s:%d\n", ip, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查进程名 及 运行路径
|
||||||
|
char run_path[4096] = {0};
|
||||||
|
char process_name[1024] = {0};
|
||||||
|
get_executable_path(run_path, process_name, sizeof(run_path));
|
||||||
|
|
||||||
|
// 获取黑名单ip
|
||||||
|
std::set<std::string> ip_set;
|
||||||
|
std::set<std::string> process_set;
|
||||||
|
read_config_file(ip_set, process_set, CONFIG_NET_IP_PATH);
|
||||||
|
auto black_ip = ip_set.find(ip);
|
||||||
|
auto safe_process = process_set.find(process_name);
|
||||||
|
|
||||||
|
// log ip
|
||||||
|
std::string temp;
|
||||||
|
temp.append(ip);
|
||||||
|
temp.append(":"+std::to_string(port)+"<"+std::to_string(sockfd)+">");
|
||||||
|
|
||||||
|
// 比较IP 是黑名单ip
|
||||||
|
if (black_ip != ip_set.end()) {
|
||||||
|
if (safe_process != process_set.end()) {
|
||||||
|
write_log(temp, ACCEPT, "允许访问",LOG_NET_IP_PATH);
|
||||||
|
return original_file_accept(sockfd, addr, addrlen);
|
||||||
|
} else {
|
||||||
|
write_log(temp, ACCEPT, "拒绝访问", LOG_NET_IP_PATH);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 放行
|
||||||
|
return original_file_accept(sockfd, addr, addrlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 初始化函数,获取原始文件访问函数的地址并替换为拦截函数
|
||||||
|
__attribute__((constructor)) void init() {
|
||||||
|
original_file_access = (file_access_func_t) dlsym(RTLD_NEXT, "access");
|
||||||
|
original_file_open = (file_open_func_t) dlsym(RTLD_NEXT, "open");
|
||||||
|
original_file_creat = (file_creat_func_t) dlsym(RTLD_NEXT, "creat");
|
||||||
|
original_file_read = (file_read_func_t) dlsym(RTLD_NEXT, "read");
|
||||||
|
original_file_connect = (ip_connect_fun_t) dlsym(RTLD_NEXT, "connect");
|
||||||
|
original_file_accept = (ip_accept_fun_t) dlsym(RTLD_NEXT, "accept");
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user