拦截 connect 函数调用(进程白名单,网址黑名单)

本文介绍了如何在Linux下通过LD_PRELOAD环境变量拦截connect函数调用,实现进程白名单和网址黑名单的功能。内容包括拦截函数的编写、白名单和黑名单的实现以及日志系统的添加。
摘要由CSDN通过智能技术生成

拦截connect 函数调用

在Linux环境下,我们可以使用LD_PRELOAD环境变量来拦截系统调用,包括connect函数。这是一个简单的C语言程序,它拦截了connect函数:

#define _GNU_SOURCE
#include <dlfcn.h>
#include <sys/types.h>
#include <sys/socket.h>

int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
   
    // 获取原始的connect函数
    int (*original_connect)(int, const struct sockaddr *, socklen_t);
    original_connect = dlsym(RTLD_NEXT, "connect");

    // 在这里,你可以添加自己的代码来处理或修改参数

    // 调用原始的connect函数
    return original_connect(sockfd, addr, addrlen);
}

你可以将这个程序编译为共享库,

gcc -shared -fPIC -o libintercept.so intercept.c -ldl

然后使用LD_PRELOAD环境变量来加载它。例如,如果你将这个程序编译为libintercept.so,你可以这样使用它:

export LD_PRELOAD=/path/to/libintercept.so

这样,当你的程序调用connect函数时,它实际上会调用你的拦截函数。在你的拦截函数中,你可以添加任何你需要的代码,然后调用原始的connect函数。

请注意,这种方法可能会对系统的稳定性和安全性产生影响,因此在生产环境中使用时需要谨慎。在使用这种方法时,你应该确保你完全理解它的工作原理和可能的影响。如果可能,你应该寻求专业的安全建议。


第二个需求

1.白名单进程 保存在 进程白名单文件, 受限制网址的网址名保存在网址黑名单文件
2.所有白名单进程能访问所有网址
3.对所有进程访问网址的 过程进行日志记录.(进程名,网址名,访问时间,成功与否)

在这里插入图片描述

准备工作

