Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

unicorn.unicorn.UcError: Invalid memory read (UC_ERR_READ_UNMAPPED) while emulating a windows binary #1532

Closed
chintanhshah opened this issue Jan 28, 2025 · 7 comments

Comments

@chintanhshah
Copy link

*Describe the bug

I have been trying to emulate the windows binary which contains some simple windows API calls ( FindResourceA -> SizeofResource, ->LoadResource -> memcpy . Windows binary contains the calc shellcode in the resource section which is retrieved by these APIs and then executed. C code is very minimal as follows :

#include <Windows.h>
#include "resource2.h"
#pragma comment(lib, "vcruntime.lib")

int main()
{
    HRSRC shellcodeRes = FindResource(NULL, MAKEINTRESOURCE(IDR_SHELLC1), "shellc");
    DWORD shellcodeSize = SizeofResource(NULL, shellcodeRes);
    HGLOBAL shellcodeResData = LoadResource(NULL, shellcodeRes);
    void* execute = VirtualAlloc(0, sizeof(shellcodeResData), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    memcpy(execute, shellcodeResData, shellcodeSize)

Sample Code

Emulator code has these APIs hooks implemented. For instance, the basic hook for FindResourceA is as follows :

@winsdkapi(cc=STDCALL,params={
	#'hModule': HMODULE,
	'lpName': LPCSTR,
	'lpType': LPCSTR
	})
def hook_FindResourceA(ql: Qiling, address: int, params):
	
	print(f"params :{params}")
	print(f"FindResourceA called at address {hex(address)}")


#Hook is set before ql.run ():
ql.os.set_api('FindResourceA',hook_FindResourceA, QL_INTERCEPT.CALL)
  : 
#some other hooks
ql.run()

Unicorn Unmapped read memory error

While executing , I end up with UC_ERR_READ_UNMAPPED error after few instructions but not sure which unmapped memory address is being attempted to read. It throws an exception in FindResourceA but hook function is never called though.

Image

Tried following hooks to see if we can intercept the invalid mem address read. Does not enter into this hook as well.


def hooklog(ql: Qiling, access: int, address: int, size: int, value: int):
        
        assert access == UC_MEM_READ_UNMAPPED

        ql.log.warning(f'unmapped memory read at address : {address:#x}')
        ql.stop()

         return QL_HOOK_BLOCK

ql.hook_mem_unmapped(self.hooklog)
ql.hook_mem_read_invalid(self.hooklog)
ql.hook_mem_fetch_invalid(self.hooklog)
ql.hook_mem_invalid(self.hooklog)

@elicn , any other steps / Worksaround that you can suggest ? Using Qiling 1.4.1 and Unicorn 2.0.0

@elicn
Copy link
Member

elicn commented Jan 28, 2025

Qiling 1.4.1 is more than 3 years old, so I'd recommend to checkout the current dev branch and work with it instead. Don't forget to update all dependencies with pip. To make sure your Qiling installation doesn't get mixed with the version you checked out, you can use a virtual environment (which is recommended anyway).

After doing that, I would recommend using the trace module to enable more visibility into emulation history; see #765 for more details.

Having said all of that, the resources API seem to have an empty implementation. We can get to that when we figure out the problem.

@chintanhshah
Copy link
Author

chintanhshah commented Jan 30, 2025

@elicn , Thanks for your comments . Just missed mentioning that when this was tested with a different windows binary using Resource APIs, it was working perfectly fine as expected . All return values are as per implementation.

Image

@elicn
Copy link
Member

elicn commented Feb 12, 2025

@chintanhshah, your last message did not clarify whether there is an issue after all or not.
If there is no issue, kindly close the issue.

@chintanhshah
Copy link
Author

chintanhshah commented Feb 13, 2025

@elicn , I was able to fix the UC_ERR_READ_UNMAPPED issue. I am not sure if it is inherent qiling hooks issue but let me quickly describe what it turned out to be :

On your suggestion, I enabled the full tracing with the newer version . UC was raising exception here :

https://github.com/unicorn-engine/unicorn/blob/master/bindings/python/unicorn/unicorn_py2.py#L560

Image

If we look at the signature of the FindResourceA Windows API :

HRSRC FindResourceA(
  [in, optional] HMODULE hModule,
  [in]           LPCSTR  lpName,
  [in]           LPCSTR  lpType
);

LPCSTR lpName corresponds to the following parameter in the source code :

HRSRC shellcodeRes = FindResource(NULL, MAKEINTRESOURCE(IDR_SHELLC1), "shellc");

Parameters that I receive in the hook code is following :

[+]     Syscalls called:
[+]     FindResourceA:
[+]     {"params": {"**lpName": 0, "lpType": "SHELLC"**}, "retval": 2684354561, "address": 1803956960, "retaddr": 4198421, "position": 0}

Issue here is that it throws UC_ERR_READ_UNMAPPED due to incorrect parameter ordering in qiling while calling user defined hook. Here hModule is treated as lpName and lpName is treated as lpType and in the hook code it raises exception as it tries to read memory address 0x65 which is invalid.

Here is how I validated by modifying the source code :

If I change the FindResourceA parameter in the source like this :

HRSRC shellcodeRes = FindResource(NULL, "shellc", "SHELLC");

This is what I get in the hook code :

[=]     6b8632e0 [kernel32.dll         + 0x0632e0]  8b ff                         mov                  edi, edi
[+]     0x6b8632e0: FindResourceA(lpName = 0, lpType = "shellc") = 0x0
[=]     00401015 [[PE]                 + 0x001015]  8b f0                         mov                  esi, eax
[=]     00401017 [[PE]                 + 0x001017]  56                            push                 esi

Is this something to be fixed at qiling source ? If not, I can close this issue for now. Let me know.

@elicn
Copy link
Member

elicn commented Feb 13, 2025

Something is off with your analysis.. The source shows there are 3 arguments, while the output shows only 2 of them. You may be using a different version than the one you think. Also, you linked an error to the Python 2 binding of Unicorn while you are using Python 3. Something is really off.

@elicn
Copy link
Member

elicn commented Feb 13, 2025

Now I realize you commented out the 'hModule' parameter on your first message here. Maybe this is part of the problem.

@chintanhshah
Copy link
Author

Yes..That's correct..I have fixed that in the code and works now..Thanks for your attention and help troubleshooting this @elicn ..Appreciated ..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants