Advice Request Protecting processes from injection via SetWindowsHookEx() ?

Please provide comments and solutions that are helpful to the author of this topic.

Mecanik

Level 1
Thread author
Verified
Mar 23, 2018
16
Hello,

I am not sure if I posted this in the right category, but here it goes. As the title says, I am analysing and trying to find a way to stop malware from injecting my process via SetWindowsHookEx.

My process is currently protected via callbacks and other techniques, but this particular technique seems to be impossible to stop. ( at least now )

If we look at: Inject All the Things - Shut Up and Hack we can see different scenarios and information regarding injecting a process, where we can also see:

SetWindowsHookEx()
In order to use this technique the first thing we need to understand is how MS Windows hooks work. Basically, hooks are a way to intercept events and act on them.

As you may guess, there are many different types of hooks. The most common ones might be WH_KEYBOARD and WH_MOUSE. You guessed right, these can be used to monitor, the keyboard and mouse input.

The ‘SetWindowsHookEx()’ “installs an application-defined hook procedure into a hook chain.”

C++:
GetWindowThreadProcessId(targetWnd, &dwProcessId);

HHOOK handle = SetWindowsHookEx(WH_KEYBOARD, addr, dll, threadID);

Maybe I should look at GetWindowThreadProcessId() to prevent getting the handle in the first place?

Long story short... does anyone know any "way" or "method" to prevent such technique ? If so, please do share. Any suggestions or feedback is highly appreciated!
 
D

Deleted member 65228

It's not impossible to prevent but there isn't much information online regarding how to stop it.

The first thing you will want to try is disabling extension point support via process mitigation policies; there's a documented API to do this in the Win32 API however you can do it manually with NtSetInformationProcess as long as you're executing under the context of the protected process; an alternative to this would be more hacky, unstable and unreliable however it'd evolve around kernel-mode structure patching for the target process (e.g. look at mitigation policies under the _KPROCESS structure).

If this does not work, or ends up being half-baked, try creating a new Desktop session on the environment dynamically and then spawn your protected process under the new Desktop environment. However, this Desktop session feature is exclusive to Windows 10 and thus there'd be no backwards compatibility for previous versions of Windows; I'd only focus on Windows 7 - Windows 10 support primarily and more on Windows 8 - Windows 10 since Windows 7 support will be dropped by Microsoft within the next 1-2 years.

Alternatively, you can try spawning the process under a new user account. You could try NT AUTHORITY\ANONYMOUS LOGON which is also an addition Sandboxie uses when it spawns a new process in the "sandbox" container.

Apart from this, the only other things you can try would be unrecommended, unreliable and hacky... And are still not guaranteed to work how'd you like it to work.

[ All of this is speculation and is not guaranteed to be 100% correct, take everything with a grain of salt ].
 

Mecanik

Level 1
Thread author
Verified
Mar 23, 2018
16
@Opcode Thanks for the information, however it seems a bit tricky and complicated, plus as you said unreliable..

What about detouring GetWindowThreadProcessId() inside the process ? Theoretically it should work, and you could compare PID's and if CURRENT_PID == PID you got a process targeting your .exe

What do you think ?
 
D

Deleted member 65228

What about detouring GetWindowThreadProcessId() inside the process ? Theoretically it should work, and you could compare PID's and if CURRENT_PID == PID you got a process targeting your .exe
Firstly, your method will be surpassed extraordinarily easily. GetWindowThreadProcessId (USER32) relies internally on NtUserQueryWindow (WIN32U). While nothing is full-proof in this world, surpassing this implementation would be completely effortless; simply call NtUserQueryWindow.

Even if you were to patch NtUserQueryWindow, you still have a problem with people using direct NT system calls or removing your patches. Protecting against behavior like this will likely end up causing more harm than good, especially in terms of performance.

Secondly, you will need to be performing Remote Code Execution (RCE) into every single running process for your idea to be effective against all processes. This really is not a good idea from a realistic stand-point, it would be better if your aim was for unknown processes.

Developers are constantly becoming frustrated with people who are using the excuse of "security development" while breaking their software with buggy and inefficient memory patches - you need to be really careful with why and how you use memory patching and consider how it will affect the targets.

If you went ahead with the idea regardless, it won't stop global window hooks (which do not care about a specific process as a target).