测试的ip地址
113.108.81.189 80
116.211.201.190 80
120.132.47.197 80
119.3.70.188 80
39.107.236.43 80
121.9.213.44 80
125.88.186.164 80
59.110.145.235 80
123.58.180.8 80
101.199.97.227 80
42.187.161.231 80
103.37.152.3 80
111.13.134.203 80
39.107.241.57 80
221.228.79.225 80
82.156.59.186 80
203.107.84.131 80
61.135.164.50 80
202.90.108.5 80
8.134.66.235 80
117.186.233.61 80
47.95.111.46 80
120.39.201.186 80
122.14.229.39 80
106.75.14.181 80
183.60.155.69 80
123.59.198.196 80
121.9.213.44 80
59.37.89.174 80
183.61.177.41 80
139.224.234.117 80
47.99.112.78 80
8.131.70.224 80
119.23.141.248 80
121.207.229.230 80
14.215.182.217 80
134.175.159.35 80
122.9.119.16 80
104.21.92.74 80
172.65.229.194 80
120.92.182.58 80
101.89.47.179 80
104.26.7.129 80
59.37.89.155 80
122.14.229.128 80
103.107.217.26 80
23.225.199.197 80
122.14.229.121 80
49.233.242.15 80
14.17.91.20 80
218.205.239.108 80
183.136.182.20 80
101.42.130.11 80
14.152.89.133 80
20.76.201.171 80
13.248.184.86 80
119.147.179.153 80
23.45.52.90 80
120.39.212.43 80
120.77.216.70 80
124.236.95.25 80
76.223.34.124 80
118.89.214.103 80
222.186.17.206 80
121.14.77.201 80
123.60.61.74 80
59.37.89.155 80
59.36.228.19 80
114.55.187.22 80
124.227.185.190 80
113.108.92.187 80
203.107.86.158 80
119.147.3.225 80
59.111.181.169 80
140.143.177.206 80
180.153.255.122 80
123.58.191.10 80
59.82.121.100 80
39.96.33.114 80
106.75.118.232 80
140.205.174.2 80
54.222.60.218 80
221.122.85.69 80
117.186.233.61 80
117.122.209.144 80
152.136.8.77 80
106.15.81.69 80
39.96.126.126 80
183.2.193.244 80
211.159.143.150 80
124.250.78.6 80
152.136.4.16 80
119.254.81.86 80
172.67.75.153 80
183.61.120.237 80
39.96.251.72 80
180.163.28.105 80
52.131.37.152 80
59.37.89.155 80
59.36.226.186 80
58.215.111.12 80
66.42.117.29 80
106.75.50.164 80
99.83.231.148 80
47.94.150.131 80
69.147.88.7 80
154.197.23.182 80
150.138.167.196 80
175.24.250.217 80
212.129.163.50 80
81.69.64.111 80
47.114.154.37 80
116.62.111.230 80
114.113.83.10 80
60.205.172.136 80
120.133.51.65 80
115.236.121.25 80
223.252.199.73 80
113.96.18.174 80
115.238.119.98 80
203.107.62.235 80
120.52.152.52 80
121.32.243.103 80
180.163.247.153 80
14.215.183.81 80
202.205.109.2 80
183.2.193.241 80
183.2.172.42 80
14.116.174.244 80
47.110.249.164 80
122.115.55.103 80
122.115.35.141 80
42.187.161.231 80
180.163.219.118 80
121.43.113.44 80
115.31.65.10 80
183.61.177.41 80
103.74.50.106 80
59.110.244.186 80
150.158.229.157 80
210.236.244.76 80
139.196.36.248 80
192.229.210.197 80
180.184.178.163 80
140.177.8.192 80
172.67.146.49 80
36.110.136.74 80
116.205.2.136 80
27.148.141.164 80
125.77.174.92 80
202.127.253.239 80
117.21.233.108 80
52.25.43.199 80
222.89.70.77 80
172.65.251.78 80
172.67.72.2 80
42.192.175.15 80
199.250.214.41 80
221.230.245.102 80
125.89.169.1 80
104.21.76.91 80
20.205.243.166 80
216.239.32.21 80
104.16.176.44 80
119.9.76.21 80
180.76.198.77 80
104.18.230.83 80
106.55.120.91 80
59.110.244.135 80
172.64.148.154 80
104.107.8.194 80
104.16.132.229 80
183.136.219.124 80
13.226.233.6 80
140.205.135.3 80
23.22.145.15 80
192.229.210.197 80
3.131.207.60 80
1.15.35.93 80
185.199.108.153 80
104.19.155.92 80
34.111.97.67 80
104.18.28.237 80
103.107.90.151 80
185.199.108.153 80
172.64.144.180 80
59.82.23.37 80
34.149.47.137 80
34.149.47.137 80
106.53.108.67 80
13.227.74.65 80
221.228.74.48 80
35.190.0.251 80
13.227.74.101 80
192.158.231.81 80
198.54.119.159 80
104.21.9.35 80
162.159.153.4 80
217.26.61.226 80
167.99.4.132 80
104.21.77.92 80
104.22.15.114 80
47.101.19.247 80
104.16.167.76 80
18.208.98.11 80
216.239.32.21 80
47.110.159.73 80
104.21.81.48 80
60.205.230.219 80
121.40.176.66 80
测试ip是否可以被tcp 客户端访问

只在connect 无法连接ip的时候 才打印 错误信息, 经验证 所有 ip 都可以 进行 tcp 连接 且不报错

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>

