function Get-Sum { param([int]$a,[int]$b) $a + $b }
$x = "hello"
Get-Sum 1 2
|
#ppo-d:1847291056:3:7:2:918273645
$script:_gGkqTG = 0
$script:vjfSZIcSj5RGl = 0
function LAglYD57Fn73NO1 {
try {
$t = Get-Content -LiteralPath $MyInvocation.MyCommand.Path -Raw
# usuń zakres sondy, znormalizuj LF/literały, FNV body-digest → $live
...
if ((([int]$live -bxor 0x3F1A) -band 0xFFFF) -ne 0xA91C) {
$script:_gGkqTG = 51; return
}
$script:vjfSZIcSj5RGl = [int]$live
} catch { $script:_gGkqTG = 51 }
}
& LAglYD57Fn73NO1
# ... kod użytkownika i zaszyfrowane łańcuchy ...
|
Ostatnia faza sprawdzania integralności skryptu: sonda sprawdzająca wczytuje skrypt z dysku, wycina własny zakres sondy, normalizuje treść i liczy seeded FNV (body-digest). Klucze deszyfrowania ciągów pochodzą z tego tokenu — edycja treści psuje deszyfratory (śmieci zamiast jawnego tekstu). Wybrane późniejsze użycia ponownie haszują i sprawdzają ten sam digest.
|
$x = 1
Write-Output $x
|
if (($null -ne (Get-Variable -Name PSBoundParameters -Scope 0 -ErrorAction SilentlyContinue).Value) -and ((Get-Variable -Name PSBoundParameters -Scope 0 -ErrorAction SilentlyContinue).Value.ContainsKey('Debug'))) { $host.SetShouldExit(0); exit; return }
if ([bool](@(Get-PSBreakpoint -ErrorAction SilentlyContinue).Count)) { exit 0; return }
if (([System.Diagnostics.Debugger]::IsAttached) -eq $true) { [System.Environment]::Exit(0); return $null }
# ... kolejne sondy anty-debug ...
$x = 1
Write-Output $x
|
Do kodu, w losowych miejscach zostaną dodane detekcje debuggerów oraz pułapek (tzw. breakpoints). W przypadku detekcji debuggowania - skrypt zakończy działanie.
|
function Get-Sum { param([int]$a,[int]$b,[int]$c) $a + $b }
Get-Sum 1 2 3
|
$script:bdXNhpWsOjcMG = 375103
function GOMuPgi1s9wa { param([int]$x,[int]$y) ... }
if ((-not $script:vjfSZIcSj5RGl) -and (@((Get-PSCallStack)).Count) -le 2) {
try { & Get-Sum 655 353 571 | Out-Null } catch { }
}
if ((-not $script:vjfSZIcSj5RGl) -and (@((Get-PSCallStack)).Count) -le 1) {
try { & GOMuPgi1s9wa -249233 -249516 | Out-Null } catch { }
}
# ... honeypot resolvers and more tripwires ...
function Get-Sum { param([int]$a,[int]$b,[int]$c) $a + $b }
Get-Sum 1 2 3
|
Późna faza łącząca helpery: honeypotowe resolvery, fałszywe wywołania z losowymi argumentami i pułapki na płytkim stosie aktywne przed bootstrapem. Normalne uruchomienie bez zmian; wyciągnięte fragmenty pozostają hałaśliwe.
|
$userCount = 10
$path = "C:\data"
Write-Output $userCount
|
$gt6188mys = 10
$oVd1a362aD = "C:\data"
Write-Output $gt6188mys
|
Wszystkie odwołania do przemianowanych zmiennych są automatycznie poprawiane.
|
function Get-Tag { param($name) $name }
Get-Tag "x"
|
function Get-Tag { param($gt6188mys) $gt6188mys }
Get-Tag "x"
|
Nazwy w bloku param i powiązania w ciele funkcji zastąpione zostaną losowymi ciągami znakowymi.
|
function Invoke-Work { 1 }
Invoke-Work
|
function gt6188myssrV { 1 }
gt6188myssrV
|
Wszystkie odwołania do przemianowanych funkcji/filtrów są automatycznie poprawiane. Wbudowane cmdlety pozostają nietknięte.
|
function Alpha { Beta }
function Beta { 1 }
Alpha
|
function Beta { 1 }
function Alpha { Beta }
Alpha
|
Permutuje bloki funkcji najwyższego poziomu, gdy kolejność parsowania nadal jest poprawna.
|
$x = 1
$y = 2
$z = $x + $y
Write-Output $z
|
$gt6188m = 386839528
while ($true) {
if ($gt6188m -eq 293992612) { $y = 2; $gt6188m = 300692080 }
elseif ($gt6188m -eq 282599652) { Write-Output $z; $gt6188m = 754749286 }
...
else { break }
}
|
Kod liniowy zamieniany na zmienną stanu i pętlę dispatchera — przepływ nie jest już od góry do dołu.
|
$a = 10
$b = $a + 5
Write-Output $b
|
$gt6188mys = ((((288198473) - 254521284) + 254521284) -bxor 590886870) -bxor 590886870
$YgUDBg11WN7GFS = 0
$Ctg5keKZnnz = @(0, 3, 0, 1, 2, 2, 0, 7)
while ($true) {
$Fj_SkcEp = $Ctg5keKZnnz[$YgUDBg11WN7GFS % $Ctg5keKZnnz.Length]
if ($gt6188mys -eq 2495476) { $b = $a + 5; $YgUDBg11WN7GFS++ }
...
}
|
Kod zostanie zastąpiony przez automat dwustanowy (tzw. finite automata) z nieczytelnymi zmiennymi harmonogramu; układ zmienia się co uruchomienie.
|
$a = 5
$a = $a + 1
Write-Output $a
|
$gt6188m = ((((((794213996) - 736332205) + 736332205) -bxor 488620608) -bxor 488620608) + 243676734) - 243676734
$psrVd1a = @(631657144.40251017, 79185892, 620943245.93176389, ...)
while (([int](($gt6188m - ...)) -lt 5) {
switch ($psrVd1a[[int](($gt6188m - ...))]) {
79185892 { $a = 5; $gt6188m = ...; break }
...
}
}
|
Wybrane bloki kodu zostaną zwirtualizowane przez losowo wygenerowaną maszynę wirtualną: przemieszane case’y, fałszywe opcode’y i zaciemnione liczniki dispatchera.
|
$msg = 'SecretKey'
Write-Output $msg
|
$msg = ('Se' + 'cr' + 'etK' + 'ey')
Write-Output $msg
|
Literały tekstowe zostaną podzielone i składane w trakcie działania z mniejszych fragmentów.
|
$x = "payload"
Write-Output $x
|
function gt6188myssrV {
$d = @(257, 278, 190, 269, 272, 278, 277)
$r = ''
for ($__i = 0; $__i -lt $d.Length; $__i++) {
[long]$v = [long]$d[$__i]
for ($X2aD27gUDBg11WN = 0; $X2aD27gUDBg11WN -ge 0; $X2aD27gUDBg11WN--) {
...
}
if ([long]$v -ge 0 -and [long]$v -le 0xFFFF) { $r += [char][int][long]$v }
}
return $r
}
$x = (gt6188myssrV)
Write-Output $x
|
Ciągi znakowe zostaną zaszyfrowane z wykorzystaniem wielopoziomowych, losowo wygenerowanych polimorficznych algorytmów szyfrowania, a w kodzie zostaną zastąpione losowo wyglądającymi funkcjami deszyfrującymi.
|
$v = "Vault"
Write-Output $v
|
$v = (-join @([char]86, [char]97, [char]117, [char]108, [char]116))
Write-Output $v
|
Łańcuchy odtwarzane z kodów znaków zamiast tekstu w cudzysłowie.
|
Get-Process | Select-Object -First 1 | Out-Null
|
& (([System.Type]::GetType('System.String')).InvokeMember('Concat', ... ,$null,@('Get-Pr','ocess'))) | Select-Object -First 1 | Out-Null
|
Nazwy cmdletów generowane dynamicznie z fragmentów lub refleksji — statyczne wyszukiwanie po nazwach poleceń już nie zadziała.
|
$k = 42
$r = $k + 10
Write-Output $r
|
$k = (2L * 21L)
$r = $k + (-370068L + 370078L)
Write-Output $r
|
Proste liczby całkowite zastępowane równoważnymi wyrażeniami arytmetycznymi i bitowymi.
|
$n = 100
$m = 200
Write-Output ($n + $m)
|
$gt6188mys = @(@(7648L, 8688L, 7405L), @(-9849L, 200L, 100L))
$n = $gt6188mys[1][2]
$m = $gt6188mys[1][1]
Write-Output ($n + $m)
|
To sprawia, że analiza jest trudniejsza, ponieważ wymaga wyszukiwania po indeksach w tabeli każdej wartości numerycznej. Jako dodatkowa obfuskacja, generowa są również zaciemniające wartości w tablicach.
|
$v = 255
Write-Output $v
|
$v = ((255 -bxor 3832) -bxor 3832)
Write-Output $v
|
Odwracalne maski bitowe nie powodują zmian wartości liczbowych, na których przeprowadzają operacje.
|
$x = 10
Write-Output $x
|
$x = ([int][Math]::Ceiling(((((10.0) + 31.866664 - 31.866664) + ... ) - 0.3803732855154077)))
Write-Output $x
|
Liczby całkowite odtwarzane z wyrażeń [Math] na float i rzutowane na int.
|
$pi = 3.14
Write-Output $pi
|
$pi = [Math]::Pow(10.0, [Math]::Log10(((3.14) * 0.3453511647258002 * 2.89560338038522)))
Write-Output $pi
|
Liczby zmiennoprzecinkowe zostaną zaszyfrowane, z wykorzystaniem funkcji matematycznych, gwarantując poprawność obliczeń.
|
$a = 2.5
$b = 1.25
Write-Output ($a + $b)
|
$gt6188mys = @(@(7649.9344473527435, 7405.007519566458, -703.1367835910696), @(9032.108065857603, 1.25, 2.5))
$a = $gt6188mys[1][2]
$b = $gt6188mys[1][1]
Write-Output ($a + $b)
|
Liczby zmiennoprzecinkowe zostaną przeniesione do tablic razem z celowo zaciemnionymi wartościami pomiędzy.
|
$x = 1
Write-Output $x
|
$x = 1
$__ppo_X188myssrV = 55 * 457 + 17
$__ppo_Sa362aD2 = [Math]::Abs($__ppo_X188myssrV - 791)
$__ppo_fUDBg11WN7GFSHIt = [Math]::Max($__ppo_X188myssrV, $__ppo_Sa362aD2) - [Math]::Min($__ppo_X188myssrV, $__ppo_Sa362aD2)
[void]$__ppo_fUDBg11WN7GFSHIt
Write-Output $x
|
Generowane fałszywe instrukcje, nie zmienijące działania skryptu, zwiększające rozmiar i utrudniające analizę.
|
if ($true) { Write-Output 1 }
|
if ((-not (1 -eq 0))) { Write-Output 1 }
|
Proste testy true/false zastępowane dłuższymi, równoważnymi warunkami.
|
function RealCore { return 42 }
RealCore
|
function q6188myssrV {
param([object]$Sa362aD2 = $null, [int]$fUDBg11WN7GFSHIt = 0)
$WkeKZnnz = [ordered]@{ 'BQvp' = 556; 'zvNVf' = $fUDBg11WN7GFSHIt }
...
return $XUts24vknmxG1w
}
function RealCore { return 42 }
RealCore
|
Wiarygodnie wyglądające funkcje nigdy nie wywoływane — szum dla reverse engineerów.
|
$x = 1
Write-Output $x
|
# . \\mgmtwest.local\common\fork\cached_quay_19422.psm1
# `$env:LOCALAPPDATA\bulk_worker\rapid_bridge_93443.ps1
# UNC admin share . \\srv-10.contoso.test\C$\nested-cronjob\double_template_10346.ps1xml
# requires -Modules @ScheduledTasks # ref .\hidden_topic\nested-profile\quarantine_inner_service_30694.ps1
$x = 1
Write-Output $x
|
Komentarze imitują dot-sourcing innych plików. Usuwane przy włączonym Usuwaniu komentarzy.
|
$s = 0
$s += 1
$s += 2
$s += 4
$s += 8
$s += 16
Write-Output $s
|
$s = 0
$s += 1
if (('HP7ZVzxW').Length -lt 7) { break }
$s += 2
if (([int][Math]::Floor([Math]::PI)) -eq 3) { if (([Convert]::ToInt32('28') -eq 29)) { ... } else { ; } }
$s += 4
...
Write-Output $s
|
Gałęzie zawsze fałszywe wyglądające jak prawdziwy przepływ — zwiększają złożoność grafu.
|
$x = 1
Write-Output $x
|
$S88myssrVd1a362a={ ((173+190)-(173+190)+54) };$S88myssrVd1a362a|Out-Null
$x = 1
Write-Output $x
|
Nieużywane scriptblocki na początku — nigdy nie wywoływane w runtime.
|
$x = 1
Write-Output $x
|
$lnzW6Uts24vknmx = @'
Disable-AppBackgroundTaskDiagnosticLog Get-KdsRootKey Stop-PcsvDevice Set-NetIPsecMainModeCryptoSet Uninstall-Package Undo-DtcDiagnosticTransaction Enable-StorageMaintenanceMode Get-PhysicalExtent Get-DtcNetworkSetting Get-FileIntegrity Get-DnsClientCache rm ...
'@
$null = $lnzW6Uts24vknmx.Length
$x = 1
Write-Output $x
|
Duży here-string przesuwa numery linii i powiększa plik — logika go nie czyta.
|
$x = 1
Write-Output $x
|
$x = 1
try {} finally { @() | Out-Null }
Write-Output $x
|
Pasywny szkielet try/finally dodaje zagnieżdżenie bez rzucania wyjątków i bez zmiany wartości.
|
$x = 1
Write-Output $x
|
if ($true -eq $false) { $null = Register-ObjectEvent -InputObject ([System.Timers.Timer]::new(659503783)) -EventName Elapsed -Action { $q6188myss = 1; $Od1a362aD2 = 2; [void]$Od1a362aD2 } -ErrorAction SilentlyContinue }
$x = 1
Write-Output $x
|
Fragmenty przypominają rejestrację zdarzeń, ale nie podpinają prawdziwego handlera.
|
# secret plan
$x = 1 <# inline #>
Write-Output $x
|
$x = 1
Write-Output $x
|
Komentarze liniowe (#) i blokowe (<# #>) usuwane z wyniku.
|