Skip to main content

Lab 8.4: Windows Registry and Persistence

Learning Objectives​

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

  • Navigate and manipulate the Windows registry
  • Understand key security-related registry entries
  • Detect suspicious registry modifications
  • Identify persistence mechanisms via the registry

Estimated Duration​

50 minutes

Prerequisites​

  • Windows 10/11 VM
  • Administrator rights
  • Completed Lab 7.2 (persistence)

Professional Context​

The Windows registry is:

  • The central configuration database
  • A prime target for malware persistence
  • A key element to monitor in security

Part 1: Navigating the Registry​

Step 1.1: Registry Structure​

The registry is organized into hives:

HiveAliasContent
HKEY_LOCAL_MACHINEHKLMSystem configuration
HKEY_CURRENT_USERHKCUCurrent user configuration
HKEY_USERSHKUAll user profiles
HKEY_CLASSES_ROOTHKCRFile associations
HKEY_CURRENT_CONFIGHKCCCurrent hardware configuration

Step 1.2: Access via PowerShell​

# Hives are accessible like drives
Get-PSDrive -PSProvider Registry

# Navigation
Set-Location HKLM:\SOFTWARE
Get-ChildItem

# Return
Set-Location C:\

Step 1.3: Reading Values​

# Read an entire key
Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion"