At this point, I'd be considering how important it is for you to protect against window hooks (if no "closer-to-home" and less-undocumented techniques are applicable) and what you could do to minimize the damage an attacker could do, should the GUI process ever become compromised by an attack like the one you're trying to prevent.

I admit that your situation is a bit of a dead end because taking unreliable and undocumented routes can catch up with you and drag you back down.
 

Mecanik

Level 1
Thread author
Verified
Mar 23, 2018
16
@Opcode Again, thanks for the information. From your expertise and what are you saying here, I have no real solution for this.

I was thinking about injecting all the process in the system, and detour NtUserQueryWindow and maybe communicate with my process via shared memory. I have seen this done by "others" with NtReadVirtualMemory and other functions for similar purpose.

What are my ( limited ) options here ? And more over, is it "OK" to inject the user's processes for this... legally ?
 
  • Like
Reactions: AtlBo
D

Deleted member 65228

What are my ( limited ) options here ? And more over, is it "OK" to inject the user's processes for this... legally ?

See:
The first thing you will want to try is disabling extension point support via process mitigation policies
try creating a new Desktop session on the environment dynamically and then spawn your protected process under the new Desktop environment
you can try spawning the process under a new user account. You could try NT AUTHORITY\ANONYMOUS LOGON


In regards to legality for RCE, it wouldn't be appropriate for me to comment on this considering I am not a lawyer. However, what I can tell you, is that having a proper legally binding Terms of Service and Privacy Policy is critical and I advise you speak to a lawyer who works in the computer law area.

I don't think that relying on RCE so you can patch NtUserQueryWindow is a good idea and a good use of time but this is not my project; you can make whatever decisions you want to make. At the end of the day, all I can do is provide my opinion, it is down to you in the end to make a decision on what you should do for your project.

I have unpacked the malware, and I saw it's using hfiref0x/DSEFix
DSEFix is for bypassing Driver Signature Enforcement (DSE) which is a feature of PatchGuard to load an unsigned device driver through exploitation of the VirtualBox device driver. It works by patching kernel-memory for CI.dll which is loaded under the address space of NTOSKRNL and setup at system boot.

I don't see what this has to do with preventing global window hooks though.

Anyway, you *could* start by making signatures for open-source projects like these. Most vendors block such projects AFAIK... Especially Mimikatz.
 

Mecanik

Level 1
Thread author
Verified
Mar 23, 2018
16
I took in consideration what you advised, and did some tests all day long - unfortunately the result is the same.

It just opens my process without a sweat. I examined my OS to the bone basically, I could not see any driver loaded or any Ring0/Ring3 hooks others than that.

This .exe is packed with Themida/WinLicense and any tool I tried to use like Api Monitors where detected.

So I decided to try and decompile it, see where it goes. It worked after 2 hours of trying, since it's packed with Themida...

I noticed in the resources:

[VersionInfo] Company Name : UG North [VersionInfo] Product Name : DSEFix [VersionInfo] Product Version : 1.2.0.1704 [VersionInfo] File Description : Windows DSE overrider [VersionInfo] File Version : 1.2.0.1704 [VersionInfo] Original FileName : dsefix.exe [VersionInfo] Internal Name : dsefix.exe [VersionInfo] Legal Copyrights : Copyright (C) 2014 - 2017 EP_X0FF. MP_ART and N.Rin. based on WinNT/Turla exploit

Which kinda makes sense why it's so "stealthy", and plus the .exe gives BSOD if I enable test signing.

Anyway, I got the malicious .exe decompiled now ( sort of ) and I need to figure out how to fix it's OEP so I can run it.

I believe if I can get it to run now that's decompiled, I can actually run an API Monitor ( like sysinternals ) and see what exactly is this .exe doing to just open and write to my dear protected process.

Regarding signatures - I left long time ago those methods, because all it takes the attacker is to recompile the .exe and re-pack it...
 
  • Like
Reactions: AtlBo
D

Deleted member 65228

It just opens my process without a sweat. I examined my OS to the bone basically, I could not see any driver loaded or any Ring0/Ring3 hooks others than that.
[VersionInfo] Original FileName : dsefix.exe
Just so you are aware, device drivers which are unsigned and being loaded by the DSEFix should be "driverless", which means they will be hidden by default. Whoever invented the sample and is using DSEFix is probably doing this.

