对 Solaris 驱动程序进行逆向工程

逆向工程 斯帕克 日光 司机 总线
2021-06-12 21:12:07

我有几个 Solaris 2.6 时代的驱动程序,我想对其进行逆向工程。

我有一个 Sparc 反汇编器,它提供了一些信息,但它不再维护,所以我认为它可能无法提供所有信息。

这些驱动程序用于我拥有的 Sbus 图形加速器。ZX aka Leo早期的 3d 加速器之一。

那么我可以通过哪些方法对该驱动程序进行逆向工程呢?我可以拆卸它,但我不确定输出的内容。我当然也有 Solaris,所以也许我也可以在那里做一些事情。

最终目标是获得足够的信息来设计操作系统的驱动程序。有 NetBSD 的驱动程序,虽然不完整,因为确实存在(不可自由访问)的硬件文档没有 Window ID 编码,因为它丢失了。此外,由于硬件在双宽夹层卡上使用 Sbus 接口,因此在除了 SparcStation 或早期 UltraSparc 机器之外的任何设备上使用它都是不切实际的。

1个回答

好吧,既然它是一个 Solaris 驱动程序,首先您需要找到一些关于 Solaris 驱动程序如何与内核(或内核与它们)通信的文档。快速搜索结果如下

_init()初始化一个可加载的模块。它在可加载模块中的任何其他例程之前调用。_init()返回由 返回的值 mod_install(9F)在执行mod_install(9F)调用之前,模块可以选择执行一些其他工作如果模块在mod_install(9F)调用函数之前已经完成了一些设置,那么它应该准备在mod_install(9F)返回错误时撤消该设置

_info()返回有关可加载模块的信息。_info()返回由 返回的值mod_info(9F)

_fini()准备用于卸载的可加载模块。当系统想要卸载模块时调用它。如果模块确定它可以被卸载,则_fini()返回由 返回的值 mod_remove(9F)_fini()模块中成功返回后,在调用之前_init()不会调用模块中的其他例程

下面有一个很好的代码示例。

本指南似乎也很相关。

找到入口点后,只需遵循调用和指针即可。

下面是它在 IDA 中的样子:

.text:00000000 _init:                                  ! DATA XREF: leo_attach+5A8o
.text:00000000                                         ! leo_attach+5BCo ...
.text:00000000                 save    %sp, -0x60, %sp
.text:00000004                 sethi   %hi(leo_debug), %i2
.text:00000008                 ld      [leo_debug], %o0
.text:0000000C                 cmp     %o0, 4
.text:00000010                 bl      loc_38
.text:00000014                 sethi   %hi(leo_state), %o0
.text:00000018                 set     aLeoCompiledSS, %o0 ! "leo: compiled %s, %s\n"
.text:00000020                 set     a141746, %o1    ! "14:17:46"
.text:00000028                 sethi   %hi(aLeo_c6_6Jun251), %l0 ! "leo.c 6.6 Jun 25 1997 14:17:46"
.text:0000002C                 call    leo_printf
.text:00000030                 set     aJun251997, %o2 ! "Jun 25 1997"
.text:00000034                 sethi   %hi(leo_state), %o0
.text:00000038
.text:00000038 loc_38:                                 ! CODE XREF: _init+10j
.text:00000038                 set     leo_state, %i1
.text:0000003C                 sethi   %hi(0x1800), %l0
.text:00000040                 mov     %i1, %o0
.text:00000044                 set     0x1980, %o1
.text:00000048                 call    ddi_soft_state_init
.text:0000004C                 mov     1, %o2
.text:00000050                 orcc    %g0, %o0, %i0
.text:00000054                 bne,a   loc_80
.text:00000058                 ld      [%i2+(leo_debug & 0x3FF)], %o0
.text:0000005C                 sethi   %hi(0x14C00), %l0
.text:00000060                 call    mod_install
.text:00000064                 set     modlinkage, %o0
.text:00000068                 orcc    %g0, %o0, %i0
.text:0000006C                 be,a    loc_80
.text:00000070                 ld      [%i2+(leo_debug & 0x3FF)], %o0
.text:00000074                 call    ddi_soft_state_fini
.text:00000078                 mov     %i1, %o0
.text:0000007C                 ld      [%i2+(leo_debug & 0x3FF)], %o0
.text:00000080
.text:00000080 loc_80:                                 ! CODE XREF: _init+54j
.text:00000080                                         ! _init+6Cj
.text:00000080                 cmp     %o0, 4
.text:00000084                 bl      locret_9C
.text:00000088                 nop
.text:0000008C                 set     aLeo_initDoneRe, %o0 ! "leo: _init done, return(%d)\n"
.text:00000094                 call    leo_printf
.text:00000098                 mov     %i0, %o1
.text:0000009C
.text:0000009C locret_9C:                              ! CODE XREF: _init+84j
.text:0000009C                 ret
.text:000000A0                 restore
.text:000000A0 ! End of function _init

在 0x60 处,您可以看到mod_install使用指向 的指针进行调用modlinkage,因此您可以在那里查看字段所指向的内容。

但你甚至不必一直这样做。在这种情况下,程序员非常周到地保留了所有符号和调试输出。这应该对你的工作有所帮助:)

根据情况,您可以直接跳到有用的命名函数,例如leo_blit_sync_startleo_init_ramdac我个人更喜欢第一种方式,自上而下,但对每个人来说都是他自己的。

编辑:您可以做的一件相当简单的事情是将部分leo_debug开头变量修补.data为 5 左右。这应该会产生大量关于驱动程序正在执行的操作的调试输出。