反转旧的 win32 应用程序以查找加密漏洞

逆向工程 视窗 吉德拉 资源
2021-06-16 11:50:17

我正在尝试对 SCADA 和 ICS(工业控制系统)上使用的旧 win32 应用程序进行逆向工程。这个应用程序有一个愚蠢的加密功能来保护用户密码,防止未经授权的访问。我很确定这种加密很容易逆转,因为它的最大大小是 10 个字符。它可能正在使用 XOR 进行一些 ROT,但我没有尝试猜测它的作用,而是尝试使用 Ghidra 反转软件并查看加密功能。

问题是我在应用程序导入的 dll 上找不到任何可疑函数。所以我试图在加密密码的对话框中寻找字符串。但是,该程序的所有对话框都存储在 dll 的资源部分(似乎它们为不同的语言提供了不同的 dll)。当我在 Ghidra 上打开这个 dll 时,我可以看到字符串,但我找不到哪个函数调用它们。使用 ResEdit 我设法获得了对话框和字符串的 ID,但是我如何将这些 ID 与调用它们的函数相匹配?有没有办法只用静态分析来做到这一点,还是我需要使用 OllyDbg?此外,更糟糕的是,包含字符串和对话框的 dll 未列在主 .exe 的导入部分中,也未列在任何导入的 dll 的任何导入部分中。我设法实际找到了动态导入资源 dll 的主 .exe 的功能。我想这会使仅使用静态分析更难找到匹配项吗?任何提示?谢谢!

1个回答

要解决这个问题,您需要了解如何通过 Windows API 加载资源。kernel32.dll 中的一些 API 是常用的,例如:

Kernel32.dll 中使用了许多 API,例如:

对于对话框/窗口,在 user32.dll 中使用了额外的 API,例如:

32 位代码中的简单 LoadString API 可能看起来像这样,其中 101 是字符串 ID。

        mov     DWORD PTR _stringID$[ebp], 101            ; string ID
        mov     DWORD PTR _pBuf$[ebp], 0
        push    0
        lea     eax, DWORD PTR _pBuf$[ebp]                ; put location to store result in eax
        push    eax
        mov     ecx, DWORD PTR _stringID$[ebp]            ; string ID = 101
        push    ecx
        mov     edx, DWORD PTR _hInstance$[ebp]           ; hInstance
        push    edx
        call    DWORD PTR __imp__LoadStringW@16
        mov     DWORD PTR _len$[ebp], eax                 ; eax holds length of string

在 64 位代码中可能如下所示:

mov     DWORD PTR stringID$[rsp], 101       ; string ID
mov     QWORD PTR pBuf$[rsp], 0
xor     r9d, r9d
lea     r8, QWORD PTR pBuf$[rsp]            ; put location to store result in r8
mov     edx, DWORD PTR stringID$[rsp]       ; string ID = 101
mov     rcx, QWORD PTR hInstance$[rsp]      ; hInstance
call    QWORD PTR __imp_LoadStringW
mov     DWORD PTR len$[rsp], eax            ; length of returned string in EAX

在 32 位中使用 FindResource 可能如下所示:

push    0
push    10         ; resource type ( 10 = RCDATA section)
push    100        ; 100 = resource ID
    mov     eax, DWORD PTR _hInstance$[ebp]    ; hInstance to module containing resource in EAX
                push    eax
                call    DWORD PTR __imp__FindResourceExA@16
                mov     DWORD PTR _rc$[ebp], eax  ; handle to the specified resource's information block returned in EAX
                mov     ecx, DWORD PTR _rc$[ebp]  ; specify resource information block handle in ECX
                push    ecx
                mov     edx, DWORD PTR _hInstance$[ebp] ; hInstance module with resource
                push    edx
                call    DWORD PTR __imp__LoadResource@8
                mov     DWORD PTR _rcData$[ebp], eax  ; hGlobal Handle returned in EAX
                mov     eax, DWORD PTR _rcData$[ebp]  ; specify hGlobal handle in EAX
                push    eax
                call    DWORD PTR __imp__LockResource@4 
                mov     DWORD PTR _data$[ebp], eax ; If the loaded resource is available, the return value in EAX is a pointer to the first byte of the resource
                mov     ecx, DWORD PTR _rc$[ebp]  ; resource information block handle
                push    ecx
                mov     edx, DWORD PTR _hInstance$[ebp] ; hInstance module with resource
                push    edx
                call    DWORD PTR __imp__SizeofResource@8 
                mov     DWORD PTR _size$[ebp], eax ; EAX contains size of resource in bytes

在 64 位中查找资源

xor     r9d, r9d
        mov     r8d, 10    ; resource type = 10 = RCDATA
        mov     edx, 100   ; resource ID = 100                    
        mov     rcx, QWORD PTR hInstance$[rsp] ; hInstance to module containing resource
        call    QWORD PTR __imp_FindResourceExA
        mov     QWORD PTR rc$[rsp], rax ; handle to the specified resource's information block returned in RAX
        mov     rdx, QWORD PTR rc$[rsp] ; specify handle to resource information block in RDX
        mov     rcx, QWORD PTR hInstance$[rsp] ; specify hInstance in RCX
        call    QWORD PTR __imp_LoadResource
        mov     QWORD PTR rcData$[rsp], rax ; HGLOBAL returned in RAX
        mov     rcx, QWORD PTR rcData$[rsp] ; specify HGLOBAL in RCX
        call    QWORD PTR __imp_LockResource
        mov     QWORD PTR data$[rsp], rax  ; If the loaded resource is available, the return value in RAX is a pointer to the first byte of the resource
        mov     rdx, QWORD PTR rc$[rsp]   ; handle to the specified resource's information block
        mov     rcx, QWORD PTR hInstance$[rsp] ; hInstance for module containing resource
        call    QWORD PTR __imp_SizeofResource
        mov     DWORD PTR size$[rsp], eax ; size of data in bytes returned in EAX