Regarding signatures - I left long time ago those methods, because all it takes the attacker is to recompile the .exe and re-pack it...
I was referring to generic signatures and you can combine these with a good memory scanner. I do not care for hash checksum either, they suck in my opinion.

Anyone can re-pack the sample but if you're scanning the memory dynamically, unless they have a bypass for your memory scanner, the signature will be matched in-memory after the unpacker engine has done its work with its loader.

You can also use behavioral monitoring techniques to develop protection against exploit attacks like these; this would be where appropriate use of memory patching could come into play.
 
  • Like
Reactions: AtlBo

Mecanik

Level 1
Thread author
Verified
Mar 23, 2018
16
Just so you are aware, device drivers which are unsigned and being loaded by the DSEFix should be "driverless", which means they will be hidden by default. Whoever invented the sample and is using DSEFix is probably doing this.

Well that's a new one for me, so that's why I cannot see it no matter what. Is there a way of "seeing" it ? Maybe I could unload it and "signature" that... or see what functions is using.

I was referring to generic signatures and you can combine these with a good memory scanner. I do not care for hash checksum either, they suck in my opinion.

Do you have something in mind ? Give me an example maybe ?

Many thanks
 
  • Like
Reactions: AtlBo
D

Deleted member 65228

Well that's a new one for me, so that's why I cannot see it no matter what. Is there a way of "seeing" it ? Maybe I could unload it and "signature" that... or see what functions is using.
Well, if you're loading an unsigned device driver, the last thing you want is for a BSOD to be triggered if the system recognizes there's an unsigned device driver loaded. Bypassing Driver Signature Enforcement in the first place is one thing, but keeping it unaware of you having bypassed it for the duration of the session is another... And quite critical.

DSEFix.exe will do the following:
1. Drop the vulnerable VirtualBox device driver to disk
2. Create a new Windows Service for the device driver
3. Start the newly created Windows Service
4. Exploitation

The VBoxDrv.sys will be dropped to SystemDrive:\\WINDOWS\\System32\\drivers directory.

Therefore a sufficient mitigation for the exploit attack could even be prevention of the vulnerable VirtualBox device driver being allowed to be installed and loaded on the environment. If it cannot, then the exploit stage cannot be reached... And you'd have killed two birds with one stone.

Do you have something in mind ?
1. Make a generic signature for dsefix.exe
2. Make a memory scanner

Use disassembly to make the signature.
 
Last edited by a moderator:
  • Like
Reactions: tim one and AtlBo
F

ForgottenSeer 69673

[VersionInfo] Legal Copyrights : Copyright (C) 2014 - 2017 EP_X0FF. MP_ART and N.Rin. based on WinNT/Turla exploit

Last I heard EP_XOFF went to work for Microsoft a few years ago. Before that he was a frequent poster at Rootkit.com.
Him and MP_ART created some rootkits, then created a rootkit finder. I think it was called RootkitUhooker.
 
  • Like
Reactions: AtlBo
D

Deleted member 65228

@Opcode Many thanks, I am on it now.
You can also check the Entry Point for the PE and attempt to find anomalies in it, as well as checking the Imports, Strings, and info in the PE Header to help determine whether it is packed. Don't forget about entropy level.

Based on the algorithm conclusion, you can then intercept operations at the start of execution and then decide when to stop the interception and apply the generic signature scanning in-memory.

Even if you prevent DSEFix.exe through cutting the legs off with blocking VBoxDrv.sys installation (the vulnerable driver version) coming from an unknown process not from VirtualBox, I'd still recommend looking into memory scanning as it can be beneficial for your real-time protection component.

You will want at-least a memory scanner in 2018. Especially once 2019 hits. Standard thing now really IMO.
 
  • Like
Reactions: tim one and AtlBo

Mecanik

Level 1
Thread author
Verified
Mar 23, 2018
16
You can also check the Entry Point for the PE and attempt to find anomalies in it, as well as checking the Imports, Strings, and info in the PE Header to help determine whether it is packed. Don't forget about entropy level.

Based on the algorithm conclusion, you can then intercept operations at the start of execution and then decide when to stop the interception and apply the generic signature scanning in-memory.

Thanks for the idea, however because it's packed with Themida/WinLicense it always changes EP at runtime, their VM is unique per build and quite sophisticated.

