CAPE icon indicating copy to clipboard operation
CAPE copied to clipboard

Monitoring DLL Running in Another process

Open JohnPeng47 opened this issue 7 years ago • 28 comments
trafficstars

Is there currently functionality in CAPE to run a dll in a specific process, instead of passing it to rundll?

JohnPeng47 avatar Oct 16 '18 19:10 JohnPeng47

I see what you mean - yes, submit the exe and dll together in a zip, and use zip package.

kevoreilly avatar Oct 16 '18 20:10 kevoreilly

you don't need to specify file=x.exe?

doomedraven avatar Oct 16 '18 20:10 doomedraven

If there is only one exe it should get picked altho I have a feeling I may have broken this with recent expansion of package to inclyde a dll (alone) in a zip. I will double check.

kevoreilly avatar Oct 16 '18 20:10 kevoreilly

so the zip package will inject the DLL into the exe file, and then capemon will be able to monitor the actions of the DLL as it executes inside the DLL?

JohnPeng47 avatar Oct 16 '18 20:10 JohnPeng47

No this depends on the exe either statically or dynamically importing the dll. Injection of a dll is rarely dependent on a particular target process in malware.

kevoreilly avatar Oct 16 '18 20:10 kevoreilly

What is the specific situation? What is the nature of this combination of exe and dll?

kevoreilly avatar Oct 16 '18 20:10 kevoreilly

For instance malicious DLL's that hook browser functions that enable the malware to render anything on screen, or read the user's input. Is there any way in CAPE to monitor the process of this DLL as it's executing in the browser (ie. hooking the PR_READ and PR_WRITE functions)?

JohnPeng47 avatar Oct 16 '18 20:10 JohnPeng47

I think in this scenario we rely on the malware to do its own injection of the dll into the browser (requiring the 'dropper' to be submitted) and ensure the monitor dll is loaded in the browser first.

kevoreilly avatar Oct 16 '18 20:10 kevoreilly

How can I configure the monitor dll is loaded in the browser executable? Because wouldn't it default to loading inside the submitted binary (or rundll)?

JohnPeng47 avatar Oct 16 '18 20:10 JohnPeng47

Otherwise this could be achieved by writing a package to do it.

kevoreilly avatar Oct 16 '18 20:10 kevoreilly

Sorry I missed your question. You don't need to configure anything to ensure the monitor is loaded into the browser, as the monitor in the process which does the injection of the malicious dll will catch the injection and ensure the monitor is loaded in the browser process first. This all happens automatically already.

The monitor in the injecting process catches the injection in hooks and uses the pipe("PROCESS:..."); call to alert the analyzer that a new process requires the monitor, and the analyzer injects the monitor before the malware has injected its dll. If you are interested you can find these calls inside the relevant hooks such as the hook for CreateRemoteThread (classic dll injection) in hook_thread.c

kevoreilly avatar Oct 16 '18 21:10 kevoreilly

From what I understand, your're saying that if the malware that's injected with the monitor creates a new process createRemoteThread, then the monitor will also be injected into this new process. I think I may have been unclear but the scenario I'm describing is if the malware overwrites the AppInit registry key, and then gets loaded into say browser.exe everytime browser.exe is executed. So the injection into the process does not happen when the malware is run, but rather, only when the process itself is run (through way of AppInit). Is there a configuration setting for CAPE to analyze this type of scenario? If not I will gladly contribute a package to implement it

JohnPeng47 avatar Oct 16 '18 22:10 JohnPeng47

From what I understand, your're saying that if the malware that's injected with the monitor creates a new process createRemoteThread, then the monitor will also be injected into this new process. I think I may have been unclear but the scenario I'm describing is if the malware overwrites the AppInit registry key, and then gets loaded into say browser.exe everytime browser.exe is executed. So the injection into the process does not happen when the malware is run, but rather, only when the process itself is run (through way of AppInit). Is there a configuration setting for CAPE to analyze this type of scenario? If not I will gladly contribute a package to implement it

JohnPeng47 avatar Oct 16 '18 23:10 JohnPeng47

