Windows 7 überzeugt mit tollem Treibermanagement
Seit nun ca 2 Monaten nutze ich Windows 7 Professional und bin sehr begeistert von diesem "Besten Windows aller Zeiten" wie Microsoft es sagt.
Warum? Nicht nur dass es sehr schnell läuft, die neuen Netzwerk Funktionen, dank welcher LAN Party noch mehr Spaß machen werden aber auch die neue Taskleiste (die "Superbar") sehr gut umgesetzt ist.
Was einem aber nicht gleich ins Auge springt, sind die Neuerungen "unter der Haube". So ist mir heute, als ich meinen Drucker an dem PC anschloss folgendes aufgefallen:
Bild 1: Automatisch Treiberinstallation
Wie immer wenn man ein neues Gerät an dem Computer schließt erscheint der Treiber Assistent und versucht passende Treiber zu finden. Dies gelang ihm aber in früheren Windows Versionen aber (so gut wie) nie!
So musste ich immer meine Treiber CD von Canon rauskramen und die Treiber installieren, die ca 100 MB Groß waren, warum auch immer!
So war ich umsomehr überrascht als Windows alles eigenständig erkannte und installierte. Und das mit nur 10 MB statt 100! Das ganze habe ich gleich auch noch mit einem Nokia 95 getestet, dass eigentlich die Nokia PC Suite benötigt.
Auch diese wurde heruntergeladen und installiert! Also hier mal ein riesen Komplement an Microsoft.
Windows 7 ist in meinen Augen ein sehr gelungenes OS geworden! Ich selber nutze es auf meinem Macbook Unibody neben Snow Leopard. Wobei ich Mac OS schon seit knapp einem Monat nicht mehr gebootet habe, was schon was heißt finde ich!
Asynchrone Programmierung mit Threads Teil 1
In diesem ersten Teil dieser Serie möchte ich auf die Theorie hinter der Asynchronen Programmierung zu Sprechen kommen, Vor- und Nachteile dieser und auf Probleme, die dabei entstehen können.
Bild 1: Mooresches Gesetz grafisch dargestellt (klicken zum vergrößern) Quelle: Wikipedia
Wenn man mal auf die letzten Jahre schaut, sieht man eine starke Entwicklung der Computerrechenpower, zB. 1998 galt ein Computer mit 500 MHz noch als sehr leistungsfähig. Bis heute gilt auch noch (naja zumindest fast) das Mooresche Gesetz, welches besagt, dass alle 2 Jahre sich die Schaltkreise auf einem Chip (CPU) verdoppeln und somit auch die Leistung.
Da die Rechenleistung der Computer stetig stieg, war es für Programmierer meist nicht nötig, bzw. gab es keine Anreize die Software effizienter zu gestalten, denn mit jedem neuen Computer lief auch das Programm schneller!
Doch heute sind wir an einer Grenze angekommen, an der es kaum noch möglich ist eine einzelne CPU leistungsfähiger zu machen, und somit stagnieren wir zur Zeit bei ca 3 - 4 GHz bei SongleCore CPUs. (Ich selbst habe vor ca 6 Jahren geschätzt, dass die Marke von 5 GHz nicht mehr überschritten wird.)
Da man die Transistorenzahl auf den Chips nicht mehr erhöhen kann bedient sich die Industrie einem Trick. Sie bauen einfach zwei (oder mehr) CPUs in eine. Das ganze nennt sich dann DualCore. Man hat also zwei echte von einander unabhängig arbeitende CPUs.
Bild 2: Im Windows Taskmanager sieht man die 2 CPUs bei der Arbeit (oben)
Das Problem hierbei ist nur, dass man nun zwar zwei Kerne hat, diese aber nicht schneller geworden sind! So hat man zB. 2x 2,2 GHz was aber nicht heißt, dass die Rechenleistung dieser CPU bei 4,4 Ghz liegt!
Denn ein Programm läuft standardmäßig nur auf einem Kern, und da dieser nicht schneller geworden ist läuft das Programm darauf genauso schnell wie auf einem SingleCore 2,2 GHz Prozessor! (Natürlich ist das nicht ganz wahr, sicher läuft das Programm auf dem DualCore etwas schneller, da das System andere Prozesse auf den zweiten Kern auslagert, aber der Performancegewinn ist nicht enorm!)
Also sind wir Programmierer nun gezwungen unsere Software so zu gestalten, dass diese möglichst alle Kerne der CPU auslasten. Also Parallelprogrammierung anwenden!
Doch das ist leider leichter gesagt als getan, denn es gibt viele Steine die da in dem Weg liegen und viele Kleinigkeiten die man beachten muss! Der Anfang ist aber verschiedene Abläufe des Programms in einzelne Threads aufzuteilen.
Zunächsteinmal muss man wissen, dass nicht jedes Programm in Threads aufgeteilt werden kann (dazu gleich mehr) und desweiteren muss man verstehen, dass egal wieviele Prozessoren ein Computer hat man ein Programm nicht unendlich schnell machen kann!
Daher ist die Aussage "je mehr Kerne desto schneller das Programm" falsch! Warum das so ist werde ich nun erklären!
Sehen wir uns eine vereinfachte Programmkette an:
Darstellung 1: Sequentieller Programmablauf
Hier steht "T" für Thread und "P" für Prozedur.
Da jedes Programm einen klaren Einstiegspunkt haben muss (was hier P1 ist) kann dieser schon mal nicht in einen zweiten Thread ausgelagert werden. Der Endpunkt der meist alle Ressourcen freigibt ist der Punkt wo alles zusammenläuft, daher kann dieser auch nicht ausgelagert/aufgeteilt werden!
Somit können schon 2 von unseren 7 Prozeduren nicht ausgelagert werden und müssen sequentiell (nacheinander) ablaufen. Gut, schauen wir uns mal die restlichen 5 Prozeduren an.
Ein Programm kommt nicht ohne sequentielle Abläufe aus, da es oft so ist, dass eine Prozedur mit Ergebnissen einer anderen Prozedur arbeitet. Logischerweise können diese zwei Prozeduren nicht parallel laufen.
Für dieses Beispiel nehmen wir an, dass jeder Thread auf einer eigenen CPU laufen würde!
Für unser Beispiel denken wir uns mal, dass P4 mit Ergebnissen von P3 arbeitet und diese daher nicht parallelisiert werden können. Somit fallen wieder 2 Prozeduren aus, die man parallelisieren könnte.
Desweiteren benötigt P6 die Daten aller Prozeduren die davor liefen und kann daher auch nicht ausgelagert werden!
Somit bleiben uns zwei Prozeduren, die wir in einen andren Thread packen könnten. Was ca. so aussehen würde:
Darstellung 2: Asynchroner Programmablauf mit 2 Threads
Wie man sieht konnten wir in diesem Programm P2 und P5 erfolgreich in einen zweiten Thread auslagern. Doch was heißt das für unser Programm? hier ein kleines Rechenbeispiel:
Nehmen wir an, dass jede Prozedur eine Laufzeit von 5 Sekunden hat, das würde bedeuten, dass unser Programm wie in Darstellung 1 aufgeführt 35 Sekunden benötigen würde, um durch zulaufen.
Da bei dem Programm aus Darstellung 2, 2 Prozeduren "Parallel" ablaufen, verringert sich die Zeit auf 25 Sekunden. Also eine Ersparnis von knapp 30 %!
Natürlich ist das hier eine Ausnahme, denn es wird wohl kein Programm geben, dessen Prozeduren alle Gleichschnell sind, was uns zu unserem Nächsten Problem führt!
Denn wenn die Prozeduren nicht alle gleich schnell sind kann es zu Verzögerungen kommen! Das ist so, als wenn man Einen Tisch bauen will, und bestellt die Tischbeine bei Amazon und die Tischplatte bei Ebay. Den Tisch wirklich zusammenbauen kann man erst wenn beide Teile da sind! Fehlt eins der Teile muss man warten bis das andere auch ankommt!
Wenn wir das nun auf unser Programm aus Darstellung 2 beziehen heißt das, P6 erst weiter machen kann, wenn sowohl P4 als auch P5 Abgeschlossen sind! Wenn P4 zB. schneller fertig ist dann pausiert der erste Thread solange bis der zweite fertig ist! Dies kann zu unangenehmen Effekten führen, die das Programm sogar verlangsamen können statt es zu beschleunigen!
Wenn P2 und P5 also 6 Sekunden benötigen würden statt 5 würde die Laufzeit unseres Programms sich um 2 Sekunden verlängern also 27!
Nun könnte man aber sagen, P2 und P5 sind ja nicht von einander abhängig also lagere ich diese zwei Prozeduren auch noch aus:
Darstellung 3: Asynchroner Programmablauf mit 3 Threads
Hier müsste P6 auf die Fertigstellung von P4, P2 und P5 warten!
Das würde allerdings nur Sinn machen, wenn die Prozeduren P2 und P5 in der Summe länger brauchen würden als P3 und P4! Denn wenn P2 und P5 zusammen schneller sind als als P3 und P4 würde dieses erneute Auslagern nichts bringen, da sie sowieso schneller fertig wären als P3 und P4!
Wie man sieht wurde unser Programm durch die Auslagerunggen von Prozeduren um fast ein Drittel schneller! Aber man sieht auch, dass unser Programm auch nicht schneller werden würde wenn man 10 oder 100 CPUs hätte! Da wir sowieso nur 2 CPUs benutzen bringen uns die restlichen CPUs nichts da wir unser Programm nicht weiter aufteilen können!
Besonders Sinn macht es Prozeduren auszulagern, die viel Zeit in Anspruch nehmen. Denn wenn man solche Prozeduren Sequentiell abarbeitet blockieren diese den Ganzen Ablauf! Besonders Schleifen machen das ganz gerne!
Wenn man zb. eine Grafische Oberfläche hat und eine lange Prozedur im selben Thread (der auch die GUI verwaltet) startet, reagiert diese solange nicht mehr bis diese Prozedur durchgelaufen ist! Dann sieht man meist folgendes:
Bild 3: Man beachte das "Keine rückmeldung"
Um das zu verhindern sollte man längere Schleifen und Rechenoperationen immer in einen Hintergrund Thread verschieben damit die Oberfläche weiterhin bedienbar bleibt!
Ansich ist Threading sehr nützlich wir haben nun einige Vorteile kennengelernt wie den Performancegewinn, aber auch Nachteile gefunden, wie etwa Verzögerungen. Aber auch bei der Programmierung von Threads gibts einige Gefahren die man nur durch genaues Debuggen finden kann!
An dieser Stelle möchte ich ein Beispiel bringen, welches die Problematik darstellt!
Nehmen wir an, wir haben ein Programm, dass für ein Ehepaar das Konto verwaltet! Jeder der beiden hat dabei seinen eigenen Thread, der für den Ehepartner das Geld vom Konto abhebt! Die Hauptaufgabe unseres Programms ist es dafür zu sorgen, dass man das Konto nicht überbelastet also mehr abhebt als drauf ist!
Ein typischer Programmablauf wäre dann wie folgt:
### Programmstart Verbinde mit Konto Frage wieviel Geld abgehoben werden soll speichere den gewünschten Betrag in Variable $Betrag Prüfe ob $Betrag kleiner ist als der Betrag auf dem Konto Wenn genug Geld auf dem Konto vorhanden ist Hebe $Betrag vom Konto ab Trenne Verbindung ### Programmende
Beide Threads (von beiden Ehepartnern) laufen dabei Parallel, damit der eine nicht waren muss und immer sofort Zugriff hat.
Auf den ersten Blick sieht das Programm sicher aus, man prüft ob genug Geld auf dem Konto ist bevor was abgehoben wird. Totsicher - oder?
Eigentlich ja, wenn das Programm nur in einem Thread laufen würde! Denn es könnte ja zu dem Fall kommen, dass beide Ehepartner gleichzeitig Geld abheben wollen:
Nehmen wir an auf dem Konto sind 100 Euro!
Dann würde folgendes passieren: Beide wollen 70 Euro abheben, nun würden die Threads "gleichzeitig" prüfen, ob genug Geld auf dem Konto ist. Und da sie beide "gleichzeitig" prüfen und noch keiner Geld abgehoben hat ist die Bedingung erfüllt und beide Threads heben 70 Euro vom Konto ab, da sie ja vorher geprüft haben, ob genug Geld da war - und es war ja auch genug da!
Als Ergebnis hätten wir einen neuen Kontostand von -40 Euro - genau das was wir mit dem Programm verhindern wollten!
Ähnliche Probleme können auftreten, wenn mehrere Threads mit mit der selben Datenquelle arbeiten. Wenn zB. Thread 1 eine Datei löscht auf die Thread 2 noch zugreifen will, stürzt das Programm mit einer Exception ab!
Man müss also Möglichkeiten suchen solche Probleme zu erkennen und vorzubeugen! Das werde ich dann im Teil 2 dieser Serie an Hand von ein paar Beispielen behandeln!
VB.NET/PHP: Kurze URLs erstellen mit Tinyurl Teil 1
Sie sind sehr beliebt und es werden immer mehr! Sogenannte URL-Shorter wie Tinyurl.com, bit.ly oder wie sie alle heißen. Diese kleinen Dienste verkürzen beliebig lange URLs in kleine handliche "URLchen".
Dienste wie Twitter, bei denen es auf die Länge der Beiträge ankommt können ohne diese Dienste nicht mehr leben, weswegen Twitter sogar die Nutzung von bit.ly vorschreibt!
Bild 1: Ein ICQ 6 Chatfenster mit einer E-BAy-URL die nun einen Smiley enthält
Aber auch eigene Projekte, egal ob online oder offline können so etwas gut gebrauchen. Denn wenn man zb eine E-Bay URL weiter geben möchte ist diese nicht selten mehrere Zeilen lang und wird, je nach Programm falsch dargestellt. Plötzlich enthalten die URLs Smileys die durch Kombinationen wie "=p" oder "8)" in der URL entstehen!
Das ist sehr unangenehm, da der Link dann auch nicht mehr angeklickt werden kann und man den Fehler erst wieder ausbügeln muss. Da erspart so ein Dienst natürlich viel Zeit!
Gut für uns, dass viele der Anbieter auch eine API für ihren Dienst anbieten. So können auch wir Gebrauch davon machen und Vorgänge automatisieren.
Wenn man bei Google nach "tinyurl API" sucht wird man sehr schnell fündig und erfährt, dass man einfach nur die URL "'http://tinyurl.com/api-create.php?url=" aufrufen muss und dann seine zulange URL dahinter packen kann.
Als Ergebnis kommt dann eine gekürzte Version raus!
Wie setzen wir das nun im Code um? Wir müssen ersteinmal auf die Internetseite zugreifen, und das Ergebnis herunterladen!
Das wars auch schon! Hier ist unsere Funktion:
Public Function shortURL(ByVal langeURL As String)
Dim retVal As String = ""
'Den API-Aufruf starten:
Dim myRequest As WebRequest = WebRequest.Create _
("http://tinyurl.com/api-create.php?url=" & langeURL)
Dim myResponse As WebResponse = myRequest.GetResponse
'Den erzeugen Strom auslesen
Dim myReader As StreamReader = _
New StreamReader(myResponse.GetResponseStream)
'Stream auslesen
retVal = myReader.ReadToEnd
myReader.Close()
Return retVal
End Function
Wie man sieht wird nichts anderes gemacht, als oben beschrieben!
Naja, man muss dazu sagen, dass tinyurl.com der wohl "einfachste" Anbieter ist, da dieser einfach nur die "nackte" URL zurück gibt. Deswegen habe ich das hier auch als Beispiel gewählt!
Noch einfacher lässt sich das Ganze in PHP ausdrücken:
//PHP Code:
function TinyURL($u){
return file_get_contents('http://tinyurl.com/api-create.php?url='.$u);
}
So kann man sehr angenehm seine langen URLs kürzen und seine Besucher erfreuen
Ich habe hierzu ein kleines Beispiel in VB.NET angefertigt, das ihr bei Interesse herunterladen könnt!
Bild 2: Das Demoprogramm in Aktion
Download Hier: Download
Wenn bei euch Interesse besteht stelle ich euch auch die anderen Anbieter wie zB. bit.ly vor und fertige ein Beispiel zu deren API an. Gebt einfach per Mail oder Kommentar bescheid!
.NET: Parallelprogrammierung
Heutzutage haben die meisten Computer und auch Laptops Prozessoren mit mehreren Kernen. Das wollen natürlich viele Programmierer für sich nutzen um ihre eigenen Programme zu beschleunigen.
Bild 1: Eine Intel CPU mit 4 Kernen
An dieser Stelle kommt das Stichwort "Multithreading" ins Spiel! Doch leider denken viele, dass wenn man mehrere Threads innerhalb eines Programms erstellt, diese dann auch auf verschiedenen Prozessoren ausgeführt werden. Doch dies ist leider nicht so!
Denn auf welchem Prozessorkern ein Thread läuft entscheidet der Thread-Sheduler des Systems, außer man sagt ihm was anderes. So werden alle Threads eines Programms meistens nur auf einem Prozessor ausgeführt und laufen somit nicht parallel sondern sequentiell!
Es sieht zwar aus, dass die beiden Threads gleichzeitig arbeiten, dem ist aber nicht so! Also ist multithreading nicht gleich parallel!
Denn nur wenn ein Programm parallel auf zwei Kernen läuft erzielt man auch einen Performance Gewinn, da erst dann die Threads wirklich parallel laufen! So kann auch Multithreading auf einem SingleCore CPU zu Performanceeinbußen kommen, da das erstellen der Threads und das Hin- und Herschlalten zwischen den Threads Zeit kostet!
Was dazu kommt ist, dass Parallelprogrammierung sehr komplex ist und es zu unvorhergesehenen Problemen kommen kann. Zum Beispiel können die so genannten "Dead Locks" entstehen, wenn zB. "Thread A" den Wert einer Varibale löscht, die "Thread B" aber noch benötigt! Ein Crash ist vorprogrammiert!
Hier müssen "Synchronistations" Techniken angewandt werden um die Bildung solcher Fehler vorzubeugen, die nur sehr schwer durch debugging entdeckt werden können!
Das ist ein sehr großes Thema, das ich demnächst auch in einer Serie weiter vorstellen werde und auch einige Beispiele dazu anfertigen!
Bisdahin kann ich euch den MSDN-Webcast zu diesem Thema empfehlen, der vom Einstieg über die Probleme auch einige Beispiele bietet! Zu finden hier!
Zusammenwohnen mit Google: Fluch oder Segen?
Was wäre wenn Google eine reale Person wäre? Und was wäre wenn ihr mit dieser Person zusammen wohnen würdet?
Diese Gedanken haben sich "The Big Honkin'" gemacht und haben das auch auf Video festgehalten!
Dabei sieht man schnell, dass alle Googles nützlichen Features dann doch etwas zu weit gehen, und dass nicht alle Menschen ihre persönlichen Informationen verbreiten möchten!
Besonders interessant und gut gemacht finde ich das Auftreten von Double Click, der Personen nahe Informationen schnell verarbeitet und in Geld verwandelt!
Etwas übertrieben aber durchaus realistisch sind auch die Szenen wo Google zu tief in die Privatsphäre eingreift und peinliche Bilder und Videos zeigt und nach einer Beschwerde dann vorschlägt die "Privacy Settings" zu ändern. Einfach herrlich!
Folge 1:
Folge 2:
Folge 3:
Codeklau & wie man eigenen Code schützen kann Teil 2
In diesem zweiten Teil werde ich darauf eingehen, wie man seinen Code möglichst gut schützen kann. Natürlich gibt es keinen 100%igen Schutz aber man kann es jemandem durchaus schwer machen an seinen Code zu kommen.
Es gibt mehrere Ansätze wie man das Problem angehen kann. Zum Einen wäre da die Möglichkeit unseren .NET Code nicht in ein Assembly sondern in eine native Anwendung zu kompilieren. Das würde die Dekompilierung um einiges erschweren.
Dafür stellt und Microsoft mit dem .NET Framework bereits ein Tool zur Verfügung. Dieses kann eure Assemblys in Maschinencode compilieren, tut also das was der JIT-Compiler sonst erst bei der Ausführung machen würde! Dies hat den Vorteil, dass die Anwendung schneller arbeitet, da sie direkt ausgeführt werden kann, aber wird erheblich größer, da alle .NET Abhängigkeiten nun in das Programm integriert werden müssen. Es kann nun sogar ohne ein Installiertes .NET Framework ausgeführt werden!
Das Programm was das für uns erledigt nennt sich "ngen.exe" und ist ein Kommandozeilen Programm. Im MSDN gibts eine umfassende Anleitung für das Programm weswegen ich hier nicht auf die Funktionsweise eingehen werde!
Leider bringt diese Art der Kompilierung einen entscheidenden Nachteil mitsich, nämlich dass das Programm die Plattformunabhängigkeit verliert und meistens nurnoch auf dem eigenen Rechner (auf dem es erstellt wurde) benutzt werden kann! Also müssen wir uns etwas anderes einfallen lassen!
Und tatsächlich gibt es eine weitere Möglichkeit seinen Code zu schützen und dennoch keine Nachteile aufkommen zu lassen! Das Visual Studio bringt bereits ein Programm mitsich das uns da helfen kann! Das ist der sogenannte "Dotfuscator Community Edition" den man über das "Extras"-Menü in Visual Studio aufrufen kann!
Diese "Ofuscatoren" machen dann, simpel ausgedrückt, den Quelltext schlechter lesbar. Was sich so simpel anhört ist aber sehr effektiv! Wie ich an einem Beispiel demonstrieren möchte:
Hier ersteinmal der Quelltext den wir geschrieben haben in der Originalform:
private void CalcPayroll(SpecialList employeeGroup) {
while (employeeGroup.HasMore()) {
employee = employeeGroup.GetNext(true);
employee.UpdateSalary();
DistributeCheck(employee);
}
}
Und nun das Ergebnis des Obfuscators:
private void a(a b) {
while (b.a()) {
a = b.a(true);
a.a();
a(a);
}
}
Wie man sieht kann man nicht mehr so einfach darauf schließen was diese Funktion eigentlich machen soll, da alle für den Menschen logischen Bezeichner fehlen!
Was macht der Obfuscator also genau? Seine Hauptaufgabe ist natürlich den Quelltext nach dem Dekompilieren für den Menschen möglichst unleserlich zu machen. Das wird dadurch erreicht, dass alle Bezeichner und alle Texte die im Quelltext vorkommen durch zufallsgenerierte Bezeichner ersetzt werden. Denn dem Computer ist es egal, ob eine Variable "anzahlBenutzer" oder "3Fdg4§§s" heißt. Aber der Benutzer der den Quelltext liest ist natürlich sehr verwirrt da er nichts mit diesen Bezeichnungen anfangen kann.
Es gibt auch andere Dritthersteller, die Software anbieten die genau das machen soll, nur besser versteht sich! Ich habe zum testen mal den Phoenix Protector, teLock und den im Visual Studio integrierten Dotfuscator ausprobiert.
Wobei ich teLock nicht weiter behandeln werde, da alle daraus erzeugten Programm nicht lauffähig waren und immer abgestürzt sind!
Wie kann man selbst vorgehen um zu testen wie gut sein Programm geschützt ist? Ganz einfach, indem man so vorgeht als ob man ein fremdes Programm "knacken" würde. Dazu können wir uns dem Tool .NET Reflector bedienen, das ich im ersten Teil vorgestellt habe!
Ich werde hier als Beispiel mal das Tool aus dem Beitrag "Den Office Lizenzschlüssel aus der Registry auslesen" verwenden. Wenn wir das Programm dekompilieren dann sehen wir ca dieses Bild:
Bild 1: Office Key Finder im Dekompilierten Zustand
Wie man sieht konnte das Programm komplett dekompiliert werden und man kann in dem Quelltext wunderbar lesen (rechts)! Ich habe des weiteren die Stellen hervorgehoben, wo man die Original Namen der Variablen und Funktionen erkennen kann! - So sieht eine ungeschützte .NET Anwendung aus.
Nun habe ich den Phoenix Protector mal drüber laufen lassen und die selben stellen markiert.
Bild 2: Dieses Mal ist der Quelltext viel schlechter lesbar!
Wie man sieht haben nun alle Klassen, Funktionen und Variablen ganz andere unlogische Namen bekommen die in keinster weise deren Funktion wiederspiegeln!
Bild 3: Der Dotfuscator beschränkt sich auf das nötigste
Bild 3 zeigt das Ergebnis des im Visual Studio eingebauten Dotfuscators. Dieser hat sogar die Klassenstruktur geändert und auf das nötigste reduziert! (links)
Ich war aber mit dem Ergebnis des Phoenix Protectors besser zufrieden, denn nach etwas herumspielen mit den Einstellungen konnte ich den Quelltext so gut "tarnen", dass selbst der Disassambler diesen nicht mehr auflösen konnte und sich mit einem Fehler verabschiedete!
Bild 4: Das perfekte Ergebnis, der Quelltext lässt sich nicht mehr einsehen!
Das ist natürlich ein super Ergebnis! Ich habe es nicht an weiteren Programmen ausprobiert, aber ich denke nicht, dass man immer dieses Ergebnis haben wird und natürlich muss man im Hinterkopf behalten, dass auch das nicht sicher ist sondern auch mit genug Zeit ebenfalls geknackt wird!
Auch wenn diese Methode keinen perfekten Schutz bietet (den es eh nicht gibt!) ist sie trotzdem effektiv! Alle Tools die ich hier benutzt habe sind auch kostenlos und leisten dafür sehr viel! Ausprobieren lohnt sich! Als Alternative die aber auch was kostet kann ich euch .NET Reactor ans Herz legen. Dieses Tool arbeitet ebenfalls sehr gründlich sodass es teilweise nicht möglich ist zu dekompilieren kostet aber auch knappe 200 €!
Gut, kommen wir zu der dritten und auch sichersten und besten Lösung! .NET bietet uns die Möglichkeit auf fremdcode zuzugreifen zb. aus der Windows-API oder eigenen DLLs. Man kann auch Code aus dem Internet nachladen oder bestimmte Dienste in WebServices auslagern.
Und das Sollte man machen! So kann man das Hauptprogramm gerne in .NET schreiben, aber man sollte dann die besonders aufwendigen und geheimen Algorithmen und Prozeduren in eigene Native DLLs auslagern, die man dann wiederum ins Programm einbinden kann!
Das garantiert eine einfache Arbeit und höchste sicherheit! Denn auch wenn man dann das Hauptprogramm dekompiliert, ist der wichtige Teil immernoch sicher in der DLL verpackt!
Zum Schluss nochmal: hier habe ich nur .NET behandelt natürlich gibt es auch für Java und auch für Javascript Obfuscators die den selben Job machen, diese aber ebenfalls vorzustellen würde den Rahmen aber sprengen!
Ich hoffe dieser Zweiteiler hat euch gefallen und freue mich auf euer Feedback!
Interessiert dich dieses Thema? Möchtest du hier mehr Beiträge darüber lesen? Schreib ein Kommentar was dir gefallen hat oder was nicht.
Codeklau & wie man eigenen Code schützen kann Teil 1
In dieser Reihe möchte ich darüber schreiben welche Probleme die Arbeit mit modernen Programmiersprachen mit sich bringt und wie man diese möglichst eindämmen und gering halten kann.
In dem ersten Teil werde ich darauf eingehen, wie und warum es möglich ist Code aus fertigen Applikationen zu extrahieren.
Das größte Problem, das jeder Closed-Source Programmierer hat, ist es den erstellten Code nicht für andere einsichtbar zu halten damit dieser nicht geklaut oder ohne Einwilligung oder Lizenzzahlungen weiterverwendet werden kann!
Aber wie ist es überhaupt möglich Code zu klauen wenn mann nur die fertige Applikation hat?
Zuerst sollte man sagen, dass es keinen 100%igen Schutz gibt! Alles kann geknackt oder modifiziert werden. Alle Firmen, die das gegenteil versprechen sind einfach nur unprofessionell. Denn alle Schutzmechanismen die es gibt sorgen lediglich dafür, dass man mehr Aufwand aufbringen muss, um diese wieder zu umgehen.
Früher war Codeklau noch sehr harte Arbeit, denn früher waren alle Anwendungen kompiliert, wurden also beim Erstellen direkt in Maschinencode gewandelt! Diesen Maschinencode wieder in lesbaren Quelltext zu wandeln ist sogut wie unmöglich, was man aber machen kann ist es diesen zu "Deassimblieren" (engl. Disassamble). Bei diesem Vorgang wird der vorliegende Native Code (Maschinencode) in ein für den Menschen lesbaren Assembler Code umgewandelt.
Was man hier noch wissen sollte, ist dass früher (vor langer langer Zeit) alles in Assembler programmiert wurde. Assembler ist eine Sprache, die es dem Programmierer Erleichtert Code zu schreiben, dabei werden Befehle benutzt die der Prozessor, auf dem später der Code ausgeführt werden soll versteht. Somit muss man sich nicht mit Nullen und Einsen herumschlagen sondern hat was, was man auch einigermaßen lesen kann.
Grafik 1: So könnte ein Programm nach dem Disassamble-Vorgang aussehen
Hier findet ihr ein kleines Beispiel wie sich Assembler von einer Hochsprache wie zb. C++ unterscheidet!
Mit diesem erzeugten Assembler Code kann man nun weiter "arbeiten" und versuchen den Ablauf des Programms zu verstehen und diesen dann auch eventuell zu kopieren, zu klauen! Das ist natürlich je nach Größe extrem aufwendig und langwierig.
Übrigens: genauso gehen die so genannten "Cracker" vor wenn sie versuchen bestimmte Sicherheitmechanismen von Programmen oder Spielen zu deaktivieren. Sie suchen nach diesen Ereignissen in dem Assembler Code und versuchen diese umzuleiten oder zu löschen, sodass die "Gecrackte" Software dann anschließend zb. ohne gültige Lizenz oder ein Spiel ohne die Original CD im Laufwerk benutzt werden kann! Wer darüber mehr wissen will sollte einen Blick in die "Hacker-Bibel von Cyberdemon98" werfen.
Natürlich kann man mit diesem Vorgehen nicht wirklich Code "klauen" sondern mehr versuchen zu verstehen wie ein Programm arbeitet um dann zb. andere Programme darauf abzustimmen ("Schnittstellen" schafften). Diesen Vorgang nennt man dann reverse Engeneering (deut. Umgekehrtes entwickeln).
Ein berühmtes Beispiel dafür ist der Instant Messaging Dienst ICQ, dieses Unternehmen hat keinerlei Spezifikationen über den Dienst oder das Protokoll veröffentlicht. Alle ICQ-Clients wie QIP, Miranda oder andere basieren komplett auf Reverse Engeneering! Deswegen kommt es auch oft, dass man sich gegenseitig keine Dateien schicken kann oder die Status-Nachricht eines Freundes lesen kann weil er einen anderen Client verwendet. Dies liegt einfach daran dass die Entwickler "raten" müssen wie diese Funktionen funktionieren und Kompabilitäten nur schwer geschaffen werden können! Dadurch geht ICQ sicher, dass nur ihr eigener Client perfekt funktioniert und alle Features beherrscht!
|
Grafik 2: Diese Schritte durchläuft C++ Code während der Compilierung |
Diese Codevariante, die so genannten unmanaged-code hervorbringt, der aus Maschinencode besteht erstellen die "alten" Programmiersprachen wie Delphi, C, VB6 und C++. Die Obere Grafik zeigt, dass nach der Kompilierung des Quelltextes, dieser noch weitere Schritte durchläuft und schließlich als Binäre Datei vorliegt, die nur auf einem bestimmten CPU-Typ und Betriebssystem läuft!
Die neueren Programmiersprachen wie etwa Microsofts .NET (Worunter auch C#, VB.NET fällt) oder Java verfolgen einen komplett anderen Ansatz der managed code erzeugt und förmlich zum Codeklauen einlädt!
Grafik 3: Compilierung von Managedcode Programmen (.NET & Java)
Die Sprachen, die managed Code erzeugen, erzeugen nämlich keinen Maschinencode sondern so genannte Assemblys welche eine Art Vorkompilierte Programme sind die nicht lauffähig sind.
Grafik 3 beschreibt im Oberen Teil, den Kompilierungs Prozess, der ziemlich einfach gestrickt ist. Der Code wird garnicht "Richtig" kompiliert sondern nur für die spätere Ausführung vorbereitet.
Warum ist das so? Nun heutzutage müssen Programme laufen, und nicht nur auf dem PC auf dem Sie geschrieben wurden sondern auch auf anderen und sogar auf anderen Betriebssystemen. Das ganze nennt sich dann Plattformunabhängigkeit!
Java Programm zb. können auf allen gängigen Betriebssystemen ausgeführt werden. Egal ob Windows, Solaris, Mac OS oder Linux Java Programme funktionieren! Und damit das möglich ist dürfen die Programme nicht kompiliert werden!
Denn wenn ein Programm kompiliert wird wird es in Maschinencode umgewandelt. Und da jede Prozessorarchitektur einen eigenen Maschinencode hat und jedes Betriebssystem auch anders aufgebaut ist kann ein kompiliertes Programm immer nur auf dem System ausgeführt werden für das es kompiliert wurde!
Um dieses Problem zu umgehen werden Java Programme nur Vorkompiliert (zu so genannten Assemblys) und dann wenn die gestartet werden (egal auf welchem Betriebssystem) werden sie erst "richtig" kompiliert, für das System auf dem sie gerade gestartet werden!
Warum ist das gut? Naja, so kann man ein Programm schreiben, und es ohne daran viel zu machen auf allen Systemen benutzen. Leider hat das System auch viele Schattenseiten, denn um ein solches vorkompiliertes Programm ausführen zu können muss eine Virtuelle Maschine installiert sein, die unser vorkompiliertes Programm "zu ende kompiliert" im Falle von Java ist es die JVM (Java Virtual Machine) diese kompiliert das Programm passend zum Betriebssystem und sorgt für dessen korrekte Ausführung.
Desweiteren sind diese Programme natürlich auch langsamer als die Nativen, denn zb. die Java Programme müssen vor deren Start erst kompiliert werden und laufen in einer Virtuellen Maschine, was natürlich auch Geschwindigkeitseinbußen. (vergleichbar mit einem Virtuell ausgeführten Betriebssystem durch VMWare und co)
Aber nun schweife ich schon wieder ab! Was wichtig ist, ist dass die Managedcode Programme nicht in Maschinencode kompiliert werden. Der Zustand in dem sie dann verweilen macht es uns sehr leicht das Programm wieder zurück in Quelltext zu verwandeln und diesen dann zu Klauen!
Dieser Vorgang, bei dem eine Kompilierte Datei wieder in lesbaren Quelltext verwandelt wird nennt man Dekompilierung. Anders als beim Disassambling wird hierbei der Original Quelltext den der Programmierer geschrieben hat fast perfekt wiederhergestellt!
Davon sind alle managedcode Sprachen betroffen, da sie alle nach dem Prinzip aus Bild 3 arbeiten! (zb. Java, C#, VB.NET)
Für jede Sprache gibt es auch den passenden Decompiler, der den Original Quellentext in Sekunden herausspuckt! Viele dieser Decompiler sind hochkomplexe Programme und deswegen auch nicht kostenlos! Besonders wenns an das dekompilieren von Nativen Programmen geht wird man keine kostenlosen Programme finden die brauchbare Ergebnisse liefern!
Um Java Programme (.jar-Dateien) zu dekompilieren empfehle ich den JD Java Compiler, dieser ist kostenlos und arbeitet sehr zuverlässig!
Bild 4: Der Java Decompiler in Action
Natürlich muss man auf so etwas wie Kommentare und Ordnungen verzichten, da diese bei dem Kompilierungs Prozess automatisch aus dem Quelltext gelöscht werden, da der Prozessor damit nix anfangen kann!
Um .NET Programme oder DLLs zu dekompilieren, wobei hier disassimbliren besser passt kann ich das Tool .NET Reflector von Redgate empfehlen, es ist einfach zu benutzen und funktioniert perfekt!
Bild 5: Arbeiten mit dem .NET Reflector
Das Gute hierdran ist, dass man sogar in die .NET System Prozesse schauen kann um diese besser zu verstehen! Dieses Programm ist ebenfalls kostenlos nach einer Registrierung zu haben!
Wer das ganze mal ausprobieren will kann das gerne ja mal machen. Sucht euch einfach mal ein einfaches Java Programm, dabei ist es egal ob es ein Desktop Java Programm ist ober ein Mobile Programm aus dem J2ME. zb. den Opera Mini und schaut euch mal dessen Innereien an.
Wenn ihr mal ein .NET Programm dekompilieren wollt kann ich für den Einstieg eins der Programme empfehlen, die ich hier im Blog veröffentlicht habe. (Schaut zb. in dem Letzten Beitrag. Ladet die Beispiel Datei herunter und entpackt den Ordner und geht in den Ordner TreeViewDemo\bin\debug\ dort müsstet ihr eine .exe Datei finden an der ihr euch austoben könnt!)
Als Ergänzung will ich noch sagen, dass ein Programm immer in managedcode UND in unmanagedcode kompiliert werden kann und somit manchmal nicht (so einfach) dekompiliert werden kann!
Wie man seinen Code schützen kann werde ich dann in dem zweiten Teil behandeln, da der hier ja schon ein bissl zuu lang geworden ist!
Interessiert dich dieses Thema? Möchtest du hier mehr Beiträge darüber lesen? Schreib ein Kommentar was dir gefallen hat oder was nicht.
Opera will morgen das Internet neu erfinden
Am Wochenende hat Opera angekündigt das Internet neu zu erfinden. Was genau das heißen soll weis man leider noch nicht auf der Homepage http://www.opera.com/freedom/ ist lediglich eine Ankündigung für den morgigen Tag zu sehen.
Die ganze Ankündigung hat auch nichts mit dem baldigen Release der 10 Version des Brosers zu tun.
Wenn man in den Quelltext der Seite schaut findet man folgendes Kommentar:
We start our little story with the invention of the modern day computer. Over the years, the computers grew in numbers, and the next natural step in the evolution was to connect them together. To share things. But as these little networks grew, some computers gained more power than the rest and called themselves servers ...
Weiter oben im Kopf der Seite findet man noch :
"The Web is your browser. Discover how fast and fun the Web can be."
Wie es aussieht geht es Opera darum das Internet schneller zu machen. Hierfür hat Opera schon verschiedene Techniken vorgestellt wie zb den Opera Mini der die Internetseiten komprimiert lädt und somit Zeit und Traffic spart!
Aber der AUsdruck "The Web is your Browser" könnte auch darauf hinweisen, dass Opera eine art Ajax Browser entwickelt hat, der selbst in dem Browser läuft. - Dies ist aber nur meine eigene Spekulation.
Desweiteren hat ein Opera Mitarbeiter per Twitter verlauten lassen, dass er "das Internet auf einen USB-Stick getan hat, so dass man jederzeit eine Verbindung hat, egal wo man sich befindet."
Man darf also gespannt sein was morgen auf uns zukommt!
Hulu.com blockt Hotspot Shield
Nun ist es doch passiert, der beliebte Videodienst hulu.com blockt nun alle Hospot Shield Nutzer.
Hulu ist ein Amerikanisches Video Portal, dass im Gegensatz zu YouTube ganze Serien anbietet, die fast zeitgleich im Netz wie im Fernsehen auftauchen. Dieser Dienst wird mit Werbung finanziert!
Leider ist dieser Dienst aber nciht in Deutshland verfügber, sondern nur für US-Bürger! Dies kann man mit Proxys ganz einfach umgehen. Der beliebteste war hier der Hotspot Shield! (ich habe darüber auch geshrieben) So konnte man auch aus Deutschland bequem die Serien gucken! - Doch leider wird dies nun geblockt und es erscheint nurnoch folgende Melsung:
Wer auf hulu nicht verzichten kann muss sich einen anderen Proxy oder VPN Dienst suchen. Wobei die kostenlosen Dienste oft überladen sind und ein gescheites gucken ist nicht möglich. Eine Brauchbare Alternative ist ein bezahlter VPN Tunnel wie UKiPVN die einen eigenen VPN Dienst anbieten, der sowohl auf Mac Windows und sogar iPhone läuft!
VB.NET: DNS Namen in IPs auflösen
In diesem Beitrag möchte ich euch zeigen, wie einfach es ist in VB.NET einen DNS Namen in eine oder mehrere IPs umzuwandeln.
Um dies zu verwirklichen stellt uns .NET das namespace System.Net zur Verfügung, das die nötigen Funktionen enthällt!
Erstellt ein neues Formular mit folgendem Form_Load() Event:
Private Sub Form1_Load() Handles MyBase.Load
Dim adressen As String = ""
Try
Dim hostInfo As IPHostEntry = Dns.Resolve(InputBox("DNS"))
Dim address As IPAddress() = hostInfo.AddressList
For index = 0 To address.Length - 1
adressen = adressen & address(index).ToString & vbNewLine
Next index
Catch
End Try
MessageBox.Show(adressen)
End
End Sub
Hier wird nichts anderes gemacht, als zu Beginn nach einer Eingabe zu fragem (InputBox) die dann in in eine IP umgewandelt wird. Dann erstellen wir einen IPAdress Array und speichern die Ergebnisse dort.
Anschließend werden alle IPAdressen in einem String gespeichert und in einer MessageBox ausgegeben!


