Jakub Čermák

Vývojářský blog Jakuba Čermáka

Podle kategorie

Hrátky s WinAPI: “buď já nebo BSOD” aneb kritické procesy systému

Jakub Čermák       28. 6. 2009       C#, Offtopic       7502 zobrazení

Dneska jsem během náhodného procházení internetu narazil (z mého pohledu) zajímavou věc – jak udělat to, co umí např. proces CSRSS, tj. že když ho někdo nebo něco killne nebo umře přirozenou programovou smrtí, tak s sebou vezme i celý systém – Windows hodí BSOD (KeBugCheckEx) s tím, že mu (volně řečeno) umřel kritický proces a bez něj už nemá smysl dál existovat :)

Windows XP Professional-2009-06-28-16-22-57

Kód Bluescreenu se liší podle toho jestli hlídaný program skončil v pořádku (vrátil 0), pak je to CRITICAL_PROCESS_DIED (0xEF), nebo jestli skončil s chybou, pak se zjeví BSOD CRIITICAL_OBJECT_TERMINATION       (0xF4).

Jak se tedy takováhle věc nastavuje? V podstatě jsou 2 cesty, kdy první používá interně tu druhou. V obou dvou případech je třeba, aby proces měl seDebugPrivilege (v .NETu to lze zařídit pomocí fcí Process.EnterDebugMode a Process.LeaveDebugMode) a nejspíš jsou potřeba i admin práva (bez nich mi to nefungovalo). Nejjednodušší je asi použít nedokumentovanou API funkci RtlSetProcessIsCritical, které se (mj.) předá BOOL vyjadřující, jestli tento proces je pro systém kritický nebo není. Zásadní nevýhoda je, že se toto nedá použít pro nastavování jiných procesů. A protože jsem člověk zvědavý, tak jsem se podíval do referenčních zdrojáků NTOSKRNL (část Windowsího kernelu) a implementaci té funkce tam ke své spokojenosti našel – je to víceméně jen obálka nad dvojicí (zase nedokumentovaných) funkcí NtSetInformationProcess a NtQueryInformationProcess, sloužících pro nastavování či čtení nejrůznějších parametrů procesů.

Implementace

Nejdřív definice těch 3 funkcí :

 [DllImport("ntdll.dll", SetLastError = true)]
extern static unsafe UInt32 NtSetInformationProcess(IntPtr ProcessHandle, int ProcessInformationClass, void* ProcessInformation, uint ProcessInformationLength);

[
DllImport("ntdll.dll", SetLastError = true)]
extern static unsafe UInt32 NtQueryInformationProcess(IntPtr ProcessHandle, int ProcessInformationClass, void* ProcessInformation, uint ProcessInformationLength, uint* ReturnLength);

[
DllImport("ntdll.dll")]
extern static unsafe void RtlSetProcessIsCritical(bool NewValue, bool* OldValue,bool CheckFlag);

ProcessInformationClass je enum vyjadřující, co vlastně chceme zjistit nebo nastavit za informaci, na internetu lze nalézt definici, my potřebujeme ProcessBreakOnTermination, což je číselně 29, ProcessInformation je pak daná informace. Pomocí toho pak už kód je jednoduchý:

 unsafe void SetCritical(Process proc, bool enable)
{
    
Process.EnterDebugMode();
    
uint ienable = enable ? 1u : 0u;
    
try
    {
        
UInt32 status = NtSetInformationProcess(proc.Handle, ProcessBreakOnTermination, &ienable, sizeof(uint));
        
if (status < 0)    MessageBox.Show("Error " + status);
     }
    
catch (Win32Exception e)
     {       
MessageBox.Show("Error " + e.Message);    }
    
Process.LeaveDebugMode();
}

unsafe bool GetCritical(Process proc)
{
    
uint ienable = 0;
    
Process.EnterDebugMode();
    
try
    {
        
UInt32 status = NtQueryInformationProcess(proc.Handle, ProcessBreakOnTermination, &ienable, sizeof(uint), (uint*)IntPtr.Zero.ToPointer());
        
if (status < 0)    MessageBox.Show("Error " + status);               
     }
    
catch (Win32Exception e)
     {       
MessageBox.Show("Error " + e.Message);    }
    
Process.LeaveDebugMode();
    
return ienable != 0;
}

Užitečnost

je v tomto případě celkem diskutabilní :) Napadá mě použítí do nějakých ochranných systémů a případně na hraní, kdy takto odděláte ochranu důležitým systémovým procesům a sledujete, co se stane po killu. Nejspíše by se to také dalo zneužít na nějaký pěkný kanadský žertík. Mě osobně se na tom líbí to, že ony systémové procesy nejsou “něco víc” než ty moje a liší se jen voláním jedné API funkce. Případné nápady na využití můžete psát do diskuze pod článkem.

Zdrojový kód aplikace si můžete stáhnout na http://dl.jcermak.cz/clanky/CriticalSysProcessExample.zip

 

hodnocení článku

0       Hodnotit mohou jen registrované uživatelé.

 

Nový příspěvek

 

Diskuse: Hrátky s WinAPI: “buď já nebo BSOD” aneb kritické procesy systému

Instantní BSOD. Hezké...

V zásadě je ale dobře, že není možné, aby běžel systém bez důležitých procesů. Ještě pamatuji Windows 95, kde prostě bylo možné mazat za běhu složku Windows. V průběhu mazání se funkce systému začali zužovat (mizení ikon, chyby ve vykreslování, nejdříve špatná, pak žádná nabídka Start atp.) a nakonec vše spadlo. To mělo do bezpečnosti hodne daleko.

nahlásit spamnahlásit spam 2 / 2 odpovědětodpovědět

Dá sa niečo takéto spraviť aj vo Visual Basic .NET ?? začínam sa učiť C# , ale hodil by sa mi takýto kód aj pre VB.NET a online konvertorom moc neverím vo winAPI :)

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.

Nyní zakládáte pod článkem nové diskusní vlákno.
Pokud chcete reagovat na jiný příspěvek, klikněte na tlačítko "Odpovědět" u některého diskusního příspěvku.

Nyní odpovídáte na příspěvek pod článkem. Nebo chcete raději založit nové vlákno?

 

  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:  
Heslo:  

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback