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

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

评论

我也想提供一种不涉及经典RCE的方法。由于您似乎能够运行二进制文件,因此可以使用WinSpy(在GitHub上)或Spy ++(在Visual Studio中包含)之类的工具来查找正在运行的应用程序的控件ID,并将其与静态分析期间看到的匹配。与吉德拉。还应了解,很可能在内存中建立斑点,这些斑点被理解为对话框资源,依此类推。因此,它根本不需要在资源部分中...

#1 楼

要解决此问题,您需要了解如何通过Windows API加载资源。通常使用kernel32.dll中的许多API,例如:

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



LoadLibrary
LoadLibraryEx
GetModuleHandle
FindResource
FindResourceEx
LockResource
FreeResource
SizeofResource

以及用于对话框/窗口user32.dll中使用了其他API,例如:


RegisterClassEx
DialogBoxParam
LoadAccelerators
LoadIcon
LoadImage
LoadMenu
LoadCursor
LoadString

用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位FindResource

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


评论


IIRC的某些功能直接获取资源ID,不需要先加载资源,例如创建对话框。

–伊戈尔·斯科钦斯基♦
20 Jan 25 '21:56