Nuking Weak Shellcode Hacker Hashes For Fun And Profit

Nuking Weak Shellcode Hacker Hashes For Fun And Profit

May 23, 2024 | Categories: Research

Shellcode disruption is just ONE thing Karma-X has scaled to protect it's customers.

Introduction to Shellcode

Shellcode is a small piece of code used as the payload in the exploitation of a software vulnerability. It is typically written in assembly language and designed to execute a particular set of instructions to exploit the target system. In the context of Windows, shellcode has been used from everything from launching applications to allowing for larger second stage executions.

Evolution of Windows Shellcode Hashing

Early Shellcode Techniques

In the early days of shellcode development, simplicity was key. Initial shellcodes were straightforward and relied on well-known system calls to achieve their objectives. However, as security mechanisms evolved, so did the complexity and sophistication of shellcodes. One significant advancement was the introduction of hashing techniques to obfuscate the API functions used by the shellcode, making detection and analysis more challenging.

Last Stage of Delirium's Contribution

One of the seminal works in the field of Windows shellcode was presented by the Polish security group, Last Stage of Delirium (LSD). Their paper, "Win32 Asm Components," provided critical insights into the construction and obfuscation of Win32 shellcode. LSD's work was instrumental in demonstrating how assembly language could be used to craft efficient and stealthy shellcode for the Windows platform.

In their paper, LSD introduced several techniques for obfuscating API calls, which included the use of hashing functions. By hashing the names of API functions, shellcode authors could obscure their intentions and evade signature-based detection mechanisms. This approach involved computing a hash of the desired API function name and comparing it against precomputed hashes stored within the shellcode.

Here is the C implementation of LSD's hash routine:

int idx;
for(idx=0;;idx++){
    unsigned int h;
    unsigned char c=sym[idx];
    while(c) h=((h<<5)|(h>>27))+*c++;
        if(h==hash) break;
}

Hick's Paper on Win32 Shellcode

Further advancements were documented by skape in his paper "Understanding Windows Shellcode" in 2003 built upon the foundation laid by LSD and introduced additional techniques for creating robust shellcode. One of the key contributions of skape's work was the use of the ROR (rotate right) 13 hashing function for obfuscating API function names.

findfunction:
    pushad
    mov ebp, [esp + 0x24]
    mov eax, [ebp + 0x3c]
    mov edx, [ebp + eax + 0x78]
    add edx, ebp
    mov ecx, [edx + 0x18]
    mov ebx, [edx + 0x20]
    add ebx, ebp
findfunctionloop:
    jecxz findfunctionfinished
    dec ecx
    mov esi, [ebx + ecx * 4]
    add esi, ebp
computehash:
    xor edi, edi
    xor eax, eax
    cld
computehashagain:
    lodsb
    test al, al
    jz computehashfinished
    ror edi, 0xd
    add edi, eax
    jmp computehashagain
computehashfinished:
findfunctioncompare:
    cmp edi, [esp + 0x28]
    jnz findfunctionloop
    mov ebx, [edx + 0x24]
    add ebx, ebp
    mov cx, [ebx + 2 * ecx]
    mov ebx, [edx + 0x1c]
    add ebx, ebp
    mov eax, [ebx + 4 * ecx]
    add eax, ebp
    mov [esp + 0x1c], eax
findfunctionfinished:
    popad
    ret

The Role of ROR 13 in Shellcode Hashing

The ROR 13 hashing function became a popular choice among shellcode developers due to its simplicity and effectiveness. The rotate right operation involves rotating the bits of a value to the right by a specified number of positions. In the context of shellcode, ROR 13 was used to generate a unique hash for each API function name.

The process of hashing an API function name using ROR 13 typically involved the following steps:

  • Initialize a hash value: Start with an initial hash value, often set to zero.
  • Iterate through each character: For each character in the API function name, update the hash value by rotating it right by 13 positions and then adding the ASCII value of the character.
  • Finalize the hash: After processing all characters, the resulting hash value represents the obfuscated API function name.