int main()
{
    // 1. 创建通信的套接字
    int fd = socket(AF_INET, SOCK_STREAM, 0);
    if(fd == -1)
    {
        perror("socket");
        exit(0);
    }

    // 从文件中读取IP地址和端口号
    FILE *file = fopen("/home/yyy/WEBSITE_LIST", "r");
    if (file == NULL) {
        perror("fopen");
        exit(0);
    }

    char ip[16];
    int port;

    // 循环读取文件中的每一行
    while (fscanf(file, "%15s %d", ip, &port) != EOF) {
        // 2. 连接服务器
        struct sockaddr_in addr;
        addr.sin_family = AF_INET;
        addr.sin_port = htons(port);   // 大端端口
        inet_pton(AF_INET, ip, &addr.sin_addr.s_addr);

        int ret = connect(fd, (struct sockaddr*)&addr, sizeof(addr));
        if(ret == -1)
        {
            perror("connect");

        printf("(IP: %s,端口: %d)没有建立连接\n", ip, port);
            continue;  // 如果连接失败,跳过当前循环,尝试下一个IP和端口
        }

        // 打印连接的 IP 地址和端口号
        // printf("已经和服务器(IP: %s,端口: %d)建立了连接\n", ip, port);

        // 3. 和服务器端通信
        int number = 0;
        while(1)
        {
            // 发送数据
            char buf[1024];
            sprintf(buf, "你好, 服务器...%d\n", number++);
            write(fd, buf, strlen(buf)+1);

            // 接收数据
            memset(buf, 0, sizeof(buf));
            int len = read(fd, buf, sizeof(buf));
            if(len > 0)
            {
         //       printf("服务器say: %s\n", buf);
            }
            else if(len  == 0)
            {
          //      printf("服务器断开了连接...\n");
                break;
            }
            else
            {

        printf("(IP: %s,端口: %d)read 报错\n", ip, port);
                perror("read");
                break;
            }
            sleep(1);   // 每隔1s发送一条数据
        }

        close(fd);

        // 重新创建通信的套接字,用于下一个连接
        fd = socket(AF_INET, SOCK_STREAM, 0);
        if(fd == -1)
        {

        printf("(IP: %s,端口: %d)socket报错\n", ip, port);
            perror("socket");
            exit(0);
        }
    }

    fclose(file);
    return 0;
}

列出当前目录下的所有文件(包括隐藏文件)的绝对路径, 对目录不做递归

 find $PWD | xargs ls -ld

文件目录

.
├── WEBSITE_LIST
├── WHITE_BLACK_LIST
│   ├── BLACK_WEBSITE_FILE
│   └── WHITE_PROC_FILE
├── intercept.c
├── libintercept.so
├── p1.c
├── p2.c
├── p3.c
└── p4.c
yyy@DESKTOP-75R3I47:~$  find $PWD | xargs ls -ld

-rw-rw-r-- 1 yyy yyy  3614 Dec  3 17:28 /home/yyy/WEBSITE_LIST
drwxrwxr-x 2 yyy yyy  4096 Dec  2 17:13 /home/yyy/WHITE_BLACK_LIST
-rw-rw-r-- 1 yyy yyy   499 Dec  2 17:13 /home/yyy/WHITE_BLACK_LIST/BLACK_WEBSITE_FILE
-rw-rw-r-- 1 yyy yyy    39 Dec  2 14:01 /home/yyy/WHITE_BLACK_LIST/WHITE_PROC_FILE
-rw-rw-r-- 1 yyy yyy  3389 Dec  3 16:21 /home/yyy/intercept.c
-rwxrwxr-x 1 yyy yyy 16680 Dec  3 16:21 /home/yyy/libintercept.so
-rw-rw-r-- 1 yyy yyy     0 Dec  3 17:34 /home/yyy/p1.c
-rw-rw-r-- 1 yyy yyy     0 Dec  3 17:34 /home/yyy/p2.c
-rw-rw-r-- 1 yyy yyy     0 Dec  3 17:34 /home/yyy/p3.c
-rw-rw-r-- 1 yyy yyy     0 Dec  3 17:34 /home/yyy/p4.c

客户端代码

好的,根据你的代码和要求,我为你改进了客户端代码。以下是一个示例:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>

#define MAX_IP_LEN 32
#define MAX_PORT_LEN 6

