
Netlink Basic Knowledge

一、基础知识
1. recv 相关
在 Linux 网络编程中,recv()
及其相关函数用于接收数据。除了 recv()
,还有多个变体和类似函数,适用于不同的场景,如 阻塞/非阻塞模式、消息边界保留、带外数据等。
1️⃣ recv()(标准接收函数)
1 | ssize_t recv(int sockfd, void *buf, size_t len, int flags); |
- 适用于: 从 TCP/UDP 套接字 接收数据。
- 主要参数:
sockfd
:套接字描述符。buf
:用于存储接收数据的缓冲区。len
:buf
的大小。flags
:0
(默认)普通接收。MSG_DONTWAIT
(非阻塞)。MSG_PEEK
(窥探数据,但不移除)。MSG_WAITALL
(等到缓冲区填满)。
- 返回值: 接收到的字节数,返回
0
表示 连接关闭,-1
表示 错误(可用errno
诊断)。
2️⃣ recvfrom()(用于 UDP/无连接套接字)
1 | ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, |
- 适用于: UDP 套接字(无连接)。
- 额外参数:
src_addr
:存储发送方地址(适用于 UDP)。addrlen
:src_addr
结构体的大小。
- 区别:
recv()
只用于 面向连接(TCP) 的 socket。recvfrom()
适用于 无连接(UDP),可以获取 数据来源地址。
✅ 示例(UDP 服务器):
1 | char buffer[1024]; |
3️⃣ recvmsg()(高级接收,多缓冲区支持)
1 | ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags); |
- 适用于: 接收带外数据(控制消息)、多缓冲区(scatter-gather I/O)。
- 参数
msghdr
结构体包含:msg_name
:可选,存储发送方地址。msg_iov
:I/O 向量数组,可接收多个缓冲区的数据。msg_control
:用于接收 辅助数据(如文件描述符传递)。
- 适用场景:
- 接收带外数据(OOB)。
- 接收多个缓冲区数据(scatter-gather I/O)。
- 用于 SO_PASSCRED 选项(传递进程凭证)。
✅ 示例(接收多个缓冲区的数据):
1 | struct iovec iov[2]; |
4️⃣ read()(通用读取,与 recv() 类似)
1 | ssize_t read(int fd, void *buf, size_t count); |
- 适用于: 任何 文件描述符(包括 sockets)。
- 区别:
read()
没有flags
参数,适用于 默认阻塞模式。recv()
适用于 socket,可以使用MSG_*
选项。
✅ 示例:
1 | char buffer[1024]; |
5️⃣ recv_flags 选项
标志 | 描述 |
---|---|
MSG_DONTWAIT |
非阻塞接收 |
MSG_PEEK |
窥探数据,不删除缓冲区数据 |
MSG_WAITALL |
直到缓冲区填满 |
MSG_TRUNC |
允许接收大于 buf 的数据 |
MSG_OOB |
接收带外数据 |
✅ 示例(窥探数据但不移除):
1 | recv(sockfd, buffer, sizeof(buffer), MSG_PEEK); |
2. send 相关
1️⃣ send()
send()
是用于通过 TCP 或 UDP 套接字发送数据的基本函数。
1 | ssize_t send(int sockfd, const void *buf, size_t len, int flags); |
sockfd
:要发送数据的套接字文件描述符。buf
:指向要发送的数据的缓冲区。len
:要发送的数据的长度。flags
:控制发送操作的标志(通常设置为 0)。
返回值:
- 成功时,返回实际发送的字节数。
- 失败时,返回 -1,并设置
errno
。
适用场景:
- 用于 TCP 或 UDP 套接字发送数据。
- 对于 UDP,它不会保证数据的可靠传输。
- 对于 TCP,它会在传输层处理数据的分段、重传等。
2️⃣ sendto()
sendto()
用于发送数据包,它不仅适用于 TCP 和 UDP 套接字,还能用在 原始套接字 和 UNIX 域套接字 等场景中。sendto()
允许指定目的地地址。
1 | ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, |
sockfd
:套接字文件描述符。buf
:要发送的数据缓冲区。len
:要发送的数据长度。flags
:标志。dest_addr
:指向目标地址的指针。对于 UDP,这是目标 IP 地址和端口;对于 原始套接字,这可能是目标的物理地址等。addrlen
:目标地址的长度。
返回值:
- 成功时,返回发送的字节数。
- 失败时,返回 -1,并设置
errno
。
适用场景:
- UDP 套接字或 原始套接字,因为它允许你指定目的地址。
- 适用于 单播、广播 或 多播 等情况。
3️⃣ sendmsg()
sendmsg()
是一个比 sendto()
更灵活的函数,允许发送更加复杂的消息,尤其是当你需要控制消息头、IOV(向量)等时。它常用于 Netlink 或其他高级套接字编程。
1 | ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags); |
sockfd
:套接字文件描述符。msg
:指向msghdr
结构的指针。msghdr
结构包含消息数据、目标地址、消息的 iov 等信息。flags
:控制发送操作的标志。
返回值:
- 成功时,返回实际发送的字节数。
- 失败时,返回 -1,并设置
errno
。
适用场景:
- 用于需要发送复杂消息的情况,如 Netlink、UNIX 域套接字,或者需要 控制信息(如
sendmsg()
用于发送带有多个 IOV 的消息)。
4️⃣ sendmmsg()
sendmmsg()
是 sendmsg()
的扩展,允许一次发送多个消息。这个函数通常用于提高网络传输效率,尤其在发送大量消息时。
1 | int sendmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags); |
sockfd
:套接字文件描述符。msgvec
:指向mmsghdr
结构数组的指针。每个mmsghdr
结构包含一个消息的发送信息。vlen
:msgvec
数组的长度。flags
:标志。
mmsghdr 结构:
1 | struct mmsghdr { |
返回值:
- 成功时,返回发送的消息数。
- 失败时,返回 -1,并设置
errno
。
适用场景:
- 用于高效地批量发送多个消息,通常在高性能网络应用中使用。
5️⃣ sendfile()
sendfile()
是一个高效的文件传输函数,它直接在内核空间中进行文件到套接字的数据传输,不需要将数据从内核复制到用户空间。它用于 TCP 套接字,可以有效地提高文件发送效率。
1 | ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count); |
参数:
out_fd
:输出文件描述符(通常是套接字)。in_fd
:输入文件描述符(通常是打开的文件)。offset
:从输入文件的哪个位置开始发送数据。count
:要发送的字节数。
返回值:
- 成功时,返回实际发送的字节数。
- 失败时,返回 -1,并设置
errno
。
适用场景:
- 高效地将文件内容传输到套接字,通常用于通过网络传输大文件。
二、Netlink 架构
这一部分内容主要来自
https://i.blackhat.com/Asia-24/Presentations/Asia-24-Ma-LinkDoor-A-Hidden-Attack.pdf
Netlink 中存在的漏洞,导致其作为 Android 的子系统可能会使 Android 变得不安全,所以这篇文章算是很好的介绍了 netlink 在安卓下的攻击利用。
Kernel mechanism of Classic Netlink
Netlink 架构图如上,其中需要注意的是Generic Netlink
和 Classic Netlink
是 Linux 内核中两种不同的 Netlink 实现方式,它们都用于内核与用户空间之间的通信,但在设计和使用上有显著的区别。
主要区别
特性 | Classic Netlink | Generic Netlink |
---|---|---|
协议类型 | 固定(如 NETLINK_ROUTE ) |
动态(使用 NETLINK_GENERIC ) |
扩展性 | 较差 | 较好(支持动态注册家族) |
消息结构 | 简单 | 复杂(支持属性机制) |
多路复用 | 不支持 | 支持(通过家族和命令) |
适用场景 | 固定功能模块 | 动态扩展功能模块 |
上图为 Classic Netlink
下常见的数据包传输格式。
Classic Netlink 实现中,存在一个比较严重的问题就是,对从用户空间传递的数据缺乏足够有效的检查,从而导致存在各种问题。
上图给出了 Netlink 从上至下在三个角度下可能存在攻击面,这可以帮助我们在审计代码的过程中注意这些提到的方面。
同理,这张图里面介绍了一些自下而上可能存在的一些问题。
Kernel mechanism of Generic Netlink
上图为 Generic Netlink
下常见的数据包传输格式,下图给出了 genlmsghdr
和 nlattr
结构体的相关说明。
攻击利用面如下,分别自上而下和自下而上两个角度阐述了在 Generic Netlink
下可能存在的攻击面。
三、Netlink基础概念
Netlink 是一种IPC(Inter Process Commumicate)机制,它是一种用于内核与用户空间通信的机制,同时它也以用于进程间通信(Netlink 更多用于内核通信,进程之间通信更多使用Unix域套接字)。
在一般情况下,用户态和内核态通信会使用:
传统的Ioctl、sysfs属性文件或者procfs属性文件,这3种通信方式都是同步通信方式,由用户态主动发起向内核态的通信,内核无法主动发起通信。
而Netlink是一种异步全双工的通信方式,它支持由内核态主动发起通信,内核为Netlink通信提供了一组特殊的API接口,用户态则基于socket API,内核发送的数据会保存在接收进程socket 的接收缓存中,由接收进程处理。
Netlink 相对于系统调用,ioctl 以及 /proc 文件系统而言具有以下优点:
- 为了使用 netlink,用户仅需要在 include/linux/netlink.h 中增加一个新类型的 netlink 协议定义即可, 如 #define NETLINK_MYTEST 17 然后,内核和用户态应用就可以立即通过 socket API 使用该 netlink 协议类型进行数据交换。但系统调用需要增加新的系统调用,ioctl 则需要增加设备或文件, 那需要不少代码,proc 文件系统则需要在 /proc 下添加新的文件或目录,那将使本来就混乱的 /proc 更加混乱。
- netlink是一种异步通信机制,在内核与用户态应用之间传递的消息保存在socket缓存队列中,发送消息只是把消息保存在接收者的socket的接收队列,而不需要等待接收者收到消息,但系统调用与 ioctl 则是同步通信机制,如果传递的数据太长,将影响调度粒度。
- 使用 netlink 的内核部分可以采用模块的方式实现,使用 netlink 的应用部分和内核部分没有编译时依赖,但系统调用就有依赖,而且新的系统调用的实现必须静态地连接到内核中,它无法在模块中实现,使用新系统调用的应用在编译时需要依赖内核。
- netlink 支持多播,内核模块或应用可以把消息多播给一个netlink组,属于该neilink 组的任何内核模块或应用都能接收到该消息,内核事件向用户态的通知机制就使用了这一特性,任何对内核事件感兴趣的应用都能收到该子系统发送的内核事件,在 后面的文章中将介绍这一机制的使用。
- 内核可以使用 netlink 首先发起会话,但系统调用和 ioctl 只能由用户应用发起调用。
- netlink 使用标准的 socket API,因此很容易使用,但系统调用和 ioctl则需要专门的培训才能使用。
Netlink 协议类型
目前 netlink 协议族支持32种协议类型,它们定义在 include/uapi/linux/netlink.h
中:
Netlink 用户态
用户态应用使用标准的socket APIs, socket(), bind(), sendmsg(), recvmsg() 和 close()。
使用 netlink 的应用必须包含头文件 linux/netlink.h
。 socket 需要的头文件也必不可少 sys/socket.h
。Netlink通信跟常用UDP Socket通信类似,struct sockaddr_nl
是netlink通信地址,跟普通socket struct sockaddr_in
类似。
struct sockaddr_nl
1 | struct sockaddr_nl { |
struct nlmsghdr
1 | /** |
nlmsg_type
:消息状态,内核在include/uapi/linux/netlink.h
中定义了以下4种通用的消息类型,它们分别是:
1 |
nlmsg_flags
:消息标记,它们用以表示消息的类型,如下:
1 | /* Flags values */ |
struct msghdr
user_msghdr msghdr
是 Linux 中用于描述消息传递的结构体(用户空间的 msghdr
结构体),主要用于实现系统调用 sendmsg
和 recvmsg
,支持更复杂的消息传递功能。通过 msghdr
,可以指定消息内容、目标地址、附加数据(如文件描述符)、标志等
1 | struct msghdr { |
msg_name 和 msg_namelen:
- 作用
- 指定消息的目标地址(对于发送)。
- 接收消息的源地址(对于接收)。
- 详细
- 典型用例是套接字地址(如
struct sockaddr_in
)。 - 若设置为
NULL
或长度为 0,则表示不关心地址信息。
- 典型用例是套接字地址(如
msg_iov 和 msg_iovlen:
作用:
- 描述消息的数据内容。
详细:
msg_iov
是一个指向struct iovec
数组的指针,每个iovec
描述一段内存区域。msg_iovlen
指定数组中元素的数量。- 通过这种方式,可以高效地发送或接收分散存储在多个内存区域的数据(称为 “scatter-gather I/O”)。
struct iovec 定义:
1
2
3
4struct iovec {
void *iov_base; // 数据的起始地址
size_t iov_len; // 数据的长度
};
msg_control 和 msg_controllen:
作用:
- 用于传递或接收附加数据,称为控制消息(control message)。
详细:
msg_control
是一个缓冲区,存储附加数据(如传递文件描述符、设置消息优先级)。msg_controllen
指定缓冲区大小。- 附加数据的内容通常是一个
cmsghdr
结构体。
struct cmsghdr 定义:
1
2
3
4
5
6struct cmsghdr {
size_t cmsg_len; // 控制消息的总长度
int cmsg_level; // 控制消息所属的协议级别(如 SOL_SOCKET)
int cmsg_type; // 控制消息的类型(如 SCM_RIGHTS)
// 后面紧跟附加数据
};
msg_flags:
- 作用
- 接收消息时返回的标志,用于指示消息的状态或行为。
- 常见标志
MSG_EOR
:表示消息的结束。MSG_TRUNC
:消息被截断。MSG_CTRUNC
:控制数据被截断。
使用流程
1. 创建套接字
1 | int skfd = socket(AF_NETLINK, SOCK_RAW, netlink_type) |
第一个参数必须是 AF_NETLINK 或 PF_NETLINK,在 Linux 中,它们俩实际为一个东西,它表示要使用netlink,第二个参数必须是SOCK_RAW或SOCK_DGRAM, 第三个参数指定netlink协议类型,如前面讲的用户自定义协议类型NETLINK_MYTEST, NETLINK_GENERIC是一个通用的协议类型,它是专门为用户使用的,因此,用户可以直接使用它,而不必再添加新的协议类型。
内核预定义的协议类型有:
2. 绑定套接字
1 | struct sockaddr_nl saddr; |
fd为前面的 socket 调用返回的文件描述符,参数 nladdr 为 struct sockaddr_nl 类型的地址。为了发送一个 netlink 消息给内核或其他用户态应用,需要填充目标 netlink socket 地址,此时,字段 nl_pid 和 nl_groups 分别表示接收消息者的进程 ID 与多播组。
如果字段 nl_pid
设置为 0,表示消息接收者为内核或多播组,如果 nl_groups
为 0,表示该消息为单播消息,否则表示多播消息。
3. 构建发送消息
使用函数 sendmsg
发送 netlink 消息时还需要引用结构 struct msghdr
、struct nlmsghdr
和 struct iovec
,结构 struct msghdr
需如下设置:
1 | struct msghdr msg; |
其中 nladdr
为消息接收者的 netlink
地址,struct nlmsghdr
为 netlink socket
自己的消息头,这用于多路复用和多路分解 netlink 定义的所有协议类型以及其它一些控制,netlink 的内核实现将利用这个消息头来多路复用和多路分解已经其它的一些控制,因此它也被称为netlink 控制块。因此,应用在发送 netlink 消息时必须提供该消息头。
1 | struct nlmsghdr |
字段 nlmsg_len 指定消息的总长度,包括紧跟该结构的数据部分长度以及该结构的大小,字段 nlmsg_type 用于应用内部定义消息的类型,它对 netlink 内核实现是透明的,因此大部分情况下设置为 0,字段 nlmsg_flags 用于设置消息标志,可用的标志包括:
1 | /* Flags values */ |
- 标志NLM_F_REQUEST用于表示消息是一个请求,所有应用首先发起的消息都应设置该标志。
- 标志NLM_F_MULTI 用于指示该消息是一个多部分消息的一部分,后续的消息可以通过宏NLMSG_NEXT来获得。
- 宏NLM_F_ACK表示该消息是前一个请求消息的响应,顺序号与进程ID可以把请求与响应关联起来。
- 标志NLM_F_ECHO表示该消息是相关的一个包的回传。
- 标志NLM_F_ROOT 被许多 netlink 协议的各种数据获取操作使用,该标志指示被请求的数据表应当整体返回用户应用,而不是一个条目一个条目地返回。有该标志的请求通常导致响应消息设置 NLM_F_MULTI标志。注意,当设置了该标志时,请求是协议特定的,因此,需要在字段 nlmsg_type 中指定协议类型。
- 标志 NLM_F_MATCH 表示该协议特定的请求只需要一个数据子集,数据子集由指定的协议特定的过滤器来匹配。
- 标志 NLM_F_ATOMIC 指示请求返回的数据应当原子地收集,这预防数据在获取期间被修改。
- 标志 NLM_F_DUMP 未实现。
- 标志 NLM_F_REPLACE 用于取代在数据表中的现有条目。
- 标志 NLM_F_EXCL_ 用于和 CREATE 和 APPEND 配合使用,如果条目已经存在,将失败。
- 标志 NLM_F_CREATE 指示应当在指定的表中创建一个条目。
- 标志 NLM_F_APPEND 指示在表末尾添加新的条目。
内核需要读取和修改这些标志,对于一般的使用,用户把它设置为 0 就可以,只是一些高级应用(如 netfilter 和路由 daemon 需要它进行一些复杂的操作),字段 nlmsg_seq 和 nlmsg_pid 用于应用追踪消息,前者表示顺序号,后者为消息来源进程 ID。下面是一个示例:
1 |
|
结构 struct iovec 用于把多个消息通过一次系统调用来发送,下面是该结构使用示例:
1 | struct iovec iov; |
在完成以上步骤后,消息就可以通过下面语句直接发送:
1 | sendmsg(fd, &msg, 0); |
应用接收消息时需要首先分配一个足够大的缓存来保存消息头以及消息的数据部分,然后填充消息头,添完后就可以直接调用函数 recvmsg() 来接收。
4. 接收回传信息
应用接收消息时需要首先分配一个足够大的缓存来保存消息头以及消息的数据部分,然后填充消息头,添完后就可以直接调用函数 recvmsg() 来接收。
1 |
|
注意:fd为socket调用打开的netlink socket描述符,在消息接收后,nlhdr指向接收到的消息的消息头,nladdr保存了接收到的消息的目标地址,宏NLMSG_DATA(nlhdr)返回指向消息的数据部分的指针。
宏定义相关
在linux/netlink.h
中定义了一些方便对消息进行处理的宏,这些宏包括:
1 |
宏NLMSG_ALIGN(len)
用于得到不小于len且字节对齐的最小数值。
1 |
宏NLMSG_LENGTH(len)
用于计算数据部分长度为len时实际的消息长度。它一般用于分配消息缓存。
1 | #define NLMSG_SPACE(len) NLMSG_ALIGN(NLMSG_LENGTH(len)) |
宏NLMSG_SPACE(len)
返回不小于NLMSG_LENGTH(len)
且字节对齐的最小数值,它也用于分配消息缓存。
1 | #define NLMSG_DATA(nlh) ((void*)(((char*)nlh) + NLMSG_LENGTH(0))) |
宏NLMSG_DATA(nlh)
用于取得消息的数据部分的首地址,设置和读取消息数据部分时需要使用该宏。
1 | #define NLMSG_NEXT(nlh,len) ((len) -= NLMSG_ALIGN((nlh)->nlmsg_len), \ |
宏NLMSG_NEXT(nlh,len)
用于得到下一个消息的首地址,同时len也减少为剩余消息的总长度,该宏一般在一个消息被分成几个部分发送或接收时使用。
1 | #define NLMSG_OK(nlh,len) ((len) >= (int)sizeof(struct nlmsghdr) && \ |
宏NLMSG_OK(nlh,len)
用于判断消息是否有len这么长。
1 | #define NLMSG_PAYLOAD(nlh,len) ((nlh)->nlmsg_len - NLMSG_SPACE((len))) |
宏NLMSG_PAYLOAD(nlh,len)
用于返回payload的长度,函数close用于关闭打开的netlink socket。
Netlink 内核态
netlink_kernel_create
内核函数用于创建内核socket与用户态通信
1 | static inline struct sock * |
单播netlink_unicast()
和 多播netlink_broadcast()
1 | /* 发送单播消息 */ |
Netlink 内核API
netlink_kernel_create
netlink的内核实现在.c文件net/core/af_netlink.c
中,内核模块要想使用 netlink,也必须包含头文件 linux /netlink.h
。内核使用netlink需要专门的API,这完全不同于用户态应用对 netlink 的使用。
增加新的netlink协议类型,用户仅需增加如下定义到 linux/netlink.h
就可以:
1 |
只要增加这个定义之后,用户就可以在内核的任何地方引用该协议,在内核中,为了创建一个netlink socket用户需要调用如下函数:
1 | struct sock * |
struct net *net
:指向网络命名空间的指针。通常传入&init_net
(表示初始网络命名空间)。int unit
:指定 Netlink 协议类型(如NETLINK_USER
、NETLINK_ROUTE
等)。struct netlink_kernel_cfg *cfg
:配置结构体,用于指定 Netlink socket 的行为。
netlink_kernel_create
是 Linux 内核中的一个函数,用于在内核模块中创建一个 Netlink socket,以便与用户空间程序进行通信。它是内核空间实现 Netlink 通信的关键函数之一。作用如下:
- 该函数用于在内核中创建一个 Netlink socket。
- 它允许内核模块通过 Netlink 协议与用户空间程序通信。
- 内核模块可以通过这个 socket 接收来自用户空间的消息,并向用户空间发送消息。
返回值:
- 成功时返回一个指向
struct sock
的指针(表示创建的 Netlink socket)。 - 失败时返回
NULL
。
struct netlink_kernel_cfg 结构体
netlink_kernel_cfg
用于配置 Netlink socket 的行为,其定义如下:
1 | struct netlink_kernel_cfg { |
input
:最重要的字段,指定接收消息的回调函数。当用户空间发送消息到内核时,内核会调用这个回调函数处理消息。groups
:指定多播组掩码,用于加入多播组。cb_mutex
:可选字段,用于保护回调函数的互斥锁。bind
和compare
:可选字段,用于高级配置。
当有消 息到达这个netlink socket
时,该input
函数指针就会被引用,一个 input 函数的使用案例大致如下:
1 | void input (struct sock *sk, int len) |
netlink_unicast()
用于将消息单播(一对一)发送到指定的用户空间进程。
1 | int netlink_unicast(struct sock *sk, struct sk_buff *skb, u32 pid, int nonblock); |
struct sock *sk
:Netlink socket(由netlink_kernel_create
创建)。struct sk_buff *skb
:要发送的消息(封装在sk_buff
中)。u32 pid
:目标用户空间进程的 PID。int nonblock
:是否非阻塞发送(通常为 0,表示阻塞)。
返回值:
- 成功时返回发送的字节数。
- 失败时返回错误码。
示例:
1 | struct sk_buff *skb; |
netlink_broadcast
用于将消息广播(一对多)发送到所有监听指定 Netlink 协议的用户空间进程。
1 | int netlink_broadcast(struct sock *sk, struct sk_buff *skb, u32 pid, u32 group, gfp_t allocation); |
struct sock *sk
:Netlink socket(由netlink_kernel_create
创建)。struct sk_buff *skb
:要发送的消息(封装在sk_buff
中)。u32 pid
:发送方的 PID(通常为 0)。u32 group
:目标多播组。gfp_t allocation
:内存分配标志(如GFP_KERNEL
)。
返回值:
- 成功时返回 0。
- 失败时返回错误码。
示例:
1 | struct sk_buff *skb; |
netlink_kernel_release
用于释放由 netlink_kernel_create
创建的 Netlink socket。
1 | void netlink_kernel_release(struct sock *sk); |
struct sock *sk
:要释放的 Netlink socket。
示例:
1 | if (nl_sk) { |
四、Netlink 使用示例
(1) 用户态程序 test.c
1 |
|
(2) Netlink 内核模块代码
1 |
|
(3)Makefile
1 | # |
目录结构:
1 | test-> |
确保有以上三个文件之后执行如下命令:
1 | test/test_netlink$ make |
五、Poc and Exploitation
Reference:https://i.blackhat.com/Asia-24/Presentations/Asia-24-Ma-LinkDoor-A-Hidden-Attack.pdf
PoC of Classic Netlink
1 | int main(int argc, char **argv) |
PoC of Generic Netlink
1 | int genl_send_msg(int sock_fd, u_int16_t family_id, u_int32_t nlmsg_pid, |
- Title: Netlink Basic Knowledge
- Author: henry
- Created at : 2025-02-10 21:14:23
- Updated at : 2025-02-10 21:32:43
- Link: https://henrymartin262.github.io/2025/02/10/netlink/
- License: This work is licensed under CC BY-NC-SA 4.0.