This hashing technique provided several advantages:

  • Compactness: The hash value was typically a 32-bit integer, making it space-efficient for use in shellcode.
  • Speed: The ROR operation and subsequent additions were computationally inexpensive, ensuring that the shellcode remained performant.
  • Obfuscation: By using hashes instead of plaintext strings, shellcode could evade simple pattern-matching detection methods employed by antivirus software.

Simple hashing algorithms are in ALOT of hacker tools

Or at least public versions of them:

  • Metasploit: One of the most widely used penetration testing frameworks, Metasploit includes various payloads, tools, and shellcode modules that use ROR 13 hashing to obfuscate API calls.
  • Cobalt Strike: This advanced threat emulation tool often employs ROR 13 hashing in its Beacon payloads to hide the use of certain Windows APIs, making it harder to detect.
  • Empire: A post-exploitation agent written in Python and PowerShell, Empire uses hashing in some of its modules to evade detection by security tools.
  • PowerSploit: A collection of PowerShell scripts for post-exploitation, PowerSploit includes modules that utilize hashing for API function resolution.
  • Meterpreter: As part of the Metasploit framework, Meterpreter is a powerful post-exploitation tool that also incorporates ROR 13 hashing in its payloads to obfuscate API calls.
  • Shellter: A dynamic shellcode injection tool that supports various encoding techniques, including the use of hashing for resolving API functions.
  • Nighthawk from MDSEC: An advanced post-exploitation framework designed for stealth and efficiency, Nighthawk has been known to use the same or similar hashing to evade detection and analysis by security tools.

Computer Science has given us better hashing functions, why ROR 13?

Using a hash function, even a weak one like ROR 13, is crucial in the context of shellcode and post-exploitation frameworks for several reasons. Firstly, hashing functions help obfuscate the names of API functions that the shellcode needs to call. This obfuscation is essential for evading detection by security tools that scan for known API function names in executable code. By converting these names into hashed values, attackers make it significantly more challenging for antivirus programs and other security defenses to recognize and block malicious activities based solely on static signatures.

Although ROR 13 is considered a weak hash function due to its simplicity and vulnerability to collisions, its use in this context is justified by compact size, efficiency, and speed. Shellcode often runs in highly constrained environments where performance and size are critical. ROR 13 provides a lightweight and fast means of generating hash values without introducing substantial overhead, which is crucial for maintaining the stealth and performance of the payload. Moreover, its simplicity allows for easy implementation in assembly language, which is commonly used for writing shellcode.

Ultimately, while stronger hash functions could provide better security, the use of a simple hash like ROR 13 strikes a balance between obfuscation and operational efficiency, enabling shellcode to remain effective while minimizing its footprint and execution time.

Defeating ROR 13 Hashing

While ROR 13 (Rotate Right by 13 bits) hashing is commonly used in shellcode for its simplicity and efficiency, it is relatively weak and susceptible to several types of attacks. The primary weakness of ROR 13 lies in its predictability and lack of complexity. Hash functions are designed to transform input data into a fixed-size string of bytes, ideally such that it is computationally infeasible to reverse the process or find two different inputs that produce the same output. ROR 13, however, does not meet these criteria effectively.

Collision Vulnerability

One of the main ways to defeat ROR 13 hashing is by exploiting its susceptibility to hash collisions. A hash collision occurs when two different inputs produce the same hash value. Due to the simplicity of the ROR 13 operation, which involves rotating the bits of the input and adding subsequent characters, it is relatively easy to generate multiple strings that result in the same hash. Attackers can leverage this weakness to create inputs that bypass hash-based checks or filters.

Reverse Engineering

Another approach to defeating ROR 13 hashing is reverse engineering. Since ROR 13 is not a cryptographic hash function, it lacks the complexity needed to resist reverse engineering efforts. By analyzing the assembly code or the hashing algorithm itself, it is possible to derive the original input from the hash or predict the hash values for given inputs. This makes it easier for defenders to identify and neutralize malicious shellcode that uses ROR 13 hashing for obfuscation.

