Disassembler

Artificial intelligence is no match for natural stupidity.
28srpna2015

Změna vlastníka souborů a registrů Windows


Windows pracuje s oprávněními poněkud komplikovaněji a nad rámec klasického a dnes už skoro archaického read, write a execute. Obvykle pro správnou funkci počítače nebo pro povolení přístupu k soukromým souborům není potřeba měnit vlastníka a vystačíte si s přidáním nového uživatele do ACL (seznamu oprávnění). Občas se ale někomu zachce se systémem udělat nějaké pořádné psí kusy a sáhnout do souborů, které jsou chráněné. Celý princip ochrany obvykle spočívá pouze právě v tom, že soubory jsou vlastněny speciálním uživatelem a nikdo jiný je nemá povoleno modifikovat.

Prohlížeč na hraně


V komentářích k článku Jak z Windows 10 udělat desktopový systém byl vznesen dotaz na odstranění prohlížeče Edge z Windows 10. To je zrovna jedna z akcí, ke které je změna oprávnění potřeba, protože soubory aplikace jsou vlastněny uživatelem TrustedInstaller, kterýžto je přesně tím zmiňovaným speciálním uživatelem pro chráněné systémové záležitosti. Odstranění Edge prohlížeče tedy bude má případová studie, na které budu úpravy vlastníka demonstrovat. Podotýkám, že se zdaleka nejedná o čistou odinstalaci, protože zůstane zaháčkován ještě na spoustě místech v registrech.

Microsoft Edge je Metro aplikace, takže jako ostatní Metro aplikace sedí nainstalovaná v umístění C:\Windows\SystemApps\. V této složce je podsložka Microsoft.MicrosoftEdge_8wekyb3d8bbwe, kterou když se pokusíte smazat, Windows akci odmítnou a řeknou vám, ať se laskavě obrátíte na uživatele TrustedInstaller a hezky ho poprosíte o přidělení příslušných oprávnění.

Kliky klik


Tůdle. Na složku kliknete pravým myšítkem a vyberete Vlastnosti a pak záložku Zabezpečení. Tam uvidíte několik uživatelů a skupin, kteří ke složce mají nějaká oprávnění, a rovnou vám prozradím, že jediným uživatelem, který může obsah složky beztrestně měnit je pouze výše zmíněný TrustedInstaller, i když to z tohoto pohledu není vidět, protože většina souborů uvnitř oprávnění nedědí a má jej nastaveno po svém. Z pohledu uživatele vás pak budou zajímat skupiny Users nebo Administrators, které mají pouze právo ke čtení a spouštění, což umožňuje používání prohlížeče, ale ne modifikaci jeho souborů. K tomu abyste si mohli přiřadit práva i k zápisu (resp. smazání) musíte být vlastníkem. Ke změně vlastníka vám ale kupodivu stačí jen obyčejná administrátorská oprávnění, která již máte. Klikněte tedy na tlačítko Upřesnit (nikoliv Upravit).

Záložka Zabezpečení

Tady už je trochu složitější, ale zato zajímavější. Nahoře vidíte, že vlastníkem je uživatel TrustedInstaller. Klikněte tedy na modrý text Změnit vedle jeho jména.

Upřesnit nastavení

Do pole pro zadání názvu objektu v objevivším se okně vepište „administrators“ (bez uvozovek) a klikněte na tlačítko Kontrola názvů. Pokud jste se neupsali, doplní se objekt o název počítače. Potvrďte hodnotu tlačítkem OK.

Změna vlastníka

Na předchozí obrazovce zatrhněte Nahradit vlastníka v subkontejnerech a objektech (To je jen složitý název pro „aplikovat i na podsložky“) a klikněte znovu na OK.

Upřesnit nastavení

Nyní jste nastavili administrátorskou skupinu jako vlastníka, takže vám bylo umožněno nastavovat oprávnění ke složce a souborům v ní. Stále však nemáte oprávnění k modifikaci a mazání souborů. Jelikož ale teď patříte do skupiny vlastníků, můžete si je přiřadit. Ani to ale není tak snadné, protože, jak jsem již naznačil, některé soubory nedění oprávnění od složky, kterou jste právě změnili.

Na stále otevřené záložce zabezpečení klikněte znovu na totéž tlačítko Upřesnit (V předchozím kroku jste okno museli zavřít, protože si Windows potřebují znovu načíst oprávnění) a tentokrát klikněte dole na tlačítko Měnit oprávnění. V tomto okně označte první řádek platný pro skupinu Administrators a ve spodní části klikněte na Upravit. V následujícím okně zatrhněte Úplné řízení a potvrďte pomocí OK.

Změna oprávnění

V předchozím okně pak dole opět zatrhněte Přepsat všechny položky oprávnění podřízených objektů zděditelnými oprávněními tohoto objektu, klikněte na OK a opět potvrďte bezpečnostní varování.

Změna oprávnění

Pak zavřete okno s vlastnostmi a složka je vaše. Můžete ji tedy konečně smazat.