This is indeed an interesting scenario! We can tackle it together if you like, let me give some thought about how it might work. I will need to dig into this AppInit mechanism a bit as ideally we would want to use the real Windows mechanism, but trigger it ourselves.

kevoreilly avatar Oct 17 '18 05:10 kevoreilly

How about a package that registers the supplied DLL with AppInit then just opens the browser?

kevoreilly avatar Oct 18 '18 18:10 kevoreilly

Or we could inject it using with writeProcMemory->loadLIbrary->createRemoteThread? Whichever one is easier to implement, as long as we can get the malicious DLL loaded into the target process somehow. By the way is there a way to modify registry values from Python or does that functionality need to be implemented in native code?

JohnPeng47 avatar Oct 19 '18 16:10 JohnPeng47

We could, I've implemented this type of injection in Loader.c if you want to have a look. But as I said, I think if you are testing something that is normally launched via a Windows mechanism, it would be best to use this mechanism rather than another implementation that may differ. I haven't looked into how AppInit performs injection but this is key.

kevoreilly avatar Oct 19 '18 17:10 kevoreilly

It may, for example, be that the Windows loader loads the AppInit DLLs as part of its startup routine, which is what the malware developers may depend upon to do their hooking. If we inject using a remote thread, this will come much later in the process life and may be too late to work with the hooking mechanism, thus the sample won't behave properly.

kevoreilly avatar Oct 19 '18 17:10 kevoreilly

Ah yes good point. And I think the AppInit DLL's gets loaded by user32.dll when that gets loaded into a process

JohnPeng47 avatar Oct 19 '18 17:10 JohnPeng47

Should this be implemented as an auxiliary module since it needs to run before the analyzer executes the targeted binary?

JohnPeng47 avatar Nov 02 '18 03:11 JohnPeng47

I haven't had time to look into this mechanism myself, but if this mechanism causes a dll to be loaded into all processes, then if set up accordingly in advance, it should be loaded in an IE process that is launched by the 'ie' package. So I would start with this simple test. Set the AppInit mechanism up, snapshot the state, then use that snapshot as the beginning of a typical run with IE, and see if the analysis catches the loading of the AppInit dll.

If it does, then the challenge would shift to making a package which first created the relevant AppInit registry key, then subsequently launches the process. This shouldn't be so hard. If the loading of the dll is missed (or doesn't occur) then we'll need to work out why not, there are things we can try in that eventuality too.

kevoreilly avatar Nov 02 '18 12:11 kevoreilly

Did you have any luck getting the AppInit registry key set? Let me know if you need any help integrating this into a package.

kevoreilly avatar Dec 03 '18 14:12 kevoreilly

I have the part done for setting registry keys, the next part I want to do is to allow the user to filter API calls based on where they came from. Have been busy with exams these past 2 weeks but will definitely work on this during christmas break.

I think I can implement a package for injecting a DLL into another process, and it would take the dll and the process as arguments. Then I think implementing return address filtering separately would make more sense, was thinking at the point in the monitor where it writes the return address to Mongo, add a line in there that also gets the name of the DLL that's loaded at that address using getModuleInformation(). Then we can change some logic in the front-end so that users can use this package and then only filter for calls with return address being the target DLL.

On Mon, Dec 3, 2018 at 2:12 AM kevoreilly [email protected] wrote:

Did you have any luck getting the AppInit registry key set? Let me know if you need any help integrating this into a package.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/ctxis/CAPE/issues/168#issuecomment-443723215, or mute the thread https://github.com/notifications/unsubscribe-auth/AJfxzQEMNNulTPGtcs-3uki8-Mulm03uks5u1TFlgaJpZM4XhADH .

JohnPeng47 avatar Dec 04 '18 02:12 JohnPeng47

Actually that last part is a little iffy

