1,系统调用日志收集系统的意义。
系统调用是用户获取系统服务的唯一入口,因此对系统调用的安全调用直接关系到系统
的安全,假如有用户恶意不断地调用系统调用,将会导致系统负载增加,所以如果能收集到时谁
调用了一些危险的系统调用,以及调用系统调用的时间和其他信息,将有助于系统管理员进行事
后追踪,从而提高系统的安全性。
--------------------------------------------------------------

2,系统调用日志收集系统总体框架图。

-----------------------------------------------------------
3,系统调用日志收集系统的实现。(以linux-2.6..39.4为例)
3.1,添加系统调用号.
位置:arch/x86/include/asm/unistd_32.h
        #define  __NR_syscall_audit   345
        #define  __NR_myaudit         346
        #ifdef   __KERNEL__
        #define  NR_syscalls   347
---------------------------------------------------------- 
3.2,在系统调用表中添加相应的表项。
        .long    sys_syscall_audit
        .long    sys_myaudit
-----------------------------------------------------------
3.3,修改系统调用入口。(有两个入口,syscall_call和sysenter)
位置:arch/x86/kernel/entry_32.S
        主要是在系统调用的两个入口进行监控,发现调用了如下四个系统调用(getpid,sysinfo,fork,execv)
将会执行sys_syscall_audit函数。

  1. syscall_call:
  2. call *sys_call_table(,%eax,4)
  3. movl %eax,PT_EAX(%esp)        # store the return value
  4. #如下位添加代码
  5. #----------------------------------------------------
  6. cmpl $20,0x2c(%esp) #getpid()
  7. je myauditsys
  8. cmpl $116,0x2c(%esp) #sysinfo()
  9. je myauditsys
  10. cmpl $2,0x2c(%esp) #fork
  11. je myauditsys
  12. cmpl $11,0x2c(%esp) #execv
  13. je myauditsys
  14. #-----------------------------------------------
  1. syscall_exit:
  2. LOCKDEP_SYS_EXIT
  3. ...
  4. jne syscall_exit_work
  5. #如下位添加代码
  6. #------------------------------------------------
  7. jmp restore_all
  8. myauditsys:
  9. pushl %eax
  10. pushl 0x30(%esp)
  11. call sys_syscall_audit
  12. popl %eax
  13. popl %eax
  14. jmp syscall_exit
  15. #------------------------------------------------
  16. restore_all:
  17. TRACE_IRQS_IRET
  1. sysenter_do_call:
  2. ...
  3. movl %eax,PT_EAX(%esp)
  4. #如下为添加代码
  5. /*--------------------------------------------------------*/
  6. cmpl $20,0x2c(%esp) #getpid()
  7. je enter_audit
  8. cmpl $116,0x2c(%esp) #sysinfo()
  9. je enter_audit
  10. cmpl $2,0x2c(%esp) #fork
  11. je enter_audit
  12. cmpl $11,0x2c(%esp) #execv
  13. je enter_audit
  14. come_back:
  15. /*--------------------------------------------------------*/
  1. sysenter_exit:
  2. ....
  3. ENABLE_INTERRUPTS_SY***IT
  4. /*--------------------------------------------------------*/
  5. jmp sysenter_audit
  6. enter_audit:
  7. pushl %eax
  8. pushl 0x30(%esp)
  9. call sys_syscall_audit
  10. popl %eax
  11. popl %eax
  12. jmp come_back
  13. /*--------------------------------------------------------*/

--------------------------------------------------------------------------------------------
       3.4,添加系统调用的服务例程。
      在arch/x86/kernel/下面添加文件myaudit.c
    该文件中实现了系统调用的服务例程,但这儿实现的服务例程都只有一个接口,
