Platforma .NET dostarcza deweloperom wielu nowych możliwości, ułatwień i ulepszeń, także w aspekcie bezpieczeństwa - zwiększając tym samym ochronę szeroko pojętych dóbr intelektualnych. Współczesne organizacje poświęcają wiele energii dbając o to, by określona informacja nie dotarła do osób niepowołanych. Stosowane są zaawansowane metodyki bezpieczeństwa, szyfrowanie, ścisła identyfikacja zasobów, firewalle itd. Tymczasem dając użytkownikowi do ręki skompilowaną do kilku plików DDL i pliku EXE aplikację .NET - dajemy mu jednocześnie na talerzu co najmniej jej algorytmiczne tajemnice, a często także szereg innych cennych informacji.
Wszystkie .NETowskie asemblacje objęte są tzw. mechanizmem reflection, który jest interfejsem do pozyskania szczegółowych metainformacji dotyczących wszystkich klas w danej assembly. To cena, jaką płacimy m.in. za intellisense w Visual Studio.
Wprawdzie self-desribing assemblies nie ujawniają własnego kodu MSIL (Microsoft Intermediate Language), jednak droga do jego pozyskania dla amatorów cudzego kodu źródłowego jest banalnie prosta. Jeszcze łatwiej natomiast zamienić instrukcje języka pośredniego na kod języka wyższego poziomu - C#, VB.NET czy managed C++. Razem z .NET Framework dostarczany jest IL Assembler - to oczywiste. Być może mniej oczywisty jest fakt, że wraz z .NET Framework SDK (dołączonym m.in. do Visual Studio), dostarczany jest także IL Disassembler. Wystarczy więc uruchomić plik
lidasm.exe i już mamy okienkowy interfejs prowadzący wprost do kodu pośredniego dowolnej aplikacji .NET, nie robiąc przy tym kompletnie nic nielegalnego. IL Disassembler jest jednak troszkę toporny, w końcu dlaczego nie mielibyśmy od razu otrzymać kodu w dowolnym języku wyższego poziomu (do wyboru), wraz z całą hierarchią obiektów, typami, metodami w przyjaznym dla oka GUI? Nic bardziej prostszego, programów tego typu jest całkiem sporo. Wystarczy polecić Lutz Roeder's .NET Reflector (
strona domowa). Na życzenie program ten wygeneruje nam w pełni funkcjonalny projekt, który natychmiast możemy otworzyć w Visual Studio.
Okrutna prawda jest taka, że każdy program można poddać mniej lub bardziej skutecznej disasemblacji, przy czym jest to o wiele trudniejsze w przypadku binarki Win32, a o wiele łatwiejsze w przypadku aplikacji .NET (analogicznie: Javy czy Perla). Potwierdza to starą zasadę, że nie ma zabezpieczenia, którego nie dałoby się złamać. Jedyne co można zrobić, to maksymalnie utrudnić reverse engineering, mając nadzieję, że skutecznie zniechęci to ewentualnych zainteresowanych. Jeżeli już musimy udostępnić komuś bezpośrednio skompilowany program, to zadbajmy chociaż o maksymalne "zaciemnienie" jego kodu źródłowego. Można użyć do tego celu jednego z powszechnie dostępnych obfuscatorów, np. programu Dotfuscator (
strona domowa, polecany przez Microsoft). Kod źródłowy zostanie wtedy odpowiednio zmodyfikowany: obfuscator zamieni nazwy zmiennych, obiektów, metod na niezrozumiałe dla człowieka sekwencje znaków, zaszyfruje wartości stringów, zastosuje instrukcje goto utrudniające zrozumienie kolejności instrukcji itp. Oczywiście wszystkie wymienione czynności nie będą wpływały na efekt działania skompilowanej aplikacji, chodzi tylko o jak największe skomplikowanie analizy kodu pozyskanego przez disasemblację. Trzeba jednak od razu zaznaczyć, że istnieje co najmniej kilka deobfuscatorów, które potrafią przywrócić kod do całkiem czytelnej formy...
Szczerze mówiąc, nie ma dobrej metody na ochronę kodu aplikacji .NET, jeżeli fizycznie przekazujemy skompilowany program osobie trzeciej. Trzeba mieć to na uwadze projektując rozwiązania z zastosowaniem tej technologii. Nie zawsze jednak sytuacja wymaga takiego kroku - wtedy otwiera się obszar dla zastosowania technologii webowej lub usług terminalowych. Może i są to rozwiązania mniej wygodne dla użytkownika, ale nie ma przecież nic za darmo.