### 前言

Linux系统中存在用户态与内核态,当用户态的进程需要申请某些系统资源时便会发起系统调用。而内核态如何将系统的相关信息实时反馈给用户态呢,便是通过proc文件系统。如此便营造了一个相对隔离的环境。
那么proc文件系统是如何呈现我们平时最关心的进程/网络连接信息的呢?在/proc目录下存在着一些以数字命名的目录,这些数字便对应了系统中正在运行的进程的pid。自然,对应进程的一些相关信息便保存在/proc/{pid}目录下。比如/proc/{pid}/fd目录中就保存了进程打开的文件描述符。
系统会将tcp协议的连接信息保存在/proc/net/tcp文件中。其他网络协议的连接信息也均保存在/proc/net对应协议的文件中。需要特别指出的是,上图中socket文件名中括号里的数字与下图中inode列是存在对应关系的。
综上所述,像ps和netstat这类命令便是读取了proc文件系统中提供的数据,然后将数据格式化输出给用户的。出于隐藏指定进程/网络连接的目的,大部分Rootkit对写proc文件的回调函数做了些手脚,造成黑客指定的一些进程/网络连接的信息不会出现在proc文件系统中。于是,也就实现了进程/网络连接的隐藏。
### 探索
那么,如何发现那些被隐藏的进程/网络连接呢?首先是进程,这个其实并不复杂。系统给我们提供了一个方便的全局变量current。current永远指向当前正在运行的进程的task_struct数据结构,而进程的主要信息都包含在这个名为task_struct的巨大结构体中。当我们遍历到系统中所有进程task_struct结构体中的pid值,然后再去/proc目录下去寻找是否有对应的值。一但我们得到的pid未出现在ps的返回结果中,那么说明该进程被隐藏了。
如何发现被隐藏的网络连接呢?其实还是基于上一步进一步挖掘,因为网络IO请求都是由进程发起的,那么理论上来说我们肯定可以从进程一步步“捋”到socket。Linux一切皆文件的准则告诉我们,所谓网络IO其实就是读写socket文件,而每个socket结构体中都会有一个对应的inet_sock结构体,来记录IP协议下网络连接的四元组信息。那么我们把这些四元组再和netstat命令的返回结果比对一下便可知是否存在隐藏的网络信道了。
总结出来在Kernel2.6.32中,进程-文件-网络三者之间大致的关系如下图所示。
fdtable结构体的成员fd字符数组中存储的是file结构体,每当进程开启了一个文件描述符之后会自动在fd数组中新增一个对应的file结构体。通过获取file结构体中的f_path成员,我们可以获得对应的path结构体。系统内置的d_path函数可以返回path结构体对应文件的绝对路径信息。当d_path返回了一个“socket:[xxx]”的信息时,就说明这是个socket文件,该进程在试图进行网络IO。我们引用这个file结构体的private_data成员就可以获得这个socket文件对应的socket结构体了。最后通过内置的inet_sk()函数我们就可以找到对应socket文件的inet_sock结构体,我们需要的四元组便存在这个结构体中。
### 代码
[C] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/file.h>
#include <linux/dcache.h>
#include <linux/fdtable.h>
#include <linux/file.h>
#include <linux/fs.h>
#include <linux/limits.h>
#include <linux/string.h>
#include <linux/net.h>
#include <net/inet_sock.h>
  
static int __init mychk_init(void);
static void __exit mychk_exit(void);
  
module_init(mychk_init);
module_exit(mychk_exit);
  
MODULE_LICENSE("GPL");
  
void get_socket(struct file *f,char* sock_name){
        struct socket *st = NULL;
        struct inet_sock *is = NULL;
        st = f->private_data;
        is = inet_sk(st->sk);
        printk(KERN_ALERT"%s: LA: %d.%d.%d.%d:%u  FA: %d.%d.%d.%d:%u\n",sock_name,NIPQUAD(is->saddr),ntohs(is->sport),NIPQUAD(is->daddr),ntohs(is->dport));
}
  
char* get_path(struct path p) {
        char *buff = NULL;
        char *path = NULL;
        buff = kmalloc(PATH_MAX,GFP_KERNEL);
        if (!buff)
                return NULL;
        path = d_path(&p,buff,PATH_MAX);
        return path;
}
  
