(kernel) hook sys\_call\_table
hook sys_call_table
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
#include <linux/module.h> // included for all kernel modules
#include <linux/kernel.h> // included for KERN\_INFO
#include <linux/init.h> // included for \_\_init and \_\_exit macros
#include <linux/cred.h>
MODULE\_LICENSE("GPL");
MODULE\_AUTHOR("umbum");
MODULE\_DESCRIPTION("sys\_call\_table hooking test");
#define page\_offset 0xc0000000
#define phys\_offset 0x1a000000
// #define \_\_NR\_write 4
#define \_\_NR\_target 4
typedef asmlinkage long (\*sys\_write\_t)(unsigned int fd, const char \_\_user \*buf, size\_t count);
sys\_write\_t orig\_sys\_write;
unsigned long \*\*sct;
asmlinkage long hook\_sys\_write(unsigned int fd, char \_\_user \*buf, size\_t count){
if (!strcmp(buf, "bum")){
buf[0] = 'B'; // not string, but char
buf[1] = 'U'; // so, these are not affected by addr\_limit
buf[2] = 'M';
}
return orig\_sys\_write(fd, buf, count);
}
static unsigned long \*\*get\_sys\_call\_table(void){
return page\_offset + phys\_offset + 0x005d3160; // sct\_offset
}
static void set\_page\_rw(unsigned long addr, int bit){
unsigned int level;
pte\_t \*pte;
pte = lookup\_address(addr, &level);
if (bit == 1) {
pte->pte |= \_PAGE\_RW;
}
else {
pte->pte &= ~\_PAGE\_RW;
}
}
static int \_\_init b\_hook\_init(void)
{
sct = get\_sys\_call\_table();
printk(KERN\_INFO "b\_hook LKM is loaded\n");
printk("origin sct[\_\_NR\_target] %p : %p : %p\n", &sct[\_\_NR\_target], sct[\_\_NR\_target], \*sct[\_\_NR\_target]);
orig\_sys\_write = (sys\_write\_t)sct[\_\_NR\_target];
set\_page\_rw((unsigned long)sct, 1);
sct[4] = (unsigned long \*)hook\_sys\_write;
printk("hooked sct[\_\_NR\_target] %p : %p : %p\n", &sct[\_\_NR\_target], sct[\_\_NR\_target], \*sct[\_\_NR\_target]);
return 0; // Non-zero return means that the module couldn't be loaded.
}
static void \_\_exit b\_hook\_exit(void)
{
sct[\_\_NR\_target] = (unsigned long \*)orig\_sys\_write;
set\_page\_rw((unsigned long)sct, 0);
printk("restored sct[\_\_NR\_target] %p : %p : %p\n", &sct[\_\_NR\_target], sct[\_\_NR\_target], \*sct[\_\_NR\_target]);
printk(KERN\_INFO "b\_hook LKM is removed.\n");
}
module\_init(b\_hook\_init);
module\_exit(b\_hook\_exit);
- LKM make 시 타입을 꽤 엄격하게 따지기 때문에, type casting 잘 해주어야 한다.
buf
의 내용을 수정하기 위해hook\_sys_write()
의 인자에c const
를 제거했는데, 잘 동작한다. 이런 식으로 실제로는 상수가 아니지만, 함수 내부에서 변경하지 못하도록 설정하고 싶은 경우const
를 활용할 수 있을 것 같다.hook\_sys_write()
내부에 있는c printk()
가 제대로 로그를 찍어주지 않는다. 단순히dmesg
로 확인이 안될 뿐 버퍼에 쌓이는 건가 싶었는데rmmod
하고 난 이후에도 로그가 찍히지 않는걸로 보아 그냥 유실되는 것 같다.
asmlinkage
를 지정하면 어셈블리 코드에서 해당 함수를 직접 호출할 수 있다. 컴파일 시 함수의 인자 전달 방식이 레지스터를 사용하는 방식으로 지정될 경우, assembly code에서 이 함수를 호출할 때 레지스터를 사용해 인자를 전달하도록 코딩하지 않는다면 함수에서 인자를 제대로 받을 수 없다. 따라서 모든 인자를 스택으로 받도록 지정하는 것이 asmlinkage
다.
This post is licensed under CC BY 4.0 by the author.