跟踪消息传递而不是调用堆栈

逆向工程 拆卸 静态分析 操作系统
2021-07-01 04:59:25

在微内核中,许多有趣的功能不是通过传统的函数调用发生的,而是通过单独实体之间的消息传递发生的。

有没有像这样的操作系统架构通常用来实现消息传递的结构?有没有一种在反汇编时标记它的有条理的方法,使跟踪消息路径和跟踪调用堆栈一样容易?

1个回答

我认为我没有反汇编任何微内核,但“消息传递”在至少两类程序中很常见:Win32 GUI(原始 Win32 和基于 MFC 的)和 Objective-C 可执行文件。

在这两种情况下,您都有某种中央调度程序例程(或例程)接受消息并将它们转发给某些接收者,这些接收者可能在当前程序内部或外部。

接收者可以动态注册(RegisterClass在 Win32 中),也可以以某种静态方式(Objective-C 类元数据或 MFC 的消息处理程序表)指定。

至于调度员,让我们考虑一下 Win32 的SendMessage. 它有参数hWndMsg(和额外的参数)。第一个指定收件人。您也许能够追踪它来自哪里,然后只需查找与窗口对应的类注册并检查其窗口过程是否处理此特定消息。我想你可以用注释“转到窗口过程0x35345800”或类似的注释来标记调用以跟踪它。使用 MFC,您需要找到类的消息表并查找相应的处理程序。

使用Objective-C,objc_msgSend接受接收对象和选择器来执行。如果您可以回溯该对象,则可以检查它是否具有具有该名称的选择器。或者,在程序中检查所有具有此名称的选择器。再次,一旦你找到它,发表评论。

因此,类似的方法可能可以扩展到所有其他消息传递系统 - 找到收件人,然后在调度程序调用的地方检查哪些可以处理它,并检查处理程序。有时您甚至不需要实际执行第一部分 - 如果消息 ID/名称足够独特,您也许可以通过搜索找到处理程序。

一个有点相关的问题是使用 C++ 和虚函数,但它已在另一个问题中介绍


我只记得另一种不使用调用堆栈的程序。它是那些使用Continuation-passing Style 的,通常是用某种函数语言编写的。Greg Sinclair 写了一篇关于拆解 CHICKEN 的恐怖的非常漂亮和有趣的论文 - 语言 Scheme 的实现。他的网站已关闭,但幸运的是 Archive.org保留了一份副本引用它的一句话:

对于逆向工程师来说,Continuation Passing Style 意味着我们所知道的文明化的结束。