static int __init mychk_init(void) {
        struct task_struct *t = NULL;
        struct files_struct *f = NULL;
        struct file *file = NULL;
        struct fdtable *fdt = NULL;
        struct path p;
        char *msg = NULL;
        int i;
        list_for_each_entry(t,¤t->tasks,tasks) {
                printk(KERN_ALERT"Process:%s [%d]\n", t->comm, t->pid);
                task_lock(t);
                f = t->files;
                if(NULL != f){
                        fdt = f->fdt;
                        for (i = 0;i<NR_OPEN_DEFAULT;i++) {
                                if (fdt != NULL) {
                                        file = fdt->fd;
                                        if(file != NULL && file->f_path.dentry != NULL) {
                                                p = file->f_path;
                                                msg = get_path(p);
                                                if (msg != NULL && msg != strstr(msg,"socket"))
                                                        printk(KERN_ALERT"-- %s\n",msg);
                                                else
                                                        get_socket(file,msg);
                                        }
                                }
                        }
                }
                task_unlock(t);
        }
        return 0;
}
  
static void __exit mychk_exit(void) {
        printk(KERN_ALERT"Remove Module!\n");
}
###运行结果
Process:sshd [1840]
-- /dev/null
-- /dev/null
-- /dev/null
socket:[16185]: LA:192.168.11.144:22  FA: 192.168.11.1:61493
-- pipe:[16256]
-- pipe:[16256]
-- /dev/ptmx
-- /dev/ptmx
-- /dev/ptmx
Process:bash [1844]
-- /dev/pts/1
-- /dev/pts/1
-- /dev/pts/1
Process:mysqld_safe [3668]
-- /dev/null
-- /dev/null
-- /dev/null
Process:mysqld [3770]
-- /dev/null
-- /var/log/mysqld.log
-- /var/log/mysqld.log
-- /var/lib/mysql/ibdata1
-- /tmp/ibABwsCH (deleted)
-- /tmp/ibLWJRBw (deleted)
-- /tmp/ibVCthBl (deleted)
-- /tmp/ibogYHLa (deleted)
-- /var/lib/mysql/ib_logfile0
-- /var/lib/mysql/ib_logfile1
socket:[18993]: LA:0.0.0.0:3306  FA: 0.0.0.0:0
-- /tmp/ibgDa0v2 (deleted)
-- /var/lib/mysql/mysql/host.MYI
-- /var/lib/mysql/mysql/host.MYD
-- /var/lib/mysql/mysql/user.MYI
-- /var/lib/mysql/mysql/user.MYD
-- /var/lib/mysql/mysql/db.MYI
-- /var/lib/mysql/mysql/db.MYD
-- /var/lib/mysql/mysql/tables_priv.MYI
-- /var/lib/mysql/mysql/tables_priv.MYD
-- /var/lib/mysql/mysql/columns_priv.MYI
-- /var/lib/mysql/mysql/columns_priv.MYD
-- /var/lib/mysql/mysql/procs_priv.MYI
-- /var/lib/mysql/mysql/procs_priv.MYD
-- /var/lib/mysql/mysql/servers.MYI
-- /var/lib/mysql/mysql/servers.MYD
-- /var/lib/mysql/mysql/event.MYI
-- /var/lib/mysql/mysql/event.MYD
 
###后记
一篇简析进程-文件-网络三者在内核中的关系的文章,偏内核方向,如有感兴趣的小伙伴欢迎留言探讨。