Velice podobný postup lze pak aplikovat i na registry, v případě, že potřebujete modifikovat nějaký zašitý a chráněný klíč, například v HKEY_CLASSES_ROOT.

Příkazový řádek


Na práci se soubory je možno v příkazovém řádku použít dvě velmi užitečné utility. První z nich je takeown, která, jak název napovídá, umožňuje převzetí vlastnictví. Druhou utilitou je pak cacls nebo její novější a preferovanější varianta icacls, která umožňuje změnu oprávnění. Oběma je možno předat přehršel různých parametrů, takže popíšu jen ty, které jsou potřeba k dosažení podobného stavu jako v případě ručního vyklikání.

takeown /F C:\Windows\SystemApps\Microsoft.MicrosoftEdge_8wekyb3d8bbwe /A /R
icacls C:\Windows\SystemApps\Microsoft.MicrosoftEdge_8wekyb3d8bbwe /grant Administrators:F /T
rd /S /Q C:\Windows\SystemApps\Microsoft.MicrosoftEdge_8wekyb3d8bbwe

První příkaz jednoduše a bezbolestně změní vlastníka na skupinu Administrators a totéž provede i pro soubory a složky uvnitř zadané cesty. Druhý příkaz pak téže skupině povolí úplné řízení a opět protlačí změny i na podobjekty. Třetí příkaz by vám pak měl být důvěrně známý a jednoduše adresář odstraní. Nezapomeňte, že příkazový řádek musí být spuštěn se správcovským oprávněním. Také doporučuju si všechny příkazy nejprve pustit jen s parametrem /? a přečíst si návod k použití dříve, než je spustíte s plnou parádou a imploduje vám počítač nebo něco takového.

Zrada pak nastává v případě, že byste chtěli změnit vlastníka a oprávnění nějakého klíče v registrech. PowerShell umí s registry zacházet jako se speciálními disky, kde jsou klíče jako adresáře a hodnoty s daty jako vlastnosti daného adresáře, takže se k nim přistupuje stejně jako k diskům, akorát místo C:\ píšete HKLM:\ a tak podobně. Tohle ale bohužel neumí ani jeden z výše zmíněných nástrojů a je potřeba se uchýlit buď k utilitám třetích stran (SetACL, RegDACL a další) nebo si napsat kus programu vlastního, kterýžto se pokusím předvést níže.

PowerShell


Jako občasný C# programátor miluju PowerShell právě proto, že běží nad celým tím .NET cirkusem a když vám dojdou příkazy, můžete si jednoduše naprogramovat vlastní. Tedy, abych byl přesný, jednoduché je to pouze v případě, že jste podobný magor jako já. Pro BFU a standardní powerusery bez znalosti programování je to někde na hranici mezi „velmi obtížné“ a „中國傳統“.

PowerShell již disponuje funkcemi pro modifikaci oprávnění ve výchozím stavu. Za všechny uvedu třeba Get-Acl a Set-Acl, ale dají se použít i nativní C# metody. Co už ale PowerShell jednoduše neumí, je ono kradení vlastnictví, takže jakákoliv akce nad soubory ke kterým nemáte oprávnění, skončí vyhozením bezpečnostní výjimky. Z předchozích odstavců ale už víme, že převzetí oprávnění možné je, takže je potřeba to „pouze“ PowerShell naučit. Dostáváme se tu do běžným uživatelům relativně neznámých vod, takže jen vysvětlím, že ne všechny procesy si mohou dělat, co chtějí. Existují jistá oprávnění, která jsou operačním systémem procesu přidělena hned po spuštění a o další si musí proces požádat. Protože chceme modifikovat vlastníka u objektů, které nevlastníme, potřebujeme oprávnění SeTakeOwnershipPrivilege, které PowerShell při spuštění nemá. Neprogramátorům hned prozradím, že se jedná o poněkud ošemetnou alchymii, kde se z PowerShellu volá C# kód a z C# kódu se volají funkce odkudsi z útrob Windows, čímž se systému v podstatě posílají požadavky na stejné akce, jakoby je uživatel vyklikal ručně tak, jak popisuji v prvním odstavci. Programátorům znalých Windows pak prozradím jediné kouzelné slovíčko. PInvoke.

# C# code for gaining SeTakeOwnershipPrivilege
$takeOwnPriv = @'
using System;
using System.Runtime.InteropServices;

public class TakeOwnPriv {
	[DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
	internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall, ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen);

	[DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
	internal static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr phtok);

	[DllImport("advapi32.dll", SetLastError = true)]
	internal static extern bool LookupPrivilegeValue(string host, string name, ref long pluid);

	[StructLayout(LayoutKind.Sequential, Pack = 1)]
	internal struct TokPriv1Luid {
		public int Count;
		public long Luid;
		public int Attr;
	}

