DLL protection

L

LabZero

The problem in an advanced attack is about dll mapping and unmapping in the memory space of any process.
CreateRemoteThread api function is an extension of the function CreateThread used to create and execute a thread in the memory space of the calling process; with the CreateRemoteThread, it is possible to create a thread (and then actually run the code) in the memory space of any process other than the caller. Both api are implemented in the kernel32.dll and the only difference between the two api is the handle to the remote process that is present as the first parameter in CreateRemoteThread.
Impossible to parse the individual parameters, but in the case of CreateRemoteThread must be a valid address in the memory space of the remote process, and it is easy to load a dll into the memory space of a remote process executing the LoadLibrary function by assigning it as a parameter the name of the dll you want to map.

I do not say that default deny or BB does not detect this technique, but it is unlikely that this is recognised at 100%. according to my concept.
As usual multilayer security is the key.
 
U

uncle bill

The problem in an advanced attack is about dll mapping and unmapping in the memory space of any process.
CreateRemoteThread api function is an extension of the function CreateThread used to create and execute a thread in the memory space of the calling process; with the CreateRemoteThread, it is possible to create a thread (and then actually run the code) in the memory space of any process other than the caller. Both api are implemented in the kernel32.dll and the only difference between the two api is the handle to the remote process that is present as the first parameter in CreateRemoteThread.
Impossible to parse the individual parameters, but in the case of CreateRemoteThread must be a valid address in the memory space of the remote process, and it is easy to load a dll into the memory space of a remote process executing the LoadLibrary function by assigning it as a parameter the name of the dll you want to map.

I do not say that default deny or BB does not detect this technique, but it is unlikely that this is recognised at 100%. according to my concept.
As usual multilayer security is the key.
The chain OpenProcess\VirtualAlloc\WriteProcessMemory\CreateRemoteThread\LoadLibrary won't work on Microsoft Edge. Microsoft have added a new layer protection in kernel32.dll that prevents loading dll not signed with a valid Microsoft certificate. I'm not sure if this new feature is available and documented but i'm sure it works (yes, i tried to inject a foreign dll inside Edge ;) ), and could be usefull for everyone against dll hijacking\injection.
 
L

LabZero

The chain OpenProcess\VirtualAlloc\WriteProcessMemory\CreateRemoteThread\LoadLibrary won't work on Microsoft Edge. Microsoft have added a new layer protection in kernel32.dll that prevents loading dll not signed with a valid Microsoft certificate. I'm not sure if this new feature is available and documented but i'm sure it works (yes, i tried to inject a foreign dll inside Edge ;) ), and could be usefull for everyone against dll hijacking\injection.
Thanks for sharing this info ;)
 
W

Wave

The chain OpenProcess\VirtualAlloc\WriteProcessMemory\CreateRemoteThread\LoadLibrary won't work on Microsoft Edge. Microsoft have added a new layer protection in kernel32.dll that prevents loading dll not signed with a valid Microsoft certificate. I'm not sure if this new feature is available and documented but i'm sure it works (yes, i tried to inject a foreign dll inside Edge ;) ), and could be usefull for everyone against dll hijacking\injection.
Nothing should be changed in kernel32.dll, the blocking of the injection will be handled by MS Edge components itself. :)

I apologise if this is going off-topic but I wanted to explain a bit... As long as we don't completely hijack the thread with answering further questions about NTAPI function stubs and MS Edge protection then it should be okay, so I'll leave this as my final response on the topic of MS Edge protection. Quick analysis explaining below:

Here is where the functions you listed trace down to:
OpenProcess = ntdll.dll!NtOpenProcess
VirtualAlloc/Ex = ntdll.dll!NtAllocateVirtualMemory
WriteProcessMemory = ntdll.dll!NtWriteVirtualMemory

Then you have the thread NTAPI functions such as: RtlCreateUserThread & NtCreateThreadEx (both present in ntdll.dll, exported by ntoskrnl.exe).

LoadLibrary function will go down to the NTAPI Loader functions ("Ldr"), such as LdrLoadDll (which will then use functions like LdrpLoadDll).

Here is the function prologue of NtAllocateVirtualMemory (x64):
Code:
4C 8B D1             mov         r10,rcx
B8 18 00 00 00       mov         eax,18h
F6 04 25 08 03 FE 7F 01 test        byte ptr [7FFE0308h],1
75 03                jne         00007FFDD22B5155
0F 05                syscall
C3                   ret

Here is the function prologue of NtWriteVirtualMemory (x64):
Code:
0F 1F 84 00 00 00 00 00 nop         dword ptr [rax+rax]
4C 8B D1             mov         r10,rcx
B8 3A 00 00 00       mov         eax,3Ah
F6 04 25 08 03 FE 7F 01 test        byte ptr [7FFE0308h],1
75 03                jne         00007FFDD22B5595
0F 05                syscall
C3                   ret

Here is the function prologue of NtOpenProcess (x64):
Code:
4C 8B D1             mov         r10,rcx
B8 26 00 00 00       mov         eax,26h
F6 04 25 08 03 FE 7F 01 test        byte ptr [7FFE0308h],1
75 03                jne         00007FFDD22B5315
0F 05                syscall
C3                   ret

I don't think I need to check the disassembly of any others, you may have already noticed the pattern for most of these functions (some don't follow the pattern like LdrLoadDll but the NT functions seem to follow the pattern). What they do is they move the system ID of the function into the EAX register and then syscall/sysenter is used (depends on the process architecture).

SYSENTER/SYSCALL is the instruction for user-mode -> kernel-mode transition, therefore the function execution is carried across to kernel-mode. When you call Win32 functions like WriteProcessMemory it will ALWAYS trace back to the NTAPI function stub (for that specific function - in this case it would be NtWriteVirtualMemory), and then it will carry execution over to kernel-mode for the call (via sysenter/syscall for example).

In kernel-mode there won't be a checkup within the function of NtWriteVirtualMemory (or even deeper than this) which will automatically block (e.g. via 0xC0000022 return) if the PID of the target process is for MS Edge (e.g. get process ID from the ProcessHandle parameter (type HANDLE) and then compare to the PID of MS Edge)...

Let's say that there IS indeed some sort of checkup within kernel32.dll specifically for MS Edge, don't you think this would be really badly done? All it would take is a few lines of code for someone to bypass it via using the NTAPI function which the WIn32 function traced backed too. It would just be insecure and inefficient to do it via modifying the functions within kernel32.dll (or even the NTAPI function prologues - system calls!... Kernel-Mode would be best, most preferably via the documented callback methods).
------------------------------------------------------

I will give a few quick methods which programs can utilise to prevent the DLL injection (no self-protection is full-proof):
- Local hook to LdrLoadDll - then in the callback you auto-block all DLLs not from the Windows directory or from your own program files installation directory (or wherever you installed your software - but make sure it's a protected directory against files being added without permission or this can be easily exploited to be bypassed).
- Kernel-mode callback to PsSetLoadImageNotifyRoutine and then you check the DLL (image) being loaded into your PE (which is running in memory). I believe some AVs do this also, not all of them will... AVs can use this to monitor load attempts of DLLs into processes altogether, though.

MS Edge is not a "protected" process by Windows, either. One of the best defences against DLL/any injection attacks is preventing a handle to your process from being able to be obtained - almost every single popular AV product out on the market will utilise ObRegisterCallbacks (for both handle creation & duplication, and same for the threads of the process) for this.

Thanks for reading and enjoy... ;)
 
  • Like
Reactions: DardiM and LabZero
U

uncle bill

Nothing should be changed in kernel32.dll, the blocking of the injection will be handled by MS Edge components itself. :)

I apologise if this is going off-topic but I wanted to explain a bit... As long as we don't completely hijack the thread with answering further questions about NTAPI function stubs and MS Edge protection then it should be okay, so I'll leave this as my final response on the topic of MS Edge protection. Quick analysis explaining below:

Here is where the functions you listed trace down to:
OpenProcess = ntdll.dll!NtOpenProcess
VirtualAlloc/Ex = ntdll.dll!NtAllocateVirtualMemory
WriteProcessMemory = ntdll.dll!NtWriteVirtualMemory

Then you have the thread NTAPI functions such as: RtlCreateUserThread & NtCreateThreadEx (both present in ntdll.dll, exported by ntoskrnl.exe).

LoadLibrary function will go down to the NTAPI Loader functions ("Ldr"), such as LdrLoadDll (which will then use functions like LdrpLoadDll).

Here is the function prologue of NtAllocateVirtualMemory (x64):
Code:
4C 8B D1             mov         r10,rcx
B8 18 00 00 00       mov         eax,18h
F6 04 25 08 03 FE 7F 01 test        byte ptr [7FFE0308h],1
75 03                jne         00007FFDD22B5155
0F 05                syscall
C3                   ret

