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

convert user32.dll to shellcode and load it into memory failed #10

Open
rainkin1993 opened this issue Jul 5, 2018 · 5 comments
Open
Labels

Comments

@rainkin1993
Copy link

rainkin1993 commented Jul 5, 2018

Environment: Win10 1709
DLL: C:\Windows\SysWOW64\user32.dll

  1. I firstly use command python Python\ConvertToShellcode.py user32.dll convert user32.dll to user32.bin.
  2. Then I change the code in Native\Loader.cpp to call API MessageBoxA after loading the user32.dll and compile the Native project using Visual Studio 2015 Debug x86.
	// Only set the first page to RWX
	// This is should sufficiently cover the sRDI shellcode up top
	if (VirtualProtect(finalShellcode, sysInfo.dwPageSize, PAGE_EXECUTE_READWRITE, &dwOldProtect1)) {
		RDI rdi = (RDI)(finalShellcode);

		printf("[+] Executing RDI\n");
 		UINT_PTR hLoadedDLL = rdi(); // Excute DLL

		free(finalShellcode); // Free the RDI blob. We no longer need it.

		/*Function exportedFunction = (Function)GetProcAddressR(hLoadedDLL, "SayGoodbye");
		if (exportedFunction) {
			printf("[+] Calling exported functon\n");
			exportedFunction();
		}*/
		MyMessageBoxA exportedFunction = (MyMessageBoxA)GetProcAddressR(hLoadedDLL, "MessageBoxA");
		if (exportedFunction) {
			printf("[+] Calling exported functon\n");
			exportedFunction(0, "Hello", "user32.dll message", 1);
		}
	}


----

typedef int (WINAPI *MyMessageBoxA)(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType);
  1. Then use command Native.exe user32.bin to load the shellcode.
    The exe crashed and report a error :

0x7774CCC5 (ntdll.dll) (located at Native.exe) Exception: 0xC0000005: Access violation reading location 0x00000008.

I ensure that the GetProcAddressR return the correct address of MessageBoxA.

I found that the 0x7774CCC5 belongs to ntdll.dll!RtlAllocateHeap function:
image

Do you have comments that which possible cause this problem? My conclusion is that reflective loading a DLL written by ourselves works fine but loading a system dll(ntdll, user32..) will not work. It seems that there is something the loader doesn't handle when load the system dll into memory.

@rainkin1993
Copy link
Author

Have you ever load a system dll(user32.dll, ntdll.dll) succeed?

@monoxgas
Copy link
Owner

monoxgas commented Jul 6, 2018

I have played with this as well, but had similar results.

I can try to find some time to take a look, I agree with your setiment that some part of the loading process is obviously being missed.

You could try loading with the MemoryModule project and see if you have better luck. Their code does a much better job of handling edge cases in the unpacking process. Off the top of my head, delayed imports and TLS call backs are still missing from sRDI

@monoxgas monoxgas added the bug label Jul 6, 2018
@rainkin1993
Copy link
Author

rainkin1993 commented Jul 9, 2018

AH, I firstly try MemoryModule but also failed with another error messages

  1. When loading user32.dll using MemoryModule in Win10, the DLLMain was invoked and I get an error code 14: ERROR_OUTOFMEMORY
  2. For urlmon.dll, the DLL was successfully loaded, but when I invoke the URLDownloadToFileA API, the program crashed as well.

It seems that totally simulating the process of loading system DLLs is very difficult.

@monoxgas
Copy link
Owner

Interesting results. I might assume there is a class of core system DLLs (kernel32, user32, ntdll, etc.) which have special handling to deny loading multiple instances in one process.

Other Microsoft DLLs like urlmon, gdi, etc. might not have this special handling and therefore might give better results. Going to do some digging to try and find out more.

The PE load process is well documented, but I can't shake the feeling that Microsoft has some special handling that doesn't conform to well-known standards.

@monoxgas
Copy link
Owner

Adding an interesting note here, kernel32.dll appears to load and run fine for those wondering.

I can validate the failure of user32 and the crash from urlmon. Looking through ReactOS and online material, my guess for the user32 failure is the relation to GDI. Potentially something about GDI heaps being allocated and mapped in the PEB.

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

No branches or pull requests

2 participants