int main()
{
   
    // 1. 创建通信的套接字
    int fd = socket(AF_INET, SOCK_STREAM, 0);
    if(fd == -1)
    {
   
        perror("socket");
        exit(0);
    }

    FILE *fp = fopen("/home/yyy/WEBSITE_LIST", "r");
    if(fp == NULL)
    {
   
        perror("fopen");
        exit(0);
    }

    char ip[MAX_IP_LEN];
    char port[MAX_PORT_LEN];

    while(fscanf(fp, "%s %s", ip, port) != EOF)
    {
   
        // 2. 连接服务器
        struct sockaddr_in addr;
        addr.sin_family = AF_INET;
        addr.sin_port = htons(atoi(port));   // 大端端口
        inet_pton(AF_INET, ip, &addr.sin_addr.s_addr);

        int ret = connect(fd, (struct sockaddr*)&addr, sizeof(addr));
        if(ret == -1)
        {
   
            perror("connect");
            continue;
        }

        // 3. 和服务器端通信
        int number = 0;
        while(1)
        {
   
            // 发送数据
            char buf[1024];
            sprintf(buf, "你好, 服务器...%d\n", number++);
            write(fd, buf, strlen(buf)+1);
            
            // 接收数据
            memset(buf, 0, sizeof(buf));
            int len = read(fd, buf, sizeof(buf));
            if(len > 0)
            {
   
                printf("服务器say: %s\n", buf);
            }
            else if(len  == 0)
            {
   
                printf("服务器断开了连接...\n");
                break;
            }
            else
            {
   
                perror("read");
                break;
            }
            sleep(1);   // 每隔1s发送一条数据
        }

        close(fd);
        fd = socket(AF_INET, SOCK_STREAM, 0); // 重新创建套接字
    }

    fclose(fp);

    return 0;
}

每个循环都重新创建了一个新的套接字(在close(fd)之后),以确保每次都是一个新的连接。

修改connect

​ 白名单进程保存在进程白名单文件 BLACK_WEBSITE_FILE 中(每行一个进程名称),受保护网址的ip地址和端口 保存在网址黑名单文件 BLACK_WEBSITE_FILE 中 (每行保存一个ip和端口 格式类似于 192.168.1.1 80 )

修改自定义connect函数,当调用connect函数的进程的进程是白名单进程时,该进程会访问所有网址(受保护网址和不受保护的网址).当调用connect函数的进程的进程是非白名单进程时,该进程不能访问网址黑名单中受保护的网址,只能访问其它不受保护的网址,

版本一

gcc -shared -fPIC -o libintercept.so intercept.c -ldl
#define _GNU_SOURCE
#include <dlfcn.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
 #include <stdlib.h>

// 检查进程是否在白名单中
int is_in_whitelist() {
    // 请替换为你的白名单文件路径
    const char *whitelist_file = "/home/yyy/WHITE_BLACK_LIST/WHITE_PROC_FILE";
    FILE *file = fopen(whitelist_file, "r");
    if (file == NULL) {
        return 0;
    }

    char line[256];
    pid_t pid = getpid();
    while (fgets(line, sizeof(line), file)) {
        if (atoi(line) == pid) {
            fclose(file);
            return 1;
        }
    }

    fclose(file);
    return 0;
}

// 检查 IP 和端口是否在黑名单中
int is_in_blacklist(const struct sockaddr *addr) {
    // 请替换为你的黑名单文件路径
    const char *blacklist_file = "/home/yyy/WHITE_BLACK_LIST/BLACK_WEBSITE_FILE";
    FILE *file = fopen(blacklist_file, "r");
    if (file == NULL) {
        return 0;
    }

    struct sockaddr_in *addr_in = (struct sockaddr_in *)addr;
    char *ip = inet_ntoa(addr_in->sin_addr);
    int port = ntohs(addr_in->sin_port);

    char line[256];
    while (fgets(line, si
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

丁金金

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值