I checked for drivers, although I have no VB installed I found:

  • VBoxNetAdp6.sys
  • VBoxNetLwf.sys

There is no VBoxDrv.sys however...
 
  • Like
Reactions: AtlBo

Mecanik

Level 1
Thread author
Verified
Mar 23, 2018
16
I managed to break this malware's sel protection and monitor API calls. The malware has inline hooks besides the winlicense to prevent debugging.

I have found these inline hooks:

len(1) ntdll.dll->DbgBreakPoint 0x00000000777E0B00->_ inline C3 CC len(5) ntdll.dll->DbgUiRemoteBreakin 0x000000007781A640->_ inline E9 EB D1 F8 FF 6A 08 68 C8 FE len(6) ntdll.dll->LdrLoadDll 0x00000000777BE860->_ inline 68 7C 15 5B 00 C3 8B FF 55 8B EC 83

After removing them with a tool, I was able to inject it and monitor API calls. The ntdll.dll->LdrLoadDll hook is interesting, because I have something similar ( lol ).

For the above, I want to ask you @Opcode if you got any idea/example how to remove these automatically hooks via code and not manually with tools ?

Continuing to monitor API calls, what I see very often called is:

NtQueryInformationProcess (GetCurrentProcess(), ProcessMitigationPolicy, 0x0019f7d8, 8, NULL )

And when the "action" starts is here, right when the process is found:

RtlReAllocateHeap ( 0x03100000, HEAP_CREATE_ENABLE_EXECUTE | HEAP_NO_SERIALIZE | HEAP_ZERO_MEMORY | 1048576, 0x031fafa8, 72 ) NtOpenSection ( 0x0019f058, SECTION_MAP_READ, 0x0019f070 ) NtMapViewOfSection ( 0x0000057c, GetCurrentProcess(), 0x0019f080, 0, 0, 0x0019f074, 0x0019f07c, ViewShare, 0, PAGE_READONLY ) NtClose ( 0x0000057c )

And now, the most funny part ( because why would you do this anyway!? )

Starts calling:

NtReadVirtualMemory ( GetCurrentProcess(), 0x0024400c, 0x0019efb4, 4, 0x0019ef58 )

More than 5000+ times on different addresses, until it finds what it wants... I'm not joking, over 5000 times.

Anyway, it stops and starts the even more interesting part ( at least for me ):

KERNELBASE.dll RtlInitAnsiStringEx ( 0x0019f17c, "Project1.dll" ) STATUS_SUCCESS 0.0000003 KERNELBASE.dll LdrGetDllHandle ( NULL, NULL, 0x0019f174, 0x0019f18c ) STATUS_DLL_NOT_FOUND 0xc0000135 = The code execution cannot proceed because %hs was not found. Reinstalling the program may fix this problem. 0.0000048 KERNELBASE.dll RtlNtStatusToDosError ( STATUS_DLL_NOT_FOUND ) ERROR_MOD_NOT_FOUND 0.0000005 KERNELBASE.dll RtlInitAnsiStringEx ( 0x0019f17c, "Project2.dll" ) STATUS_SUCCESS 0.0000003 KERNELBASE.dll LdrGetDllHandle ( NULL, NULL, 0x0019f174, 0x0019f18c ) STATUS_DLL_NOT_FOUND 0xc0000135 = The code execution cannot proceed because %hs was not found. Reinstalling the program may fix this problem. 0.0000015 KERNELBASE.dll RtlNtStatusToDosError ( STATUS_DLL_NOT_FOUND ) ERROR_MOD_NOT_FOUND 0.0000003 KERNELBASE.dll RtlInitAnsiStringEx ( 0x0019f17c, "Project3.dll" ) STATUS_SUCCESS 0.0000000 KERNELBASE.dll LdrGetDllHandle ( NULL, NULL, 0x0019f174, 0x0019f18c ) STATUS_DLL_NOT_FOUND 0xc0000135 = The code execution cannot proceed because %hs was not found. Reinstalling the program may fix this problem. 0.0000015 KERNELBASE.dll RtlNtStatusToDosError ( STATUS_DLL_NOT_FOUND ) ERROR_MOD_NOT_FOUND 0.0000003 KERNELBASE.dll RtlInitAnsiStringEx ( 0x0019f17c, "WriteProcessMemory_Hook.dll" ) STATUS_SUCCESS 0.0000003 KERNELBASE.dll LdrGetDllHandle ( NULL, NULL, 0x0019f174, 0x0019f18c ) STATUS_DLL_NOT_FOUND 0xc0000135 = The code execution cannot proceed because %hs was not found. Reinstalling the program may fix this problem. 0.0000015 KERNELBASE.dll RtlNtStatusToDosError ( STATUS_DLL_NOT_FOUND ) ERROR_MOD_NOT_FOUND 0.0000003 KERNELBASE.dll RtlInitAnsiStringEx ( 0x0019f17c, "WriteProcessMemory_Hook64.dll" ) STATUS_SUCCESS 0.0000003 KERNELBASE.dll LdrGetDllHandle ( NULL, NULL, 0x0019f174, 0x0019f18c ) STATUS_DLL_NOT_FOUND 0xc0000135 = The code execution cannot proceed because %hs was not found. Reinstalling the program may fix this problem. 0.0000015 KERNELBASE.dll RtlNtStatusToDosError ( STATUS_DLL_NOT_FOUND ) ERROR_MOD_NOT_FOUND 0.0000003 KERNELBASE.dll RtlInitAnsiStringEx ( 0x0019ebb8, "WS2_32.DLL" ) STATUS_SUCCESS 0.0000003 KERNELBASE.dll RtlInitUnicodeStringEx ( 0x0019ebb0, "WS2_32.DLL" ) STATUS_SUCCESS 0.0000003 KERNELBASE.dll LdrLoadDll ( 0x0001, 0x0019eba0, 0x0019ebb0, 0x0019eba4 ) STATUS_SUCCESS 0.0009120 KERNELBASE.dll RtlRunOnceExecuteOnce ( 0x762f0770, 0x7626db70, NULL, NULL ) STATUS_SUCCESS 0.0000003 KERNEL32.DLL LdrResFindResourceDirectory ( 0x77700000, 0x00000018, 0x00000002, 0x0019e778, NULL, NULL, 0x00000010 ) STATUS_RESOURCE_TYPE_NOT_FOUND 0xc000008a = Indicates the specified resource type cannot be found in the image file. 0.0000041 apphelp.dll LdrGetDllHandle ( NULL, NULL, 0x0019e558, 0x0019e564 ) STATUS_DLL_NOT_FOUND 0xc0000135 = The code execution cannot proceed because %hs was not found. Reinstalling the program may fix this problem. 0.0000015 apphelp.dll RtlDosPathNameToNtPathName_U ( "C:\WINDOWS\System32\WS2_32.DLL", 0x0019e760, NULL, NULL ) TRUE 0.0000038 apphelp.dll NtOpenFile ( 0x0019e770, READ_CONTROL, 0x0019e740, 0x0019e758, FILE_SHARE_DELETE | FILE_SHARE_READ, 0x00000000 ) STATUS_SUCCESS 0.0000892 apphelp.dll NtQuerySecurityObject ( 0x0000057c, OWNER_SECURITY_INFORMATION, NULL, 0x00000000, 0x0019e76c ) STATUS_BUFFER_TOO_SMALL 0xc0000023 = {Buffer Too Small} The buffer is too small to contain the entry. No information has been written to the buffer. 0.0000102 apphelp.dll NtQuerySecurityObject ( 0x0000057c, OWNER_SECURITY_INFORMATION, 0x0314cdb8, 0x00000034, 0x0019e76c ) STATUS_SUCCESS 0.0000041 apphelp.dll RtlGetOwnerSecurityDescriptor ( 0x0314cdb8, 0x0019e768, 0x0019e777 ) STATUS_SUCCESS 0.0000005 apphelp.dll RtlEqualSid ( 0x0314cdcc, 0x03105138 ) TRUE 0.0000005 apphelp.dll NtClose ( 0x0000057c ) STATUS_SUCCESS 0.0000375 apphelp.dll LdrFindEntryForAddress ( 0x77700000, 0x0019e7bc ) STATUS_SUCCESS 0.0000005 apphelp.dll LdrFindEntryForAddress ( 0x77700000, 0x0019e7bc ) STATUS_SUCCESS 0.0000003 apphelp.dll LdrFindEntryForAddress ( 0x77700000, 0x0019e7bc ) STATUS_SUCCESS 0.0000003 apphelp.dll RtlImageDirectoryEntryToData ( 0x77700000, TRUE, 0x000c, 0x0019e704 ) 0x7774c000 0.0000000 apphelp.dll NtProtectVirtualMemory ( GetCurrentProcess(), 0x0019e798, 0x0019e79c, PAGE_EXECUTE_READWRITE, 0x0019e7a0 ) STATUS_SUCCESS 0.0000048 apphelp.dll LdrFindEntryForAddress ( 0x77700000, 0x0019e7bc ) STATUS_SUCCESS 0.0000003 apphelp.dll NtProtectVirtualMemory ( GetCurrentProcess(), 0x0019e798, 0x0019e79c, PAGE_READONLY, 0x0019e7a0 ) STATUS_SUCCESS 0.0000046 KERNELBASE.dll RtlEncodePointer ( 0x7774b4c4 ) 0x2ec11f68 0.0000018 KERNELBASE.dll RtlEncodePointer ( 0x7771b400 ) 0x2ed51c78 0.0000005 KERNELBASE.dll RtlEncodePointer ( 0x7774b4c8 ) 0x2ec11f58 0.0000005 KERNELBASE.dll RtlAcquirePebLock ( ) 0.0000005 KERNELBASE.dll RtlFindClearBitsAndSet ( 0x77887c38, 0x00000001, 0x00000000 ) 0x00000032 0.0000010 KERNELBASE.dll RtlReleasePebLock ( ) 0.0000000 KERNELBASE.dll RtlInitString ( 0x0019ebdc, "WSAStartup" ) 0.0000003 apphelp.dll RtlCaptureStackBackTrace ( 0x00000000, 0x00000010, 0x0019e9dc, NULL ) 0x0002 0.0000005 KERNELBASE.dll NtOpenProcessToken ( GetCurrentProcess(), TOKEN_QUERY, 0x0019e8e4 ) STATUS_SUCCESS 0.0000043 KERNELBASE.dll NtQueryInformationToken ( 0x00000584, TokenIsAppContainer, 0x0019e8e8, 0x00000004, 0x0019e8e0 ) STATUS_SUCCESS 0.0000015 KERNELBASE.dll NtClose ( 0x00000584 ) STATUS_SUCCESS 0.0000010 KERNELBASE.dll RtlGetCurrentTransaction ( ) NULL 0.0000000 KERNELBASE.dll RtlSetCurrentTransaction ( NULL ) TRUE 0.0000000 KERNELBASE.dll RtlSetCurrentTransaction ( NULL ) TRUE 0.0000003 KERNELBASE.dll RtlInitUnicodeStringEx ( 0x0019e878, "System\CurrentControlSet\Services\WinSock2\Parameters" ) STATUS_SUCCESS 0.0000003 KERNELBASE.dll NtOpenKeyEx ( 0x0019e918, KEY_ALL_ACCESS, 0x0019e7c8, 0x00000000 ) STATUS_SUCCESS 0.0000433 KERNELBASE.dll RtlNtStatusToDosError ( STATUS_SUCCESS ) ERROR_SUCCESS 0.0000003 KERNELBASE.dll RtlInitAnsiStringEx ( 0x0019e874, "WinSock_Registry_Version" ) STATUS_SUCCESS 0.0000003 KERNELBASE.dll NtQueryValueKey ( 0x00000584, 0x0019e87c, KeyValuePartialInformation, 0x0019e7b4, 0x00000090, 0x0019e790 ) STATUS_SUCCESS 0.0000046