On Mon, Dec 3, 2018 at 2:27 PM John Peng` [email protected] wrote:

I have the part done for setting registry keys, the next part I want to do is to allow the user to filter API calls based on where they came from. Have been busy with exams these past 2 weeks but will definitely work on this during christmas break.

I think I can implement a package for injecting a DLL into another process, and it would take the dll and the process as arguments. Then I think implementing return address filtering separately would make more sense, was thinking at the point in the monitor where it writes the return address to Mongo, add a line in there that also gets the name of the DLL that's loaded at that address using getModuleInformation(). Then we can change some logic in the front-end so that users can use this package and then only filter for calls with return address being the target DLL.

On Mon, Dec 3, 2018 at 2:12 AM kevoreilly [email protected] wrote:

Did you have any luck getting the AppInit registry key set? Let me know if you need any help integrating this into a package.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/ctxis/CAPE/issues/168#issuecomment-443723215, or mute the thread https://github.com/notifications/unsubscribe-auth/AJfxzQEMNNulTPGtcs-3uki8-Mulm03uks5u1TFlgaJpZM4XhADH .

JohnPeng47 avatar Dec 04 '18 02:12 JohnPeng47

One thing I've learned over the years is that it's wise to break things down into pieces, so let's get this AppInit package done first before tackling this other idea.

Another classic gem of wisdom is many hands make light work! So if you are happy to show me what you've done so far, perhaps with a smattering of relevant malware samples, perhaps I can help drive it to completion...!

kevoreilly avatar Dec 04 '18 03:12 kevoreilly

Ah yes u are right sometimes I get a little too ahead of myself. Below code shud load VIRUS.EXE into every process that also loads user32, by way of LoadAppInitDLL, test on Win7 v6.2:

from  _winreg import *

dllpath = "C:\\Users\\IEUser\\Documents\\test_dll\\msgbox.dll"
keyVal = r'SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows
try:
	print "hello"
	key = OpenKey(HKEY_LOCAL_MACHINE, keyVal, 0, KEY_ALL_ACCESS)
except:
	print "creating key"
	key = CreateKey(HKEY_LOCAL_MACHINE, keyVal)

SetValueEx(key, "LoadAppInit_DLLs", 1, REG_DWORD, 0)
SetValueEx(key, "RequireSignedAppInit_DLLs", 1, REG_DWORD, 1)
SetValueEx(key, "AppInit_DLLs", 1, REG_SZ, dllpath)

print QueryValueEx(key, u'AppInit_DLLs') 
CloseKey(key)

After running the above, the process to be injected will be provided by the user as a parameter, and the package will hook/start that process. Then once analysis is complete, find a way to filter out the results by only looking for calls made by the DLL. And then stopping the analysis after the DLL has finished executing (not sure best way to do this). What do you think?

JohnPeng47 avatar Dec 05 '18 08:12 JohnPeng47

Thanks - do you have a sample I can test this with?

kevoreilly avatar Dec 05 '18 15:12 kevoreilly

Yep I have a small DLL that pops a text box in DLLMain. https://drive.google.com/file/d/1I_tMZb22xbPMj4v5DNP5EZowWoQylXs4/view?usp=sharing

So just download the DLL, and change the dllpath variable in the script to point to the downloaded file. Run the script, and then afterwards, any program you open (ie. calculator, browser, etc.) should pop a text box. Note: I actually posted the wrong version of the script it shud be as follows:


from  _winreg import *

dllpath = "C:\\Users\\IEUser\\Documents\\test_dll\\msgbox.dll"
keyVal = r'SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows
try:
	print "hello"
	key = OpenKey(HKEY_LOCAL_MACHINE, keyVal, 0, KEY_ALL_ACCESS)
except:
	print "creating key"
	key = CreateKey(HKEY_LOCAL_MACHINE, keyVal)

SetValueEx(key, "LoadAppInit_DLLs", 1, REG_DWORD, 1)
SetValueEx(key, "RequireSignedAppInit_DLLs", 1, REG_DWORD, 0)
SetValueEx(key, "AppInit_DLLs", 1, REG_SZ, dllpath)

print QueryValueEx(key, u'AppInit_DLLs') 
CloseKey(key)

JohnPeng47 avatar Dec 06 '18 00:12 JohnPeng47