本文是「驭龙」系列的第三篇文章,对照代码解析了驭龙在Linux执行命令监控驱动这块的实现方式。在正式宣布驭龙项目开源之前,YSRC已经发了一篇关于驭龙EventLog 读取模块迭代历程的文章。

0x00 背景介绍

Linux上的HIDS需要实时对执行的命令进行监控,分析异常或入侵行为,有助于安全事件的发现和预防。为了获取执行命令,大致有如下方法:

遍历/proc目录,无法捕获瞬间结束的进程。

Linux kprobes调试技术,并非所有Linux都有此特性,需要编译内核时配置。

修改glic库中的execve函数,但是可通过int0x80绕过glic库,这个之前360 A-TEAM一篇文章有写到过。

修改sys_call_table,通过LKM(loadable kernel module)实时安装和卸载监控模块,但是内核模块需要适配内核版本。

综合上面方案的优缺点,我们选择修改sys_call_table中的execve系统调用,虽然要适配内核版本,但是能100%监控执行的命令。

0x01 总体架构

首先sys_execve监控模块,需要替换原有的execve系统调用。在执行命令时,首先会进入监控函数,将日志通过NetLink发送到用户态分析程序(如想在此处进行命令拦截,修改代码后也是可以实现的),然后继续执行系统原生的execve函数。

0x02 获取sys_call_table地址

获取sys_call_table的数组地址,可以通过/boot目录下的System.map文件中查找。

命令如下:

cat /boot/System.map-`uname-r` | grep sys_call_table

这种方式比较麻烦,在每次insmod内核模块的时候,需要将获取到的地址通过内核模块传参的方式传入。而且System.map并不是每个系统都有的,删除System.map对于系统运行无影响。

我们通过假设加偏移的方法获取到sys_call_table地址,首先假设sys_call_tale地址为sys_close,然后判断sys_call_table[__NR_close]是否等于sys_close,如果不等于则将刚才的sys_call_table偏移sizeof(void *)这么多字节,直到满足之前的判断条件,则说明找到正确的sys_call_table的地址了。

代码如下:

unsigned long **find_sys_call_table(void) {

unsigned long ptr;

unsigned long *p;

pr_err("Start foundsys_call_table.n");

for (ptr = (unsignedlong)sys_close;

ptr < (unsignedlong)&loops_per_jiffy;

ptr += sizeof(void*)) {

p = (unsigned long*)ptr;

if (p[__NR_close] ==(unsigned long)sys_close) {

pr_err("Foundthe sys_call_table!!! __NR_close[%d] sys_close[%lx]n"

"__NR_execve[%d] sct[__NR_execve][0x%lx]n",

__NR_close,

(unsigned long)sys_close,

__NR_execve,

p[__NR_execve]);

return (unsignedlong **)p;

}

}

return NULL;

}

0x03 修改__NR_execve地址

即使获取到了sys_call_table也无法修改其中的值,因为sys_call_table是一个const类型,在修改时会报错。因此需要将寄存器cr0中的写保护位关掉,wp写保护的对应的bit位为0x00010000。

代码如下:

unsigned long original_cr0;

original_cr0 = read_cr0();

write_cr0(original_cr0 & ~0x00010000); #解除写保护

orig_stub_execve = (void *)(sys_call_table_ptr[__NR_execve]);

sys_call_table_ptr[__NR_execve]= (void *)monitor_stub_execve_hook;

write_cr0(original_cr0); #加上写保护

在修改sys_call_hook[__NR_execve]中的地址时,不只是保存原始的execve的地址,同时把所有原始的系统调用全部保存下载。

void *orig_sys_call_table [NR_syscalls];

for(i = 0; i < NR_syscalls - 1; i ++) {

orig_sys_call_table[i] =sys_call_table_ptr[i];

}

0x04 Execve进行栈平衡

除了execve之外的其他系统调用,基本只要自定义函数例如:my_sys_write函数,在此函数中预先执行我们的逻辑,然后再执行orig_sys_write函数,参数原模原样传入即可。但是execve不能模仿上面的写法,用以上的方法可能会导致Kernel Panic。

需要进行一下栈平衡,操作如下:

1.义替换原始execve函数的函数monitor_stub_execve_hook

.text

.global monitor_stub_execve_hook

monitor_stub_execve_hook:

2.在执行execve监控函数之前,将原始的寄存器进行入栈操作:

pushq %rbx

pushq %rdi

pushq %rsi

pushq %rdx

pushq %rcx

pushq %rax

pushq %r8

pushq %r9

pushq %r10

pushq %r11

3.执行监控函数并Netlink上报操作:

call monitor_execve_hook

4.入栈的寄存器值进行出栈操作

pop %r11

pop %r10

pop %r9

pop %r8

pop %rax

pop %rcx

pop %rdx

pop %rsi

pop %rdi

pushq %rbx

5.执行系统的execve函数

jmp *orig_sys_call_table(, %rax, 8)

0x05 执行命令信息获取

监控执行命令,如果用户态使用的是相对路径执行,此模块也需要获取出全路径。通过getname()函数获取执行文件名,通过open_exec()和d_path()获取出执行文件全路径。通过current结构体变量获取进程pid,父进程名,ppid等信息。同时也获取运行时的环境变量中PWD,LOGIN相关的值。

最终将获取到的数据组装成字符串,用ascii码值为0x1作为分隔符,通过netlink_broadcast()发送到到用户态分析程序处理。