Here is the function prologue of NtWriteVirtualMemory (x64):
Code:
0F 1F 84 00 00 00 00 00 nop         dword ptr [rax+rax]
4C 8B D1             mov         r10,rcx
B8 3A 00 00 00       mov         eax,3Ah
F6 04 25 08 03 FE 7F 01 test        byte ptr [7FFE0308h],1
75 03                jne         00007FFDD22B5595
0F 05                syscall
C3                   ret

Here is the function prologue of NtOpenProcess (x64):
Code:
4C 8B D1             mov         r10,rcx
B8 26 00 00 00       mov         eax,26h
F6 04 25 08 03 FE 7F 01 test        byte ptr [7FFE0308h],1
75 03                jne         00007FFDD22B5315
0F 05                syscall
C3                   ret

I don't think I need to check the disassembly of any others, you may have already noticed the pattern for most of these functions (some don't follow the pattern like LdrLoadDll but the NT functions seem to follow the pattern). What they do is they move the system ID of the function into the EAX register and then syscall/sysenter is used (depends on the process architecture).

SYSENTER/SYSCALL is the instruction for user-mode -> kernel-mode transition, therefore the function execution is carried across to kernel-mode. When you call Win32 functions like WriteProcessMemory it will ALWAYS trace back to the NTAPI function stub (for that specific function - in this case it would be NtWriteVirtualMemory), and then it will carry execution over to kernel-mode for the call (via sysenter/syscall for example).

In kernel-mode there won't be a checkup within the function of NtWriteVirtualMemory (or even deeper than this) which will automatically block (e.g. via 0xC0000022 return) if the PID of the target process is for MS Edge (e.g. get process ID from the ProcessHandle parameter (type HANDLE) and then compare to the PID of MS Edge)...

Let's say that there IS indeed some sort of checkup within kernel32.dll specifically for MS Edge, don't you think this would be really badly done? All it would take is a few lines of code for someone to bypass it via using the NTAPI function which the WIn32 function traced backed too. It would just be insecure and inefficient to do it via modifying the functions within kernel32.dll (or even the NTAPI function prologues - system calls!... Kernel-Mode would be best, most preferably via the documented callback methods).
------------------------------------------------------

I will give a few quick methods which programs can utilise to prevent the DLL injection (no self-protection is full-proof):
- Local hook to LdrLoadDll - then in the callback you auto-block all DLLs not from the Windows directory or from your own program files installation directory (or wherever you installed your software - but make sure it's a protected directory against files being added without permission or this can be easily exploited to be bypassed).
- Kernel-mode callback to PsSetLoadImageNotifyRoutine and then you check the DLL (image) being loaded into your PE (which is running in memory). I believe some AVs do this also, not all of them will... AVs can use this to monitor load attempts of DLLs into processes altogether, though.

MS Edge is not a "protected" process by Windows, either. One of the best defences against DLL/any injection attacks is preventing a handle to your process from being able to be obtained - almost every single popular AV product out on the market will utilise ObRegisterCallbacks (for both handle creation & duplication, and same for the threads of the process) for this.

Thanks for reading and enjoy... ;)
Just a last reply (i don't want to go out of bounds :) ). Mitigation works at a kernel level but everyone can set it using SetProcessMitigationPolicy which is a kernel32.dll exported function.
Microsoft Edge binary injection mitigation overview ‹ The Cybersecurity & FastForensic Blog
 
  • Like
Reactions: DardiM and Wave
W

Wave

Just a last reply (i don't want to go out of bounds :) ). Mitigation works at a kernel level but everyone can set it using SetProcessMitigationPolicy which is a kernel32.dll exported function.
Microsoft Edge binary injection mitigation overview ‹ The Cybersecurity & FastForensic Blog
No problem. It's still good information you shared and I still find it interesting and think what MS Edge has for anti-injection is much better than nothing! :)

But from the article:
The mitigation is performed during the LoadLibrary() API call.
Therefore, manual map injection should bypass it, since it utilises the usage of the NTAPI Ldr functions as opposed to using the LoadLibrary() wrapper. ;)
 

About us

  • MalwareTips is a community-driven platform providing the latest information and resources on malware and cyber threats. Our team of experienced professionals and passionate volunteers work to keep the internet safe and secure. We provide accurate, up-to-date information and strive to build a strong and supportive community dedicated to cybersecurity.

User Menu

Follow us

Follow us on Facebook or Twitter to know first about the latest cybersecurity incidents and malware threats.

Top