Ochrana .NET aplikací

Ondřej Linhart       18.08.2011       Architektura, Bezpečnost, .NET       13171 zobrazení

Základní principy ochrany software a její implementace na platformě Microsoft .NET.

Úvod do problematiky ochrany software

Ochrana duševního vlastnictví u software byla vždy problémem číslo jedna. Obzvlášť v dnešní době, kdy komerční software vyvíjí desítky až stovky lidí řádově roky je v zájmu firem ho co nejlépe zabezpečit před potenciální nelegální distribucí a zpětným získáním zdrojového kódu. Jako první je třeba poznamenat, že stoprocentně spolehlivá ochrana software neexistuje, dá se pouze více či méně znesnadnit prolomení ochrany. Před implementací ochrany je třeba zvážit mnoho faktorů, například složitost implementace vs. účinnost, nebo dopad na uživatele softwaru. Online ověřování, hardwarový klíč, nebo nutnost přítomnosti DVD v mechanice patří mezi ty typy ochran, které mají nejvíce negativní působení na uživatele. Naopak prosté sériové číslo má prakticky nulovou účinnost.

Problematika ochrany ještě narůstá s příchodem a rozšířením platformy Microsoft .NET, kde je zpětné získání zdrojového kódu nebo vložení vlastních instrukcí do existující aplikace skutečně hračka ve srovnání s nativními Win32 aplikacemi, kde je obvykle nutná velmi dobrá znalost assembleru a jazyků C/C++.

Zabránění zpětného získání zdrojového kódu