# Read a specific value
(Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion").ProductName

# Value with Get-ItemPropertyValue
Get-ItemPropertyValue "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion" -Name ProductName

Step 1.4: Modifying the Registry​

# Create a key
New-Item -Path "HKCU:\Software\LabTest" -Force

# Create/modify a value
Set-ItemProperty -Path "HKCU:\Software\LabTest" -Name "TestValue" -Value "Hello World"
Set-ItemProperty -Path "HKCU:\Software\LabTest" -Name "TestNumber" -Value 42 -Type DWord

# Verify
Get-ItemProperty "HKCU:\Software\LabTest"

# Delete
Remove-ItemProperty -Path "HKCU:\Software\LabTest" -Name "TestValue"
Remove-Item -Path "HKCU:\Software\LabTest" -Recurse

Question 1: Why do we use -Type DWord for numbers?


Part 2: Important Security Keys​

Step 2.1: Run Keys (Auto-start)​

These keys automatically execute programs:

# Display all Run keys
Write-Host "=== RUN KEYS ===" -ForegroundColor Cyan

$runKeys = @(
"HKCU:\Software\Microsoft\Windows\CurrentVersion\Run",
"HKCU:\Software\Microsoft\Windows\CurrentVersion\RunOnce",
"HKLM:\Software\Microsoft\Windows\CurrentVersion\Run",
"HKLM:\Software\Microsoft\Windows\CurrentVersion\RunOnce",
"HKLM:\Software\Microsoft\Windows\CurrentVersion\RunServices",
"HKLM:\Software\Microsoft\Windows\CurrentVersion\RunServicesOnce"
)

foreach ($key in $runKeys) {
Write-Host "`n$key" -ForegroundColor Yellow
if (Test-Path $key) {
Get-ItemProperty $key | Format-List
} else {
Write-Host " (does not exist)"
}
}

Step 2.2: Service Keys​

# Registered services
Get-ChildItem "HKLM:\SYSTEM\CurrentControlSet\Services" |
Select-Object -First 10 |
ForEach-Object {
$svc = Get-ItemProperty $_.PSPath
[PSCustomObject]@{
Name = $_.PSChildName
DisplayName = $svc.DisplayName
ImagePath = $svc.ImagePath
Start = $svc.Start
}
} | Format-Table -AutoSize

Step 2.3: Security Keys​

# LSA security settings
Write-Host "=== LSA Security ===" -ForegroundColor Cyan
Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa" -ErrorAction SilentlyContinue

# RunAsPPL (LSASS protection)
$runAsPPL = Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa" -Name "RunAsPPL" -ErrorAction SilentlyContinue
if ($runAsPPL.RunAsPPL -eq 1) {
Write-Host "LSA Protection: ACTIVE" -ForegroundColor Green
} else {
Write-Host "LSA Protection: INACTIVE" -ForegroundColor Red
}

# WDigest (credentials in clear text)
Write-Host "`n=== WDigest ===" -ForegroundColor Cyan
$wdigest = Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest" -Name "UseLogonCredential" -ErrorAction SilentlyContinue
if ($wdigest.UseLogonCredential -eq 1) {
Write-Host "WDigest credentials in clear text: ACTIVE (DANGER!)" -ForegroundColor Red
} else {
Write-Host "WDigest credentials in clear text: INACTIVE" -ForegroundColor Green
}

Step 2.4: File Associations​

# Check associations (used for hijacking)
Write-Host "=== Dangerous Associations ===" -ForegroundColor Cyan

$extensions = @(".exe", ".bat", ".cmd", ".ps1", ".vbs", ".js")

foreach ($ext in $extensions) {
$assoc = (Get-ItemProperty "HKCR:\$ext" -ErrorAction SilentlyContinue).'(default)'
if ($assoc) {
$command = (Get-ItemProperty "HKCR:\$assoc\shell\open\command" -ErrorAction SilentlyContinue).'(default)'
Write-Host "$ext -> $assoc -> $command"
}
}

Part 3: Persistence Detection​

Step 3.1: Complete Detection Script​

<#
.SYNOPSIS
Detection of persistence mechanisms via registry
#>

Write-Host @"
==============================================
REGISTRY PERSISTENCE DETECTION
==============================================
"@ -ForegroundColor Cyan

$findings = @()

# 1. Run Keys
$runKeys = @(
"HKCU:\Software\Microsoft\Windows\CurrentVersion\Run",
"HKCU:\Software\Microsoft\Windows\CurrentVersion\RunOnce",
"HKLM:\Software\Microsoft\Windows\CurrentVersion\Run",
"HKLM:\Software\Microsoft\Windows\CurrentVersion\RunOnce"
)

Write-Host "`n[1/5] Analyzing Run keys..." -ForegroundColor Yellow

foreach ($key in $runKeys) {
if (Test-Path $key) {
$props = Get-ItemProperty $key -ErrorAction SilentlyContinue
$props.PSObject.Properties | Where-Object {
$_.Name -notmatch "^PS"
} | ForEach-Object {
$value = $_.Value

# Suspicion criteria
$suspicious = $false
$reasons = @()

if ($value -match "\\Temp\\|\\AppData\\Local\\Temp") {
$suspicious = $true
$reasons += "Temp Path"
}
if ($value -match "-[Ee]ncoded|-[Ww]indowStyle\s+[Hh]idden") {
$suspicious = $true
$reasons += "Suspicious arguments"
}
if ($value -match "powershell.*-[Cc]ommand") {
$suspicious = $true
$reasons += "PowerShell inline"
}

$findings += [PSCustomObject]@{
Type = "Run Key"
Location = $key
Name = $_.Name
Value = $value.Substring(0, [Math]::Min(80, $value.Length))
Suspicious = $suspicious
Reasons = ($reasons -join ", ")
}
}
}
}

# 2. Services in suspicious paths
Write-Host "[2/5] Analyzing services..." -ForegroundColor Yellow

Get-ChildItem "HKLM:\SYSTEM\CurrentControlSet\Services" -ErrorAction SilentlyContinue | ForEach-Object {
$svc = Get-ItemProperty $_.PSPath -ErrorAction SilentlyContinue
if ($svc.ImagePath -match "\\Temp\\|\\AppData\\|\\Downloads\\") {
$findings += [PSCustomObject]@{
Type = "Service"
Location = $_.PSPath
Name = $_.PSChildName
Value = $svc.ImagePath
Suspicious = $true
Reasons = "Suspicious path"
}
}
}

# 3. Shell Extensions
Write-Host "[3/5] Analyzing Shell Extensions..." -ForegroundColor Yellow

$shellExt = @(
"HKCU:\Software\Classes\*\shellex\ContextMenuHandlers",
"HKLM:\Software\Classes\*\shellex\ContextMenuHandlers"
)

foreach ($key in $shellExt) {
if (Test-Path $key) {
Get-ChildItem $key -ErrorAction SilentlyContinue | ForEach-Object {
$handler = Get-ItemProperty $_.PSPath -ErrorAction SilentlyContinue
$clsid = $handler.'(default)'

if ($clsid -and $clsid -match "^\{") {
# Check if the CLSID exists
$clsidPath = "HKCR:\CLSID\$clsid"
if (-not (Test-Path $clsidPath)) {
$findings += [PSCustomObject]@{
Type = "Shell Extension"
Location = $_.PSPath
Name = $_.PSChildName
Value = $clsid
Suspicious = $true
Reasons = "Missing CLSID"
}
}
}
}
}
}

# 4. AppInit_DLLs
Write-Host "[4/5] Checking AppInit_DLLs..." -ForegroundColor Yellow

$appInit = Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows" -Name "AppInit_DLLs" -ErrorAction SilentlyContinue
if ($appInit.AppInit_DLLs) {
$findings += [PSCustomObject]@{
Type = "AppInit_DLLs"
Location = "HKLM:\...\Windows"
Name = "AppInit_DLLs"
Value = $appInit.AppInit_DLLs
Suspicious = $true
Reasons = "Startup DLL injection"
}
}

# 5. Image File Execution Options (Debugger)
Write-Host "[5/5] Checking IFEO..." -ForegroundColor Yellow

Get-ChildItem "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options" -ErrorAction SilentlyContinue | ForEach-Object {
$ifeo = Get-ItemProperty $_.PSPath -ErrorAction SilentlyContinue
if ($ifeo.Debugger) {
$findings += [PSCustomObject]@{
Type = "IFEO Debugger"
Location = $_.PSPath
Name = $_.PSChildName
Value = $ifeo.Debugger
Suspicious = $true
Reasons = "Debugger set"
}
}
}

# Report
Write-Host "`n==============================================`n" -ForegroundColor Cyan

$suspiciousFindings = $findings | Where-Object { $_.Suspicious }

if ($suspiciousFindings.Count -eq 0) {
Write-Host "[OK] No suspicious persistence detected" -ForegroundColor Green
} else {
Write-Host "[!] $($suspiciousFindings.Count) suspicious element(s) detected:" -ForegroundColor Red
$suspiciousFindings | Format-Table Type, Name, Reasons -AutoSize

Write-Host "`nDetails:" -ForegroundColor Yellow
$suspiciousFindings | ForEach-Object {
Write-Host "`n Type: $($_.Type)" -ForegroundColor Cyan
Write-Host " Name: $($_.Name)"
Write-Host " Value: $($_.Value)"
Write-Host " Reasons: $($_.Reasons)" -ForegroundColor Yellow
}
}

# Summary of normal entries
Write-Host "`n==============================================`n" -ForegroundColor Cyan
$normalFindings = $findings | Where-Object { -not $_.Suspicious }
Write-Host "Normal entries detected: $($normalFindings.Count)"

Question 2: Did the script detect any suspicious elements on your VM?


Part 4: Practical Exercise​

Step 4.1: Create a Test Persistence​

# WARNING: For testing purposes only!
# Create a Run entry to understand the mechanism

# Create a harmless entry
Set-ItemProperty `
-Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Run" `
-Name "LabTestPersistence" `
-Value "cmd.exe /c echo Test persistence > C:\Temp\persistence_test.txt"

Write-Host "Test entry created" -ForegroundColor Yellow

Step 4.2: Detect Persistence​

# Run the detection script
# Your entry should be detected

# Verify manually
Get-ItemProperty "HKCU:\Software\Microsoft\Windows\CurrentVersion\Run" | Select-Object LabTestPersistence

Step 4.3: Clean Up​

# Remove the test entry
Remove-ItemProperty `
-Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Run" `
-Name "LabTestPersistence" `
-ErrorAction SilentlyContinue

Write-Host "Cleanup completed" -ForegroundColor Green

Part 5: Backup and Restore​

Step 5.1: Export a Key​

# Export a key
$exportPath = "$env:USERPROFILE\Desktop\backup_run_keys.reg"
reg export "HKCU\Software\Microsoft\Windows\CurrentVersion\Run" $exportPath /y

Write-Host "Key exported to: $exportPath" -ForegroundColor Green

Step 5.2: Automatic Backup Script​

# Backup important security keys
$backupFolder = "$env:USERPROFILE\Desktop\RegistryBackup_$(Get-Date -Format 'yyyyMMdd')"
New-Item -Path $backupFolder -ItemType Directory -Force | Out-Null

$keysToBackup = @(
@{Path = "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run"; Name = "HKLM_Run"},
@{Path = "HKCU\Software\Microsoft\Windows\CurrentVersion\Run"; Name = "HKCU_Run"},
@{Path = "HKLM\SYSTEM\CurrentControlSet\Control\Lsa"; Name = "LSA"},
@{Path = "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows"; Name = "Windows"}
)

foreach ($key in $keysToBackup) {
$file = Join-Path $backupFolder "$($key.Name).reg"
reg export $key.Path $file /y 2>$null
if ($?) {
Write-Host "[OK] $($key.Name)" -ForegroundColor Green
} else {
Write-Host "[ERROR] $($key.Name)" -ForegroundColor Red
}
}

Write-Host "`nBackup completed: $backupFolder" -ForegroundColor Cyan

Deliverables​

  1. Answers to the 2 questions

  2. Screenshots:

    • Registry navigation
    • Detection script executed
    • Test persistence created and detected
  3. Customized detection script

  4. Report (1 page):

    • Important registry keys
    • Identified risks
    • Monitoring recommendations

Evaluation Criteria​

CriteriaPoints
Registry navigation20%
Security keys25%
Detection script35%
Practical exercise20%

Reference Commands​

# Reading
Get-ItemProperty "HKLM:\path"
Get-ItemPropertyValue "HKLM:\path" -Name "value"

# Writing
Set-ItemProperty -Path "path" -Name "name" -Value "value"
New-Item -Path "path" -Force

# Deletion
Remove-ItemProperty -Path "path" -Name "name"
Remove-Item -Path "path" -Recurse

# Export (via reg.exe)
reg export "HKLM\path" file.reg /y
reg import file.reg

Resources​


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