真正的实现将在模块中实现,这样是为了方便调试,避免了多次编译内核。这儿主要
是通过两个全局变量(my_audit和my_sysaudit)与内核模块之间建立了联系。

  1. /**
  2. * myaudit.c
  3. */
  4. #include <linux/proc_fs.h>
  5. #include <linux/init.h>
  6. #include <linux/types.h>
  7. #include <linux/sched.h>
  8. #include <asm/current.h>
  9. void (*my_audit)(int, int) = 0;
  10. asmlinkage void sys_syscall_audit(int syscall_number, int return_value)
  11. {
  12. if (my_audit) {
  13. return (*my_audit)(syscall_number, return_value);
  14. printk("IN KERNEL: %s(%d), syscall: %d, return: %d\n", current->comm, (int)current->pid, syscall_number, return_value);
  15. //printk("IN KERNEL: %s\n", current);
  16. } else {
  17. printk("my_audit is empty!\n");
  18. }
  19. return ;
  20. }
  21. int (*my_sysaudit)(u8, u8*, u16, u8) = 0;
  22. asmlinkage int sys_myaudit(u8 type, u8 *us_buf, u16 us_buf_size, u8 reset)
  23. {
  24. if (my_sysaudit) {
  25. return (*my_sysaudit)(type, us_buf, us_buf_size, reset);
  26. printk("IN KERNEL: my system call sys_myaudit() working...\n");
  27. } else {
  28. printk("my_sysaudit is empty!\n");
  29. }
  30. return 0;
  31. }

----------------------------------------------------------------------------------------------
       3.5,修改makefile。位置:arch/x86/kernel/Makefile

  1. obj-y            := process_$(BITS).o signal.o entry_$(BITS).o myaudit.o

----------------------------------------------------------------------------------------------
       3.6,导出全局变量。(不导出的话,内核模块将对其不可见)
            修改arch/x86/kernel/i386_ksyms_32.c文件,在其末尾追加:

  1. EXPORT_SYMBOL(my_audit);
  2. EXPORT_SYMBOL(my_sysaudit);

----------------------------------------------------------------------------------------------
        3.7,声明全局变量。
             修改:include/linux/module.h 添加:

  1. extern void (*my_audit)(int,int);
  2. extern int (*my_sysaudit)(u8,u8*,u16,u8);

接系统调用日志收集系统 (1)
---------------------------------------------------------------
3.8重新编译内核。
     如何编译内核就不再说了。
----------------------------------------------------------------
3.9插入模块。

  1. #include <linux/module.h>
  2. #include <linux/init.h>
  3. #include <linux/kernel.h>
  4. #include <linux/types.h>
  5. #include <asm/current.h>
  6. #include <linux/sched.h>
  7. #include <asm/uaccess.h>
  8. #define COMM_SIZE 16
  9. struct syscall_buf {
  10. u32 serial;
  11. u32 ts_sec;
  12. u32 syscall;
  13. u32 status;
  14. pid_t pid;
  15. uid_t uid;
  16. u8 comm[COMM_SIZE];
  17. };
  18. //初始化一个队列buffer_wait
  19. DECLARE_WAIT_QUEUE_HEAD(buffer_wait);
  20. #define AUDIT_BUF_SIZE 100
  21. //长度为100的缓冲区。
  22. static struct syscall_buf audit_buf[AUDIT_BUF_SIZE];
  23. static int current_pos = 0;//缓冲区中的位置.
  24. static u32 serial = 0;//序列号
  25. void write_buf_audit(int syscall,int return_value)
  26. {
  27. struct syscall_buf *ppb_tmp;
  28. printk("write_buf_audit is execing!\n");
  29. if (current_pos < AUDIT_BUF_SIZE) {
  30. ppb_tmp = &audit_buf[current_pos];
  31. ppb_tmp->serial = serial++;
  32. ppb_tmp->ts_sec = 1;
  33. ppb_tmp->syscall = syscall;
  34. ppb_tmp->status = return_value;
  35. ppb_tmp->pid = current->pid;
  36. ppb_tmp->uid = current->tgid;
  37. memcpy(ppb_tmp->comm,current->comm,COMM_SIZE);
  38. if (++current_pos == AUDIT_BUF_SIZE *1/10) {
  39. printk("in syscall_audit,it near full!\n");
  40. wake_up_interruptible(&buffer_wait);
  41. }
  42. }
  43. return ;
  44. }
  45. int read_buf_audit(u8 type,u8 *us_buf,u16 us_buf_size,u8 reset)
  46. {
  47. int ret = 0;
  48. printk("read_buf_audit is execving!\n");
  49. if (!type) {
  50. if (clear_user((void *)us_buf, (unsigned long)us_buf_size)) {
  51. printk("error:clear_user!\n");
  52. return 0;
  53. }
  54. ret= wait_event_interruptible(buffer_wait,current_pos >= AUDIT_BUF_SIZE*1/10);
  55. if (copy_to_user((void *)us_buf,audit_buf,(current_pos)*sizeof(struct syscall_buf))) {
  56. printk("error:copy error!\n");
  57. return 0;
  58. }
  59. ret = current_pos;
  60. current_pos = 0;
  61. }
  62. return ret;
  63. }
  64. static int __init audit_init(void)
  65. {
  66. my_audit = write_buf_audit;
  67. my_sysaudit = read_buf_audit;
  68. printk("starting syscall audit!\n");
  69. return 0;
  70. }
  71. static void __exit audit_exit(void)
  72. {
  73. my_audit = NULL;
  74. my_sysaudit = NULL;
  75. printk("exiting syscall audit!\n");
  76. return ;
  77. }
  78. module_init(audit_init);
  79. module_exit(audit_exit);
  80. MODULE_LICENSE("GPL");

