利用msg_msg实现任意地址读写msgsnd和msgrcv的源码分析内核通过msgsnd和msgrcv来进行
IPC通信 。内核消息分为两个部分,一个是消息头
msg_msg(0x30),以及后面跟着的
消息数据 。整个内核消息的长度是从
kmalloc-64到kmalloc-4096` 。
/* one msg_msg structure for each message */struct msg_msg { struct list_head m_list; long m_type; size_t m_ts;/* message text size */ struct msg_msgseg *next; void *security; /* the actual message follows immediately */};
msgsnd发送数据调用链及方法调用链:通过msgsnd() -> ksys_msgsnd() -> do_msgsnd() -> load_msg() -> alloc_msg()
来分配消息头和消息的数据,接着通过load_msg() -> copy_from_user()
来将用户数据拷贝进内核 。
使用方法:例如我们想要发送一个包含0x1000个'A'
的消息,代码如下:
struct msgbuf{long mtype;char mtext[0x1000];} msg;msg.mtype = 1;memset(msg.mtext, 'A', sizeof(msg.mtext));qid = msgget(IPC_PRIVATE, 0666 | IPC_CREAT));msgsnd(qid, &msg, sizeof(msg.mtext), 0);
此外如果消息长度超过0xfd0
,那么就会采取分段储存的方式,采用单向链表进行连接 。第一个称作消息头,用msg_msg
结构进行储存,第二个和第三个称作segment
,用msg_msgseg
结构进行储存 。消息的最大长度由/proc/sys/kernel/msgmax
确定,默认大小为8192
个字节,所以最多连接三个成员 。
msgrcv接收数据的调用链及方法调用链msgrcv() -> ksys_msgrcv() -> do_msgrcv() -> find_msg() & do_msg_fill() & free_msg()
。通过find_msg
来定位消息,并将消息从队列中unlink
,再调用do_msg_fill() -> store_msg()
来将消息从内核空间拷贝到用户空间,最后调用free_msg
释放消息 。
使用方法:例如我们想要接收一个包含0x1000个'A'
的消息,代码如下:
void *memdump = malloc(0x1000);msgrcv(qid, memdump, 0x1000, 1, IPC_NOWAIT | MSG_COPY | MSG_NOERROR);
此外值得注意的是:如果用flag:MSG_COPY
来调用msgrcv()
,就会调用prepare_copy()
分配临时消息,并调用copy_msg()
将请求的数据拷贝到该临时消息 。在将消息拷贝到用户空间之后,原始消息会被保留,不会从队列中unlink
,而是直接goto out_unlock0
,然后调用free_msg()
删除该临时消息,有些题目中这一点对于利用很重要 。为什么?因为有些题目漏洞在UAF的时候,没有泄露正确地址,所以会破坏msg_msg->m_list
双链表指针,unlink
会触发崩溃 。如果某漏洞可以跳过前16字节,那就不需要注意这一点 。
数据泄露越界读取数据在拷贝数据的时候,我们对数据长度的判断主要是依靠msg_msg->m_ts
。所以我们可以想到如果我们可以控制某一个消息的msg_msg
使得msg_msg->m_ts
被改为一个较大的数,那么我们就能够实现越界读取数据 。
任意地址读取对于大于0xfd0
的数据,内核会在msg_msg
的基础上再加上msg_msgseg
结构体,形成一个单向链表,如果我们能够同时控制msg_msg->m_ts
及msg_msg->next
,我们便可以实现任意地址读 。但是这里需要注意的是,无论我们采用MSG_COPY
还是常规消息接收,拷贝消息的主要依据还是msg_msg->next
,所以为了避免遍历消息时出现访存崩溃,实现对特定地址以后数据的读取,我们需使得segment
的前8
字节为NULL
。
任意地址写我们可以通过结合
经验总结扩展阅读
- 微商如何利用抖音推广产品?
- 用AR Engine手部骨骼跟踪能力实现虚拟手表试戴
- 土豆怎么去除龙葵素
- 争做新时代自信好少年
- 一个人该如何去实现自己的理想
- 含源码 手把手教你使用LabVIEW人工智能视觉工具包快速实现传统Opencv算子的调用
- 如何利用好你的地下室
- Jmix 中 REST API 的两种实现
- 含源码 手把手教你使用LabVIEW人工智能视觉工具包快速实现图像读取与采集
- 之三 2流高手速成记:SpringBoot整合mybatis/mybatis-plus实现数据持久化