Brute Force Attacks

Due to its limited entropy, ROR 13 hashing is also vulnerable to brute force attacks. Given enough computational resources, an attacker can generate and hash all possible strings until a collision or the original input is found. This method is feasible because the ROR 13 hash function is fast and does not significantly increase the computational workload. Consequently, defenders can precompute hash values for known API functions and compare them against observed hashes to identify obfuscated API calls in shellcode.

Python Code to Fuzz Strings for ROR 13 Hash Collisions

The following Python code demonstrates how to fuzz strings to find ROR 13 hash collisions. This code generates random strings and computes their ROR 13 hashes, checking for collisions.

import random
import string


def ror13hash(s):
    hashvalue = 0
    for char in s:
        hashvalue = (hashvalue >> 13) | (hashvalue << (32 - 13)) 
        hashvalue = (hashvalue + ord(char)) & 0xFFFFFFFF  # Add the character's ASCII value
    return hashvalue


def randomstring(length):
    return ''.join(random.choices(string.asciiletters + string.digits, k=length))


def findcollisions(targethash, maxattempts=1000000, stringlength=10):
    collisions = []
    attempts = 0
    while attempts < maxattempts:
        s = randomstring(stringlength)
        if ror13hash(s) == targethash:
            collisions.append(s)
            print(f"Collision found: {s}")
        attempts += 1
    return collisions


targethash = ror13hash("example")
collisions = findcollisions(targethash)


print(f"Collisions for hash {targethash}: {collisions}")

Shellcode Hash Collisions can be cleverly inserted into an operating system to cause attack failure

Defenders can exploit hash collisions to counteract shellcode resolution techniques by inserted precomputed collisions in the resolution path of shellcode routines. When a collision is encountered and unwittingly used —i.e., an unexpected match between a computed hash and a shellcode stored hash—defenders can intercept shellcode execution before it can interact successfully with the Operating System and take any action it so chooses, even before other shellcode mitigation techniques which rely on Function Hooking and other inspection. This approach allows defenders to identify and isolate shellcode at an extremely early stage causing attack failure. By focusing on the predictable nature of weak hash functions like ROR 13, defenders can defend against malicious payloads that might otherwise evade detection through conventional signature-based methods. Additionally, leveraging hash collisions helps in creating robust protection in endpoint detection and response (EDR) systems, enhancing the overall security posture against advanced threats​.

Further, we do this at scale at an accelerated pace. Not only have we cracked hundreds of existing commonly used hashes, we have cracked and implemented future hash algorithms that adversaries don't know that we have yet. That is the Karma-X advantage, thinking ahead.

Karma-X is an emerging technology company with an advanced EDR platform

Shellcode Hash Protection is just ONE thing Karma-X has scaled to protect it's customers. We have scaled our patent-pending technology to help defend the enterprise from broad classes of Arbitrary Code vulnerabilities and execution risks. This technology is available in our Karma Browser product and our Karma-X Commercial and Enterprise products.

Get in touch today for a demo! Getting Started

Update: 5/23/2024

Some may argue that "we can get around this by doing x or y", but it is what we haven't told them or you yet that is most interesting: Undisclosed Defenses

References:

http://files.my-hosts.com/funkywindows/exploitation/winasm-1.0.1.pdf
https://www.hick.org/code/skape/papers/win32-shellcode.pdf
https://github.com/Karma-X-Inc/Shellcode-Hash-Collisions

Update May 25, 2024:

document
Easy Install

From small business to enterprise, Karma-X installs simply and immediately adds peace of mind

shop
Integration Ready

Karma-X doesn't interfere with other software, only malware and exploits, due to its unique design.

time-alarm
Reduce Risk

Whether adversary nation or criminal actors, Karma-X significantly reduces exploitation risk of any organization

office
Updated Regularly

Update to deploy new defensive techniques to suit your organization's needs as they are offered

box-3d-50

Deploy
Karma-X

Get Karma-X!