Jenom zajímavůstka pro PowerShellisty. Do skriptu v PowerShell jde vložit (ne)přímo kus kódu v jazyce C# (csharp, c-sharp, cs). PowerShell ho potom umí spustit. Používá se to například, pokud chcete využívat PInvoke metodu na volání Win32 API, což jinak přímo z PowerShell nejde. Já to mám například ve svém keyloggeru, a zrovna se tím chystám přidat nějakou funkcionalitu do forensní analýzy.
Právě kvůli tomu volatile forensics scriptu jsem ale zkoumal, jak to dělá.
Kompilace pomocí Add-Type a temp adresáře
Kód napsaný v jazyce C# se do PowerShellu vloží pomocí herestring. Příklad následuje. Je to prostě jen jednoduchá třídička (class) s konstantou a její okamžité použití:
$cs = @'
namespace Sevecek.PowerShell {
public class Constants {
public const int OneValue = 5;
}
}
'@
Add-Type -TypeDefinition $cs
[Sevecek.PowerShell.Constants]::OneValue
Jenže ten C# se musí zkompilovat. Kompiluje se pomocí cs.exe kompilátoru, který máte vždycky nainstalovaný spolu s .NET framework. PowerShell potřebuje .NET framework, takže tam ten kompilátor je úplně vždycky.
Použil jsem process monitor (procmon) k tomu, abych zjistil, kam to zapisuje. Jakmile zavoláte Add-Type, celý obsah toho herestring se vyextrahuje a uloží do soubouru v tempu - konkrétně v té cestě, která je v proměnné %tmp%, neboli pro PowerShell tedy $env:tmp. Existuje ještě jedna úplně stejná proměnná %temp%, tedy $env:temp, ale ta se v tomto okamžiku nepoužije. PowerShell to ukládá opravdu do dočasného adresáře, který je v proměnné $env:tmp. Vyzkoušeno pro všechny verze PowerShellu 2, 3 i 4.
Vytvoří to tam několik souborů, kód je v souboru .cs a příkazová řádka pro cs.exe kompilátor je v souboru .cmdline. Příkazové řádky pro C# compiller jsou zde:
# PowerShell version 2 CS/C# compiller command line
# used by Add-Type -TypeDefinition.
# The temporary files goe into the path specified by
# the $env:TMP (%TMP%) environment variable:
#
# /t:library /utf8output /R:"System.dll" /R:"C:\Windows\assembly\GAC_MSIL\System.Management.Automation\1.0.0.0__31bf3856ad364e35\System.Management.Automation.dll" /out:"qbrwvho.dll" /D:DEBUG /debug+ /optimize- /warnaserror "qbrwvho.0.cs"
# PowerShell version 4 CS/C# compiller command line
# used by Add-Type -TypeDefinition
# The temporary files goe into the path specified by
# the $env:TMP (%TMP%) environment variable:
#
# /t:library /utf8output /R:"System.dll" /R:"C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Management.Automation\v4.0_3.0.0.0__31bf3856ad364e35\System.Management.Automation.dll" /R:"System.Core.dll" /out:"sxbfvua.dll" /D:DEBUG /debug+ /optimize- /warnaserror "sxbfvua.0.cs"
Změna dočasného adresáře pro kompilaci
Za normálních okolností asi nebudete chtít měnit adresář, do kterého se budou dočasné kompilační soubory ukládat. Jde to do dočasného adresáře tmp, u kterého se očekává, že prostě plní tuto funkci. V mém případě to ale není dobře, protože potřebuji kompilaci provádět do vyhrazeného adresáře ve svém forensním balíčku, abych minimalizoval zanášení změn do zkoumaného systému.
Jak tedy změníte dočasný adresář pro kompilace vloženého C# kódu? Jednoduše. Stačí nastavit jinou cestu do proměnné $evn:tmp.
$env:tmp = 'C:\MyTempCompilationTarget'