------------------------------------------------------------------------------------------------------
3.10,启动用户测试程序。

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <errno.h>
  4. #include <signal.h>
  5. #include <unistd.h>
  6. #include <sys/syscall.h>
  7. #include <sys/types.h>
  8. typedef unsigned char u8;
  9. typedef unsigned int u32;
  10. #define COMM_SIZE 16
  11. struct syscall_buf {
  12. u32 serial;
  13. u32 ts_sec;
  14. u32 syscall;
  15. u32 status;
  16. pid_t pid;
  17. uid_t uid;
  18. u8 comm[COMM_SIZE];
  19. };
  20. #define AUDIT_BUF_SIZE 100*sizeof(struct syscall_buf)
  21. int main(int argc, char *argv[])
  22. {
  23. u8 col_buf[AUDIT_BUF_SIZE];
  24. unsigned char reset = 1;
  25. int num = 0;
  26. struct syscall_buf *p = NULL;
  27. u8 j = 0;
  28. int i;
  29. while (1) {
  30. num = syscall(346, 0, col_buf, AUDIT_BUF_SIZE, reset);
  31. printf("num is: %d\n", num);
  32. p = (struct syscall_buf *)col_buf;
  33. for (i = 0; i < num; i++) {
  34. printf("serial: %d ", p[i].serial);
  35. printf("syscall: %d ", p[i].syscall);
  36. printf("ts_sec: %d ", ((struct syscall_buf *)col_buf)[i].ts_sec);
  37. printf("status: %d ", p[i].status);
  38. printf("pid: %d ", ((struct syscall_buf *)col_buf)[i].pid);
  39. printf("uid: %d ", ((struct syscall_buf *)col_buf)[i].uid);
  40. printf("comm: %s\n", ((struct syscall_buf *)col_buf)[i].comm);
  41. }
  42. putchar('\n');
  43. }
  44. return 0;
  45. }

--------------------------------------------------------------------------------------------------------
3.11,其中用户触发程序。(向内核不断地申请系统调用)

  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <sys/sysinfo.h>
  4. int main(void)
  5. {
  6. struct sysinfo info;
  7. unsigned long value = 0;
  8. int i = 0;
  9. while (1) {
  10. sysinfo(&info);
  11. printf("sysinfo is execving!\n");
  12. value = (unsigned long)getpid();
  13. printf("pid = %lu\n",value);
  14. sleep(1);
  15. }
  16. return 0;
  17. }

----------------------------------------------------------------------------------------------------------------
感想:
          经过几天的时间调试这个程序,最终还是调试通过了,收获还是蛮大的,这个程序中
既要内核编程,还有编写内核模块,还要编写用户态程序。内核态和用户态协调合作。当然
在其中也出现了不少问题,开始我们就没有考虑到sysenter,结果导致使用库函数,对内核
就没有触发,只能使用int 0x80,直接在用户态使用汇编或嵌入汇编才能对其触发。后来把
sysenter这条路“堵死”就好了。
------------------------------------------------------------------------------------------------------------------

