Linux:内核模块实现替换系统调用的简单例子
2018-01-09 15:13
941 查看
原文链接:http://blog.csdn.net/ddk3001/article/details/51485135
编写Linux内核模块,可以实现替换系统调用功能。
本文提供一个替换open系统调用的样例代码,功能和说明见代码。
参考代码:https://github.com/ricardoteixas/hook
在 https://github.com 中搜索 hook、kernel等,可以搜到很多可参考的代码。
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
下面是Makefile文件内容:
2
3
4
5
6
7
8
9
编译模块 : make
编译清除:make clean
安装模块 : sudo insmod hook_open.ko
卸载模块 : sudo rmmod hook_open
查看模块 : lsmod | grep hook_open
编写Linux内核模块,可以实现替换系统调用功能。
本文提供一个替换open系统调用的样例代码,功能和说明见代码。
参考代码:https://github.com/ricardoteixas/hook
在 https://github.com 中搜索 hook、kernel等,可以搜到很多可参考的代码。
/*************************************************************************** 文件 : hook_open.c 功能 : 这是一个简单的内核模块,功能是替换了系统调用oepn,实现自定义open功能。 关键函数 : my_sys_open // 自定义的open系统调用处理函数 syscall_init // 内核模块初始化函数 syscall_release // 内核模块退出函数 源代码参考 : https://github.com/ricardoteixas/hook ***************************************************************************/ #include <linux/module.h> #include <linux/init.h> #include <linux/types.h> #include <linux/syscalls.h> #include <linux/delay.h> #include <linux/sched.h> #include <linux/version.h> /**************************************************************************/ // /**************************************************************************/ // Write Protect Bit (CR0:16) #define CR0_WP 0x00010000 MODULE_LICENSE("GPL"); void **syscall_table; unsigned long **find_sys_call_table(void); // !!!!! asmlinkage long (*orig_sys_open)(const char __user *filename, int flags, umode_t mode); /*************************************************************************** * /boot/System.map-3.13.0-43-generic: * * ffffffff811bb230 T sys_close * ffffffff81801400 R sys_call_table * ffffffff81c15020 D loops_per_jiffy * **************************************************************************/ unsigned long **find_sys_call_table() { unsigned long ptr; unsigned long *p; for (ptr = (unsigned long) sys_close; ptr < (unsigned long) &loops_per_jiffy; ptr += sizeof(void *)) { p = (unsigned long *) ptr; if (p[__NR_close] == (unsigned long) sys_close) { return (unsigned long **) p; } } return NULL; } /**************************************************************************/ // // 自定的open系统调用函数: 如果要打开的是 /home/test1.txt,则改为打开 /home/test2.txt // // 关键函数: strncpy_from_user 、 set_fs 、set_fs // /**************************************************************************/ asmlinkage long my_sys_open( const char __user *filename, int flags, umode_t mode ) { char temp[256] = { 0 }; char *test2 = "/home/test2.txt"; // 需要把用户空间的数据拷贝到内核空间,才能使用 (void)strncpy_from_user( temp, filename, PATH_MAX ); if ( !strcmp( temp, "/home/test1.txt" ) ) { mm_segment_t fs_save; long ret; // get_fs 和 set_fs 是为了使系统调用函数能够访问内核空间数据(本来参数应该是用户空间数据) // 关于 get_fs 和 set_fs,参考: http://blog.chinaunix.net/uid-27717694-id-4076498.html fs_save = get_fs(); set_fs( get_ds() ); ret = orig_sys_open( (const char __user *)test2, flags, mode ); set_fs( fs_save ); return ret; } return orig_sys_open(filename, flags, mode); } /**************************************************************************/ // // 内核模块初始化函数 // /**************************************************************************/ static int __init syscall_init(void) { unsigned long cr0; printk(KERN_DEBUG "Let's do some magic!\n"); syscall_table = (void **) find_sys_call_table(); if (! syscall_table) { printk(KERN_DEBUG "ERROR: Cannot find the system call table address.\n"); return -1; } printk(KERN_DEBUG "Found the sys_call_table at %16lx.\n", (unsigned long) syscall_table); cr0 = read_cr0(); write_cr0(cr0 & ~CR0_WP); printk(KERN_DEBUG "Houston! We have full write access to all pages. Proceeding...\n"); orig_sys_open = syscall_table[__NR_open]; syscall_table[__NR_open] = my_sys_open; write_cr0(cr0); return 0; } /**************************************************************************/ // // 内核模块退出函数 // /**************************************************************************/ static void __exit syscall_release(void) { unsigned long cr0; printk(KERN_DEBUG "I hate you!\n"); cr0 = read_cr0(); write_cr0(cr0 & ~CR0_WP); syscall_table[__NR_open] = orig_sys_open; //syscall_table[__NR_access] = orig_sys_access; write_cr0(cr0); } /**************************************************************************/ // /**************************************************************************/ module_init(syscall_init); module_exit(syscall_release);1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
下面是Makefile文件内容:
# Makefile obj-m:=hook_open.o KERNELBUILD:=/lib/modules/$(shell uname -r)/build default: make -C $(KERNELBUILD) M=$(shell pwd) modules clean: rm -rf *.o *.ko *.mod.c .*.cmd *.markers *.order *.symvers .tmp_versions1
2
3
4
5
6
7
8
9
编译模块 : make
编译清除:make clean
安装模块 : sudo insmod hook_open.ko
卸载模块 : sudo rmmod hook_open
查看模块 : lsmod | grep hook_open
相关文章推荐
- Linux:内核模块实现替换系统调用的简单例子
- Linux:内核模块实现替换系统调用的简单例子
- 在 Linux 下用户空间与内核空间数据交换的方式,第 1 部分: 内核启动参数、模块参数与sysfs、sysctl、系统调用和netlink
- 【转载】在 Linux 下用户空间与内核空间数据交换的方式,第 1 部分: 内核启动参数、模块参数与sysfs、sysctl、系统调用和netlink
- 在 Linux 下用户空间与内核空间数据交换的方式,第 1 部分: 内核启动参数、模块参数与sysfs、sysctl、系统调用和netlink
- linux 2.6.11内核文件IO的系统调用实现分析(read,write)(转载)
- linux 2.6.11内核文件IO的系统调用实现分析--再续
- 在 Linux 下用户空间与内核空间数据交换的方式,第 1 部分: 内核启动参数、模块参数与sysfs、sysctl、系统调用和netlink
- 读薄《Linux 内核设计与实现》(3) - 系统调用
- 在 Linux 下用户空间与内核空间数据交换的方式,第 1 部分: 内核启动参数、模块参数与sysfs、sysctl、系统调用和netlink
- linux 使用/proc文件系统 实现用户空间与内核模块之间通信
- 增加Linux系统调用——通过Hack增加内核模块
- 2.6版本Linux上替换系统调用函数实现隐藏文件学习
- linux内核文件IO的系统调用实现分析(open)
- Linux之使用内核模块增加一个系统调用
- 在 Linux 下用户空间与内核空间数据交换的方式,第 1 部分: 内核启动参数、模块参数与sysfs、sysctl、系统调用和netlink
- (转载) 在 Linux 下用户空间与内核空间数据交换的方式,第 1 部分: 内核启动参数、模块参数与sysfs、sysctl、系统调用和netlink
- 模块替换方式实现添加系统调用
- 一个内核模块例子(实现调用其他模块中的方法,传递参数等)
- 在 Linux 下用户空间与内核空间数据交换的方式,第 1 部分: 内核启动参数、模块参数与sysfs、sysctl、系统调用和netlink