	public static void EnableSeTakeOwnershipPrivilege(long processHandle) {
		TokPriv1Luid tp = new TokPriv1Luid() {Count = 1, Luid = 0, Attr = 2};
		IntPtr hproc = new IntPtr(processHandle);
		IntPtr htok = IntPtr.Zero;
		OpenProcessToken(hproc, 0x28, ref htok);
		LookupPrivilegeValue(null, "SeTakeOwnershipPrivilege", ref tp.Luid);
		AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
	}
}
'@

# Call the code above to get the privilege for current PID
$type = Add-Type $takeOwnPriv -PassThru
$type[0]::EnableSeTakeOwnershipPrivilege((Get-Process -id $pid).Handle)

Tenhle kousek přidělí procesu PowerShellu práva k nastavení vlastníka u cizích objektů. Je to docela šílenost a je tam spousta magických čísel kvůli úspoře místa a jednodušší orientaci. Kdyby měl někdo zájem o rozšířenou verzi, ze které můj kód vychází a která umí nastavovat i veškerá další privilegia, může pokračovat na http://www.leeholmes.com/blog/2010/09/24/adjusting-token-privileges-in-powershell/. Alternativně můžete také použít PowerShellovský modul PowerShell Community Extensions (PSCX), který celou tuhle taškařici zjednoduší na

Import-Module "PSCX"
Set-Privilege (new-object Pscx.Interop.TokenPrivilege "SeTakeOwnershipPrivilege", $true)

Náš PowerShell má tedy nyní povoleno měnit vlastníka, takže toho využijeme a stvoříme funkci, která onu změnu bude v registrech skutečně provádět. Zároveň také jedním vrzem nastavíme oprávnění k zápisu.

# Function for taking ownership and granting full control on registry keys
function RegTakeOwn([string]$path) {
	$hives = @{"HKEY_LOCAL_MACHINE"=[Microsoft.Win32.Registry]::LocalMachine; "HKEY_CURRENT_USER"=[Microsoft.Win32.Registry]::CurrentUser; "HKEY_CLASSES_ROOT"=[Microsoft.Win32.Registry]::ClassesRoot}

	ForEach ($itempath in @(Get-Item $path) + (Get-ChildItem -Recurse $path)) {
		$itempath = $itempath.Name.Split("\", 2)
		$key = $hives[$itempath[0]].OpenSubKey($itempath[1],[Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree,[System.Security.AccessControl.RegistryRights]::TakeOwnership)

		# Change owner to Administrators
		$blankacl = $key.GetAccessControl([System.Security.AccessControl.AccessControlSections]::None)
		$blankacl.SetOwner([System.Security.Principal.NTAccount]"Administrators")
		$key.SetAccessControl($blankacl)

		# Allow full control for Administrators
		$acl = $key.GetAccessControl()
		$rule = New-Object System.Security.AccessControl.RegistryAccessRule("Administrators", "FullControl", "ContainerInherit, ObjectInherit", "None", "Allow")
		$acl.SetAccessRule($rule)
		$key.SetAccessControl($acl)

		$key.Close()
	}
}

V tuhle chvíli máme tedy všechno připraveno a na neposlušný klíč pak stačí zavolat funkci RegTakeOwn a předat jí k němu v parametru cestu.

# Call the function with path as parameter
RegTakeOwn "HKLM:\Some\Protected\Key"

A proč je to tak strašně složitý?


Dalo by se říct, že je to pro vaše dobro. Zasahujete do systémových záležitostí, do kterých byste měli sahat opravdu jen v případech, kdy jste si naprosto jistí, že víte, co děláte, a že neexistuje jiná a lepší cesta, jak kýženého výsledku dosáhnout. A ve chvíli, kdy už máte jistou představu, jak Windows vevnitř fungují, vám to už tak komplikované připadat nebude. Stinná stránka věci je pak ta, že v honbě za bezpečností začne být uživatel jistým způsobem omezován. Výrobce software se na jednu stranu snaží zajistit, aby jeho produkt mohla používat i totální lama a měla při ruce vše, co může k běžným operacím potřebovat. Na straně druhé je pak potřeba poklidně přežvykující lamy ochránit před predátory, což není vždy možné, protože spousta lam je fakt extrémně hloupých. Nastává tedy fáze dvě, kdy výrobce počítá s tím, že puma do stáda již vběhla a je potřeba zajistit, aby její řádění napáchalo co nejmenší škody. Právě tento přístup k bezpečnosti je pak vnímán jako házení klacků pod nohy, protože pak na vás začnou vyskakovat všelijaká UAC, firewally a podobné výmysly. Někteří uživatelé je vypnou, protože mají pocit, že je to obtěžuje, ale nemají dostatečnou úroveň počítačové gramotnosti nebo kritického myšlení a pak se nestíhají divit, když po nich chce policie 2000,- za jejich vlastní fotky z dovolené. Samozřejmě se to netýká jen Windows. Ono třeba takové nastavení SELinuxu pro aplikace z vlastní zahrádky taky není žádná legrace. Údržba zabezpečení je vůbec strašně nevděčná práce.