使用 IDA Pro 在 Windows 3.1 16 位 DLL 中查找对资源字符串的引用

逆向工程 艾达 视窗 部件 x86
2021-06-20 21:13:10

在 Windows 10 上运行的 DosBox + Windows 3.1 中试验 Visual Basic 4。虽然我已经从 MS-DOS 6.22 安装了 SHARE.exe 并且它似乎运行正常,但它仍然无法检测到它。

我得到的错误是:“必须安装 SHARE.exe 才能运行 Visual Basic”

我想弄清楚 SHARE.exe 检测是如何工作的。我安装了 Windows 3.1 SDK 并尝试使用 CodeView 进行调试。但是,我不知道如何在 MESSAGEBOX 上设置断点,而且我无法使用键盘快捷键“暂停”系统并闯入 CodeView,因为它似乎传递给了 Windows 主机而不是 Dosbox。

分析VBIDE.dll我可以找到错误信息:

res098:0000 ; Resource, type (8006): String table
res098:0000 ; File offset      : 26CB0h  Length: 0100h
res098:0000 ; Attributes (1C30): Movable Pure
res098:0000 ; Resource ID      : 3143
res098:0000 ; ===========================================================================
res098:0000
res098:0000 ; Segment type: Regular
res098:0000 res098          segment para public 'RESOURCE' use16
res098:0000                 assume cs:res098
res098:0000                 assume es:nothing, ss:nothing, ds:nothing, fs:nothing, gs:nothing
res098:0000 a8shareExeMustB db '8SHARE.EXE must be installed in order to run Visual Basic',0
res098:003A aRecordsourcePr db '>RecordSource property of the associated data control is empty.MV'
res098:003A                 db 'isual Basic was not able to start up due to an invalid system con'

VBIDE.dll 以这种方式在 VB.exe 中被引用:

cseg15:2EBF                 mov     es, [bp+var_4+2]
cseg15:2EC2                 mov     byte ptr es:[si+1], 0
cseg15:2EC7                 lea     ax, [bp+var_17A]
cseg15:2ECB                 push    ss
cseg15:2ECC                 push    ax              ; LPCSTR
cseg15:2ECD                 push    ds
cseg15:2ECE                 push    offset aVbideDll ; "VBIDE.DLL"
cseg15:2ED1                 call    sub_37E70
cseg15:2ED6                 mov     word_10C9DC, ax
cseg15:2ED9                 or      ax, ax
cseg15:2EDB                 jnz     short loc_389CC
cseg15:2EDD                 push    ds
cseg15:2EDE                 push    offset aVbideDll_0 ; "VBIDE.DLL"
cseg15:2EE1                 push    ds
cseg15:2EE2                 push    offset aTheLanguageDll ; "The language DLL '%s' could not be foun"...
cseg15:2EE5                 lea     ax, [bp+var_27A]

我怀疑这个 word_10C9DC 位置很重要,它在调用 LOADSTRING 时被引用(一些例子还有更多)

cseg09:269A                 enter   50h, 0
cseg09:269E                 push    word_10C9DC     ; HINSTANCE
cseg09:26A2                 push    7D0h            ; UINT
cseg09:26A5                 lea     ax, [bp+var_28]
cseg09:26A8                 push    ss
cseg09:26A9                 push    ax              ; LPSTR
cseg09:26AA                 push    28h ; '('       ; int
cseg09:26AC                 call    LOADSTRING
cseg09:26B1                 push    word_10C9DC     ; HINSTANCE
cseg09:26B5                 push    [bp+arg_2]      ; UINT
cseg09:26B8                 lea     ax, [bp+var_50]
cseg09:26BB                 push    ss
cseg09:26BC                 push    ax              ; LPSTR
cseg09:26BD                 push    28h ; '('       ; int
cseg09:26BF                 call    LOADSTRING
cseg09:26C4                 lea     ax, [bp+var_28]
cseg09:26C7                 push    ss
cseg09:26C8                 push    ax              ; LPCSTR
cseg09:26C9                 lea     ax, [bp+var_50]
cseg09:26CC                 push    ss
cseg09:26CD                 push    ax              ; LPCSTR
cseg09:26CE                 push    [bp+arg_0]      ; int
cseg09:26D1                 push    seg cseg04
cseg09:26D4                 push    offset aVbIni   ; "VB.INI"
cseg09:26D7                 call    GETPRIVATEPROFILEINT
cseg09:26DC                 leave

有一些 MESSAGEBOX 引用:

消息框 #1

cseg05:0EC8                 push    0               ; HWND
cseg05:0ECA                 les     bx, dword_10C1F8
cseg05:0ECE                 add     bx, es:[bx+9Ah]
cseg05:0ED3                 push    es
cseg05:0ED4                 push    bx              ; LPCSTR
cseg05:0ED5                 push    0
cseg05:0ED7                 push    0               ; LPCSTR
cseg05:0ED9                 push    10h             ; UINT
cseg05:0EDB                 call    MESSAGEBOX