Nástroje jako .NET Reflector dokážou ze zkompilované .NET assembly získat téměř identický původní zdrojový kód a zobrazit ho v jazyce vlastního výběru (IL, Visual Basic, C#, F#…). Tento proces je znám jako tzv. Reverse engineering a díky němu lze vytvářet např. ilegální generátory licencí známé jako keygeny. Jako první krok v ochraně aplikace je tedy potřeba co nejvíce znesnadnit tento proces. To se provádí pomocí různých nástrojů k tomu určených, příkladem může být Dotfuscator Community Edition, který je dodáván s Visual Studiem Standard nebo lepším. Tento nástroj ale dokáže pouze přejmenovávat a to ještě tak hloupě, že jsou názvy čitelné. Ideální obfuskátor (nástroj pro “zmatení” kódu) by měl kromě přejmenování tříd a jejich členů (tzv. Unicode normalizace) nějakým způsobem zabránit zobrazení původního zdrojového kódu při zachování plné funkčnosti aplikace a žádném nebo minimálním negativním dopadu na výkon. Následující příklad ukazuje původní kód, kód dekompilovaný před obfuskací a po obfuskaci.

Private Function GetQueryValue(ByVal url As String, ByVal parameter As String) As String
  Dim firstOccurence = url.IndexOf(parameter, StringComparison.OrdinalIgnoreCase)
  If firstOccurence > -1 Then
    Dim builder As New StringBuilder(url.Length - firstOccurence - parameter.Length)
    Dim a = firstOccurence + parameter.Length
    Dim z = url.Length - 1
    For index = a To z
      If url(index) <> "&" Then
        builder.Append(url(index))
      Else
        Exit For
      End If
    Next
    Return builder.ToString()
  Else
    Return Nothing
  End If
End Function

Nástrojů pro obfuskaci kódu existuje velké množství (bezplatné i komerční), ale pouze malá část z nich je skutečně účinná a stojí za to (např. ten, který používám já a jehož výsledek můžete vidět na obrázku je jeden z těch nejlepších). I když to ve většině případů není potřeba, umí některé obfuskátory i šifrovat textové řetězce v kódu a v resources. To se vám bude hodit, pokud máte hesla a jiné citlivé informace prasácky uložené přímo v kódu. Obfuskátory jsou buď plnohodnotné aplikace s uživatelským rozhraním, nebo konzolové aplikace ovládané parametry z příkazové řádky což je lepší, protože je lze integrovat do build procesu (pomocí Post-build události).

Zabránění nežádoucí modifikace nebo podvržení assembly

Nejdůležitější část ochrany aplikace je zabránění možnosti nežádoucí změny assembly nebo jejímu podvržení falešnou knihovnou. Realizace takové ochrany je velmi jednoduchá a vystačíte si s prostředky Visual Studia. Klíčem k realizaci je podepsání assembly silným názvem (Strong Name). Silný název zajišťuje unikátnost assembly v rámci systému, integritu assembly a autora assembly. Assembly můžete podepsat buď párem klíčů vytvořeným ve Visual Studiu (nebo nástroji z .NET Framework SDK) nebo komerčním certifikátem Authenticode vydaným některou z důvěryhodných certifikačních autorit. Druhá možnost má tu nevýhodu, že se kontroluje platnost certifikátu a po jejím ukončení vám systém nedovolí takto podepsanou aplikaci spustit (kromě toho obnovení platnosti certifikátu stojí nemalou částku a je ho třeba obnovovat pravidelně). Může se vám tak klidně stát, že zákazník, kterému jste aplikaci prodali si bude po roce stěžovat, že mu aplikace nefunguje a bude to jen z důvodu ukončení platnosti certifikátu. Budu tedy předpokládat, že budete assembly podepisovat klíčem .snk z VS/SDK. Aby bylo možné podvrhnout knihovnu referencovanou vaší aplikací, musela by tato knihovna být podepsaná stejným silným názvem což je prakticky nemožné, protože pro podepsání je nutné mít soukromou část klíče, kterou má pouze autor. Ještě by bylo dobré poznamenat, že pokud vaše aplikace referencuje knihovnu podepsanou silným názvem, musí být vaše aplikace rovněž podepsaná silným názvem.

Až do vydání .NET Frameworku 3.5 Service Pack 1 to fungovalo tak, že runtime CLR kontroloval hash všech zaváděných assembly a pokud tento hash neodpovídal, CLR nedovolilo assembly načíst. V Service Pack 1 tuto kontrolu omezili pouze na assembly pocházející z nedůvěryhodných umístění (Internet, LAN). Sám jsem narazil na tento problém, který je včetně řešení diskutován zde.

Pokud je tedy zapnuto ověřování a někdo změní ve vaší assembly jediný bit, CLR to pozná a změněnou assembly nedovolí načíst. Vytvořte si tedy svůj pár klíčů (návodů jak to udělat je na MSDN i jinde nepřeberné množství) a tím podepisujte všechny svoje projekty.

Ukázková signatura assembly podepsané klíčem snk (všimněte si hodnoty PublicKeyToken, což je právě SHA hash veřejné části klíče snk):

OL.Licensing, Version=3.0.4217.28505, Culture=neutral, PublicKeyToken=fa9d171f092a4ca1

Implementace licenčního mechanizmu

Poslední části v ochraně softwaru je implementace samotného licenčního mechanizmu. Pokud je vaše aplikace komerční, nebo nechcete, aby se nekontrolovaně šířila, měli byste takový mechanizmus určitě implementovat. Existují již hotová API pro tyto účely, nebo pokud jste dobří, můžete se pokusit napsat vlastní. Je potřeba brát na vědomí všechny výše uvedené faktory a také způsob použití aplikace. Pokud například bude aplikace používána pouze na jednom počítači, můžete licenci vázat na systémový disk, pokud bude potřeba používat aplikaci na více počítačích, můžete licenci vázat na disk USB Flash, nebo vytvořit licenci síťovou. Vždy se zkuste vžít do role uživatele aplikace a představit si, jestli pro něho nebude konkrétní typ licence otravný nebo nevyhovující. Já jsem ve svém licenčním API zvolil cestu licence vázané na systémový disk, nebo na disk USB Flash pro mobilní uživatele. V obou případech mohu navíc licenci omezit platností na určitou dobu a mnoha dalšími praktickými věcmi. Licenci mám ve formátu XML takže je snadno rozšiřitelná a digitálně podepsanou, což zabraňuje její neoprávněné modifikaci.

 

Doufám, že tento článek osvětlil alespoň základní principy ochrany software a detaily je možné řešit v případné diskusi komentáři.

 

hodnocení článku

3 bodů / 3 hlasů       Hodnotit mohou jen registrované uživatelé.

 

 

 

Nový příspěvek

 

Diskuse: Ochrana .NET aplikací

Neviem čo s tým mám Visual Studio 2010 a hlási to túto chybu : Type 'StringBuilder' is not defined. Neviete čo s tým ?

nahlásit spamnahlásit spam -1 / 1 odpovědětodpovědět

Jak to souvisí s tímto článkem?!

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Private Function GetQueryValue(ByVal url As String, ByVal parameter As String) As String

Dim firstOccurence = url.IndexOf(parameter, StringComparison.OrdinalIgnoreCase)

If firstOccurence > -1 Then

Dim builder As New StringBuilder(url.Length - firstOccurence - parameter.Length)

Dim a = firstOccurence + parameter.Length

Dim z = url.Length - 1

For index = a To z

If url(index) <> "&" Then

builder.Append(url(index))

Else

Exit For

End If

Next

Return builder.ToString()

Else

Return Nothing

End If

End Function

Vložil som tam tento kód a hlási mi to chybu so StringBuilder

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Ten kód slouží jen pro ukázku obfuskace. Proč ste ho někam vkládal, když ani nevíte, co dělá?

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

StringBuilder je třída definovaná v jmenném prostoru System.Text. Ví to váš program?

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Diskuse: Ochrana .NET aplikací

Dobrý den,

chtěl bych se zeptat, jestli je nějaká možnost, jak podepsat projekt, který referencuje nepodepsanou knihovnu.

Nemáte nějaký nápad?

Děkuji

nahlásit spamnahlásit spam 0 odpovědětodpovědět

To nejde z jednoho prostého důvodu: Pokud by podepsaná assembly referencovala nepodepsanou assembly, narušila by se tím bezpečnost aplikace v tom smyslu, že by nebyl problém podvrhnout nepodepsanou assembly, proto podepsané assembly musí vždy referencovat pouze podepsané assembly, jinak to ani nepůjde zkompilovat.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Diskuse: Ochrana .NET aplikací

V tom článku píšete, že používáte nějaký profesionální nástroj. Můžu vědět který to je? Díky

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

Babel Obfuscator, ale konkrétní verzi 3.5.0.0. Od verze 4.x je tento nástroj placený (stojí od 3 700,- výš) a ve zkušebním režimu obfuskovaná assembly funguje pouze určitou dobu. Verze 3.5 byla poslední neplacená plně funkční verze bez omezení, podobně jako .NET Reflector 6.8. Tu starší verzi už ale neseženete, autor po ní dokonale zametl stopy.

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

Diskuse: Ochrana .NET aplikací

Pěkný článek, patří vám vřelý dík !

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

Skvělý článek :-), toto je bohužel jedna z největších slabostí .NETu, bohužel :-(, ještě jednou díky za skvělý a hlavně informativně velice hodnotný článek :-)

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Stejný problém má například i Java.

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

