TTPs: BadAsm
In this writeup we use the capabilities of inline assembly to overwrite part of our program's .text section and achieve non-standard payload self-injection and execution
Part One: Introduction
If you're at all familiar with malware development, you know that most malware delivers payloads from remote servers via some implementation of memory allocation -> memory writing -> execution of code. As discussed in my JmpNoCall article, this frequently results in API calls returning to unbacked RX or RWX sections of memory. Because this is almost always anomalous/malicious behavior, advanced EDR/AV technologies flag/block this behavior thereby rendering most primitive implant implementations useless.
In this article I will propose a technique that overwrites the standard .text section of our implant at runtime in order to execute code from a "known" area of memory. We’re going to use inline assembly to get some addresses, overwrite sacrificial instructions, and ultimately execute some malicious code in a modern EDR environment that blocks typical memory execution.
Note: A lot of what we're doing here is going to be very memory unsafe so you might have to tweak the assembly and payloads used in this writeup to achieve successful execution
Part Two: Getting Started
We can use the following code to get started:
Now that we have a pretty clear idea of what we want to happen, lets compile the code and run inside of x64dbg.
We see that we successfully hit an interrupt instruction
And if we follow that instruction in our memory map, we can see that our payload is in the .text section of memory
We can even see that if we execute our payload to termination, it returns to main and continues execution like we expect.
Part Three: A proper payload
In order for this to work, we'll have to pre-allocate a larger sacrificial area in our .text section. We can do that with some command line python code:
If we want to use an msfvenom payload, our code should look something like this:
And we get payload execution!
However, because we used an encoder our payload will need RWX permission to execute, additionally msfvenom payloads have a bad habit of not exiting nicely and allowing for implant recovery without low level modifications.
An alternative is to use a slight variant of @boku's popcalc payload to be able to better achieve OPSEC and recoverable exectution. We'll skip the discussion of that implementation, but the code is available on my github.
Part Four: Better execution
Our better solution looks something like this:
Part Five: ???
[Intentionally left blank]
Part Six: Profit
Part Six: Conclusion
EDRs are very complex, and this is only one aspect of EDR detection that must be overcome in order to successfully infect protected enterprise level systems. But my testing showed that this technique avoided threat detection on some vendors, though achieving code execution proper is another matter. We did not implement any unhooking or more complex bypass techniques in this article which is bound to leave us very vulnerable to detection.
This is the second article that I've written on the use of inline assembly in order to bypass protections. The granularity of control that can be achieved with inline assembly is a huge capability that is largely unexplored on x64 systems. This is probably due to the fact that Visual Studio does not support inline assembly for x64 or ARM architectures. In any case, inline assembly is a powerful capability that requires further research.
References
Last updated