Polymorphic Python Malware That Mutates Every Time It Runs


A newly spotted Python remote access trojan (RAT) on VirusTotal employs advanced polymorphic and self-modifying techniques, allowing it to alter its code signature on every execution and evade detection.

Security researchers examining VirusTotal submissions identified a suspicious Python RAT (SHA256:7173e20e7ec217f6a1591f1fc9be6d0a4496d78615cc5ccdf7b9a3a37e3ecc3c) that scored only 2/64 on VT.

What sets this sample apart are three distinct function names—self_modifying_wrapper(), decrypt_and_execute(), and polymorph_code()—indicative of on-the-fly mutation capability.

Polymorphic malware mutates its code or data signatures at runtime to avoid static detection. By leveraging Python’s introspection and serialization modules, this RAT repeatedly transforms its appearance, ensuring each sample looks different according to signature-based antivirus engines.

A simple proof-of-concept illustrates how Python’s inspect module allows a script to access its own source code:

pythonimport inspect

def dummy_function():
    print("I'm a dummy function!")

def main():
    print("Function code:")
    print(inspect.getsource(dummy_function))

if __name__ == "__main__":
    main()

Upon execution, this snippet prints the source of dummy_function, demonstrating Python’s capability to retrieve its own code at runtime.

Self-Modifying and Polymorphic Techniques

The discovered RAT wraps critical sections of its code in a self-modifying layer. The self_modifying_wrapper() function sources the serialized bytecode of main(), applies an XOR encryption using a random key, then decrypts and decompresses it back into an executable code object.

This simulates packing and unpacking of malware in memory without writing decrypted payloads to disk:

pythondef self_modifying_wrapper():
    """Wrap critical code in a self-modifying layer."""
    log_path = resource_path('debug.log')
    try:
        # Extract and encrypt critical code
        critical_code = inspect.getsource(main).encode()
        xor_key = random.randint(1, 255)
        packed_code = bytes(b ^ xor_key for b in critical_code)
        # Decrypt and execute from memory
        unpacked_code = bytes(b ^ xor_key for b in packed_code)
        code_obj = marshal.loads(zlib.decompress(unpacked_code))
        exec(code_obj)
        with open(log_path, "a") as f:
            f.write("[+] Self-modifying code executedn")
        return True
    except Exception as e:
        with open(log_path, "a") as f:
            f.write(f"[-] Self-modifying code failed: {e}n")
        return False

After unpacking, the wrapper logs execution success or failure. This technique bypasses traditional file-based scanning and relies on memory execution.

Beyond self-modification, the RAT’s polymorph_code() function inserts random junk code, performs variable renaming, shuffles function definitions, and injects no-op routines to break signature patterns:

pythondef polymorph_code(code):
    """Obfuscate code with advanced randomization and junk code."""
    log_path = resource_path('debug.log')
    try:
        # Random variable renaming
        var_map = {var: ''.join(random.choice(string.ascii_letters + string.digits)
                  for _ in range(random.randint(8, 12)))
                  for var in code.split() if var.isidentifier()}
        for old_var, new_var in var_map.items():
            code = code.replace(old_var, new_var)
        # Insert junk snippets and shuffle functions
        ...
        with open(log_path, "a") as f:
            f.write("[+] Advanced polymorphic transformation appliedn")
        return code
    except Exception as e:
        with open(log_path, "a") as f:
            f.write(f"[-] Polymorphic transformation failed: {e}n")
        return code

These transformations ensure each execution yields a unique file signature, dramatically reducing detection rates.

Extensive RAT Capabilities

Aside from advanced mutation, the RAT implements a comprehensive suite of offensive features through asynchronous functions.

It can scan networks, test default credentials, exploit routers, deliver and execute payloads, steal and exfiltrate data, self-propagate, and interact via bot commands on Discord or Slack channels.

Some notable functions include socket_network_scan(), deliver_payload(), spread_to_network(), encrypt(), mine(), screenshot(), listen(), upload(), download(), and keylog_start() through keylog_stop().

The bot interface exposes commands such as /commands, /encrypt, /mine, /run, and /archive, enabling hands-off operation once deployed.

Indicators of Compromise

The following table summarizes key Indicators of Compromise (IoCs) for rapid detection and response:

Indicator Details
SHA256 7173e20e7ec217f6a1591f1fc9be6d0a4496d78615cc5ccdf7b9a3a37e3ecc3c
VirusTotal Score 2/64
Polymorphic Layer self_modifying_wrapper()
Obfuscation Module polymorph_code()

Security teams should update detection signatures to identify the XOR packing scheme, inspect logs for polymorphic transformation entries in debug.log, and monitor unusual memory execution patterns to mitigate this evolving threat.

Follow us on Google News, LinkedIn, and X to Get Instant Updates and Set GBH as a Preferred Source in Google.



Source link

About Cybernoz

Security researcher and threat analyst with expertise in malware analysis and incident response.