And the list goes on, but among others interesting calls are:

RPCRT4.dll NtOpenThreadToken ( GetCurrentThread(), TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY, TRUE, 0x0019db14 ) STATUS_NO_TOKEN 0xc000007c = An attempt was made to reference a token that doesn't exist. This is typically done by referencing the token associated with a thread when the thread is not impersonating a client. 0.0000005 RPCRT4.dll NtOpenThreadToken ( GetCurrentThread(), TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY, TRUE, 0x0019db10 ) STATUS_NO_TOKEN 0xc000007c = An attempt was made to reference a token that doesn't exist. This is typically done by referencing the token associated with a thread when the thread is not impersonating a client. 0.0000008 RPCRT4.dll NtOpenThreadToken ( GetCurrentThread(), TOKEN_IMPERSONATE | TOKEN_QUERY, TRUE, 0x0019dd2c ) STATUS_NO_TOKEN 0xc000007c = An attempt was made to reference a token that doesn't exist. This is typically done by referencing the token associated with a thread when the thread is not impersonating a client. 0.0000025 RPCRT4.dll NtSetInformationThread ( GetCurrentThread(), ThreadImpersonationToken, 0x0019dd24, 0x00000004 ) STATUS_SUCCESS 0.0000010 RPCRT4.dll NtSetInformationThread ( GetCurrentThread(), ThreadImpersonationToken, 0x0019dd28, 0x00000004 ) STATUS_SUCCESS 0.0000010

