sk_buff学习笔记


背景知识

sk_buff 在内核网络协议栈中代表一个「包」,我们不难想到的是我们只需要创建一对 socket,在上面发送与接收数据包就能完成 sk_buff 的分配与释放,最简单的办法便是用 socketpair 系统调用创建一对 socket,之后对其 read & write 便能完成收发包的工作

总结其核心意思就是:

socketpair创建一对socket;

read&write完成收发包的工作;

结构体首先看sk_buff:

原博客对此的解释是:

data 和 tail 可以这么理解:数据包每经过网络层次模型中的一层都会被添加/删除一个 header (有时还有一个 tail),data 与 tail 便是用以对此进行标识的

也就是网络层、传输层这些都可以发数据包,每一层都有可能加上一些头或者尾巴;

多个sk_buff还会形成双链表:

从Pwn的角度看sk_buff结构

sk_buff分配自特殊的cache,不好用;

但是其数据部分分配自kmalloc_reserve(),最终会走__kmalloc分配路径,因此还是常规cache;

data会在后边有一个“尾巴”——skb_shared_info :(skb_shared_info 结构体的大小为 320 字节

实操

模板:

#include <sys/types.h>       
#include <sys/socket.h>
int main(){
int sock[2];
if (socketpair(AF_UNIX, SOCK_STREAM, 0, sock) < 0) {
perror("socketpair");
return -1;
}
size_t data[0x100];
write(sock[1], "AAAA", 4);
read(sock[0], data, 4);
puts(data);

}

调试技巧如下,我们首先重点关注这个sk_buff的data的创建:

现在__alloc_skb下断点,可以看到这是sk_buff的专用cache:

然后在这里分配skb:

然后是分配data,这里的size就是我们write的长度,之后取对齐、加上skb_shared_info的长度,之后通过kmalloc_reserve函数来分配内存(看a3师傅的博客应该最后还是调用到了__kmalloc函数):

之后初始化sk_buff:

全执行完之后data中会填充进去数据:(甚至原来的数据还有所残留,😀)

sk_buff的释放借助kfree_skb函数;

data的释放是通过skb_release_data函数释放;

参考

https://arttnba3.cn/2022/04/06/CVE-0X08-CVE-2022-0995/

https://arttnba3.cn/2021/11/29/PWN-0X02-LINUX-KERNEL-PWN-PART-II/#0x09-sk-buff%EF%BC%9A%E5%86%85%E6%A0%B8%E4%B8%AD%E7%9A%84%E2%80%9C%E5%A4%A7%E5%AF%B9%E8%B1%A1%E8%8F%9C%E5%8D%95%E5%A0%86%E2%80%9D


文章作者: q1ming
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 q1ming !
  目录