当前位置:首页 » 操作系统 » linux钩子函数

linux钩子函数

发布时间: 2023-02-03 06:30:07

linux内核源码中如何加载自己的钩子函数

(但不总是)位于 /usr/src/linux-。我们不会研究得过于详细,因为 Linux 源代码经常会发生变化,但是,我们将尝试让给出的信息足以找出特定驱动程序或函数的位置。

Makefile:这个文件是整个源代码树的顶层 makefile。它定义了很多实用的变量和规则,比如默认的 gcc 编译标记。

Documentation/:这个目录中包含很多关于配置内核、运行 ramdisk 等任务的实用信息(但通常是过时的)。不过,与不同配置选项相应的帮助条目并不在这里 —— 它们在每个源代码目录的 Kconfig 文件中。

arch/:所有与体系结构相关的代码都在这个目录以及 include/asm- 目录中。在此目录中,每种体系结构都有自己的目录。例如,用于基于 PowerPC 的计算机的代码位于 arch/ppc 目录中。在这些目录里,可以找到底层内存管理、中断处理、早期初始化、汇编例程,等等。

crypto/:这是内核本身所用的加密 API。

drivers/:按照惯例,在此目录的子目录中可以找到运行外围设备的代码。包括视频驱动程序、网卡驱动程序、底层 SCSI 驱动程序,以及其他类似的驱动程序。例如,在 drivers/net 中可以找到大部分网卡驱动程序。将一类驱动程序组合在一起的某些更高层代码,可能会(也可能不会)像底层驱动程序本身那些包含在同一目录中。

fs/:通用文件系统的代码(称做 VFS,即 Virtual File System)和各个不同文件系统的代码都可以在这个目录中找到。ext2 文件系统是在 Linux 中最常广泛使用的文件系统之一;在 fs/ext2 中可以找到读取 ext2 格式的代码。并不是所有文件系统都会编译或运行;对某些寻找内核项目的人而言,更生僻的文件系统永远都是理想的候选者。

include/:在 .c 文件的开头所包含的大部分头文件都可以在这个目录中找到。 asm- 目录下是与体系结构相关的包含(include )文件。部分内核构建过程创建从 asm 指定 asm- 的符号链接。这样,无需将其固定编码到 .c 文件 #include 就可以获得用于那个体系结构的正确文件。其他目录中包含的是 非-体系结构-相关 的头文件。如果在不只一个 .c 文件中使用了某个结构体、常量或者变量,那么它可能应该放入其中一个头文件中。

init/:这个目录中的文件包括 main.c、创建 早期用户空间(early userspace) 的代码,以及其他初始化代码。可以认为 main.c 是内核“粘合剂(glue)”。在下一部分将深入讨论 main.c。早期用户空间提供了 Linux 内核引导起来时所需要的功能,而这些功能并不需要在内核本身运行。

ipc/:IPC 的意思是 进程间通信(interprocess communication)。它包含了共享内存、信号量以及其他形式 IPC 的代码。

kernel/:不适合放在任何其他位置的通用内核级代码位于此处。这里有高层系统调用代码,以及 printk() 代码、调度程序、信号处理代码,等等。文件名包含很多信息,所以可以使用 ls kernel/,并非能常准确地猜到每个文件的功能。

lib/:这里是对所有内核代码都通用的实用例程。常见的字符串操作、调试例程,以及命令行解析代码都位于此处。