消息框 #2

cseg15:2FE2                 push    0               ; HWND
cseg15:2FE4                 les     bx, dword_10C1F8
cseg15:2FE8                 add     bx, es:[bx+9Eh]
cseg15:2FED                 push    es
cseg15:2FEE                 push    bx              ; LPCSTR
cseg15:2FEF                 push    seg cseg02
cseg15:2FF2                 push    offset byte_9EC8 ; LPCSTR
cseg15:2FF5                 push    1010h           ; UINT
cseg15:2FF8                 call    MESSAGEBOX

消息框 #4 & 5

cseg47:297E                 push    bp
cseg47:297F                 mov     bp, sp
cseg47:2981                 push    di
cseg47:2982                 push    si
cseg47:2983                 mov     di, [bp+6]
cseg47:2986                 mov     es, word ptr [bp+8]
cseg47:2989                 push    word ptr es:[di]
cseg47:298C                 push    word ptr es:[di+4]
cseg47:2990                 push    word ptr es:[di+2]
cseg47:2994                 push    word ptr es:[di+8]
cseg47:2998                 push    word ptr es:[di+6]
cseg47:299C                 push    word ptr es:[di+0Ah]
cseg47:29A0                 call    MESSAGEBOX
cseg47:29A5                 mov     si, ax
cseg47:29A7                 or      si, ax
cseg47:29A9                 jnz     short loc_B517F
cseg47:29AB                 mov     es, word ptr [bp+8]
cseg47:29AE                 and     word ptr es:[di+0Ah], 0CF0Fh
cseg47:29B4                 push    word ptr es:[di]
cseg47:29B7                 push    word ptr es:[di+4]
cseg47:29BB                 push    word ptr es:[di+2]
cseg47:29BF                 push    word ptr es:[di+8]
cseg47:29C3                 push    word ptr es:[di+6]
cseg47:29C7                 or      word ptr es:[di+0Ah], 1010h
cseg47:29CD                 push    word ptr es:[di+0Ah]
cseg47:29D1                 call    MESSAGEBOX

我无法确定哪个消息框正在显示消息,因此我将它们全部替换为 int 3,这使我能够进入 CodeView 调试器。由此我计算出相关的 MESSAGEBOX 代码显示错误是:

cseg47:297E                 push    bp
cseg47:297F                 mov     bp, sp
cseg47:2981                 push    di
cseg47:2982                 push    si
cseg47:2983                 mov     di, [bp+6]
cseg47:2986                 mov     es, word ptr [bp+8]
cseg47:2989                 push    word ptr es:[di]
cseg47:298C                 push    word ptr es:[di+4]
cseg47:2990                 push    word ptr es:[di+2]
cseg47:2994                 push    word ptr es:[di+8]
cseg47:2998                 push    word ptr es:[di+6]
cseg47:299C                 push    word ptr es:[di+0Ah]
cseg47:29A0                 call    MESSAGEBOX

然而,这部分代码没有外部参照,我能找到的这个位置的唯一参考是这些 push 语句:

loc_B51AB:
mov     ax, [bp+arg_6]
mov     dx, [bp+arg_8]
mov     [bp+var_A], ax
mov     [bp+var_8], dx
mov     ax, [bp+arg_2]
mov     dx, [bp+arg_4]
mov     [bp+var_6], ax
mov     [bp+var_4], dx
mov     ax, [bp+arg_0]
mov     [bp+var_2], ax
push    seg cseg47
push    297Eh
lea     ax, [bp+var_C]
push    ss
push    ax
push    ss
push    ax
call    sub_B4F7C
leave
retf    0Ch
sub_B5188 endp

什么代码在这里设置了消息框字符串,有没有办法通过了解资源 DLL 中的详细信息来加载字符串时我应该查找什么程序集。

1个回答

从您发布的代码来看,这似乎sub_B4F7C是一个注册处理程序函数,在本例中为 function at 297Eh该地址(函数指针)可能被保存在某处,sub_B4F7C并且在SHARE.EXE未检测到时将被调用

因此,不会直接调用此处理程序;当事件发生时,代码将在相关地址检查为该事件注册的函数并调用它。它将使用之前放入内存的地址sub_B4F7C,而不是硬编码的值。

简而言之:别担心,这个函数会被调用。您可以通过在其开头放置断点来验证它。将此处理程序标记为函数也是值得的(选择相关片段并按P)。然后您可以右键单击297Eh,选择offset并选择要显示的新创建函数的偏移量。

注意:根据文档(对于32位,但签名似乎相同),word_10C9DC是包含要加载的字符串的模块的标识符。