Skip to content

WordPress Malware Research Entry

XOR-Decoding Temporary-File Loader in wp-config.php

Found XOR-obfuscated PHP at the top of wp-config.php? Review a temporary-file loader pattern and why the site may still look normal.

Reviewed: July 22, 2026
Artifact class Request-gated PHP loader
Evidence confidence High
Risk assessment High

Start with the problem you are seeing

Could this match the problem on your WordPress site?

This entry is relevant when wp-config.php contains unreadable PHP before the normal WordPress configuration. The supplied code decoded data, wrote a temporary PHP file, included it, and attempted cleanup; the decoded payload was not retained.

Observed in this investigation

  • The supplied wp-config.php modification used XOR-style decoding and a write-include-delete temporary-file sequence.

Possible warning signs

  • The site may continue to load normally while the injected block runs before WordPress initialization.
  • A scanner may repeatedly flag wp-config.php even when the temporary file is no longer present.

These signs are investigation leads, not proof of this artifact by themselves.

Questions this research can help answer

  • Why is there XOR-obfuscated PHP in wp-config.php?
  • Can a temporary PHP loader delete its dropped file after inclusion?

Evidence boundary: The loader sequence is confirmed; the decoded payload, execution trace, and original entry point are unavailable.

Seeing one of these signs on your site?

I can investigate the files, database records, users, and server evidence, explain what is confirmed, and help plan a safe cleanup.

Research focus: Forensic analysis of a wp-config.php loader that hex-decodes request data, applies single-byte XOR, and includes a temporary .desc file.

Summary

This entry examines a compact PHP loader observed before the normal configuration statements in wp-config.php. The supplied code checks for an obfuscated request key that resolves to mrk, hex-decodes the associated value, applies a byte-wise XOR transformation, and searches several temporary directories for a writable location.

When a write succeeds, the code includes a file named .desc, attempts to delete it, and exits. The evidence directly supports that control flow. It does not include a triggering request or payload and therefore does not establish what code, if any, executed during the investigated incident.

Investigation context

The artifact was retained during one anonymized WordPress client investigation. The screenshot shows the entire injected line at the top of wp-config.php, immediately before a normal WP_CACHE definition and the standard WordPress configuration comments.

The broad obfuscated PHP malware guide explains how to inspect encoded PHP safely. This research entry focuses on one distinctive request-to-temporary-file flow and does not reproduce a working handler.

Observed artifact in wp-config.php

The screenshot confirms the location and overall structure: request-key check, hex2bin(), an XOR loop, an array of candidate temporary directories, a write to .desc, include, and cleanup with unlink().

wp-config.php editor showing a compact request-gated XOR loader before normal WordPress configuration
The injected first line reads a request value, transforms it, and tries writable temporary directories before normal wp-config.php content begins.

Confirmed findings

  • The injected code was located before the normal WordPress configuration body.
  • It checks the request collection for the string represented as mr\x6B, which resolves to mrk.
  • It passes the supplied value through hex2bin().
  • It transforms the decoded bytes with a repeated XOR operation using decimal 66.
  • It enumerates environment, session, upload, working, and system temporary-directory candidates.
  • On a successful write, it includes .desc, attempts to unlink the file, and exits.

Technical analysis of the XOR temporary-file loader

The sample separates transport from execution. Request data is not included directly. It is first converted from hexadecimal text into bytes and then transformed one byte at a time. The result is assigned to a buffer that the code attempts to write to a hidden-looking filename in the first usable temporary location.

Defensive control-flow summary

Redacted defensive excerpt

if a distinctive request marker is present:
    bytes = hex_decode(the supplied value)
    transformed = apply_a_fixed_single_byte_xor(bytes)

    for each candidate temporary directory:
        if the directory is writable:
            write transformed bytes to a hidden .desc file
            include that temporary file
            attempt to delete it
            stop processing

The public excerpt deliberately omits runnable PHP, the complete request handler, and an operational payload format. The exact static tokens remain listed as defensive indicators.

Disk activity and cleanup

The previous draft said the loader avoided direct disk alteration. That was inaccurate. The supplied code explicitly calls file_put_contents() before include. The later unlink() attempt may shorten the file’s lifetime, but it does not mean no file was created, and deletion is not guaranteed to succeed.

Analyst assessment

The request gate, reversible transformation, transient write, include, and delete sequence are consistent with a loader intended to execute a supplied PHP stage while reducing how long that stage remains on disk. That intent is an analyst assessment based on the visible code structure. Actual payload execution would require evidence of a triggering request and a successful write/include path, neither of which is retained here.

Indicators of compromise

Higher-confidence indicators

  • Request-key representation: mr\x6B
  • Hidden temporary filename: .desc
  • hex2bin() followed by a byte-wise XOR using decimal 66
  • The sequence of candidate-directory search, write, include, unlink, and exit
  • This compact sequence placed before normal wp-config.php content

Contextual indicators

  • Modified wp-config.php
  • $_REQUEST
  • file_put_contents()
  • include
  • unlink()
  • References to /tmp, /var/tmp, /dev/shm, or sys_get_temp_dir()

Those filenames, variables, functions, and directories have legitimate uses. They become meaningful when they occur in the distinctive combined flow.

What this evidence does not establish

  • No triggering HTTP request was retained.
  • No transformed payload is published or analyzed here.
  • The screenshot does not prove that a temporary write, include, or delete succeeded.
  • The initial compromise method was not confirmed.
  • No vulnerable plugin, theme, core version, or server component was identified.
  • The evidence does not establish attribution, prevalence, duration, or client outcome.

Artifact-specific remediation

Preserve the affected wp-config.php, relevant timestamps, and access logs before replacement when investigation history matters. Compare the file with a known-good configuration, remove the confirmed injected line, and preserve legitimate salts and configuration values during restoration.

Search the account for the distinctive marker and full transformation/write/include structure. Inspect temporary directories and other bootstrap files, review administrator and hosting access, and rotate credentials appropriate to the confirmed exposure scope. For full incident response, use the WordPress malware removal guide.

Recurrence verification

  • Recompare wp-config.php after normal requests and scheduled tasks.
  • Repeat the structural search across PHP files and writable temporary locations.
  • Review access logs for suspicious requests to the site entry points; do not replay a suspected payload.
  • Monitor file creation for .desc in relevant temporary directories where operationally safe.
  • Confirm that the injected line does not return after deployments or administrator logins.

Methodology and privacy note

This page is based on one privacy-reviewed screenshot and supplied PHP source from an anonymized investigation. The code was reviewed statically and was not executed. The complete request handler and any payload remain outside the public page; the excerpt is an inert defensive summary. Confirmed code operations are separated from the unobserved runtime outcome.