通过修改pte页表属性使内存可写

通过修改pte页表属性使内存可写
一、相关API
/*
 * Lookup the page table entry for a virtual address. Return a pointer
 * to the entry and the level of the mapping.
 *
 * Note: We return pud and pmd either when the entry is marked large
 * or when the present bit is not set. Otherwise we would return a
 * pointer to a nonexisting mapping.
 */
pte_t *lookup_address(unsigned long address, unsigned int *level)
{
        return lookup_address_in_pgd(pgd_offset_k(address), address, level);
}
EXPORT_SYMBOL_GPL(lookup_address);

#define _PAGE_PRESENT   0x001
#define _PAGE_NEWPAGE   0x002
#define _PAGE_NEWPROT   0x004
#define _PAGE_RW        0x020
#define _PAGE_USER      0x040
#define _PAGE_ACCESSED  0x080
#define _PAGE_DIRTY     0x100
#define _PAGE_PROTNONE  0x010 

lookup_address通过传入的虚拟地址找到对应的页表项,通过修改页表项的属性来修改对应物理读写属性。

二、修改内存写保护并hook 系统调用mkdir
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/kallsyms.h>

unsigned long *sys_call_table = NULL;
unsigned long (*orig_mkdir)(const char __user *path, int mode);

static int make_memory_rw(unsigned long address)
{
	unsigned int level = 0;	
	pte_t *pte = NULL;

	pte = lookup_address(address, &level);
	if(pte == NULL) {
		printk("%s: get pte failed\n", __func__);
		return -1;
	} 
	
	if(pte->pte & ~_PAGE_RW)
		pte->pte |= _PAGE_RW;

	return 0;
}

static int make_memory_ro(unsigned long address)
{
	unsigned int level = 0;	
	pte_t *pte = NULL;

	pte = lookup_address(address, &level);
	if(pte == NULL) {
		printk("%s: get pte failed\n", __func__);
		return -1;
	} 
	
	pte->pte &= ~_PAGE_RW;

	return 0;
}

asmlinkage long hook_mkdir(const char __user *path, int mode)
{
	printk("%s: the mkdir has been hook\n", __func__);

	return orig_mkdir(path, mode);
}

static int __init lkm_init(void)
{

	sys_call_table = (unsigned long *)kallsyms_lookup_name("sys_call_table");
	if(sys_call_table == NULL) {
		printk("%s: can not find sys_call_table address\n", __func__);
		return -1;
	}
	printk("%s: sys_call_addr = 0x%lx\n", __func__, sys_call_table);

	orig_mkdir = (unsigned long)(sys_call_table[__NR_mkdir]);
	make_memory_rw((unsigned long)sys_call_table);
	sys_call_table[__NR_mkdir] = (unsigned long)hook_mkdir;
	make_memory_ro((unsigned long)sys_call_table);

	return 0;
}

static void __exit lkm_exit(void)
{
	make_memory_rw((unsigned long)sys_call_table);
	sys_call_table[__NR_mkdir] = (unsigned long)orig_mkdir;
	make_memory_ro((unsigned long)sys_call_table);

	printk("Goodbye\n");
}

module_init(lkm_init);
module_exit(lkm_exit);

MODULE_LICENSE("GPL");
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值