type
status
date
slug
summary
tags
category
icon
password
6.26
0:demo运行
跑通demo,在dmesg中观察到日志内容,解决内存问题
1: 阅读源码框架+学习
阅读demo源码,分别处理各个功能
系统调用重载 - old函数替换 new函数内容
- 在syscalltable.c中利用kprobe获得sys_call_table的首地址,尝试打印地址内容
- netlink通信 - 内核态 用户态
todo:
0. 有关审计路径的操作设置,运行模块时需要进行一定修改
- 从open函数中regs->bx获取的寄存器值无法有效的转换为文件路径的字符串 —— solved
- netlink的操作原理学习(如何实现双向通信,及通信相关知识,传输数据包如何处理等)
- 用户程序源码分析
- 系统调用表重载hook部分分析,demo中如何实现重载的hook与日志记录的功能(前期可以用printk先糊弄过去 -- solved
- probe方法获取系统调用表的简单原理学习
- 完成第一部分 -- demo代码执行 -- solved
6.27
完成核心态代码注释
解决了在vscode或nvim下可能出现的include报错问题(搭建模块时有默认的include路径,因此无需更改)
试图解决问题0:尝试如下
分析后问题主要集中在这部分代码
pt_regs为用户态的寄存器结构体,其内容大致为
在本次项目中,依据demo给出的regs->bx,判断使用i386(x86)汇编,之后搜索相关资料,试图将原本的系统调用函数open_at的各个参数意义与寄存器对应,并搜索相关资料,得到:
x86架构中,系统调用函数的参数传递对应:ebx,ecx,edx,esi,edi...(按序)
再搜索open_at函数:
sys_openat 函数的参数如下:
int dfd:打开文件的基于目录描述符的路径名。
const char __user * filename:要打开的文件的路径名。
int flags:打开文件的标志,如读取、写入、追加等。
umode_t mode:文件的访问权限。
struct file __user *file:指向表示打开文件的文件结构体的指针。
其中,dfd 和 filename 组合起来表示完整的文件路径名。
如果按照x86的构成,打印regs->bx的过程就是打开了dfd,即“打开文件的基于目录描述符的路径名”,但非常奇怪的是,这是一个int变量,而非char*,而demo的代码中试图直接将dfd转换为char* 的做法好像是不对劲的
但是很奇怪的是,在一些情况下,可以直接打印出可读的文件目录,但大部分都是以\xff格式的乱码
目前存在的问题分为两个
其一为strncpy_from_user出现的报错信息,即大量的负数返回值(返回值代表传输字符个数),demo中这个函数将bx寄存器的值转换为char*,再传输到内核态的buffer字符数组,而返回值-14代表发生了地址错误:
源字符串的地址指针不可访问,即源字符串指针超出了进程的有效地址空间范围。
目标缓冲区的地址指针不可访问,即目标缓冲区指针超出了进程的有效地址空间范围。
目标缓冲区的地址指针是demo中自己定义的buffer,而regs->bx是unsigned long的变量,明天要尝试找到问题所在
其二为乱码问题,这个更加棘手,因为目前可以打印出正确的内容,但只能打印出一点点
可能的入手点就是int dfd以及文件目录的一些关系,可以对demo进行修改
此外,关于hook部分的代码看起来比较完备和简单,关于这部分可以抽掉出一定的精力来直接进行后续第一个模块的处理。重点放在hook.c文件中的audit_init函数等。(即问题4的处理)
另外就是不需要五个人一起解决open中这个小细节的问题,我的个人感觉是在之后可以分一个人来处理netlink的通信机制,一个人解决hook的原理与其他功能的系统调用函数重载,一个人可以开始做用户程序的分析(即前端相关工作),来找一个人和我搞调用重载时寄存器的转换和修demo的bug(即问题1)
时间紧任务重啊(悲
... 修改demo代码以使其完成相关功能
6.28
在 x86 架构上,常用的系统调用参数传递规则如下:
第一个参数:存储在 pt_regs->di 寄存器中。
第二个参数:存储在 pt_regs->si 寄存器中。
第三个参数:存储在 pt_regs->dx 寄存器中。
第四个参数:存储在 pt_regs->r10 寄存器中。
第五个参数:存储在 pt_regs->r8 寄存器中。
第六个参数:存储在 pt_regs->r9 寄存器中。
转用这套架构之后,打印转换为char* 的si寄存器,可以打印出可读的文件路径
经测试,打印dx寄存器的内容后,发现为合理的权限变量。
由此,解决问题1
下一个目标,解决hook的初始化与退出相关内容,并确定从内核态到用户态的传输接口。
但是probe获取table时会报错-22.查找相关信息后发现是一个可能的内核bug,不过似乎对功能没有很大的影响,索性先隐藏下来
完成sdthook与syscalltable两个内核文件的分析,开始分析netlink
sendmsg传输的buffer:
buffer:动态分配的内存缓冲区,大小为 size。其中包含以下内容:
int 类型的用户ID(UID):存储在 buffer 的起始位置。
int 类型的进程ID(PID):存储在 buffer 的第二个 int 处。
regs->dx 的值:存储在 buffer 的第三个 int 处。这是打开文件的模式。
ret:打开文件的返回值,存储在 buffer 的第四个 int 处。
commandname 的字符串内容:紧随 buffer 中的 int 值,即位于 buffer 的 int 值之后。
fullname 的字符串内容:紧随 commandname 的字符串内容,即位于 buffer 的 int 值和 commandname 之后。
最后,通过调用 netlink_sendmsg 函数,将 buffer 中的数据发送到 Netlink 套接字。
自此,open函数的内核态hook与发送程序基本完成,可以进行下一步操作
- 对每一个系统调用,需要的内容
- 在table中的位置,即对应NR宏(数组位置)
- 函数参数,及函数参数作用
- 函数功能
目前任务:重写传输模块,hook模块与用户程序使其适应更多的重载函数。
前端工作:
搭建对文件不同操作的记录的架构,根据传递的buffer的第三个int变量来判断操作类型,接受消息时按照格式记录,对于只读的文件采取原有的架构,其他操作进行类似的记录。
由于提供对记录中某一特征的筛选合并,这里采用sql数据库来快速实现,将存储的log文件读入数据库,将合并后的结果重新写入文件。定时清理日志文件。
6.29
基本已经完成demo分析,开始进入分模块处理
今天要尽量把所有安全⽇志范围的扩展中需要涉及到的系统调用和参数找全,并初步完成功能框架(反正大部分都是复制粘贴)
放一个今日todo在这里
- 搜索各系统调用的参数与相关作用,返回值等
- 学习基于socket的通信原理,以更好的实现通信类的系统调用重载
- 开始进行部分子模块的开发
- 重新考虑demo中各个模块的架构是否合理
资源访问类操作:
!!!
关于索引位置:例如sys_call_table[__NR_openat] 对应的函数是 sys_openat,sys_call_table[__NR_unlink] 对应的函数是 sys_unlink,以此类推。
!!!
有部分函数还没有完成查找,同时关于一些系统调用(尤其是网络相关)需要学习相关知识来完成日志审计系统的开发,至少我现在是看不懂网络相关调用都在做些什么
打开文件(openat):
删除文件(unlinkat):
参数列表:
- regs->di: int dirfd: 文件描述符
- regs->si: const char *pathname:被删除文件的路径名。可以是绝对路径或相对 dirfd 参数的相对路径。
- regs->dx: flags:0表示删除文件 200表示删除文件夹(16进制) 目前已经可以实现unlinkat重载。
执行程序:
对应的系统调用函数是execve。它的参数是一个字符串指针数组,包含可执行程序的路径和命令行参数。该函数的作用是执行指定的可执行程序。审计内容可能包括执行的程序路径、命令行参数和执行该操作的进程信息。
const char __user *filename:要执行的程序的路径名。
const char __user *const __user *argv:命令行参数列表。
const char __user *const __user *envp:环境变量列表。
sys_execve 函数用于执行指定路径下的程序。它接受一个程序的路径名以及命令行参数列表和环境变量列表作为参数。该函数将加载指定的程序到当前进程的地址空间,并将其执行。通过命令行参数和环境变量,可以向程序传递额外的参数和配置信息。执行过程中,操作系统会根据程序的权限和当前用户的权限进行权限检查,并在权限验证通过后执行程序。
系统管理类操作:
关机或重启系统:
对应的系统调用函数是reboot。它的参数是一个整数,表示要执行的操作类型。该函数的作用是关机或重启系统。审计内容可能包括操作类型和执行该操作的进程信息。
int magic1:用于验证系统重启请求的幻数。
int magic2:用于验证系统重启请求的幻数。
unsigned int cmd:重启命令参数。
sys_reboot 函数用于执行系统重启操作。它接受两个幻数参数和一个重启命令参数。幻数的目的是为了验证系统重启请求的合法性,以防止误操作。重启命令参数指示了具体的重启操作,例如立即重启、重新启动到特定的引导程序或进入电源管理状态等。执行系统重启操作需要特权权限,因此只有具有足够权限的进程才能调用该函数。
内核模块加载:
对应的系统调用函数是init_module。它的参数是一个指向模块信息的结构体指针。该函数的作用是加载内核模块。审计内容可能包括加载的模块信息和执行该操作的进程信息。
void __user *umod:指向要加载的内核模块的用户空间指针。
unsigned long len:内核模块的大小。
const char __user *uargs:加载内核模块时传递的参数。
sys_init_module 函数用于加载内核模块。它接受一个指向内核模块的用户空间指针、内核模块的大小以及加载模块时传递的参数。该函数将加载指定的内核模块到内核中,并执行相关的初始化操作。加载内核模块需要特权权限,因此只有具有足够权限的进程才能调用该函数。
设备添加:
对应的系统调用函数可能是mknod。它的参数是一个字符串,表示设备文件的路径和类型。该函数的作用是在文件系统中创建设备节点。审计内容可能包括设备文件路径、设备类型和执行该操作的进程信息。
const char __user *filename:要创建的文件的路径名。
umode_t mode:文件的访问权限。
unsigned dev:设备号。
sys_mknod 函数用于创建一个设备节点(特殊文件)。它接受一个文件路径名、文件的访问权限以及设备号作为参数。通过指定的参数,函数将在指定路径下创建一个特殊文件,用于与设备进行交互。设备号标识了要与之关联的设备。创建设备节点需要特权权限,因此只有具有足够权限的进程才能调用该函数。
挂载及卸载文件系统:
对应的系统调用函数可能是mount和umount。它们的参数包括文件系统类型、挂载点路径等。mount函数的作用是挂载文件系统,umount函数的作用是卸载文件系统。审计内容可能包括文件系统类型、挂载点路径和执行该操作的进程信息。
char __user *dev_name:设备名称或文件路径名。
char __user *dir_name:挂载点的路径名。
char __user *type:文件系统类型。
unsigned long flags:挂载选项。
void __user *data:文件系统特定的数据。
sys_mount 函数用于挂载文件系统。它接受设备名称或文件路径名、挂载点的路径名、文件系统类型、挂载选项以及文件系统特定的数据作为参数。通过指定的参数,函数将指定的文件系统挂载到指定的挂载点上。挂载操作将文件系统与指定的设备或文件关联起来,使得可以在挂载点上访问文件系统中的内容。挂载文件系统需要特权权限,因此只有具有足够权限的进程才能调用该函数。
char __user *name:要卸载的挂载点路径名。
int flags:卸载选项。
sys_umount 函数用于卸载文件系统。它接受要卸载的挂载点路径名和卸载选项作为参数。通过指定的参数,函数将卸载指定的挂载点上挂载的文件系统。卸载操作将断开文件系统与挂载点之间的关联,并释放相关的资源。卸载文件系统需要特权权限,因此只有具有足够权限的进程才能调用该函数。
通信类操作:
网络类通信:
涉及的系统调用函数有很多,如socket、bind、connect、send、recv等,它们位于sys_call_table中的相应索引位置。这些函数的参数包括协议类型、套接字描述符、地址信息、数据缓冲等。这些函数用于创建和管理网络连接以及进行数据传输。审计内容可能包括通信协议、套接字描述符、地址信息、数据内容和执行该操作的进程信息。
在Linux中,通信类操作涉及各种类型的通信,其中包括网络类通信。网络通信是在不同主机之间进行数据交换和传输的过程。在Linux中,通信过程涉及到以下几个步骤:
- 创建套接字(Socket):通信的起点是创建套接字,它是进行网络通信的接口。套接字可以被认为是一种特殊的文件描述符,用于读取和写入网络数据。在Linux中,可以使用系统调用函数socket()来创建套接字。该函数返回一个文件描述符,用于后续的通信操作。
- 绑定地址和端口:在进行网络通信时,需要将套接字绑定到一个特定的地址和端口上。这可以通过系统调用函数bind()来实现。绑定操作将指定的地址和端口与套接字关联起来,使得其他主机能够通过该地址和端口与本主机进行通信。
- 监听连接请求(可选):如果本主机需要接受其他主机的连接请求(如在服务器端),则需要使用系统调用函数listen()来监听连接请求。监听操作使得套接字处于等待连接状态,等待其他主机的连接请求。
- 接受连接请求(可选):当套接字处于监听状态时,可以使用系统调用函数accept()来接受其他主机的连接请求。接受操作创建一个新的套接字,用于与请求方进行通信。该新套接字将作为后续通信的文件描述符。
- 发起连接请求(可选):如果本主机需要连接到其他主机(如在客户端),则可以使用系统调用函数connect()来发起连接请求。连接操作将套接字连接到目标主机的指定地址和端口上,使得本主机能够与目标主机进行通信。
- 数据传输:一旦连接建立或者连接请求接受,就可以通过已连接的套接字进行数据传输。数据传输可以使用系统调用函数send()和recv()来发送和接收数据。send()函数用于将数据从本主机发送到目标主机,而recv()函数用于接收来自目标主机的数据。
- 关闭连接:当通信结束时,可以使用系统调用函数close()来关闭套接字。关闭操作释放套接字所占用的资源,并终止通信。
在这个过程中,涉及到的一些关键的系统调用函数包括:
- socket():创建套接字。
- bind():绑定地址和端口。
- listen():监听连接请求。
- accept():接受连接请求。
- connect():发起连接请求。
- send():发送数据。
- recv():接收数据。
- close():关闭套接字。
注意,除了主机与主机之间的通信之外,网络通信还涉及以下几种类型:
进程间通信(Inter-Process Communication,IPC):在同一台主机上的不同进程之间进行通信。这种通信可以通过套接字(Socket)编程、管道(Pipe)、消息队列(Message Queue)、共享内存(Shared Memory)等机制实现。
客户端-服务器通信:在网络环境中,客户端与服务器之间进行通信是最常见的情况。客户端向服务器发送请求,服务器处理请求并返回响应。这种通信模式使用套接字编程,客户端使用connect()建立与服务器的连接,服务器使用accept()接受客户端连接。
广播通信:广播通信是一种将数据包从一个主机发送到同一网络中的所有主机的通信方式。发送方使用特定的广播地址将数据包发送到网络上的所有主机。接收方的所有主机都能够接收到这个数据包。
等等
socket
int family:套接字的地址族。
int type:套接字的类型。
int protocol:协议类型。
sys_socket 函数用于创建一个套接字。它接受一个地址族、套接字类型和协议类型作为参数,并根据指定的参数创建相应的套接字。套接字用于在网络上进行通信,它具有唯一的地址和端口号,可以用于发送和接收数据。创建套接字时,操作系统会分配相应的资源并返回套接字的文件描述符。
bind
int sockfd:要绑定地址的套接字的文件描述符。
struct sockaddr __user *addr:指向要绑定的地址结构的用户空间指针。
int addrlen:要绑定的地址结构的长度。
sys_bind 函数用于将一个套接字绑定到指定的地址。它接受一个套接字的文件描述符、指向要绑定的地址结构的用户空间指针以及地址结构的长度作为参数。通过指定的参数,函数将套接字绑定到指定的地址上,使得套接字与该地址关联起来。绑定套接字时,可以指定不同的地址族和地址类型,例如IP地址和端口号。成功绑定后,套接字就可以通过该地址进行通信。
可能的打印addr相关信息的代码(包括ip与port)
connect
int sockfd:要连接的套接字的文件描述符。
struct sockaddr __user *addr:指向要连接的目标地址结构的用户空间指针。
int addrlen:目标地址结构的长度。
sys_connect 函数用于通过套接字与远程主机建立连接。它接受一个套接字的文件描述符、指向要连接的目标地址结构的用户空间指针以及目标地址结构的长度作为参数。通过指定的参数,函数将套接字与指定的目标地址建立连接,使得可以通过套接字进行数据的发送和接收。连接操作涉及网络通信,需要目标主机的地址和端口号等信息。
一个关于socket讲的很好的视频:
https://www.bilibili.com/video/BV12A411X7gY/?spm_id_from=333.337.search-card.all.click&vd_source=1792303ecb1720785d8b0e23ac4aa209
再一次分析以前的作业,有许多可以借鉴的地方。值得注意的是,在这个项目中出现了比目前demo复杂的多的netlink模块,之后可能需要改进。同时,在后续分子模块实现功能时,宏定义是比较有必要的,因此分离出h和c文件可以列入todo中
6.30
reboot重载遇到挫折
使用reboot命令会调用的关键函数:https://elixir.bootlin.com/linux/latest/source/kernel/reboot.c源码中line700开始的SYSCALL_DEFINE4
reboot流程:https://blog.csdn.net/zhouhuacai/article/details/78154359
研究发现,直接采用openat类似的方法尝试截获reboot的系统调用的方法不可行(即修改__NR_openat为__NR_reboot),若不是修改方式错误的问题,目前猜测可能的原因有以下两种:
- 直接调用reboot不会像openat那样调用syscall_table,而是通过/usr/sbin/reboot可执行文件进行后续处理。这一过程中主要用到的是kernel/reboot.c中的SYSCALL_DEFINE4函数,在本次粗略观察中并未发现直接与syscall_table指向的地址相联系的部分。故如果需要修改,可能会涉及内核重编译(?),与本项目的实现方式相悖。
- syscall_table中的__NR_reboot部分有效,但支持的重启操作不包括在命令行中执行reboot。为验证此想法进行文章搜索,并未有较为明确指明syscall_table和SYSCALL_DEFINE4函数联系的文章,但因为梯子挂了所以没用gpt和外网,还存在一定的探索空间。
可能的解决方案:
- linux有自带的诸如
last reboot
命令等方式查看reboot、shutdown等行为的发生时间,或许可以偷懒直接想办法读取相应位置的日志信息来进行我们的审计记录。
- 重编译内核,但如果沿用netlink,将会涉及发送日志信息后要等待用户态回复记载完毕的信号,再进行后续操作(避免记载完全前就被kill),涉及的工程量与收益差距较大,同时不一定符合项目要求。 同理,研究linux自身的记录reboot的log的机制再加以应用也不一定能逃得开重编译内核的问题。
- 关于reboot的补充研究...
TODO
系统重载的范围扩展
reboot的debug
关于
似乎是可以的(参照过去作业
文件系统目录和路径关系
@sfx 似乎可能出现的文件路径问题
目前已解决
新的重载?
hth
用户态和核心态的netlink通信传输——双向?
3模块
后台程序的开发
zts
前端日志处理数据库
wck
CLI交互界面?
kernel.ko --buffer--> 后台程序 --xxx--> database --xxx--> UI
可以抄😈
7.1
netlink
宏观介绍:https://zhuanlan.zhihu.com/p/530687422
sendmsg&recvmsg:https://blog.csdn.net/u014209688/article/details/71311973
基本逻辑:
装载模块---->模块初始化---->audit_init()内部netlink_init()---->调用netlink_kernel_create()---->注册消息处理回调input为函数nl_data_ready()---->等待用户态sendmsg,函数input会在发送进程执行sendmsg()时被调用
当用户态开启监听程序auditdemo.c时:调用sendpid()---->经过包装将pid通过sendmsg发送---->内核态收到信息触发nl_data_ready()---->将pid值赋给netlinkp.c中声明的pid---->此后netlink_sendmsg()中可以越过pid==0的判断进行消息发送,发送方式为netlink_unicast()函数,发送目标需指定进程号
netlink_unicast()
int netlink_unicast(struct sock *ssk, struct sk_buff *skb, u32 pid, int nonblock)
参数说明:
(1) ssk:为函数 netlink_kernel_create()返回的socket。
(2) skb:存放消息,它的data字段指向要发送的netlink消息结构,而 skb的控制块保存了消息的地址信息,宏NETLINK_CB(skb)就用于方便设置该控制块。
(3) pid:为接收此消息进程的pid,即目标地址,如果目标为组或内核,它设置为 0。
(4) nonblock:表示该函数是否为非阻塞,如果为1,该函数将在没有接收缓存可利用时立即返回;而如果为0,该函数在没有接收缓存可利用定时睡眠。
总结:
监听模块多开的话后开的会取代前开的,内核可以根据进程号来发送信息(即支持每一个审计的功能开一个程序);
只开一个进程统一接收所有内核发来的信息再进行筛选是可行的,且此筛选可以在接收到信息时进行(即写在代码里,但这样如果要调整的话就需要重编译)。
如果之后遇到系统负载过大、sql处理不过来等问题的话再考虑将每个模块的信息发送接收独立开。
7.2
系统调用重载指南:
目前的架构允许进行多种重载的共同监听。
- sdthook.c文件中audit_init函数内添加syscall_table[__NR__XX]对应位置的拦截,改为指向hacked_XX
- 仿照sdthook.c文件中hacked_openat写hacked_XX,调用AuditXX
- 仿照netlinkp.c文件中AuditOpenat写AuditXX,并记得使用对应的flag位(注意在传输内容的第一位传输flag);其中netlink_sendmsg函数不需改动
- 在audidemo.c文件中recvmsg后添加接收到对应flag位的信息时要调用的log函数,在while(1)循环中添加对应log位置
- 进行简单测试,验证是否完成重载操作
关于reboot
Fuck it
应该转向使用更好的记录方式
更好的记录方式:在用户态运行一个程序,其利用系统自身的命令获取开关机记录,本程序(GetRebootLog.c)将这些信息进行处理后输出到另一个文件或其他接收信息的接口上,本程序已在github上AuditReboot文件夹下上传。
即reboot可能不需要重载来解决...
用户态数据库
目前已完成功能:数据库的初始化、表的创建,插入某字符串常量,查询某字符串常量(但是返回found和callback函数两个参数意义不清)。
接下来要完成:
1.对char*和char[]的明确区分
2.写双线程,保证用户随时输入都能够响应
3.将字符串常量变成字符串变量
4.sql其他语句的构造
5.最后需要将users和其他元素的sql查询语句写成重载函数,保证代码的精简。
关于通信类的重载问题
关于通信类我大概推定的是三个重载点
其中socket重载提供的信息主要是开始了网络通信,以及标注通信的对应文件fd
bind和connect重载都可以提供连接的id和port信息,作为可读信息而言较重要
然而我经过一段时间的尝试,发现在重载bind之后无法正常打开浏览器,也会经常出现内存消耗过大sudo进程全部被kill的情况
因此转向为尝试connect重载,发现可以打开浏览器,也可以区分dmesg和浏览器之间一些信息的差异
但是问题就是包含网络通信参数的结构体需要一些路径的配置才能有效读取,依赖关系较为复杂,目前主要研究这个难点
7.3
一些疑惑
目前auditdemo能审计到的进程(含有openat)有ls, touch, pool-gjs(这个是hook的进程,有时能审计到有时审计不到)。rm cd 这种命令应该也会调用printk,但是不知道为什么审计不到。
7.4
hth
unlinkat、openat和execve的重载已经完成。
execve 在sudo 之类的操作时都会调用(比如运行sudo sfx.sh时会先运行sudo,再运行sh 最后再运行sfx.sh ),目前是都过滤掉的,后面再考虑是否要显示。
但是我的代码显示没问题写到log里面好像不成功,我暂时先没管这个。
7.5
日志还是要写的
关于通信的研究
在这里卡了三天之后终于解决的killed问题:
我试图打印的connect和bind的相关信息中有部分内存是不可读不可写内存(至少对于模块的重载而言是这样),因此在进行操作时会进入保护模式
之后采用地址转换的方法,直接抓取参数对应地址并转移到用户态,此后再分为各个参数处理
关于重载传输到用户态(即Auditopen类似函数)
经过测试,目前Github上main分支的传输可以建立
module的install和delete
安装模块时会将所安装的模块的路径输出
卸载模块时会将所卸载的模块的名字输出
7.6
今天晚上开会!
关于branch
在之后的更新中最好直接从main分支拉取,这次我会手动合并不同分支的内容,如果是main的话就可以自动merge
重载名称 | 功能 | 审计值(传输值) |
openat | 打开文件 | 文件路径 文件类型 是否成功 |
unlinkat | 删除文件 | 删除文件地址 是否成功 |
execve | 执行程序 | 执行程序地址 是否成功 |
read | 读文件 | 读的文件地址 是否成功 |
write | 写文件 | 写到文件的路径(写到终端的忽略了) 是否成功 |
close | 关闭文件 | 关闭文件的路径 |
reboot | 记录重启、关机的时间等信息 | 比较特殊,本程序是独立在用户态运行的,不会传输 |
socket | 创建套接字 | 套接字内容 是否成功 |
connect | 与主机建立连接 | ip port 是否成功 |
init_module | 记录装载模块 | 装载的模块的路径 |
mknod | 创建各种文件 | 文件路径 文件类型 是否成功 |
mount | ㅤ | ㅤ |
umount | ㅤ | ㅤ |
delete_module | 记录卸载模块 | 卸载的模块的名称 |
下周三开会
系统重载
file last hth
mount umount sfx
mknod
通信类 close recv lfz
后台程序
规范一下传输内容 all
github
需要把不同文件夹的分支内容进行审计,测试和合并。。。
灵活性拓展
关于灵活性拓展,我认为应该暂时不采用netlink动态调整配置的方法
工作流应该如下:
在ui中可视化的调整配置(如监听哪些功能,只监听哪些路径) -> 传输到后台程序 -> 后台程序更改本地配置文件 -> 运行脚本,将后台程序与内核模块重新编译 -> 重新开始
关于实现这种功能的方法,也许可以使用ifdef和宏定义来简单的实现,之后我会做更多关于这个的研究。
前端
going
通过看之前作业,可能还需要做关于自动测试脚本(只交pdf真的需要这个吗w)
7.8
github合并
完成各个分支的合并,现在main分支为物理合并的样子
log统一化
mount和umount
基本截取已完成,但mount有不同的调用方式,目前只用了U盘插入时的mount调试,能够得到设备名、所用的文件系统等信息。在此之外还有其他的系统自身的mount调用参数格式与之不一样,还需研究。
关于log的统一化
我设定的信息流如下:
hacked_xxx获取参数 -> Auditxxx传输 -> PreLog中按照传输规范来进行分类和获取参数 -> 分别传输到不同的LogXXX中进行处理
其中我约定的传输规范如下:
buffer -->
0: flag(__NR_XXX)
1: uid
2: pid
3: arg1(int) 可能传输的3个int值参数
4: arg2
5: arg3
6: ret
7: command name(char *)
8: arg_char(char *) 可能传输的字符串
具体可以参考openat函数的信息流
- sfx部分的后台程序那里没有写,所以我就都没改,之后按照这个格式自己改一下 sfx:已改已传
7.9
7.10
mount&umount
目前mount可正常工作,umount存在问题,经过debug排查初步判定为与AuditOpenat()中get_fullname()中kern_path()相冲突,分析解决方案有二:
一、 重写get_fullname函数:替换掉kern_path,但尚未找到较好的替换函数,且不确定替换后是否能用;
二、 在运行umount时暂停AuditOpenat()的功能,但经过尝试后,初步判断发生冲突的时间节点不在hacked_umount()函数周期内,仍需深入研究冲突原因并寻找其他方案。
hth
mknodat搞完了,目前在尝试给insmod传参数。
发现可以直接利用module_param()给insmod传参数,不需要编译到时候可以写一个脚本直接执行rmmod和insmod即可,就是需要修改一下可能需要给每个重载的函数都增加传入一些参数。
实现了。是可以传参数的。
退出功能
我认为每次都ctrl+c退出有点不对劲,以后写前端也不好写,正在找一个合适的退出方法
7.12
todo
sfx 吊函数 logfile格式化
不用吊函数了,在前人的馈赠的基础上改,测试下来貌似没太大问题,明天把他写了
hth 吊函数 logfile格式化
lfz 退出功能 通信的函数如recv等 github审核
wck zts 前端
这周六上午11:00开会
7.13
7.14
getfullname解决了(openat监听重写了一下,用的是getinfofromfd),initmodule、deletemodule、mount、umount更新了,但不会push,不知道传上去没,发发开会的时候直播指导一下
- Author:faii
- URL:https://www.faii.top/article/742b3bfd-1e4b-42f2-98b7-9e9b3bab6cd4
- Copyright:All articles in this blog, except for special statements, adopt BY-NC-SA agreement. Please indicate the source!
Relate Posts