0x06 监控效果

在加载内核模块,在用户态执行netlink消息接收程序。然后使用相对路径执行命令./t my name is xxxx,然后查看用户态测试程序获取的数据。

0x07 版本支持及代码

支持内核版本:2.6.32, >=3.10.0

关注公众号后回复 驭龙,加入驭龙讨论群。

linux运行驱动的命令,「驭龙」Linux执行命令监控驱动实现解析相关推荐

  1. docker 容器运行 golang程序_「Docker」 - 运行 amp; 管理容器

    容器是基于容器技术所建立和运行的轻量级应用运行环境,它是Docker封装和管理应用程序或微服务的「集装箱」,在Docker中,容器是最核心的部分. 一.容器的创建和启动 Docker容器的生命周期里分 ...

  2. 「推荐」Linux远程连接工具之ssh客户端工具

    Ubuntu下Finalshell的安装 Ubuntu20.04安装 FinalShell远程工具 「推荐」Linux远程连接工具之ssh客户端工具

  3. 通达信板块监控指标_「600503」通达信主力监控系统指标公式

    「600503」通达信主力监控系统指标公式 DRAWRECTREL(0,0,990,990,RGB(20,18,12)); DRAWTEXT_FIX(1,0.14,0.01,1,"股东股份: ...

  4. linux开源社区贡献代码,4岁小萝莉向Linux内核贡献代码修复「漏洞」而且代码已经合并到内核...

    最近国外社区 Reddit 上有个非常有趣的讨论 ,  在过去发布的Linux内核中有处代码改进是名4岁的小萝莉提交的. 这名小萝莉向内核提交代码以修复某处「漏洞」,这次代码修订还是在 2014 年发 ...

  5. 冒充linux内核,4岁小萝莉向Linux内核贡献代码修复「漏洞」而且已经合并到内核...

    最近国外社区 Reddit 上有个非常有趣的讨论 , 在过去发布的 Linux 内核中有处代码改进是名4岁的小萝莉提交的. 这名小萝莉向内核提交代码以修复某处「漏洞」,这次代码修订还是在 2014 年 ...

  6. linux 增加自动恩物,「4bays」窮人備份恩物! Synology DiskStation 418

    Synology DiskStation 418 處於數據幾何級增長及病毒肆虐的時代,資料備份相信對企業.家庭或個人用戶應該並不陌生,或許面對過加密病毒或硬碟磁區損壞的用家應更為深刻,而 Synolo ...

  7. linux 最小 电脑,世上最小「电脑」,能让一颗白米都显得像庞然大物

    University of Michigan IBM 在年初刚获得的「世上最小电脑」的宝座,似乎还没坐热就要送给这由密歇根大学研究员所制造的温度感知「电脑」了,因为这款电脑就只有 0.04 立方毫米, ...

  8. Linux后台开发系列之「01.安装 Linux 软件的 3 种方法」

    版权声明:本文为 cdeveloper 原创文章,可以随意转载,但必须在明确位置注明出处! 前言 学习 Linux 必须要学会如何安装和卸载应用程序,这次就来简单介绍下在 Linux 上安装和卸载软件 ...

  9. linux命令之watch -- 周期性地执行命令

    watch是一个非常实用的命令,基本所有的Linux发行版都带有这个小工具,如同名字一样,watch可以帮你监测一个命令的运行结果,省得你一遍遍的手动运行. 在Linux下,watch是周期性的执行下 ...

最新文章

  1. linux-进程切换,用户态进程,内核态进程
  2. 鬼泣4计算机丢失xinput,Win7系统运行游戏报错“计算机丢失XINPUT1-3.dll”
  3. wireshark抓包分析tcp连接与断开
  4. Windows集群网络配置最佳做法
  5. Basic Calculator II
  6. Hello World@@@@
  7. 利用DOSBox运行汇编超详细步骤
  8. Mac下如何修改IDEA的背景颜色
  9. c语言字符串常量表达,C语言基础教程:字符常量和字符串常量
  10. Java将指定文件/文件夹压缩成zip、rar压缩文件--解決中文乱码
  11. 高动态范围(High-Dynamic Range,简称HDR)
  12. linux终端串口调试(RS232 serial ttyS)
  13. 为perf4j提供集中式监控项目perf4j-dashboard
  14. Pr 视频效果:扭曲
  15. ASP.NET Image Manipulation Examples: Adding, Zooming, Enlarging
  16. 大学计算机基础模拟试题
  17. C++:实现量化Integration积分测试实例
  18. Android Watchdog框架解析、应用与改造(上)
  19. 假设你是个妹子,你敢这样谈恋爱吗?
  20. 上海车展,没有争奇斗艳的车模,只有往死里卷的智能汽车

热门文章

  1. 正则表达式 我们的泷泽萝拉
  2. Linux wget 命令下载文件示例
  3. Java 静态方法与非静态方法的调用
  4. QTextEdit详解(设置显示内容的两种方式(setPlainText/insertPlainText、滚动条自动(往下、往上)滚动……)
  5. 破解10亿数据点数据实时可视化
  6. 搜狗推出卫星地图服务
  7. C#版系统自检,支持网络、摄像头、麦克风、扬声器、蓝牙检测
  8. 基于Docker搭建分布式文件系统FastDfs
  9. “回复TD退订”的短信,到底要不要回?终于有答案了
  10. 基于VMware创建虚拟机以及安装虚拟机系统