系统调用日志收集系统相关推荐

  1. execve系统调用_张凯捷—系统调用分析(3) (基于最新Linux5.0版本系统调用日志收集系统)...

    在上一篇文章<系统调用分析(2)>中介绍和分析了32位和64位的快速系统调用指令--sysenter/sysexit和syscall/sysret,以及内核对快速系统调用部分的相关代码,并 ...

  2. 基于Flume的美团日志收集系统(二)改进和优化

    在<基于Flume的美团日志收集系统(一)架构和设计>中,我们详述了基于Flume的美团日志收集系统的架构设计,以及为什么做这样的设计.在本节中,我们将会讲述在实际部署和使用过程中遇到的问 ...

  3. 借鉴开源框架自研日志收集系统

    踏浪无痕 岂安科技高级架构师 十余年数据研发经验,擅长数据处理领域工作,如爬虫.搜索引擎.大数据应用高并发等.担任过架构师,研发经理等岗位.曾主导开发过大型爬虫,搜索引擎及大数据广告DMP系统目前负责 ...

  4. python分布式日志收集系统_Go实现海量日志收集系统(一)

    项目背景 每个系统都有日志,当系统出现问题时,需要通过日志解决问题 当系统机器比较少时,登陆到服务器上查看即可满足 当系统机器规模巨大,登陆到机器上查看几乎不现实 当然即使是机器规模不大,一个系统通常 ...

  5. 探秘Hadoop生态12:分布式日志收集系统Flume

    这位大侠,这是我的公众号:程序员江湖.  分享程序员面试与技术的那些事. 干货满满,关注就送.  在具体介绍本文内容之前,先给大家看一下Hadoop业务的整体开发流程:  从Hadoop的业务开发流程 ...

  6. Flume日志收集系统架构详解--转

    2017-09-06朱洁大数据和云计算技术 任何一个生产系统在运行过程中都会产生大量的日志,日志往往隐藏了很多有价值的信息.在没有分析方法之前,这些日志存储一段时间后就会被清理.随着技术的发展和分析能 ...

  7. fluentd mysql_使用Fluentd + MongoDB构建实时日志收集系统

    日志处理场景 日志量大 日志分散不易进行统一分析 难以添加有效监控 系统实现 Fluentd(td-agent) MongoDB Python Script(PyMongo module) Zabbi ...

  8. 你居然还去服务器上捞日志,搭个日志收集系统难道不香么!

    摘要 ELK日志收集系统进阶使用,本文主要讲解如何打造一个线上环境真实可用的日志收集系统.有了它,你就可以和去服务器上捞日志说再见了! ELK环境安装 ELK是指Elasticsearch.Kiban ...

  9. java 如何去掉http debug日志_你居然还去服务器上捞日志,搭个日志收集系统难道不香吗?...

    作者:MacroZheng 链接:https://juejin.im/post/5eef217d51882565d74fb4eb 来源:掘金 SpringBoot实战电商项目mall(35k+star ...

最新文章

  1. c java 开发android_java代码与纯C代码混编完成android应用的开发
  2. linux负载很高是什么原因导致的?
  3. Jerry的ABAP, Java和JavaScript乱炖
  4. python实现文件转数组
  5. Source Insight 4.0 常用设置
  6. eclipse中安装TestNg
  7. Ubuntu视频教程
  8. 自相关函数互相关函数
  9. 入门级概述光学相干层析(OCT)原理
  10. NFC framework introduce(一)
  11. Python将Qt的ui文件转成py代码文件
  12. vue中细枝末节的知识点总结
  13. “金三银四”春招指南!java语言程序设计第二版答案朱庆生
  14. 毛绒玩具需做哪些测试项目?出口欧盟CE认证
  15. 实验二 词频统计软件项目报告
  16. 目前互联网最详细的5G注册流程
  17. java实现来电弹屏_屏信小编告诉你呼叫中心的来电弹屏有哪些功能
  18. 安装配有NVIDIA GRID K2服务器系统不能正常安装和其他的GPU卡如K20x不能正常安装原厂驱动
  19. 由于文件不可访问,或者内存或磁盘空间不足,所以无法打开数据库 ‘msdb‘。无法打开数据库msdb 恢复操作已将该数据库标记为SUSPECT
  20. 用Shell脚本画矩形;直角、等腰三角形;梯形;菱形

热门文章

  1. windows charles response 乱码解决办法
  2. 面向对象设计模式纵横谈:Singelton单件模式(笔记记录)
  3. Python常用内置函数(二)
  4. 经典的printk 写法
  5. 探讨DHCP之一:了解DHCP
  6. 在Quick-cocos2dx中使用云风pbc解析Protocol Buffers,支持win、mac、ios、android
  7. 在 Web 应用中增加用户跟踪功能
  8. 张孝祥Java培训视频及孙鑫java视频网址
  9. LeetCode-166- Fraction to Recurring Decimal
  10. C语言实现链式栈(LinkStack)