在进行inline hook时,会调用mmap()函数来目标函数的内存映射到当前进程的地址空间中,这个说法对面
时间: 2024-05-22 15:10:24 浏览: 114
是正确的。在进行 inline hook 时,我们需要修改目标函数的代码,因此需要将其内存映射到当前进程的地址空间中,以便我们可以访问和修改其中的指令。mmap() 函数可以将一个文件或者设备映射到进程的地址空间中,从而使得进程可以像操作内存一样操作这个文件或设备的数据。在进行 inline hook 时,我们可以使用 mmap() 函数将目标函数所在的内存页映射到当前进程的地址空间中,从而进行修改。
相关问题
编写代码,通过lsm 编写hook函数,防止通过地址inline hook修改linux 系统调用内存区域
LSM(Linux Security Module)是Linux内核的一个安全框架,可以用于实现各种安全策略。其中,LSM提供了一种称为“hook”的机制,可以在Linux内核的关键点上插入代码,以实现各种安全策略。
在Linux内核中,系统调用是非常关键的一部分,因为它们允许用户空间程序向内核发出请求,访问系统资源。因此,系统调用的安全性至关重要,需要采取一些措施来保护它们。
对于本题,我们可以编写一个LSM hook函数来防止通过地址inline hook修改Linux系统调用内存区域。具体步骤如下:
1. 在内核中注册一个LSM hook函数,例如:
```
static struct security_operations my_security_ops = {
.name = "my_security",
.bprm_check_security = my_bprm_check_security,
.file_permission = my_file_permission,
.inode_permission = my_inode_permission,
.inode_setattr = my_inode_setattr,
.task_create = my_task_create,
.task_free = my_task_free,
.inode_init_security = my_inode_init_security,
.inode_create = my_inode_create,
.inode_link = my_inode_link,
.inode_unlink = my_inode_unlink,
.inode_symlink = my_inode_symlink,
.inode_mkdir = my_inode_mkdir,
.inode_rmdir = my_inode_rmdir,
.inode_rename = my_inode_rename,
.inode_readlink = my_inode_readlink,
.inode_follow_link = my_inode_follow_link,
.inode_permission = my_inode_permission,
.inode_setattr = my_inode_setattr,
.inode_getattr = my_inode_getattr,
.task_prctl = my_task_prctl,
.task_setpgid = my_task_setpgid,
.task_getpgid = my_task_getpgid,
.task_getsid = my_task_getsid,
.task_setuid = my_task_setuid,
.task_setgid = my_task_setgid,
.task_setgroups = my_task_setgroups,
};
```
这里我们只需要关注`inode_setattr`和`inode_getattr`两个函数,因为它们可以用于检查和修改inode的属性,从而保护系统调用内存区域。
2. 实现LSM hook函数,例如:
```
static int my_inode_setattr(struct dentry *dentry, struct iattr *attr)
{
int rc;
rc = inode_setattr(dentry->d_inode, attr);
if (rc != 0)
return rc;
/* 检查是否有inline hook */
if (check_for_inline_hook(dentry->d_inode->i_addr))
{
printk(KERN_ALERT "Inline hook detected on system call memory!\n");
return -EPERM;
}
return 0;
}
static int my_inode_getattr(const struct path *path, struct kstat *stat,
u32 request_mask, unsigned int flags)
{
int rc;
rc = vfs_getattr(path, stat, request_mask, flags);
if (rc != 0)
return rc;
/* 检查是否有inline hook */
if (check_for_inline_hook(stat->ino))
{
printk(KERN_ALERT "Inline hook detected on system call memory!\n");
return -EPERM;
}
return 0;
}
```
在这里,我们使用`check_for_inline_hook`函数来检查inode是否被inline hook修改。如果检测到这种情况,我们会记录一条日志,并返回错误码`-EPERM`。
3. 编写`check_for_inline_hook`函数,例如:
```
static bool check_for_inline_hook(unsigned long addr)
{
struct page *page;
void *kaddr;
bool ret = false;
/* 将虚拟地址转换为物理地址 */
page = pfn_to_page(__pa(addr) >> PAGE_SHIFT);
if (!page)
return false;
/* 将物理地址映射到内核地址空间 */
kaddr = kmap_atomic(page);
if (!kaddr)
return false;
/* 检查内存区域是否被修改 */
if (memcmp(kaddr, original_syscall_memory, sizeof(original_syscall_memory)) != 0)
ret = true;
/* 解除内存映射 */
kunmap_atomic(kaddr);
return ret;
}
```
在这里,我们使用`kmap_atomic`函数将物理地址映射到内核地址空间,然后使用`memcmp`函数比较内存区域是否被修改。如果被修改,就返回`true`,否则返回`false`。
4. 在`init`函数中注册LSM hook函数,例如:
```
static int __init my_security_init(void)
{
/* 注册LSM hook函数 */
if (register_security(&my_security_ops))
return -ENOMEM;
return 0;
}
security_initcall(my_security_init);
```
在这里,我们使用`register_security`函数注册LSM hook函数。
最后,我们需要编译内核,并将编译好的内核安装到系统中。这样,我们就可以通过LSM hook函数防止通过地址inline hook修改Linux系统调用内存区域。
inline hook时使用的函数
在进行inline hook时,我们需要使用以下函数:
1. `mmap()`:用于映射内存区域,可以将一段内存映射到另一个进程的地址空间中。
2. `mprotect()`:用于修改内存区域的保护属性,可以将可读写的内存区域变为只读或不可访问,从而实现保护目标代码不被修改。
3. `memcpy()`:用于内存拷贝,可以将一个函数的原始代码备份,以便恢复被修改的代码。
4. `jump_target()`:用于跳转到hook函数的执行位置,从而执行我们自己的代码。
5. `original_func()`:用于调用原始函数,从而保证目标函数的正常执行。