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

SRDI_CLEARMEMORY bug or missing feature? #22

Open
RiccardoAncarani opened this issue May 30, 2021 · 3 comments
Open

SRDI_CLEARMEMORY bug or missing feature? #22

RiccardoAncarani opened this issue May 30, 2021 · 3 comments

Comments

@RiccardoAncarani
Copy link

I am trying to use the SRDI_CLEARMEMORY flag, but I am having a couple of issues. First, if I try running the shellcode generated using the PIC code of ShellcodeRDI.c I don't get any call to VirtualFree and it seems that there is no visible effect on the allocated memory.
After reading the ShellcodeRDI.c, the code responsible for the memory cleaning looks like is the following:

if (flags & SRDI_CLEARMEMORY && pVirtualFree && pLocalFree) {
		if (!pVirtualFree((LPVOID)dllData, 0, 0x00008000))
		{
			pLocalFree((LPVOID)dllData);
		}
		
	}

However, it looks to me that pVirtualFree and pLocalFree are initialised but no value is assigned to them?
I tried modifying the code myself and added the following at line ~ 260 of ShellcodeRDI.c:

BYTE sLocalFree[] = { 'L', 'o', 'c', 'a', 'l', 'F', 'r', 'e', 'e' };
BYTE sVirtualFree[] = { 'V', 'i', 'r', 't', 'u', 'a', 'l', 'F', 'r', 'e', 'e' };

FILL_STRING_WITH_BUF(aString, sLocalFree);
pLdrGetProcAddress(library, &aString, 0, (PVOID*)&pLocalFree);

FILL_STRING_WITH_BUF(aString, sVirtualFree);
pLdrGetProcAddress(library, &aString, 0, (PVOID*)&pVirtualFree);

Now, if I debug the program with something like x64dbg, I can see the invocation to VirtualFree but the following error is returned:

image

LocalFree fails as well with this:

image

The program I used to inject the sRDI shellcode is the DotNet loader in the main repository, where the ConvertToShellcode function is called with the 0x2 flag.

Am I doing something wrong here (except for spending my Sunday reading C code)?

@monoxgas
Copy link
Owner

monoxgas commented Jun 9, 2021

Just seeing this, I'll have to dig in a take a look, it's been a while since I've looked at the memory free option

Thanks for the helpful info!

@monoxgas
Copy link
Owner

monoxgas commented Jun 9, 2021

Alright, here are my thoughts based on my quick 5m walk through:

  1. You're absolutely right about those function pointers not being assigned, and your code above looks like an easy fix there.

  2. The error codes you are seeing are somewhat expected, and it actually brings up a larger issue I hadn't considered before:

  • For any given memory address, we can't be sure the best way to free it without more context

  • The strategy currently employed is in two phases:
    - First - attempt to free the memory with VirtualFree, which should simply fail the memory was not allocated with VirtualAlloc
    - Second - attempt to free the memory with LocalFree, which for some reason I considered more unsafe at the time. I'm not sure what scenarios may cause this to fail vs crash in terms of target address.

  • The mistake is in assuming that dllData could be freed directly from inside the sRDI blob. If we are assuming a normal use case, the whole block of data, bootstrap and dll combined, are all allocated together. In other words, not other is sRDI potentially trying to free a memory pointer inside it's own virtual block, but it also is not using the base address of the virtual block. Instead it's likely an offset sitting right past the bootstrap PiC.

I don't know that actually freeing the memory will ever be reasonable without creating some sort of shellcode jump to safely free the memory, but never actually try to return there.

The next best solution would be to simply zero out the DLL data in memory, but leave the block allocated. I think this achieves 80% of most people would want, but still leaves the memory region as an artifact.

@RiccardoAncarani
Copy link
Author

Hi Nick,

Thanks a lot for taking the time to look into this. I was in fact experimenting with subtracting an offset to the dllData pointer to make it point to the start of the bootstrap code, but without much success.
The workaround I was using was just applying an XOR to the first N bytes from dllData and obfuscate it (did not use zero because my lack of knowledge, visual studio was optimising the code and making it a memset).

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

No branches or pull requests

2 participants