💀
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: Editing Opcodes
  • Part Three: Lets get to work
  • Part Four: ???
  • Part Five: Profit
  • Part Six: Conclusion
  • References
  1. ZeroTotal

ZeroTotal: Msfvenom Calc

The quest for an undetectable calc payload on VirtusTotal

PreviousZeroTotalNextZeroTotal: Self-Injecting Calc

Last updated 1 year ago

Part One: Introduction

The motivation for this research is to demonstrate the fact that at the end of the day, a skilled attacker can overcome detection. Lets begin this series with our initial payload and results.

Part Two: Getting Started

We make our shellcode with msfvenom. This is particularly a bad idea because these payloads should be thoroughly signatured.

We test our payload with runshc64.exe and get a working payload. Let see what VirusTotal says about this payload.

It's worth noting that in my experiments, using some of msfvenom's built in encoders was enough to return zero results from VirusTotal. But in the spirit of this research, lets aim to achieve that manually.

Part Three: Editing Opcodes

If we open up our binary in a hex editor, this is what we'll see:

Lets disassemble that.

Hmm..it looks like we should be able to scramble some of the opcodes around without affecting the functionality of the program. That might be enough to break some of the signatures.

Notice that the xor instruction is now on line f instead of line 11 where it was previously.

We run our shellcode to ensure that it still works.

Lets try VirusTotal again and see if anything changed.

It looks like that single opcode swap reduced our detection from 20 to 14! That’s a 20% reduction with one change.

Before we start getting too complicated, we can try to adding some nops in a couple places (like the very beginning to see if we get positive effects).

And it looks like we've reduced our detectability by two more.

Lets move a little bit past this primitive workflow and open this binary up in BinaryNinja for a more useful interface.

Part Three: Lets get to work

We open up our payload and see the following:

We tell BinaryNinja to interpret this binary dump as a function for clarity, and we get a nice flow graph of our payload.

We change "test rax, rax":

To "cmp eax, 0x0".

Note: This change is not perfectly equivalent, but it doesn't break the payload.

We can change "mov rdx, 0x1" to "mov edx, 0x1". We can now fill the newly empty space with garbage instructions.

And now it looks like this:

Lastly, we can make some changes to how we clear variables off the stack. This should help get rid of the things we don't need, and confuse automated analysis because it will break how a function is identified in some cases.

Let see what VirusTotal says about our payload now.

And it looks like we're down to two contenders. Let see if there's something we can do about that.

If we take another look at our payload in BinaryNinja we notice some hardcoded constants:

After doing some research into how msfvenom generates payload, we know that it does not pass the API call by name, but rather by a hash value. It's super likely that one of those values is what's getting us flagged.

Earlier, we turned this instruction:

Into this:

But we can rewrite that more succinctly to achieve 0x1 in edx and generate some empty space for us to play with.

So we turn this:

Into this:

Part Four: ???

[Intentionally left blank]

Part Five: Profit

We check that our payload still works.

Lets see what VirusTotal says about our payload now.

Part Six: Conclusion

In this write up, we saw how we were able to bypass all VirusTotal checks without encrypting, encoding, or wrapping our payload in any way. This demonstrates the value that that low-level binary manipulations bring to Red Teams and validates how important these skills are in any engagement.

However, this is not the end of the battle for the Red Team. More advanced analysis by EDR that leverage machine learning, heuristic analysis, or executable emulation are still apt to detect our payload. This is but one skillset and one data point to draw from when analyzing a target's attack surface.

Astute readers might notice that my payload size changed throughout this write up. I ended up injecting a few NOP bytes to give myself space to work and write the opcodes that got use from 2 to 0 detections in Part 4.

References

Red_Team_Code_Snippets/Assembly/Winx64/payloads/5.ZeroTotal/calc at main · 0xTriboulet/Red_Team_Code_SnippetsGitHub
The Shellcoder's Handbook: Discovering and Exploiting Security Holes, 2nd EditionAmazon.com
Logo
metasploit-framework/msfvenom at master · rapid7/metasploit-frameworkGitHub
Logo
Logo
Page cover image
Results:
https://www.virustotal.com/gui/file/470abc7f80b75727785f3f5561a5ce60c2c0a7d8b876d5cb9e5a17ef88aff5f7?nocache=1