Skip to content

Instantly share code, notes, and snippets.

@Purp1eW0lf
Last active April 6, 2023 22:17
Show Gist options
  • Save Purp1eW0lf/6bbb2c1e22fe64a151d7ab97be8e83bb to your computer and use it in GitHub Desktop.
Save Purp1eW0lf/6bbb2c1e22fe64a151d7ab97be8e83bb to your computer and use it in GitHub Desktop.
<#
Meta
Date: 2023 January 7th
Authors: Harlan Carvey (Twitter @keydet89) and Dray Agha (Twitter @purp1ew0lf)
Company: Huntress Labs
Purpose: Automate collecting Windows Registry hives, including related .DATs for all users.
Notes:
Will trigger AV as it's technically credential dumping.
Also relies on having internet access, to wget TSCopy
Kudos for TrustedSec's TScopy.exe tool, which this script leverages: https://github.com/trustedsec/tscopy
#>
# check admin
function admin_check{
if (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole(`
[Security.Principal.WindowsBuiltInRole] "Administrator")) {
Write-Warning "Insufficient permissions. Run this Powershell script as Admin please"
Break
}
# if we're all good, let's fire it off
else {Collect_via_Reg}
}
# Collect basic hives
function Collect_via_Reg{
#print to re-assure user things are happening until ZIP
write-host "`n`nHuntress "-NoNewline -ForegroundColor green ; write-host "Registry collection script is running...`n`n";
#Ensure errors don't ruin anything for us
$ErrorActionPreference = "SilentlyContinue"
$progressPreference = 'silentlyContinue'
# Make the various directories, to be neat and tidy
mkdir c:\ir, C:\ir\Collected_ntuser_files, C:\ir\Collected_UsrClass_files, C:\ir\amcache
# save the registry files
reg save HKLM\Software c:\ir\Software
reg save HKLM\System c:\ir\System
reg save HKLM\SECURITY c:\ir\SECURITY
reg save HKLM\SAM C:\ir\SAM
#Next Stage
Collect_via_TSCopy
}
## TSCopy for further registry hives
function Collect_via_TSCopy{
# pull TScropy exe this way, because invoke-webrequests progress bar is slow and I am a bad scripter
(New-Object Net.WebClient).DownloadFile("https://github.com/trustedsec/tscopy/raw/master/dist/TScopy_x64.exe", "C:\ir\TScopy_x64.exe");
# each user's ntuser.dat
C:\ir\TScopy_x64.exe -f c:\users\*\ntuser.dat* -o C:\ir\Collected_ntuser_files
# each user's usrclass.dat
C:\ir\TScopy_x64.exe -f C:\Users\*\AppData\Local\Microsoft\Windows\UsrClass.dat* -o C:\ir\Collected_UsrClass_files
# collect amcache hive
C:\ir\TScopy_x64.exe -f C:\Windows\AppCompat\Programs\Amcache.hve -o C:\ir\amcache
# Next stage
Zip_Collected
}
# zip it all up
function Zip_Collected{
#Delete excess files
rm C:\IR\TScopy_x64.exe
#Tree for a directory map
tree C:\IR /f >> C:\IR\tree_output.txt
# Get current user's desktop to save zip to.
$DesktopPath = [Environment]::GetFolderPath("Desktop")
Get-ChildItem -Path C:\ir | Compress-Archive -DestinationPath $DesktopPath\Registry_Collection_$(Get-Date -UFormat "%Y_%b_%d_%a_UTC%Z").zip
write-host "`n`nYour ZIP is waiting at: "-NoNewline; write-host "$DesktopPath\Registry_Collection_$(Get-Date -UFormat "%Y_%b_%d_%a_UTC%Z").zip`n`n" -ForegroundColor green ;
# Clean up C:\IR on host after ZIP
Remove-Item "C:\IR" -Recurse -force
# Open up dir
sleep 2; ii "$DesktopPath\Registry_Collection_$(Get-Date -UFormat "%Y_%b_%d_%a_UTC%Z").zip"
}
#Execute main function in silence
Admin_Check | out-null
@Purp1eW0lf
Copy link
Author

Purp1eW0lf commented Dec 30, 2022

Download and run:

# Download
(New-Object Net.WebClient).DownloadFile("https://gist.githubusercontent.com/Purp1eW0lf/6bbb2c1e22fe64a151d7ab97be8e83bb/raw/e062d923ab6dd60f8cb5e8de1c8c249a704792d6/Registry_Collect.ps1", "C:\Registry_Collect.ps1")

# Execute as Admin in PowerShell prompt
./Registry_Collect.ps1

image

@JohnHammond
Copy link

JohnHammond commented Jan 11, 2023

Per SC-72825, here is a revision of this script, with just small quality-of-life improvements.

You can remove the need for the Administrator check with the #Requires -RunAsAdministrator tag in modern versions of PowerShell. I've added the traditional "command-line help" docstrings, added some extra color and verbose output (default, but it can be silenced) alongside customizable parameters, so if a support member is helping a partner, they could be suggested to run with other locations or registry hives to pull. This does still download TSCopyx64.exe. I'm also thinking what else we could do to avoid that (embed the file? It's 4 MB... rewrite TSCopy in PowerShell..?) but I figure these enhancements are worth sharing in the interim.

<#
.SYNOPSIS
    Rapid incident response collection script.

.DESCRIPTION
    Automate collecting Windows Registry hives, including related .DATs for all users. 

.EXAMPLE
    ./Registry_Collect.ps1

.EXAMPLE
    ./Registry_Collect.ps1 -CollectionDir "C:\CollectedData" -ExportRegHives @("HKLM\SAM", "HKLM\SYSTEM") -$CollectionGlobs @("C:\Windows\AppCompat\Programs\Amcache.hve") -Quiet

.NOTES
    File Name: Registry_Collect.ps1
    Author: Huntress Labs, Harlan Carvey (@keydet89), Dray Agha (@purp1ew0lf)
    Date: 2023 January 7th
    Requires: PowerShell 4.0+

    This script requires administrator privileges to run. Execution will likely trigger antivirus 
    as this code does perform credential dumping techniques.
#>

#Requires -RunAsAdministrator

param (
    [string[]]$ExportRegHives = @( 
        "HKLM\SOFTWARE", 
        "HKLM\System", 
        "HKLM\SECURITY", 
        "HKLM\SAM"
        ),

    [string[]]$CollectionGlobs = @( 
        "C:\Users\*\NTUser.dat*", 
        "C:\Users\*\AppData\Local\Microsoft\Windows\UsrClass.dat*", 
        "C:\Windows\AppCompat\Programs\Amcache.hve"
     ),

    [string]$CollectionDir="$env:SystemDrive\IR",

    [switch]$Quiet
)

function Status-Update([string] $message, [switch]$NoNewLine){
    if ($Quiet) {
    return 
    }
    Write-Host "[*] "-NoNewline -ForegroundColor Blue;
    
    $color_index=0;
    $message -Split "'" | ForEach {
    if ($color_index % 2 -ne 0){
        Write-Host "`'$_`'" -NoNewline -ForegroundColor Yellow
    }else{
        Write-Host $_ -NoNewline
    }
    $color_index++

    }
    Write-Host ""

}