NSRC技术分享——自制Linux Rootkit检测工具的更多相关文章

  1. Linux入侵检测工具 - RKHunter

    RKHunter是Linux系统平台下的一款开源入侵检测工具 特点 (1)安装便捷,运行快速 (2)扫描范围全,能够检测各种已知的rootkit特征码.端口扫描.常用程序文件的变动情况检查 主要功能 ...

  2. Linux入侵检测工具

    原文:https://www.cnblogs.com/lvcisco/p/4045203.html 一.rootkit简介 rootkit是Linux平台下最常见的一种木马后门工具,它主要通过替换系统 ...

  3. 技术分享 | 自制GreatSQL Docker镜像

    GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. 近期打算制作一个GreatSQL的docker镜像,方便社区用户使用GreatSQL. 制作docker镜像的环境基于Ce ...

  4. 网易视频云技术分享:linux软raid的bitmap分析

    网易视频云是网易倾力打造的一款基于云计算的分布式多媒体处理集群和专业音视频技术,提供稳定流畅.低时延.高并发的视频直播.录制.存储.转码及点播等音视频的PAAS服务,在线教育.远程医疗.娱乐秀场.在线 ...

  5. 【技术分享】linux各种一句话反弹shell总结——攻击者指定服务端,受害者主机(无公网IP)主动连接攻击者的服务端程序(CC server),开启一个shell交互,就叫反弹shell。

    反弹shell背景: 想要搞清楚这个问题,首先要搞清楚什么是反弹,为什么要反弹.假设我们攻击了一台机器,打开了该机器的一个端口,攻击者在自己的机器去连接目标机器(目标ip:目标机器端口),这是比较常规 ...

  6. [Linux 性能检测工具]PIDSTAT

    PIDSTAT NAME pidstat对linux任务的统计 语法 pidstat [ -C comm ] [ -d ] [ -h ] [ -I ] [ -l ] [ -p { pid [,...] ...

  7. [Linux 性能检测工具]TOP

    TOP NAME 显示linux任务 语法 top -hv | -abcHimMsS -d delay -n iterations -p pid [, pid ...] 描述 top程序提供了系统实时 ...

  8. [Linux 性能检测工具]FREE

    FREE NAME free显示系统可用内存和已使用内存 语法 free [-b | -k | -m] [-o] [-s delay ] [-t] [-l] [-V] 描述 free显示了总可用和被用 ...

  9. [Linux 性能检测工具]SAR

    SAR NAME: SAR报告,收集,保存系统活动信息 语法: sar  [ -A ] [ -b ] [ -B ] [ -C ] [ -d ] [ -h ] [ -i interval ] [ -m ...

随机推荐

  1. Linux显示USB设备

    Linux显示USB设备 youhaidong@youhaidong-ThinkPad-Edge-E545:~$ lsusb -tv /: Bus 08.Port 1: Dev 1, Class=ro ...

  2. FFMPEG:H264解码-SDL显示(RGB32、RGB24、YUV420P、YUV422)

    FFMpeg对视频文件进行解码的大致流程 1. 注册所有容器格式: av_register_all()2. 打开文件: av_open_input_file()3. 从文件中提取流信息: av_fin ...

  3. 芝麻HTTP:记scikit-learn贝叶斯文本分类的坑

    基本步骤: 1.训练素材分类: 我是参考官方的目录结构: 每个目录中放对应的文本,一个txt文件一篇对应的文章:就像下面这样 需要注意的是所有素材比例请保持在相同的比例(根据训练结果酌情调整.不可比例 ...

  4. OpenStack_I版 6.Neutron部署

    Neutron是不能自己创建网络的,它需要借助插件才能创建虚拟网桥.网卡 依赖插件 配置ml2为核心插件 本次网络模型采用扁平化网络,不同的网络类型不同的配置,不同的使用方法 打开安全组功能 Linu ...

  5. 关于json.parse和json.stringify的区别

    json.parse是将字符串解析成json格式 而json.stringify是将json解析成字符串格式

  6. Dynamics CRM中一个查找字段引发的【血案】

    摘要: 本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复267或者20180311可方便获取本文,同时可以在第一间得到我发布的最新的博文信息,follow me!我的网站是 www.luoyon ...

  7. C++标准库bitset类型(简单使用方法)

    转自此人博客 ```cpp #include<bister> using std::bitset; ``` 一句话定义:可自定义位数,用作记录二进制的数据类型. 一,定义和初始化 ```c ...

  8. 【Luogu3808】多项式乘法FFT(FFT)

    题目戳我 一道模板题 自己尝试证明了大部分... 剩下的还是没太证出来... 所以就是一个模板放在这里 以后再来补东西吧.... #include<iostream> #include&l ...

  9. [BZOJ1045] [HAOI2008] 糖果传递 (贪心)

    Description 有n个小朋友坐成一圈,每人有ai个糖果.每人只能给左右两人传递糖果.每人每次传递一个糖果代价为1. Input 第一行一个正整数n<=,表示小朋友的个数.接下来n行,每行 ...

  10. ORM Basic

    ORM即object relational mapping 对象关系映射程序,可以在操作数据库的时候使用自有的语言而不必使用数据库的语言. 在python中,最强大的ORM框架就是SQLAlchemy ...