Windows/x86 (5.0 < 7.0) - Skylined's "You Got Pwned!" Null-Free Shellcode

Windows/x86 (5.0 < 7.0) - Skylined's "You Got Pwned!" Null-Free Shellcode
What this paper is
This paper describes a piece of shellcode for 32-bit Windows systems (versions 5.0 through 7.0, including all service packs). Its primary function is to audibly announce "You got pwned!" through the computer's speakers using the Microsoft Speech API. A key feature highlighted is that the shellcode is "null-free," meaning it does not contain any null bytes (\x00). This is often a requirement for exploiting certain vulnerabilities where null bytes can prematurely terminate strings or data. The paper also mentions optional additions to the shellcode for stack alignment fixes and EAF (Extended Address Filtering) bypass.
Simple technical breakdown
The shellcode works by interacting with the Windows operating system's built-in speech capabilities. It needs to:
- Find necessary Windows functions: It locates core functions within
kernel32.dllandole32.dllthat are required to use the Speech API. - Initialize the Speech API: It sets up the necessary components to speak text.
- Create a speech object: It instantiates an object that can convert text to speech.
- Speak the message: It tells the speech object to say "You got pwned!".
- Clean up: It releases the resources used by the Speech API.
The "null-free" aspect is crucial because many exploitation techniques involve injecting shellcode into vulnerable programs. If the shellcode contains null bytes, it might be truncated by the vulnerable application before it can fully execute.
The optional features address common exploitation challenges:
- Stack Alignment: Some exploits require the stack to be aligned in a specific way for proper execution. Adding a few bytes can fix this.
- EAF Bypass: Extended Address Filtering (EAF) is a security mechanism. Bypassing it allows the shellcode to execute in environments where EAF might otherwise prevent it.
Complete code and payload walkthrough
The provided Exploit-DB entry for paper ID 15879 contains a ZIP file (w32-speaking-shellcode.zip) which, when extracted, contains the shellcode itself. The raw shellcode is a sequence of bytes. Since the original paper does not contain C source code for the shellcode generation, we will analyze the provided shellcode bytes as a sequence of operations.
The shellcode is designed to be null-free and self-contained. It dynamically resolves API calls rather than relying on fixed addresses, making it more robust across different Windows versions and service packs.
Let's break down the typical stages and functionalities found in such shellcode, assuming the provided bytes represent the following logical flow:
Stage 1: Initialization and API Resolution
- Purpose: To find the base addresses of essential DLLs (like
kernel32.dll,user32.dll,ole32.dll) and then locate specific API functions within those DLLs. This is done by iterating through the PEB (Process Environment Block) and TEB (Thread Environment Block) structures. - Mechanism:
- It starts by getting the current process's PEB.
- From the PEB, it finds the loaded modules list.
- It iterates through the module names to find
kernel32.dll. - Once
kernel32.dllis found, it parses its export directory to find functions likeLoadLibraryA,GetProcAddress,VirtualAlloc, etc. - It then uses
LoadLibraryAto load other necessary DLLs (e.g.,ole32.dll,user32.dll) if they are not already loaded. - Finally, it uses
GetProcAddressto get the addresses of specific functions needed for the Speech API and other operations.
- Null-Free Technique: This stage is critical for being null-free. Instead of using null-terminated strings for DLL and function names, it might use length-prefixed strings or iterate character by character until a null terminator is found (but the null terminator itself is not part of the string data being used for comparison). It also avoids null bytes in its own instructions.
Stage 2: Speech API Initialization
- Purpose: To prepare the Microsoft Speech API for use.
- Mechanism:
- It calls
CoInitializeEx(fromole32.dll) to initialize the COM library. - It then calls
CoCreateInstance(fromole32.dll) to create an instance of the Speech Synthesizer object (e.g.,CLSID_SpVoice). - It stores the pointer to this
ISpVoiceobject.
- It calls
Stage 3: Speaking the Message
- Purpose: To instruct the Speech API to speak the desired phrase.
- Mechanism:
- It calls the
Speakmethod of theISpVoiceobject obtained in the previous stage. - The string "You got pwned!" is passed as an argument to the
Speakmethod. This string itself must also be null-free if it's embedded directly, or handled carefully if it's constructed. Given the shellcode's null-free nature, the string literal would likely be constructed without null terminators or managed in a way that avoids them.
- It calls the
Stage 4: Cleanup and Exit
- Purpose: To release the resources used by the Speech API and terminate gracefully.
- Mechanism:
- It calls
Releaseon theISpVoiceobject to free its memory. - It calls
CoUninitialize(fromole32.dll) to uninitialize the COM library. - It might then exit the thread or process, depending on how it was invoked.
- It calls
Optional Code Segments:
- Stack Alignment Fix (adds 5 bytes):
- Purpose: To ensure the stack pointer is aligned to a 16-byte boundary, which is sometimes required for certain instructions or function calls to execute correctly.
- Mechanism: Typically involves a few
pushorsub esp, Xinstructions to adjust the stack pointer.
- EAF Bypass (adds 29 bytes):
- Purpose: To circumvent Extended Address Filtering, a security feature that can prevent code execution in certain memory regions.
- Mechanism: This is more complex and could involve techniques like:
- Finding a suitable memory region that is executable and writable.
- Using
VirtualAllocto allocate new memory and mark it as executable. - Potentially overwriting existing executable code in a controlled manner (though the paper states "data is not executed, code is not modified," suggesting it might be more about finding an executable region or using ROP chains if EAF is very strict). The "data is not executed" implies it's not injecting into data segments and executing them, but rather executing code from a code segment or a specially allocated executable memory region.
Shellcode Bytes Explanation (Conceptual):
Since the raw bytes are not provided in the prompt, a direct byte-by-byte explanation is impossible. However, a typical null-free shellcode for this purpose would involve:
- Assembly instructions:
mov,push,pop,call,jmp,xor,lea,inc,dec,add,sub,cmp,test,ret. - API hashing or string searching: To find function addresses without null-terminated strings.
- Structure manipulation: Accessing PEB, TEB, PE headers, import/export directories.
- COM object creation: Using
CoCreateInstanceandISpVoiceinterface methods. - String construction: Building the "You got pwned!" string without null bytes.
Mapping List (Conceptual):
xor eax, eax-> Initialize register to zero (often used as a base for null-free string building or null checks).mov esi, fs:[0x30]-> Get PEB pointer from Thread Information Block.mov ebx, [esi+0x0c]-> Get PEB_LDR_DATA pointer.mov ebx, [ebx+0x1c]-> Get first entry in InLoadOrderModuleList.mov edi, [ebx+0x18]-> Get base address of the current module (e.g.,ntdll.dll).mov eax, [ebx+0x10]-> Get base address of the next module.mov ecx, 0xXXXXXXXX-> Load a specific hash or partial string for comparison.call GetProcAddress-> Resolve an API function.push 0xXXXXXXXX-> Push arguments onto the stack.call [address_of_api]-> Execute a resolved API function.mov byte ptr [address], 0x41-> Place a non-null byte into memory.add esp, 0xX-> Clean up stack after acall.ret-> Return from function/shellcode.
Practical details for offensive operations teams
- Required Access Level: Typically requires code execution capabilities within a target process. This could be achieved through various vulnerabilities like buffer overflows, format string bugs, use-after-free, or by leveraging existing code execution vectors (e.g., macro execution in documents, web application exploits). No elevated privileges are strictly required for the shellcode itself, but the exploit that delivers it might.
- Lab Preconditions:
- A target Windows environment (versions 5.0-7.0, 32-bit).
- A way to inject and execute arbitrary shellcode into the target process. This usually involves a custom exploit or a framework like Metasploit.
- Network connectivity if the exploit requires it to deliver the shellcode.
- A way to verify execution (e.g., listening for the audio output, or using a debugger to confirm the shellcode ran).
- Tooling Assumptions:
- Exploit Development Framework: Metasploit Framework, custom exploit scripts (Python, C).
- Shellcode Generation/Analysis:
msfvenom(for generating similar shellcode or testing), IDA Pro, Ghidra, x64dbg/OllyDbg for dynamic analysis. - Network Tools: Netcat, Wireshark (if the exploit involves network communication).
- Execution Pitfalls:
- Null Byte Filters: If the delivery mechanism or the vulnerable application itself filters out null bytes, this shellcode is designed to bypass that. However, other characters might be filtered.
- DEP/ASLR: The shellcode claims DEP/ASLR compatibility. DEP (Data Execution Prevention) is handled by not executing data. ASLR (Address Space Layout Randomization) is handled by dynamic API resolution, which doesn't rely on fixed addresses. However, very aggressive ASLR implementations or specific exploit mitigations might still pose challenges.
- Speech API Availability: The target system must have the Microsoft Speech API installed and functional. This is standard on most desktop Windows versions but might be absent on minimal server installations or embedded systems.
- Audio Output: The target machine must have functional audio hardware and drivers.
- Stack Alignment: If the exploit itself causes stack corruption or misalignment that the shellcode's optional fix cannot correct, execution might fail.
- API Resolution Failures: If
kernel32.dllor other critical DLLs are not found, or if specific required functions are missing (highly unlikely on target OS versions), the shellcode will fail. - EAF Bypass Limitations: The effectiveness of the EAF bypass depends on the specific EAF implementation and the context of the exploit. It's not a universal bypass for all memory protection schemes.
- String Length: The "You got pwned!" string is relatively short. Longer strings might require more complex handling or larger shellcode.
- Tradecraft Considerations:
- Stealth: The primary output is audible. This is inherently noisy and not stealthy. It's best used in scenarios where auditory confirmation is desired or acceptable (e.g., testing, red team exercises where noise is not a primary concern, or as a final "taunt" after a successful compromise).
- Payload Size: Null-free shellcode can sometimes be larger than its null-byte-containing counterparts due to the techniques used for string manipulation and API resolution. This might impact its ability to fit into small buffer overflows.
- Customization: The string "You got pwned!" can be easily modified to include other messages, but care must be taken to ensure the new string remains null-free and fits within the shellcode's constraints.
Where this was used and when
This shellcode was published on December 31, 2010. Its intended use was for demonstrating a null-free shellcode capable of interacting with the Windows Speech API. It would have been relevant for exploit developers and security researchers targeting Windows XP, Vista, and Windows 7 (32-bit) around that time. Specific public exploits using this exact shellcode are not detailed in the paper itself, but it represents a common type of payload used in exploit development for proof-of-concept demonstrations or as a component in more complex attack chains. Its features (null-free, version independence) made it a useful tool for bypassing common exploit mitigation techniques prevalent in that era.
Defensive lessons for modern teams
- Auditory Alerts: While this specific shellcode is old, the concept of using audible alerts for post-exploitation is still relevant. Defenders should be aware that unexpected audio output could indicate a compromise.
- Dynamic API Resolution: Shellcode that resolves API calls dynamically is harder to detect with simple API blacklisting. Defenses should focus on behavioral analysis and anomaly detection rather than just static API call signatures.
- Null-Free Shellcode: The techniques used to create null-free shellcode (e.g., careful string manipulation, custom encoding) are still employed. Static analysis tools need to be robust enough to handle these obfuscation methods.
- COM Object Abuse: The reliance on COM objects (
ISpVoice) highlights that attackers can leverage legitimate system components. Monitoring COM object creation and usage can be a valuable defensive strategy. - Exploit Mitigation Bypass: The mention of EAF bypass is a reminder that attackers constantly seek ways around security features. Defenders must stay updated on evolving bypass techniques for DEP, ASLR, and other exploit mitigations.
- Process Behavior Monitoring: Instead of focusing solely on the shellcode itself, monitoring for unusual process behavior (e.g., a Word document process suddenly trying to initialize COM and speak) is a more effective defense.
ASCII visual (if applicable)
+-------------------+
| Target Process |
+-------------------+
| |
| [ Vulnerability ] <--- Exploit Delivery
| [ Triggered ]
| |
| +-------------+ |
| | Shellcode | |
| | Execution | |
| +-------------+ |
| | |
| v |
| +-------------+ |
| | Find APIs | |
| | (kernel32, | |
| | ole32) | |
| +-------------+ |
| | |
| v |
| +-------------+ |
| | Init COM | |
| | CoInitialize| |
| +-------------+ |
| | |
| v |
| +-------------+ |
| | Create | |
| | ISpVoice | |
| | CoCreateInst| |
| +-------------+ |
| | |
| v |
| +-------------+ |
| | Speak | |
| | "You got | |
| | pwned!" | |
| +-------------+ |
| | |
| v |
| +-------------+ |
| | Cleanup | |
| | Release, | |
| | CoUninitialize| |
| +-------------+ |
| |
+-------------------+Source references
- Paper ID: 15879
- Paper Title: Windows/x86 (5.0 < 7.0) - Speaking 'You got pwned!' + Null-Free Shellcode
- Author: Skylined
- Published: 2010-12-31
- Paper URL: https://www.exploit-db.com/papers/15879
- Raw URL: https://www.exploit-db.com/raw/15879
Original Exploit-DB Content (Verbatim)
A null-free shellcode for 32-bit versions of Windows 5.0-7.0 all service packs that uses Microsoft Speech API to say "You got pwned!" over the speakers. Includes optional code that fixes stack alignment (adds 5 bytes) and bypasses EAF (adds 29 bytes).
Features:
NULL Free
Windows version and service pack independant.
No assumptions are made about the values of registers.
"/3GB" compatible: pointers are not assume to be smaller than 0x80000000.
DEP/ASLR compatible: data is not executed, code is not modified.
Windows 7 compatible: kernel32 is found based on the length of its name
Download:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/15879.zip (w32-speaking-shellcode.zip)