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

DLL injection detection #19

Open
simakhan785 opened this issue Oct 9, 2018 · 15 comments
Open

DLL injection detection #19

simakhan785 opened this issue Oct 9, 2018 · 15 comments
Assignees

Comments

@simakhan785
Copy link

Hi,
I am currently experimenting with pe-sieve for detection of various DLL injection methods. but I have found it is able to detect only the reflective DLL injection. What about the other mode of DLL injection - such as using -a) CreateRemoteThread, b) NtCreateThreadEx etc. How pe-sieve can be used to detect those things.

thanks,
Sima

@hasherezade hasherezade self-assigned this Oct 9, 2018
@hasherezade
Copy link
Owner

Hi! Indeed, the classic DLL injection (such as this one) is not supported yet. But it is on my TODO list and it will be implemented in the future.

@muse117
Copy link

muse117 commented Mar 15, 2021

Hi, Is the classic DLL injection already supported?

@muse117
Copy link

muse117 commented Mar 16, 2021

Hi! Indeed, the classic DLL injection (such as this one) is not supported yet. But it is on my TODO list and it will be implemented in the future.

Hi, How to detect a classic DLL injection?

@hasherezade
Copy link
Owner

Sorry, this is not supported yet. It is rarely used by malware so I give it a low priority. But sure I am planning to add it at some point.

@muse117
Copy link

muse117 commented Mar 17, 2021

Sorry, this is not supported yet. It is rarely used by malware so I give it a low priority. But sure I am planning to add it at some point.

I hope to add APC injection. This will be perfect! ^_^

@hasherezade
Copy link
Owner

I hope to add APC injection. This will be perfect! ^_^

"APC injection" is in reality about how you run the injected code, not about how you implant it. In contrast, the detection in PE-sieve is about how the code was implanted. So, it works the same for all the code running methods - whether you add the code as a new thread, or to the existing thread. This includes APC injection. As long as the implant can be found, PE-sieve detects it.

@hasherezade
Copy link
Owner

Classic DLL injection is atypical in this way, that the DLL is mapped in a legitimate way - using LoadLibrary. Which means that the characteristics of mapping are indistinguishable from the normally loaded DLL. This is what makes this type of injection more difficult to detect (and also very prone to false positives). It is not about how the code was run (whether you used CreateRemoteThread / NtCreateThreadEx / APC injection / others).

@muse117
Copy link

muse117 commented Mar 19, 2021

Classic DLL injection is atypical in this way, that the DLL is mapped in a legitimate way - using LoadLibrary. Which means that the characteristics of mapping are indistinguishable from the normally loaded DLL. This is what makes this type of injection more difficult to detect (and also very prone to false positives). It is not about how the code was run (whether you used CreateRemoteThread / NtCreateThreadEx / APC injection / others).

wonderful! l learn to so much from you, thx a lot of!

@hasherezade
Copy link
Owner

Classic DLL injection is atypical in this way, that the DLL is mapped in a legitimate way - using LoadLibrary. Which means that the characteristics of mapping are indistinguishable from the normally loaded DLL. This is what makes this type of injection more difficult to detect (and also very prone to false positives). It is not about how the code was run (whether you used CreateRemoteThread / NtCreateThreadEx / APC injection / others).

wonderful! l learn to so much from you, thx a lot of!

If you will like to learn more about PE-sieve internals, I recommend you to see my presentation about it: https://www.youtube.com/watch?v=fwo4XE2xgis

@AndyWatterman
Copy link

AndyWatterman commented Nov 15, 2021

"APC injection" is in reality about how you run the injected code,

It seems this is a bit incorrect. It is possible to use APC to run gadgets, but not to run the injected code. Thus, it might becomes about "how you implant it".

@hasherezade
Copy link
Owner

"APC injection" is in reality about how you run the injected code,

It seems this is a bit incorrect. It is possible to use APC to run gadgets, but not to run the injected code. Thus, it might becomes about "how you implant it".

@AndyWatterman - Sorry, but you are incorrect. Running the injected code with APC is totally fine. It really doesn't matter if you add to an APC a pointer to a gadget, or a pointer to the code that you just implanted. It just has to be a pointer that points to valid code. Check out this example:

https://github.com/hasherezade/demos/blob/master/inject_shellcode/src/main.cpp#L54

First you map the shellcode to the remote process, and then you add the pointer to the beginning of the shellcode to the APC of the selected thread, just like this:

 if ((status = NtQueueApcThread(hThread, remote_shellcode_ptr, 0, 0, 0)) != STATUS_SUCCESS)
...

Thus, what I previously said is correct:

"APC injection" is in reality about how you run the injected code

APC is not used for implanting the code, but exactly for running it.

@AndyWatterman
Copy link

AndyWatterman commented Nov 15, 2021

The question is "Could we use APC to run chain (or some elements from) like VirtualAlloc, VirtualProtect and, then, NtWriteVirtualMemory(or any similar gadget) as many times as necessary to fill previously allocated buffer?". We could construct our shellcode from bytes and gadgets of the original program, not necessary to map anything first. So, if we can do this, thus it means we can use APC for injection without previously mapped shellcode. Therefore, it becomes about "how you implant it" (by using APC), but not only "how to run injected code". Am I right? :-)

As the result: "APC injection" is in reality about how you may inject and run some code.

@hasherezade
Copy link
Owner

You first wrote:

It is possible to use APC to run gadgets, but not to run the injected code.

so my answer was: sure, you can run gadgets, but it is not just for gadgets - you can use it to run the injected code directly too.

Now regarding:

The question is "Could we use APC to run chain (or some elements from) like VirtualAlloc, VirtualProtect and, then, NtWriteVirtualMemory(or any similar gadget) as many times as necessary to fill previously allocated buffer?". We could construct our shellcode from bytes and gadgets of the original program, not necessary to map anything first. So, if we can do this, thus it means we can use APC for injection without previously mapped shellcode. Therefore, it becomes about "how you implant it" (by using APC), but not only "how to run injected code". Am I right? :-)

As the result: "APC injection" is in reality about how you may inject and run some code.

Sure you can call this sequence via gadgets, but still I would not say that it means that "the APC was used for the injection".
APC was just used for running the stub composed of gadgets. What you used for the injection was the sequence of the functions: VirtualAlloc, VirtualProtect, NtWriteVirtualMemory.
And why does it matter?
Because from the point of view of memory artifacts, it really doesn't matter if you call VirtualAlloc etc. via gadget, or if you call it directly. It will still leave the same artifacts. That's why it does not make it an APC-specific case.

@AndyWatterman
Copy link

AndyWatterman commented Nov 15, 2021

APC was just used for running the stub composed of gadgets...

...to [purpose] inject a shellcode :-) Easy like this.

it really doesn't matter if you call VirtualAlloc etc. via gadget,

Here I absolutely agree with you.

This seems a wordplay. Thanks for the clarification.

@hasherezade
Copy link
Owner

hasherezade commented Nov 15, 2021

APC was just used for running the stub composed of gadgets...

...to [purpose] inject a shellcode :-) Easy like this.

You can call it like this in a colloquial way, but since it is a thread about detecting memory artifacts, I am describing how it looks from this perspective.

Anyways I am glad that we clarified it now!

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

4 participants