Write-Host "Huntress "-NoNewline -ForegroundColor Cyan
Write-Host "IR collection script v0.1.0"

New-Item $CollectionDir -ItemType Directory -Force | Out-Null

# Collect registry hives
ForEach ($regHive in $ExportRegHives ){
    $HiveName=$($regHive -Split "\\")[-1]

    Status-Update "exporting registry hive '$regHive'"
    & $env:SystemRoot\System32\reg.exe save $regHive ${CollectionDir}\$HiveName /Y | Out-Null
}

# Download TSCopy
$TSCopyx64URL = "https://github.com/trustedsec/tscopy/raw/master/dist/TScopy_x64.exe"
$TSCopyx64Localfile= [System.IO.Path]::GetTempPath() + "TScopy_x64.exe"

Status-Update "downloading TSCopy to '$TSCopyx64Localfile'... " -NoNewLine
$Global:ProgressPreference = 'silentlyContinue'
Invoke-WebRequest $TSCopyx64URL -OutFile $TSCopyx64Localfile

# Collect given files
ForEach ($collectPath in $CollectionGlobs ){
    $folderName=($collectPath).Split("\\")[-1].Split(".")[0].Replace("*","")
    $outputDir="${CollectionDir}\Collected_${folderName}_Files"

    New-Item $outputDir -ItemType Directory -Force | Out-Null
    Status-Update "collecting '$collectPath'"
    & $TSCopyx64Localfile -f $collectPath -o $outputDir | Out-Null
}
    
& $env:SystemRoot\System32\tree.com $CollectionDir /f | Out-File "$CollectionDir\tree_output.txt"

$DesktopPath = [Environment]::GetFolderPath("Desktop")
$ZIPLocation = "$DesktopPath\Registry_Collection_$(Get-Date -UFormat "%Y_%b_%d_%a_UTC%Z").zip"    

Status-Update "zipping up all collected files..."
Get-ChildItem -Path $CollectionDir | Compress-Archive -DestinationPath $ZIPLocation -Force
    
# Clean up the collection directory.
Remove-Item $CollectionDir -Recurse -force
Status-Update "removing '$TSCopyx64Localfile'"
Remove-Item $TSCopyx64Localfile

Write-Host "[+] success! collection saved at: `n$ZIPLocation" -ForegroundColor Green

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment