Chinaunix首页 | 论坛 | 博客
  • 博客访问: 439070
  • 博文数量: 71
  • 博客积分: 26
  • 博客等级: 民兵
  • 技术积分: 1246
  • 用 户 组: 普通用户
  • 注册时间: 2012-07-23 14:46
个人简介

linux --- 一切皆文件

文章分类

全部博文(71)

文章存档

2021年(1)

2019年(2)

2018年(4)

2017年(7)

2016年(11)

2015年(1)

2014年(2)

2013年(33)

2012年(10)

分类: LINUX

2018-02-07 12:04:27

Linux系统调用函数替换

===================


#### 获取系统调用数组首地址


首先寻找一个系统调用函数,我们选择sys_close函数。根据这个地址进行偏移,当某个偏移地址+__NR_close的值等于sys_close相等时,则认为此偏移后的地址为系统调用首地址。


点击(此处)折叠或打开

  1. unsigned long **find_sys_call_table(void) {
  2. unsigned long ptr;
  3. unsigned long *p;
  4. pr_err("Start found sys_call_table.\n");
  5. for (ptr = (unsigned long)sys_close;
  6. ptr < (unsigned long)&loops_per_jiffy;
  7. ptr += sizeof(void *)) {
  8. p = (unsigned long *)ptr;
  9. if (p[__NR_close] == (unsigned long)sys_close) {
  10. pr_err("Found the sys_call_table!!! __NR_close[%d] sys_close[%lx]\n"
  11. " __NR_execve[%d] sct[__NR_execve][0x%lx]\n",
  12. __NR_close,
  13. (unsigned long)sys_close,
  14. __NR_execve,
  15. p[__NR_execve]);
  16. return (unsigned long **)p;
  17. }
  18. }
  19. return NULL;
  20. }


#### 修改指定的系统调用


因为系统调用的数组是只读类型的,所以其值是不可以修改的,因此我们需要将只读保护位去掉。

cr0中有一个WP位,wp0禁止写保护 实模式。wp1开启写保护 保护模式。

wp对应的位为:0x00010000


点击(此处)折叠或打开

  1. unsigned long original_cr0;
  2. original_cr0 = read_cr0(); #获取rc0寄存器数据
  3. write_cr0(original_cr0 & ~0x00010000); #将常量保护标记位去掉
  4. ##此处修改系统调用表等操作
  5. write_cr0(original_cr0); #将寄存器值恢复,常量保护恢复


代码如下:

内核模块init时:


点击(此处)折叠或打开

  1. void *orig_sys_call_table [NR_syscalls];
  2. original_cr0 = read_cr0();
  3. write_cr0(original_cr0 & ~0x00010000);
  4. pr_err("Loading module change_write, sys_call_table at %p\n", sys_call_table_ptr);
  5. for(i = 0; i < NR_syscalls - 1; i ++) {
  6. orig_sys_call_table[i] = sys_call_table_ptr[i];
  7. }
  8. orig_write = (void *)(sys_call_table_ptr[__NR_write]);
  9. sys_call_table_ptr[__NR_write]= (void *)my_write;
  10. write_cr0(original_cr0);


内核模块exit时,恢复正常write函数:


点击(此处)折叠或打开

  1. write_cr0(original_cr0 & ~0x00010000);
  2. sys_call_table_ptr[__NR_write] = (void *)orig_write;
  3. write_cr0(original_cr0);


syscall_write_hook.rar


#### 修改sys_execve系统调用


修改sys_execve函数不像普通系统调用一样,在此系统调用执行之前先进拦截或者记录相关信息的操作,就需要进行平衡栈。


在替换系统调用时需要调用此汇编函数,将my_stub_execve_hook替换原有的系统调用,当进入此函数时,先将寄存器入栈,再执行自定义函数(比如行为记录,行为拦截等功能),自定义函数执行完成后,将之前入栈的寄存器恢复出来,然后再执行原生的execve函数:


sys_call_table_ptr[__NR_execve]= (void *)my_stub_execve_hook;


execve必须执行栈平衡,这是和其他系统调用区别的地方。



点击(此处)折叠或打开

  1. .text
  2. .global my_stub_execve_hook
  3. my_stub_execve_hook:
  4. pushq %rbx
  5. pushq %rdi
  6. pushq %rsi
  7. pushq %rdx
  8. pushq %rcx
  9. pushq %rax
  10. pushq %r8
  11. pushq %r9
  12. pushq %r10
  13. pushq %r11
  14. call my_execve_hook
  15. pop %r11
  16. pop %r10
  17. pop %r9
  18. pop %r8
  19. pop %rax
  20. pop %rcx
  21. pop %rdx
  22. pop %rsi
  23. pop %rdi
  24. pop %rbx
  25. jmp *orig_sys_call_table(, %rax, 8)


syscall_execve_hook.rar


 

阅读(10075) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~