mm/:这个目录中是高层次内核管理代码。联合使用这些例程以及底层的与体系结构相关的例程(通常位于 arch//mm/ 目录中)来实现虚拟内存(Virtual memory,VM)。在这里会完成早期内存管理(在内存子系统完全建立起来之前需要它),以及文件的内存映射、页高速缓存管理、内存分配、RAM 中页的清除(还有很多其他事情)。

net/:这里是高层网络代码。底层网络驱动程序与此层次代码交换数据包,这个层次的代码可以根据数据包将数据传递给用户层应用程序,或者丢弃数据,或者在内核中使用它。net/core 包含大部分不同的网络协议都可以使用的代码,和某些位于 net/ 目录本身中的文件一样。特定的网络协议在 net/ 的子目录下实现。例如,在 net/ipv4 目录中可以找到 IP(版本 4)代码。

scripts/:这个目录中包含的脚本可用于内核的构建,但并不将任何代码加入到内核本身之中。例如,各种配置工具可以将它们的文件放在这里。

security/:在这里可以找到不同 Linux 安全模型的代码,比如 NSA Security-Enhanced Linux 以及套接字和网络安全钩子函数(hooks),以及其他安全选项。

sound/:这里放置的是声卡驱动程序和其他与声音相关的代码。

usr/:此目录中的代码用于构建包含 root 文件系统映像的 cpio-格式 的归档文件,用于早期用户空间。

㈡ linux内核态,在LSM框架中的文件操作hook接口中如何获取一个正在被操作的文件的内容(linux4.4版本)

LSM是Linux Secrity Mole的简称,即linux安全模块。其是一种轻量级通用访
问控制框架,适合于多种访问控制模型在它上面以内核可加载模块的形实现。用
户可以根据自己的需求选择合适的安全模块加载到内核上实现。

LSM设计思想:
LSM的设计思想:在最少改变内核代码的情况下,提供一个能够成功实现强制访
问控制模块需要的结构或者接口。LSM避免了利用如在systrace系统调用中的出
现过的系统调用干预,因为它不能扩展到多处理器内核,并且它受制于参数替换
攻击。还有LSM在设计时做了两点考虑:对不使用的人来说尽量少引入麻烦,对
使用的人来说要带来效率。以Linus Torvalds为代表的内核开发人员对Linux安

全模块(LSM)提出了三点要求:
1、真正的通用,当使用一个不同的安全模型的时候,只需要加载一个不同的内
核模块。
2、概念上简单,对Linux内核影响最小,高效,并且。
3、能够支持现存的POSIX.1e capabilities逻辑,作为一个可选的安全模块。
还有,针对linux上提出的各种不同的Linux安全增强系统对Linux安全模块(LSM
)提出的要求是:能够允许他们以可加载内核模块的形式重新实现其安全功能,

并且不会在安全性方面带来明显的损失,也不会带来额外的系统开销。
LSM框架结构:
LSM框架主要由五部分构成:
1、在特定的内核数据结构中加入安全域。
2、在内核源代码中不同的关键点插入对安全钩子函数的调用。
3、加入一个通用的安全系统调用。
4、提供了函数允许内核模块注册为安全模块或者注销。
5、5、将capabilities逻辑的大部分移植为一个可选的安全模块。
安全域是一个void*类型的指针,它使得安全模块把安全信息和内核内部对象联
系起来。下面列出被修改加入了安全域的内核数据结构,以及各自所代表的内核

内部对象:
task_struct结构:代表任务(进程)
linux_binprm结构:代表程序
super_block结构:代表文件系统
inode结构:代表管道,文件,或者Socket套接字
file结构:代表打开的文件
sk_buff结构:代表网络缓冲区(包)
net_device结构:代表网络设备
kern_ipc_perm结构:代表Semaphore信号,共享内存段,或者消息队列
msg_msg:代表单个的消息

Linux安全模块(LSM)提供了两类对安全钩子函数的调用:一类管理内核对象的
安全域,另一类仲裁对这些内核对象的访问。对安全钩子函数的调用通过钩子来
实现,钩子是全局表security_ops中的函数指针,这个全局表的类型是
security_operations结构,这个结构定义在include/linux/security.h这个头
文件中。
LSM接口的核心是security_ops,当系统启动时,他们被初始化为传统的DAC策略
。传统DAC访问控制是指控制系统中的主体(如进程)对系统中的客体(如文件
目录、文件)的访问(读、写和执行等)。自主访问控制DAC 是指主体(进程,
用户)对客体(文件、目录、特殊设备文件、IPC等)的访问权限是由客体的属
主或超级用户决定的,而且此权限一旦确定,将作为以后判断主体对客体是否有

访问权限的依据。
在加载安全模块时,我们必需先对模块进行注册,我们可以使用
register_security()函数向LSM注册一个安全模块。在我们的模块被加载成
功后,就可以进行访问控制操作。如果此时还有一个安全模块要使用
register_security()函数进行加载,则会出现错误,直到使用
unregister_security()函数向框架注销后,下一个模块才可以载入。当然LS
M还提供了mod_reg_security()函数和mod_unreg_security()函数,可以连续注
册多个安全模块。如果有其他后来的模块需要载入,可以通过mod_reg_security
()向第一个模块注册,形成支持不同策略的模块栈。
注:以上出现的函数均基于2.6.22以前的版本,对于后续的版本,出现了
register_security()函数未被导出或者取消掉了unregister_security()函数。
LSM执行过程:
根据下图的执行步骤:用户在执行系统调用时,先通过原有的内核接口依次执行
功能性的错误检查,接着进行传统的DAC检查,并在即将访问内核的内部对象之
前,通过LSM钩子函数调用LSM。LSM再调用具体的访问控制策略来决定访问的合
法性。图三显示了LSM钩子的调用:

图三:基于LSM的内核对象访问过程

Lilinux安全模块(LSM)主要支持"限制型"的访问控制决策:当Linux内核授予
文件或目录访问权限时,Linux安全模块(LSM)可能会拒绝,而当 Linux内核拒
绝访问时,可以跳过LSM。

========

使用LSM实现自己的访问控制

首先对LSM 进行简单介绍。虽然linux下的各位基本都知道一些,但是还要罗嗦
一下。
LSM中文全称是linux安全模块。英文全称:linux security mole.
LSM是一种轻量级、通用的访问控制框架,适合多种访问控制模型以内核模块的
形式实现。其特点是通用、简单、高效、支持POSIX。1e能力机制。
LSM的架构图如下:

通过系统调用进入内核之后,系统首先进行传统的权限检查(传统权限检查主要
是基于用户的,用户通过验证之后就可以访问资源),通过之后才会进行强制访
问控制。(强制访问控制是不允许主体干涉的一种访问控制,其采用安全标识、
信息分级等信息敏感性进行访问控制。并且通过比较主体的级别和资源的敏感性
来确定是否允许访问。比如说系统设置A用户不允许访问文件B,即便A是文件B的
所有者,访问也是受限制的。)从图上看来,LSM实现访问控制主要通过安全模
块的钩子函数实现。

LSM框架主要由五部分组成:这个网上资料很多。
在关键的特定内核数据结构中加入了安全域;
在内核源码中不同的关键点处插入对安全钩子函数的调用;
提供了一个通用的安全系统调用;
提供了注册和注销函数,使得访问控制策略可以以内核模块方式实现;
将capabilities逻辑的大部分功能移植为一个可选的安全模块。

我们这里重点结合源码对LSM框架进行解释。我使用的源码是3.5.4
首先介绍安全域字段,它是一个空类型的指针,在内核中的很多内核结构中都存
在,比如inode、superblock、dentry、file等等。类型字段为void *
security;
那么安全域怎么和安全模块中的信息关联起来?
当安全模块加载之后,安全域中的指针便指向安全模块中的安全信息。这里以
selinux为例进行介绍。
内核里面security/selinux/include/objsec.h中定义了不同对象的安全信息,
格式为XXX_security_strut.

上面的文件的安全信息里面包含打开文件描述符时的安全ID、文件所有者的安全
ID等等。
要联系安全模块中安全信息和安全域需要几个控制钩子函数。这些钩子函数实现
了对内核关键信息的设置和管理。这里主要介绍alloc_security、
free_security。
selinux里面通过实现安全信息空间分配实现关联。比如以文件安全信息为例
这里分配空间成功之后,通过file->f_security = fsec实现了关联。
撤销关联是在安全模块卸载之后调用file_free_security.

这里具体通过设置file->f_secrity为NULL,然后释放安全信息结构实现。
现在来看看内核如何实现selinux的访问控制。这里主要就是实现LSM里面的钩子
函数了。LSM里面给出了结构体security_operations,里面给出了很多钩子函数
,实现了相关钩子函数就可以实现访问控制了。

上面的函数就实现了file_permission钩子函数。可以看下inode结构体的获得,
感受内核是通过文件->目录项->inode。该函数主要实现自己的访问控制策略就
OK 了。
哪selinux来说,在获得文件安全ID之后,主要对掩码和文件打开时相关的安全
信息进行检测,符合就通过访问控制。
selinux基本实现了LSM里面的所有钩子函数,待钩子函数实现后,对LSM里面钩
子域进行填充就OK了。

做完以上这些还需要注册安全模块到LSM,这里注册和注销使用了
register_security和unregister_security。
比如selinux在注册时使用语句register_security(&selinux_ops)实现。

接下来通过上面的分析我们可以实现简单的基于LSM的访问控制。
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/mole.h>
#include <linux/fs.h>
#include <linux/security.h>
#include <linux/types.h>
#include <asm/uaccess.h>
#include <linux/fcntl.h>
#include <linux/uaccess.h>
#include <linux/file.h>
#include <linux/namei.h>

static int lsm_test_file_permission(struct file *file,int mask)
{
int path=0;
struct file *filp;
struct nameidata nd;

path = path_lookup(FILENAME,LOOKUP_FOLLOW,&nd);

if(!mask)
return 0;

if(path)
{
printk("lookup file failed!\n");
return -1;
}

filp = filp_open("/home/yuyunchao/code/sb.c",O_RDONLY,0);
{
printk("open failed!\n");
}
return 0;
}

static struct security_operations lsm_test_security_ops = {
.file_permission = lsm_test_file_permission,
};

static int __init lsm_file_init(void)
{
if(register_security(&lsm_test_security_ops)){
printk("register error ..........\n");
return -1;
}

printk("lsm_file init..\n ");
return 0;
}

static void __exit lsm_file_exit(void)
{
if(unregister_security(&lsm_test_security_ops)){
printk("unregister error................\n");
return ;
}

printk("mole exit.......\n");
}

MODULE_LICENSE("GPL");
mole_init(lsm_file_init);
mole_exit(lsm_file_exit);
========

LSM(Linux Security Mole)应用方法(简单例子)

LSM在内核中很多地方已经插入了hook函数,并且在security.c函数中声明了
security_ops结构,要实现你自己的安全模块,只需要定义你自己的struct
security_operations,并且用register_security注册即可,下面举个简单例子

test.c代码如下:
/*
* Test Linux Security Mole
*
* Author: penghuan <[email protected]>
*
* Copyright (C) 2010 UbuntuKylin, Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2, as
* published by the Free Software Foundation.
*
*/

#include <linux/security.h>
#include <linux/sysctl.h>
#include <linux/ptrace.h>
#include <linux/prctl.h>
#include <linux/ratelimit.h>
#include <linux/workqueue.h>
#include <linux/file.h>
#include <linux/fs.h>
#include <linux/dcache.h>
#include <linux/path.h>

int test_file_permission(struct file *file, int mask)
{
char *name = file->f_path.dentry->d_name.name;
if(!strcmp(name, "test.txt"))
{
file->f_flags |= O_RDONLY;
printk("you can have your control code here!\n");
}
return 0;
}

static struct security_operations test_security_ops = {
.name = "test",

.file_permission = test_file_permission,
};

static __init int test_init(void)
{
printk("enter test init!\n");

printk(KERN_INFO "Test: becoming......\n")

if (register_security(&test_security_ops))
panic("Test: kernel registration failed.\n");

return 0;
}

security_initcall(test_init);

将该文件以模块的形式放到security/下编译进内核,启用新的内核后,当你操
作文件test.txt时,通过dmesg命令就能再终端看到”you can have your
control code here!“输出
所以一般的做法是:定义你自己的struct security_operations,实现你自己的
hook函数,具体有哪些hook函数可以查询include/linux/security.h文件,然后
调用register_security来用你的test_security_ops初始化全局的security_ops
指针

楼主,我刚开始研究LSM,但网上资料太少,您这个代码,我编译成ko文件老是
有警告,并且insmod时,说Unknown symbol register_security。我最近看了看
内核模块变成,没有对内核进行太深入的了解。不知能否把LSM的实验步骤给出
的再详细点,谢谢。

你需要把代码编进内核

是需要把那段源码拷到内核目录下,然后重新编译内核?。。没有不编译内核的
方法吗?。。直接按照模块进行编译。另外那个test.txt放在哪个文件夹里?。

是需要把那段源码拷到内核目录下,然后重新编译内核?。。没有不编译内核的
方法吗?。。直接按照模块进行 ...

是的,你去网上找下怎么把模块编进内核,lsm模块不能以模块方式加载,涉及
安全;test.txt是测试文件,当你把代码编进内核后,用新内核启动,然后操作
test.txt文件,就会有输出,test.txt随便放哪里

楼主,您好,我刚开始学习lsm模块,把您的模块编译进内核,新的内核加载后
,register_security总是失败,请问下可能是什么原因导致的。我的内核版本
是3.13.11。

register_security的返回值是-11

========

LSM在Linux中的实现方式
LSM(Linux Secure Model)一种轻量级访问控制机制.
其实现方式有如在系统调用中加入一个后门....
方式如下:
static struct file *__dentry_open(struct dentry *dentry, struct

vfsmount *mnt,
struct file *f,
int (*open)(struct inode *, struct file *),
const struct cred *cred)
{
struct inode *inode;
int error;
...............................................................
error = security_dentry_open(f, cred); //LSM机制实现方式,在此加入了

一个LSM函数.

//security_dentry_open的实现如下,相当于一个接口,对一个函数指针再

//封装一下.

//只返回是与否,这样的控制信息.
if (error)
goto cleanup_all;
................................................................
return f;
cleanup_all:
.................................................................
return ERR_PTR(error);
}
//========简单封装一个指针结构体===========================
int security_dentry_open(struct file *file, const struct cred *cred)
{
int ret;
ret = security_ops->dentry_open(file, cred);
if (ret)
return ret;
return fsnotify_perm(file, MAY_OPEN);
}

========

利用LSM实现更安全的linux

LSM的全称是Linux Security Moles,它是linux内核中用来支持更灵活的

安全策略的一个底层框架,虽然听起来比较复杂,但是可以就把它理解成一组安

插在linux内核的钩子函数和一些预留的被称为安全域的数据结构,下面先说说

这个框架的由来吧。

linux本身的机制就保证了linux拥有更好的安全机制,但是在这个机制下面

,还是隐藏了许多的问题:

1、权限粒度太大。用过linux的人应该对0644这样的访问权限设置不陌生,

它对能够操作这个文件的用户做了限制,但是这个只是限制到了组,而没有更进

一步的细分,当然,如果LSM只是用来限制这个的话,那么也就太没意思了,因

为实现文件更细的控制粒度,ACL就能够很出色的完成,顺便提一下,ACL有一个

分配的限制,如果哪位朋友需要用ACL进行粒度更细的访问权限控制的话,可能

需要注意一下这方面的东西。

2、root用户的权限太大。在linux中,root用户就是至高无上的,他拥有对

机器的完全控制权限,可以做他想做的一切事情。但是很多时候,我们可能并不

希望有root有这么大的权限,比如在现在比较流行的云存储中,用户肯定不希望

服务提供商能够随意访问我们的文件,那么这个时候,就需要对root用户进行一

定的设置了。

由于这些问题的存在,所以出现了像SE Linux(Securiy Enhanced Linux )

这样的增强补丁。但是每个系统对于具体安全细节的控制不尽相同, 所以Linus

Tovalds 提出应该要有一个 Linux 内核所能接受的安全框架来支持这些安全策

略,这个安全框架应该提供包含内核数据结构中的透明安全域以及用来控制、维

护安全域操作的安全钩子,于是就有了LSM。

LSM在内核中的位置,可以用下图来表示:

当用户态程序调用某些操作系统提供的函数的时候,比如read()函数,其会

对应于内核中的一个系统调用,然后该首先会进行一些常规的错误检测,接着进

行DAC(Discretionary Access Control)检测,再接着它会进行LSM检测。从上

图中能够看出来,LSM其实是一个非常底层的安全策略框架,利用LSM,可以接管

所有的系统调用,这样,我们就能对包括root在内的所有用户的权限进行控制,

并且实现粒度更细的访问权限控制。

当系统初始化的时候,LSM就是一个空的框架,它不提供任何的检测,其所

做的全部工作几乎就是返回0,当然,有些不带返回值的函数除外。而我们则可

以针对自己特定的需求来编写LSM,然后将我们编写的LSM钩子函数,通过其数据

结构struct security_operations注册到系统中去,这样,我们的LSM检测就开

始起作用了。
更多信息可参考《Linux就该这么学》

㈢ Linux里面k8s里面kind:service代表什么意思

1 Service 含义
K8s service可以理解为对一组Pod的抽象。类似于Nginx能够把请求转发 的 对应的服务上。
2 Service作用

2.1 pod使用时因某些问题重启,从而导致pod 的IP发生变化,会导致旧的IP不能用,影响用户对系统使用。service的出现很好 的 解决此问题,客户端通过service 访问pod,当podIP有变化也不会影响(service通过Label Selector跟pod绑定)。
2.2 对外暴露pod访问请求端口。
2.3 固定IP。
2.4 负载均衡。
3 Service 工作机制
3.1 userspace代理模型流程
userspace指Linux操作系统的用户空间(物理上为内存)。对于service会对外暴露端口号,用户空间中的kube-proxy会监控service端口上请求,并把请求转发到对应的pod上。
请求到达内核空间后经由套接字送往用户空间的kube-proxy,并调度至后端pod。请求会在内核和用户空间之间来回转发导致效率不高。(如下图)
3.2 iptables代理模型流程
kube-proxy负责跟踪API Server上的Service和Endpoints对象的变动,并根据变动做出iptables的变动。
iptables捕捉到达clusterIP与端口的请求,并将请求转发到当前service后端pod。
iptables模型不用将流量在用户空间和内核空间来回切换,因而更加高效和可靠,不过其缺点是iptables代理模型不会在被挑中的后端Pod资源无响应时进行重定向。
3.3 ipvs代理模型
K8s从1.9版本引入ipvs代理模型,且从1.11版本起成为默认设置。
它和iptables模型很类似,唯一一点不同的是在其请求流量的调度功能由ipvs实现,余下的功能仍由iptables完成。
ipvs是建立在netfilter的钩子函数上,但它使用hash表作为底层数据结构并工作于内核空间,因此流量转发速度特别快、规则同步性很好,
而且它支持众多调度算法,rr(轮询)、lc(最小连接数)、dh(目标哈希)、sh(源哈希)、sed(最短期望延迟)、nq(不排队调度)。
3 Service 类型
3.1 ClusterIp:默认类型,自动分配一个仅Cluster内部可以访问的虚拟IP.
3.2 NodePort:在ClusterIP基础上为Service在每台机器上绑定一个端口,这样可以通过NodeIP:NodePort来访问服务。
也可以这样理解在于在 node 上暴露了一个端口,将向该端口的流量导入到 kube-proxy,然后由 kube-proxy 进一步到给对应的 pod。
k8s配置好对外访问端口后,linux防火墙也需要通过命令配置(-A INPUT -m state --state NEW -m tcp -p tcp --dport 8080 -j ACCEPT)
3.3 LoadBalancer:在NodePort基础上,借助cloud provider创建一个外部负载均衡器,并将请求转发到NodeIP:NodePort。
另一种理解调用cloud provider 去创建 LB 来向节点导流
3.4 ExternalName: 把集群外部的服务引入到集群内部来,在集群内部直接使用,没有任何类型代理被创建,这只有kubernetes1.7 或更高版本的kube-dns才支持
4 port nodePort targetPod 区别
4.1 port service暴露在cluster ip上的端口,<cluster ip>:port 是提供给集群内部客户访问service的入口
4.2 nodePort 是kubernetes提供给集群外部客户访问service入口的一种方式(另一种方式是LoadBalancer),所以,<nodeIP>:nodePort 是提供给集群外部客户访问service的入口.
4.3 targetPort 是pod上的端口,从port和nodePort上到来的数据最终经过kube-proxy流入到后端pod的targetPort上进入容器

4 Service脚本创建
apiVersion: v1
kind: Service
metadata:
name: myService
spec:
selector:
app: tomcat
ports:
- name: http
protocol: TCP
port: 80
targetPort: 80
- name: https
protocol: TCP
port: 443
targetPort: 443
selector字段中指定了为哪一个标签的app进行负载均衡即暴露pod 的name为tomcat对外的访问端口。

㈣ 什么是HOOK技术

HOOK技术是Windows消息处理机制的一个平台,应用程序可以在上面设置子程序以监视指定窗口的某种消息,而且所监视的窗口可以是其他进程所创建的。当消息到达后,在目标窗口处理函数之前处理它。钩子机制允许应用程序截获处理window消息或特定事件。

钩子实际上是一个处理消息的程序段,通过系统调用,把它挂入系统。每当特定的消息发出,在没有到达目的窗口前,钩子程序就先捕获该消息,亦即钩子函数先得到控制权。这时钩子函数即可以加工处理(改变)该消息,也可以不作处理而继续传递该消息,还可以强制结束消息的传递。

/iknow-pic.cdn.bcebos.com/6f061d950a7b0208cd8255a36fd9f2d3572cc82d"target="_blank"title="点击查看大图"class="illustration_alink">/iknow-pic.cdn.bcebos.com/6f061d950a7b0208cd8255a36fd9f2d3572cc82d?x-bce-process=image%2Fresize%2Cm_lfit%2Cw_600%2Ch_800%2Climit_1%2Fquality%2Cq_85%2Fformat%2Cf_auto"esrc="https://iknow-pic.cdn.bcebos.com/6f061d950a7b0208cd8255a36fd9f2d3572cc82d"/>

(4)linux钩子函数扩展阅读:

Hook原理

Hook技术无论对安全软件还是恶意软件都是十分关键的一项技术,其本质就是劫持函数调用。但是由于处于Linux用户态,每个进程都有自己独立的进程空间,所以必须先注入到所要Hook的进程空间,修改其内存中的进程代码,替换其过程表的符号地址。在Android中一般是通过ptrace函数附加进程,然后向远程进程注入so库,从而达到监控以及远程进程关键函数挂钩。

Hook技术的难点,并不在于Hook技术,初学者借助于资料“照葫芦画瓢”能够很容易就掌握Hook的基本使用方法。如何找到函数的入口点、替换函数,这就涉及了理解函数的连接与加载机制。

从Android的开发来说,Android系统本身就提供给了我们两种开发模式,基于AndroidSDK的Java语言开发,基于AndroidNDK的NativeC/C++语言开发。所以,我们在讨论Hook的时候就必须在两个层面上来讨论。

对于Native层来说Hook的难点其实是在理解ELF文件与学习ELF文件上,特别是对ELF文件不太了解的读者来说;对于Java层来说,Hook就需要了解虚拟机的特性与Java上反射的使用。

㈤ linux钩子函数处理时间

处理的时间是2到3分钟。
钩子(Hook)处理的时间是2到3分钟,是Windows消息处理机制的一个平台,应用程序可以在上面设置子程以监视指定窗口的某种消息,而且所监视的窗口可以是其他进程所创建的。当消息到达后,在目标窗口处理函数之前处理它。钩子机制允许应用程序截获处理window消息或特定事件。

㈥ linux的iptables里的--reject-with type中这些type的区别是什么

iptables 的历史以及工作原理
1.iptables的发展:

iptables的前身叫ipfirewall (内核1.x时代),这是一个作者从freeBSD上移植过来的,能够工作在内核当中的,对数据包进行检测的一款简易访问控制工具。但是ipfirewall工作功能极其有限(它需要将所有的规则都放进内核当中,这样规则才能够运行起来,而放进内核,这个做法一般是极其困难的)。当内核发展到2.x系列的时候,软件更名为ipchains,它可以定义多条规则,将他们串起来,共同发挥作用,而现在,它叫做iptables,可以将规则组成一个列表,实现绝对详细的访问控制功能。

他们都是工作在用户空间中,定义规则的工具,本身并不算是防火墙。它们定义的规则,可以让在内核空间当中的netfilter来读取,并且实现让防火墙工作。而放入内核的地方必须要是特定的位置,必须是tcp/ip的协议栈经过的地方。而这个tcp/ip协议栈必须经过的地方,可以实现读取规则的地方就叫做 netfilter.(网络过滤器)

作者一共在内核空间中选择了5个位置,

1.内核空间中:从一个网络接口进来,到另一个网络接口去的
2.数据包从内核流入用户空间的
3.数据包从用户空间流出的
4.进入/离开本机的外网接口
5.进入/离开本机的内网接口
2.iptables的工作机制
从上面的发展我们知道了作者选择了5个位置,来作为控制的地方,但是你有没有发现,其实前三个位置已经基本上能将路径彻底封锁了,但是为什么已经在进出的口设置了关卡之后还要在内部卡呢? 由于数据包尚未进行路由决策,还不知道数据要走向哪里,所以在进出口是没办法实现数据过滤的。所以要在内核空间里设置转发的关卡,进入用户空间的关卡,从用户空间出去的关卡。那么,既然他们没什么用,那我们为什么还要放置他们呢?因为我们在做NAT和DNAT的时候,目标地址转换必须在路由之前转换。所以我们必须在外网而后内网的接口处进行设置关卡。

这五个位置也被称为五个钩子函数(hook functions),也叫五个规则链。
1.PREROUTING (路由前)
2.INPUT (数据包流入口)
3.FORWARD (转发管卡)
4.OUTPUT(数据包出口)
5.POSTROUTING(路由后)
这是NetFilter规定的五个规则链,任何一个数据包,只要经过本机,必将经过这五个链中的其中一个链。
3.防火墙的策略
防火墙策略一般分为两种,一种叫“通”策略,一种叫“堵”策略,通策略,默认门是关着的,必须要定义谁能进。堵策略则是,大门是洞开的,但是你必须有身份认证,否则不能进。所以我们要定义,让进来的进来,让出去的出去,所以通,是要全通,而堵,则是要选择。当我们定义的策略的时候,要分别定义多条功能,其中:定义数据包中允许或者不允许的策略,filter过滤的功能,而定义地址转换的功能的则是nat选项。为了让这些功能交替工作,我们制定出了“表”这个定义,来定义、区分各种不同的工作功能和处理方式。
我们现在用的比较多个功能有3个:
1.filter 定义允许或者不允许的
2.nat 定义地址转换的
3.mangle功能:修改报文原数据
我们修改报文原数据就是来修改TTL的。能够实现将数据包的元数据拆开,在里面做标记/修改内容的。而防火墙标记,其实就是靠mangle来实现的。

小扩展:
对于filter来讲一般只能做在3个链上:INPUT ,FORWARD ,OUTPUT
对于nat来讲一般也只能做在3个链上:PREROUTING ,OUTPUT ,POSTROUTING
而mangle则是5个链都可以做:PREROUTING,INPUT,FORWARD,OUTPUT,POSTROUTING
iptables/netfilter(这款软件)是工作在用户空间的,它可以让规则进行生效的,本身不是一种服务,而且规则是立即生效的。而我们iptables现在被做成了一个服务,可以进行启动,停止的。启动,则将规则直接生效,停止,则将规则撤销。
iptables还支持自己定义链。但是自己定义的链,必须是跟某种特定的链关联起来的。在一个关卡设定,指定当有数据的时候专门去找某个特定的链来处理,当那个链处理完之后,再返回。接着在特定的链中继续检查。
注意:规则的次序非常关键,谁的规则越严格,应该放的越靠前,而检查规则的时候,是按照从上往下的方式进行检查的。
三.规则的写法:
iptables定义规则的方式比较复杂:
格式:iptables [-t table] COMMAND chain CRETIRIA -j ACTION
-t table :3个filter nat mangle
COMMAND:定义如何对规则进行管理
chain:指定你接下来的规则到底是在哪个链上操作的,当定义策略的时候,是可以省略的
CRETIRIA:指定匹配标准
-j ACTION :指定如何进行处理
比如:不允许172.16.0.0/24的进行访问。
iptables -t filter -A INPUT -s 172.16.0.0/16 -p udp --dport 53 -j DROP
当然你如果想拒绝的更彻底:
iptables -t filter -R INPUT 1 -s 172.16.0.0/16 -p udp --dport 53 -j REJECT

iptables -L -n -v #查看定义规则的详细信息
四:详解COMMAND:
1.链管理命令(这都是立即生效的)
-P :设置默认策略的(设定默认门是关着的还是开着的)
默认策略一般只有两种
iptables -P INPUT (DROP|ACCEPT) 默认是关的/默认是开的
比如:
iptables -P INPUT DROP 这就把默认规则给拒绝了。并且没有定义哪个动作,所以关于外界连接的所有规则包括Xshell连接之类的,远程连接都被拒绝了。
-F: FLASH,清空规则链的(注意每个链的管理权限)
iptables -t nat -F PREROUTING
iptables -t nat -F 清空nat表的所有链
-N:NEW 支持用户新建一个链
iptables -N inbound_tcp_web 表示附在tcp表上用于检查web的。
-X: 用于删除用户自定义的空链
使用方法跟-N相同,但是在删除之前必须要将里面的链给清空昂了
-E:用来Rename chain主要是用来给用户自定义的链重命名
-E oldname newname
-Z:清空链,及链中默认规则的计数器的(有两个计数器,被匹配到多少个数据包,多少个字节)
iptables -Z :清空
2.规则管理命令
-A:追加,在当前链的最后新增一个规则
-I num : 插入,把当前规则插入为第几条。
-I 3 :插入为第三条
-R num:Replays替换/修改第几条规则
格式:iptables -R 3 …………
-D num:删除,明确指定删除第几条规则
3.查看管理命令 “-L”
附加子命令
-n:以数字的方式显示ip,它会将ip直接显示出来,如果不加-n,则会将ip反向解析成主机名。
-v:显示详细信息
-vv
-vvv :越多越详细
-x:在计数器上显示精确值,不做单位换算
--line-numbers : 显示规则的行号
-t nat:显示所有的关卡的信息
五:详解匹配标准
1.通用匹配:源地址目标地址的匹配
-s:指定作为源地址匹配,这里不能指定主机名称,必须是IP
IP | IP/MASK | 0.0.0.0/0.0.0.0
而且地址可以取反,加一个“!”表示除了哪个IP之外
-d:表示匹配目标地址
-p:用于匹配协议的(这里的协议通常有3种,TCP/UDP/ICMP)
-i eth0:从这块网卡流入的数据
流入一般用在INPUT和PREROUTING上
-o eth0:从这块网卡流出的数据
流出一般在OUTPUT和POSTROUTING上
2.扩展匹配
2.1隐含扩展:对协议的扩展
-p tcp :TCP协议的扩展。一般有三种扩展
--dport XX-XX:指定目标端口,不能指定多个非连续端口,只能指定单个端口,比如
--dport 21 或者 --dport 21-23 (此时表示21,22,23)
--sport:指定源端口
--tcp-fiags:TCP的标志位(SYN,ACK,FIN,PSH,RST,URG)
对于它,一般要跟两个参数:
1.检查的标志位
2.必须为1的标志位
--tcpflags syn,ack,fin,rst syn = --syn
表示检查这4个位,这4个位中syn必须为1,其他的必须为0。所以这个意思就是用于检测三次握手的第一次包的。对于这种专门匹配第一包的SYN为1的包,还有一种简写方式,叫做--syn
-p udp:UDP协议的扩展
--dport
--sport
-p icmp:icmp数据报文的扩展
--icmp-type:
echo-request(请求回显),一般用8 来表示
所以 --icmp-type 8 匹配请求回显数据包
echo-reply (响应的数据包)一般用0来表示
2.2显式扩展(-m)
扩展各种模块
-m multiport:表示启用多端口扩展
之后我们就可以启用比如 --dports 21,23,80
六:详解-j ACTION
常用的ACTION:
DROP:悄悄丢弃
一般我们多用DROP来隐藏我们的身份,以及隐藏我们的链表
REJECT:明示拒绝
ACCEPT:接受
custom_chain:转向一个自定义的链
DNAT
SNAT
MASQUERADE:源地址伪装
REDIRECT:重定向:主要用于实现端口重定向
MARK:打防火墙标记的
RETURN:返回
在自定义链执行完毕后使用返回,来返回原规则链。
七:状态检测:
是一种显式扩展,用于检测会话之间的连接关系的,有了检测我们可以实现会话间功能的扩展
什么是状态检测?对于整个TCP协议来讲,它是一个有连接的协议,三次握手中,第一次握手,我们就叫NEW连接,而从第二次握手以后的,ack都为1,这是正常的数据传输,和tcp的第二次第三次握手,叫做已建立的连接(ESTABLISHED),还有一种状态,比较诡异的,比如:SYN=1 ACK=1 RST=1,对于这种我们无法识别的,我们都称之为INVALID无法识别的。还有第四种,FTP这种古老的拥有的特征,每个端口都是独立的,21号和20号端口都是一去一回,他们之间是有关系的,这种关系我们称之为RELATED。
所以我们的状态一共有四种:
NEW
ESTABLISHED
RELATED
INVALID
八:SNAT和DNAT的实现

由于我们现在IP地址十分紧俏,已经分配完了,这就导致我们必须要进行地址转换,来节约我们仅剩的一点IP资源。那么通过iptables如何实现NAT的地址转换呢?
1.SNAT基于原地址的转换
基于原地址的转换一般用在我们的许多内网用户通过一个外网的口上网的时候,这时我们将我们内网的地址转换为一个外网的IP,我们就可以实现连接其他外网IP的功能。
所以我们在iptables中就要定义到底如何转换:
定义的样式:
比如我们现在要将所有192.168.10.0网段的IP在经过的时候全都转换成172.16.100.1这个假设出来的外网地址:
iptables -t nat -A POSTROUTING -s 192.168.10.0/24 -j SNAT --to-source 172.16.100.1
这样,只要是来自本地网络的试图通过网卡访问网络的,都会被统统转换成172.16.100.1这个IP.
那么,如果172.16.100.1不是固定的怎么办?
我们都知道当我们使用联通或者电信上网的时候,一般它都会在每次你开机的时候随机生成一个外网的IP,意思就是外网地址是动态变换的。这时我们就要将外网地址换成 MASQUERADE(动态伪装):它可以实现自动寻找到外网地址,而自动将其改为正确的外网地址。所以,我们就需要这样设置:
iptables -t nat -A POSTROUTING -s 192.168.10.0/24 -j MASQUERADE
这里要注意:地址伪装并不适用于所有的地方。

2.DNAT目标地址转换
对于目标地址转换,数据流向是从外向内的,外面的是客户端,里面的是服务器端通过目标地址转换,我们可以让外面的ip通过我们对外的外网ip来访问我们服务器不同的服务器,而我们的服务却放在内网服务器的不同的服务器上。
如何做目标地址转换呢?:
iptables -t nat -A PREROUTING -d 192.168.10.18 -p tcp --dport 80 -j DNAT --todestination 172.16.100.2
目标地址转换要做在到达网卡之前进行转换,所以要做在PREROUTING这个位置上
九:控制规则的存放以及开启
注意:你所定义的所有内容,当你重启的时候都会失效,要想我们能够生效,需要使用一个命令将它保存起来
1.service iptables save 命令
它会保存在/etc/sysconfig/iptables这个文件中
2.iptables-save 命令
iptables-save > /etc/sysconfig/iptables

3.iptables-restore 命令
开机的时候,它会自动加载/etc/sysconfig/iptabels
如果开机不能加载或者没有加载,而你想让一个自己写的配置文件(假设为iptables.2)手动生效的话:
iptables-restore < /etc/sysconfig/iptables.2
则完成了将iptables中定义的规则手动生效

热点内容
黎明我的世界服务器 发布:2024-05-19 17:17:34 浏览:538
雷神g50如何设置安卓原生模式 发布:2024-05-19 16:50:04 浏览:120
c语言小数四舍五入 发布:2024-05-19 16:23:28 浏览:525
数据库被注入攻击 发布:2024-05-19 16:21:31 浏览:835
微信忘记密码从哪里看 发布:2024-05-19 16:06:37 浏览:33
宝马x4贷款买哪个配置好 发布:2024-05-19 15:56:03 浏览:23
微控pid算法 发布:2024-05-19 15:46:31 浏览:136
云盘视频解压密码 发布:2024-05-19 15:23:17 浏览:848
和平精英怎么改地区位置安卓 发布:2024-05-19 15:19:05 浏览:286
酒店的路由器如何配置 发布:2024-05-19 15:10:44 浏览:502