And this right at the "end" of all this after the process is opened:

KERNELBASE.dll NtOpenSection ( 0x0019f030, SECTION_MAP_READ, 0x0019f048 ) STATUS_SUCCESS 0.0000196 KERNELBASE.dll NtMapViewOfSection ( 0x00000990, GetCurrentProcess(), 0x0019f058, 0x00000000, 0x00000000, 0x0019f04c, 0x0019f054, ViewShare, 0x00000000, PAGE_READONLY ) STATUS_SUCCESS 0.0000066 KERNELBASE.dll NtClose ( 0x00000990 ) STATUS_SUCCESS 0.0000028

I also found the driver, it's actually just a few lines of code... and also decompiled it. The driver is nothing to worry about, the worry part is how does the malware get the handle if my process is protected.
 
  • Like
Reactions: harlan4096
F

ForgottenSeer 69673

Nice you read the links I posted . Still waiting for opcodes answers about the links I posted.
 
D

Deleted member 65228

For the above, I want to ask you @Opcode if you got any idea/example how to remove these automatically hooks via code and not manually with tools ?
Method 1:
1. NtQuerySystemInformation -> find PID of target process
2. NtOpenProcess -> open a handle to the target process
3. EAT scanning -> locate the address of the routines you want to re-patch in the target process within your own process (for your own virtual address space)
4. NtProtectVirtualMemory -> change the memory access protection at the target address within the address space of the target process remotely
5. NtWriteVirtualMemory -> remotely patch the memory at the address in the address space of the target process
6. NtProtectVirtualMemory -> re-protect the memory back to the original memory access protection remotely

Make sure the address is right though. E.g. x86 address of LdrLoadDll for WOW64 process, not an x64 address for the x64 processes.

Method 2:
1. NtQuerySystemInformation -> find PID of target process
2. NtOpenProcess -> open a handle to the target process
3. NtAllocateVirtualMemory -> allocate memory for your code-cave buffer
4. NtWriteVirtualMemory -> write to the code-cave buffer
5. NtCreateThreadEx -> get a new thread to start executing at the address of the allocated memory (now containing your injected code)

Method 3:
Same as Method 2 but targeting threads of the target process and relying on NtQueueApcThread/NtQueueApcThreadEx (Asynchronous Procedure Calls instead of Remote Thread Creation). By the way, NtQueueApcThread is just a wrapper for NtQueueApcThreadEx internally in the Windows Kernel.

Method 4:
Same as Method 3 except instead of using NtQueueApcThread/NtQueueApcThreadEx, you hijack the EIP/RIP of the targeted thread via NtSetContextThread.

Method 5:
1. RCE (target csrss.exe for Windows 7 or lsass.exe for Windows 8+) and steal an open handle for the targeted process
2. Now do either Method 1 or Method 2 using the stolen handle

You can use code-cave as a "file-less" injection method (no DLL required) and within the injected code you could then remove the third-party memory patches on routines like LdrLoadDll. Alternatively, go for method 1 and do it remotely 100%.

Patching LdrLoadDll will stop traditional DLL injection via LoadLibraryA/W and remote thread creation or APC but it won't block the actual remote thread creation or APC operation which leaves the process still vulnerable to shell-code/code-cave injection... Only way to stop remote thread creation/APC via local patching would be patching a routine like LdrInitializeThunk and KiUserApcDispatcher, both of those ideas are not practical realistically and will cause problems.

Anyway, if you really wanted to you could manually map your DLL through a file-less loader (e.g. code-cave) and thus the LdrLoadDll code execution flow redirection would never be triggered for your API monitoring module in the first place.
 

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