- 论坛徽章:
- 0
|
如何在Linux系统下实现对特定进程发出的系统调用进行拦截?
实验环境:RedHat linux,内核版本2.6.32,32位处理器。
查到有两种比较好的方法,一种是修改中断向量表法,代码如下:
有两个问题,在代码中添加了注释,希望大家能帮忙解答!
==========================================================
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/tty.h>
#include <asm/unistd.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/types.h>
#include <linux/dirent.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/fs.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("SHY");
MODULE_DESCRIPTION("test");
void my_stub();
static unsigned long old_stub;
static unsigned long stub_eax,stub_ebx,stub_ecx,stub_edx,stub_esi,stub_edi;
struct{
unsigned short limit;
unsigned long base;
}__attribute__((packed)) idtr;
//中断描述符
struct descriptor_idt{
unsigned short offset_low;
unsigned short selector;
unsigned char reserved;
unsigned char type:4;
unsigned char segmentflag:1;
unsigned char DPL:2;
unsigned char present:1;
unsigned short offset_high;
};
//拦截处理函数
void my_handler(){
// if(current_comm=="ls"){ //问题1:想实现对特定进程发出的系统调用进行拦截,最好是根据进程名称来区分,如果是根据进程ID,那么每次程序执行ID都不同,所以应该如何通过进程名判断?
__asm__("movl %%eax,%0\n"
"movl %%ebx,%1\n"
"movl %%ecx,%2\n"
"movl %%edx,%3\n"
"movl %%esi,%4\n"
"movl %%edi,%5\n"
"popl %%ebx\n"
"popl %%ecx\n"
"popl %%edx\n"
"popl %%esi\n"
"popl %%edi\n"
"popl %%ebp\n"
"popl %%eax\n"
"popl %%ds\n"
"popl %%es\n"
"jmp *old_stub"
::"m" (stub_eax),"m" (stub_ebx),"m" (stub_ecx),"m" (stub_edx),"m" (stub_esi),"m" (stub_edi));
printk("syscall number == %d",stub_eax);
// }else{
// __asm__("popl %%ebx\n"
// "popl %%ecx\n"
// "popl %%edx\n"
// "popl %%esi\n"
// "popl %%edi\n"
// "popl %%ebp\n"
// "popl %%eax\n"
// "popl %%ds\n"
// "popl %%es\n"
// "jmp *old_stub");
// }
}
void stub_kad(void){
__asm__(".globl my_stub \n"
".align 4,0x90 \n"
"my_stub: \n"
"pushl %es\n"
"pushl %ds\n"
"pushl %eax\n"
"pushl %ebp\n"
"pushl %edi\n"
"pushl %esi\n"
"pushl %edx\n"
"pushl %ecx\n"
"pushl %ebx\n"
"call my_handler \n");
}
static void disable_page_protection(){
unsigned long value;
asm volatile("mov %%cr0, %0":"=r" (value));
if(!(value&0x00010000)){
return;
}
asm volatile("mov %0, %%cr0"::"r" (value&~0x00010000));
}
static void enable_page_protection(){
unsigned long value;
asm volatile("mov %%cr0, %0":"=r" (value));
if(!(value&0x00010000)){
return;
}
asm volatile("mov %0, %%cr0"::"r" (value|0x00010000));
}
static void replace_system_call(void){
struct descriptor_idt* idte;
__asm__ volatile("sidt %0":"=m" (idtr));
idte=(struct descriptor_idt*)(idtr.base+8*0x80);
old_stub=(idte->offset_high+16|idte->offset_low);
unsigned long new_addr=(unsigned long)my_stub;
idte->offset_high=(unsigned short)(new_addr>>16); //问题2:关键问题!这条语句的执行会导致系统死机,怀疑是因为没有对该地址的修改权限
idte->offset_low=(unsigned short)(new_addr & 0x0000ffff);
}
static int __init _init_module(void){
disable_page_protection();
replace_system_call();
printk("Intercept Module Installed!\n");
return 0;
}
static void __exit _cleanup_module(void){
struct descriptor_idt *idte;
__asm__ volatile("sidt %0":"=m" (idtr));
idte=(struct descriptor_idt*)(idtr.base+8*0x80);
idte->offset_high=(unsigned short)(old_stub>>16); //与问题2同样的问题
idte->offset_low=(unsigned short)(old_stub & 0x0000ffff);
enable_page_protection();
printk("Intercept Module Uninstalled!\n");
}
module_init(_init_module);
module_exit(_cleanup_module);
=======================================================
另外一种拦截方法,是通过修改sysenter指令的跳转目的地址,这种方法运行通过了,但是在获取进程信息时存在问题,同样在代码中注释,代码如下:
功能是统计特定进程发出的不同的系统调用数量
=======================================================
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <asm/thread_info.h>
#include <asm/unistd.h>
#include <asm/msr.h>
#include <asm/pgtable.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("SHY");
MODULE_DESCRIPTION("system call interception");
asmlinkage char* my_function();
unsigned long handler_code=(unsigned long)&my_function;
unsigned long old_sysenter;
extern asmlinkage void my_stub();
unsigned long handled_times;
unsigned long counts[300];
void stub_trtr(void){
__asm__(".globl my_stub \n"
".align 4,0x90 \n"
"my_stub: \n"
" call *%0 \n"
" jmp *%1 \n"
::"m"(handler_code),"m"(old_sysenter));
}
asmlinkage char* my_function(){
struct thread_info *info=current_thread_info();
struct task_struct *task=info->task;
// if(task->pid==1000){ //问题:拦截特定进程发出的系统调用,但是当加入这条if语句时加载模块会发生死机现象
int my_eax;
handled_times++;
__asm__("movl %%eax,%0;":"=r"(my_eax));
counts[my_eax]++;
// }
return;
}
void my_hook(){
unsigned int a;
rdmsr(MSR_IA32_SYSENTER_EIP,old_sysenter,a);
wrmsr(MSR_IA32_SYSENTER_EIP,my_stub,0);
}
static int __init trtr_init(void){
printk("interception module enter!\n");
int i;
for(i=0;i<300;i++){
counts[i]=0;
}
my_hook();
handled_times=0;
return 0;
}
static void trtr_exit(void){
int j;
wrmsr(MSR_IA32_SYSENTER_EIP,old_sysenter,0);
for(j=0;j<300;j++){
if(counts[j]!=0){
printk("System call %d has been handled %ld times!\n",j,counts[j]);
}
}
printk("interception module exit!\n");
}
module_init(trtr_init);
module_exit(trtr_exit);
======================================================= |
|