Reflective DLL Injection - AV detects at runtime

Hello people

(This is my first post on 0x00sec)

I have a DLL injector - say injector.exe - that uses the Reflective DLL Injection technique. When executed, all the steps until VirtualAllocEx and WriteProcessMemory run perfectly (I put up debug print statements which show up in the cmd indicating the flow of execution). But, when it comes to the step of executing the DLL using CreateRemoteThread, an AV called ‘eScan’ is blocking the injector.exe. I have tried using RtlCreateUserThread and NtCreateThreadEx instead of CreateRemoteThread, but to no avail.

Can anyone please tell me why is it happening?

Thank you

2 Likes

@dtm , I’ve read your post on Reflective DLL Injection. Big fan of your content. Can you please shed some light on this?

Thanks

Can you check your process’s memory space for any of the AV’s mapped DLLs or if there are any hooks installed in the API functions?

@dtm, how do I check for hooks installed by the AV?

P.S. Sorry for the delayed response. I was on leave.

You can either look for suspicious modules in the memory space (e.g. Avast has modules named aswhookx.dll or similar) or you can check each function’s beginning bytes and look for instructions that correspond to software interrupts or jumps to suspicious locations (e.g. a WinAPI function that jumps to an address space that is marked as executable but has no name).

Hi dtm

You can either look for suspicious modules in the memory space (e.g. Avast has modules named aswhookx.dll or similar)

I have used EnumProcessModules to list loaded modules and there are no suspicious modules, they are all trusted windows DLLs.

or you can check each function’s beginning bytes and look for instructions that correspond to software interrupts or jumps to suspicious locations (e.g. a WinAPI function that jumps to an address space that is marked as executable but has no name).

I need to get the entrypoint to the imported functions (like VirtualAllocEx, WriteProcessMemory, createRemoteThread) to check their beginning bytes, right? How do I get the entrypoint to these imported functions?

Pardon me if my doubts are too obvious or silly. I’m a beginner.
I will document all of these learnings in a blog post for posterity.

Thanks

You might be able to do it like so:

FARPROC VirtualAllocExFunc = GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "VirtualAllocEx");

BYTE bytes[10];
memcpy(bytes, VirtualAllocExFunc, sizeof(bytes));

// check if bytes are instructions to hook

The first 10 bytes of these 3 functions -

VirtualAllocEx
48 83 ec 38 8b 44 24 60 89 44

WriteProcessmemory
48 83 ec 38 48 8b 44 24 60 48

ReadProcessMemory
48 83 ec 38 48 8b 44 24 60 48

These bytes are not suspicious, right?
What could be the way forward?

The disassembly does not look like anything I am familiar with, but can you check the corresponding NtXxx functions of those? e.g. WriteProcessMemory is NtWriteVirtualMemory. Also, is your architecture x86 or x64? You can also try extracting the disassembly in a debugger if that’s easier or more convenient.

VirtualAllocEx
48 83 ec 38 8b 44 24 60 89 44

WriteProcessMemory
48 83 ec 38 48 8b 44 24 60 48

ReadProcessMemory
48 83 ec 38 48 8b 44 24 60 48

NtAllocateVirtualMemory
4c 8b d1 b8 15 0 0 0 f 5

NtWriteVirtualMemory
4c 8b d1 b8 37 0 0 0 f 5

NtReadVirtualMemory
4c 8b d1 b8 3c 0 0 0 f 5

My machine is a Win 7 x64 VM

They look normal. You were saying that CreateThread was the issue? Perhaps the disassembly there may be interesting.

CreateRemoteThread
48 83 ec 48 48 8b 84 24 80 0

RtlCreateUserThread
48 83 ec 68 41 80 f8 1 f 85

NtCreateThreadEx
4c 8b d1 b8 a5 0 0 0 f 5

I am using either CreateRemoteThread, RtlCreateUserThread, NtCreateThreadEx depending on a commandline argument. All 3 are caught by the AV at realtime, when they are being executed. Say, if there are no AV hooks on these functions and no AV-related DLLs loaded in my process, what other trick by the AV could be at play?

The AV detecting this injection on my VM is QuickHeal. In a QuickHeal blog post, they discuss how malware uses ‘CreateRemoteThread’ and API such as, ‘VirtualAlloc’, ‘VirtualAllocEx’, ‘WriteProcessMemory’, and ‘ReadProcessMemory’.
I think it’s fair to assume that they do check for the execution of these functions to detect injection. If yes, then how else could they be doing it?

It could be possible that your process is getting triggered within the kernel using a driver belonging to the AV via PsSetCreateThreadNotifyRoutine to detect creation of new threads which might also stop any other standard DLL injection method (maybe they could still work, I’m not 100% sure). Is your payload malicious? If it is, perhaps try using a non-malicious payload and see if the results are the same. Or perhaps you could deobfuscate your payload on runtime after injection.

Even with a non-malicious payload, with just a MessageBox, the injection is getting detected. The AV detects the file injector.exe using Behaviour Detection and quarantines it.

Try with a different DLL injection method like APC or SetWindowsHookEx.

Sure. It will take some time. I’ll keep you posted. Thank you.

Hi @dtm

The AV is simply flagging any exe which calls CreateRemoteThread or any of its variants.

So, I’ve tried suspending a remote thread (already existing), changing its context structure, and resuming it. I’m encountering 2 issues here -

  1. The injected DLL is not executed until I bring focus back to the target process, i.e.
  • click on the target process in the task bar ( if it’s minimized ) or
  • alt-tab into the target process or take my mouse pointer to it and click on it ( if it’s in the background )

This problem persists irrespective of the kind of DLL used for injection ( basic message box DLL or keylogger DLL)

  1. and when I inject a keylogger DLL, the target process becomes Not Responding, immediately after I take focus back to the target process

This I’m thinking could be because of the while loop that is inherent to a keylogger DLL. If that’s the case, can you suggest how can I go about it? If not, then what could be the reason?

Thank you

Oh wow, that actually sounds incredibly unstable to me. I’ve never even attempted something like this fearing that the process will just break.

I’m not sure about how your keylogger works so I cannot comment on anything about that. Of course, if the process has some sort of GUI and the thread that handles the Windows messages does not operate correctly, it may cause the “Not Responding” message.

Have you tried what I previously suggested? Using APC or SetWindowsHookEx DLL injection.

I knew that it could be unstable, but didn’t know the gravity of it. So, suspend and inject is a definite no-go in terms of reliability, right?

I haven’t tried them. I will try and get back to you.

I don’t think this is the case. From what I can understand, you are just completely hijacking a thread by setting the instruction pointer at the entry point of your DLL without returning execution back to it. It wouldn’t be surprising that something goes wrong with the process.