3

I’m trying to reverse engineer an old win32 application used on SCADA and ICS (Industrial Control Systems). This app has a silly encryption function to protect the user password to prevent unauthorized access. I’m pretty sure this encryption is easy to reverse as its maximum size is 10 chars. It’s probably doing some ROT with XOR, but instead of trying to guess what it does, I’m trying to reverse the software with Ghidra and take a look at the encryption function.

The problem is that I couldn’t find any suspicious function on the dlls that the app imports. So I’m trying to look for strings on the dialog box that encrypts the password. However all dialogs of this program are stored on a resource section of a dll (it seems that they provided different dlls for different languages). When I open this dll on Ghidra I can see the strings, but I can’t find which function calls them. Using ResEdit I managed to get the IDs of the dialog box and of the strings, but how can I match these IDs with the functions that call them? Is there a way to do it with static analysis only or will I need to use OllyDbg? Also, to make it worse, the dlls that contains the strings and dialog boxes isn’t listed in the import section of the main .exe neither on any import section of any of the imported dlls. I managed to actually find the function of the main .exe that dynamically imports the resource dll. I guess this would make it harder to find the match with static analysis only right? Any hints? Thanks!

  • I would like to offer a different approach as well, which would not involve classic RCE. Since you seem to be able to run the binary, you may use a tool like WinSpy (on GitHub) or Spy++ (included with Visual Studio) to look up the control IDs of the running application and match them to what you see during static analysis with Ghidra. Also understand that it's well possible to build blobs in memory which are understood as dialog resources and so on. Therefore it needn't be in the resource section at all ... – 0xC0000022L Jan 23 at 16:36
2

To work this out you need to understand how resources are loaded via Windows APIs. A number of APIs in kernel32.dll are commonly used such as:

A number of APIs in Kernel32.dll are used for example:

And for dialogs/windows additional APIs are used in user32.dll, such as:

A simple LoadString API in 32-bit code may look something like this where 101 is the string 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

In 64-bit code may look something like this:

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

Using FindResource in 32-bit may look something like this:

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

FindResource in 64-bit

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
| improve this answer | |
  • 2
    IIRC some functions take the resource ID directly and don’t require the resource to be loaded first, e.g. CreateDialog. – Igor Skochinsky Jan 25 at 21:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.