Vždycky je to něco za něco - .NET nabízí spoustu hezkých věcí a daleko snadnější vývoj než C++, na druhou stranu někde se to projeví negativně - v tomto případě nepatrně na výkonu a na "rozluštitelnosti" kódu.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Diskuse: Ochrana .NET aplikací

Moc hezké, konečně jsem alespon trochu v obraze. Nemáš nějaké slušné odkazy, kde by se probíralo více? Klidně v angličtině, pokud je to napsané sorzumitelně a není to moc odborné.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Následující odkazy se týkají této problematiky:

http://msdn.microsoft.com/en-us/magazine...

http://msdn.microsoft.com/en-us/library/...

http://msdn.microsoft.com/en-us/magazine...

http://www.codeproject.com/KB/security/S...

http://ianpicknell.blogspot.com/2010/02/...

A netykejte lidem, které osobně neznáte.

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

nejsem zastánce tykání kdekoliv, ale zrovna na odborném fóru bych zrovna vykání nevyžadoval (a neočekával), ale respektuji, že zrovna tady si rádi vykáte :)

http://www.lupa.cz/clanky/nebud-netykavk...

jinak kdyby tu i anonymní přispěvatelé měli možnost se podepsat, tak by to někteří třeba rádi udělali

nahlásit spamnahlásit spam 0 odpovědětodpovědět

V běžném životě byste panu Linhartovi také netykal, pokud ho neznáte, v čem je internetová diskuse jiná?

A podepsat se může každý do textu příspěvku, spousta lidí to tak i dělá.

nahlásit spamnahlásit spam 2 / 2 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