Freitag, 28. September 2012

Passwort Generator

Heute möchte ich einen in C# geschriebenen "Passwort Generator" vorstellen. Der Name ist vielleicht etwas irreführend, es geht darum, dass das Programm alle möglichen Passwörter einer bestimmten Länge erzeugt und speichert, sodass diese zum Beispiel für einen Brute-Force-Angriff genutzt werden können.

Der Generator ist in einer Klasse gekapselt, beim Anlegen einer Instanz davon wird ein neuer Thread gestartet, welcher die Passwörter generiert und in eine Queue (Warteschlange) schreibt. Diese kann dann von außen abgefragt werden, sodass die Erzeugung der Passwörter und ein eventuelles Benutzen der Passwörter getrennt voneinander bzw. parallel geschehen kann.
Das Erzeugen der Passwörter geschieht in der Funktion FillQueue(). Hier zählt eine Schleife von der übergebenen minimalen bis maximalen Länge des Passworts durch und nach dem Prinzip der Rekursion wird für jede dieser Stellen die Funktion SetLetter() aufgerufen.
Diese durchläuft alle möglichen Zeichen (in meinem Programm kann eingestellt werden, dass die Zeichen A-Z, a-z sowie 0-9 benutzt werden), stellt die aktuelle Position auf das aktuelle Zeichen ein und ruft die Funktion mit der nächsten Stelle auf. Ist die letzte Stelle erreicht, wird das aktuelle Passwort in die Queue geschrieben.
Über die öffentliche Funktion Dequeue() der Klasse wird das unterste Element aus der Warteschlange entfernt und zurückgegeben, auf diese Weise können die erzeugten Passwörter abgerufen werden.

Der Code:
public class PasswordGenerator
    {
        Queue<string> Results; // Warteschlange mit erzeugten Passwörtern

        bool UpperAZ; // true wenn Großbuchstaben benutzt werden sollen
        bool LowerAZ; // true wenn Kleinbuchstaben benutzt werden sollen
        bool Numbers; // true wenn Zahlen benutzt werden sollen

        int Min; // minimale Länge des Passworts
        int Max; // maximale Länge des Passworts

        const int MaxQueueSize = 30000000; // maximale Zahl von Passwörtern, die gleichzeitig in der Queue gespeichert werden dürfen (Schutz vor Speicherüberlauf)

        public PasswordGenerator(bool upperAZ, bool lowerAZ, bool numbers, int min, int max)
        {
            UpperAZ = upperAZ;
            LowerAZ = lowerAZ;
            Numbers = numbers;

            Min = min;
            Max = max;
            Results = new Queue<string>();

            // neuen Thread zur Passwortgenerierung erstellen und starten
            Thread Creator = new Thread(new ThreadStart(FillQueue));
            Creator.Start();
        }

        private void FillQueue()
        {
            // Warteschlange füllen
            for (int i = Min; i <= Max; i++)
            {
                SetLetter(i, 0, "");
            }
        }

        private void SetLetter(int length, int pos, string temp)
        {
            // aktuelle Position mit allen möglichen Zeichen füllen
            if (UpperAZ)
            {
                for (int i = 65; i <= 90; i++)
                {
                    NextStep(length, pos, temp + (char)i);
                }
            }
            if (LowerAZ)
            {
                for (int i = 97; i <= 122; i++)
                {
                    NextStep(length, pos, temp + (char)i);
                }
            }
            if (Numbers)
            {
                for (int i = 0; i <= 9; i++)
                {
                    NextStep(length, pos, temp + i.ToString());
                }
            }
        }

        private void NextStep(int length, int pos, string temp)
        {
           // Funktion zum Abschließen eines Schrittes

           // ist die Warteschlange "voll", wird der Thread pausiert
           while (Results.Count > MaxQueueSize)
               Thread.Sleep(500);

            // ist noch nicht die Endposition im Passwort erreicht, wird SetLetters() mit der nächsten Position aufgerufen
            if (pos < length - 1)
                SetLetter(length, pos + 1, temp);
            else
                // ansonsten wird das aktuelle Passwort der Warteschlange hinzugefügt
                Results.Enqueue(temp);
        }

        public string Dequeue()
        {
            // liefert das unterste Element der Warteschlange
            if (Results.Count > 0)
                return Results.Dequeue();
            else
                return "";
        }
    }
Die Initialisierung des Generators erfolgt dann über
PasswordGenerator Generator = new PasswordGenerator(true, true, true, 1, 4);
Das Abfragen eines Passwortes über
Generator.Dequeue();

Dienstag, 25. September 2012

Passwort eines Word Dokuments automatisiert überprüfen

Nachdem ich im vorigen Post Grundlegendes zur Einbindung von Microsoft Office Word erklärt habe, möchte ich heute nochmal speziellen Augenmerk auf das Öffnen von passwortgeschützten Dokumenten legen.
Mit folgendem Code lässt sich überprüfen, ob ein Passwort das richtige zum Öffnen des Dokumentes ist.
Durch Iteration kann so beispielsweise auch automatisiert nach einem Passwort gesucht werden.
            Object oMissing = System.Reflection.Missing.Value;

            Word.Application WordApp = new Word.Application();

            try
            {
                Word.Document ExistingDocument = WordApp.Documents.Open("Dateiname", oMissing, false, oMissing, "Passwort");
                MessageBox.Show("Richtiges Passwort");
            }
            catch (System.Runtime.InteropServices.COMException ex)
            {
                MessageBox.Show("Falsches Passwort");
            }

Freitag, 21. September 2012

Word Tutorial

In diesem Post möchte ich zeigen, wie man C# und Microsoft Office Word verbindet. Ich werde zeigen, wie man mit C# neue Word Dokumente erstellt, Texte einfügt, Einstellungen vornimmt, Dokumente öffnet, speichert und anzeigt.
Zuerst müssen wir die entsprechende Komponente in unser Projekt einbinden, dies geschieht über Projekt - Verweis hinzufügen - COM - Microsoft Word xx Object Library. xx steht hierbei für die jeweilige Versionsnummer.
Dann benutzen wir den Code using Word = Microsoft.Office.Interop.Word, um auf das Word Objekt über das Wort Word zugreifen zu können.

Word Instanz erstellen und anzeigen:
Word.Application WordApp = new Word.Application();
WordApp.Visible = true;
Hiermit wird eine neue Instanz eines Word Objektes angelegt. Durch Aktivieren der Sichtbarkeit, wird dieses angezeigt. Da noch keine Dokumente geladen worden, wird einfach das graue Word Fenster angezeigt.

Neues Word Dokument erstellen:
Die Eigenschaft Documents der Instanz beinhaltet geöffnete Dokumente, zu dieser Aufzählung können wir nun Dokumente, z.B. durch Öffnen oder Erstellen, hinzufügen. Um ein neues Dokument zu erstellen, ist folgender Befehl nötig:
Word.Document NewDocument = WordApp.Documents.Add();

Dokument schließen
Hierfür ist die Funktion Close() zuständig, die von dem entsprechenden Dokument aufgerufen wird, also mit obigem Beispiel z.B.:
NewDocument.Close();

Bestehendes Word Dokument öffnen:
Object oMissing = System.Reflection.Missing.Value;
Word.Document ExistingDocument = WordApp.Documents.Open("Dateiname", oMissing, true, oMissing, "Passwort");
Alle Argumente außer dem ersten sind optional. Das 3. gibt an (true wenn ja), ob das Dokument schreibgeschützt geöffnet werden soll. Das 5. gibt ein eventuelles Passwort an.
Das Argument oMissing mit dem Wert System.Reflection.Missing.Value ist sehr praktisch, es liefert immer den Standardwert des aktuellen Arguments zurück und kann so einfach bei ungebrauchten Argumenten als Füller genommen werden.

Text einfügen
WordApp.Selection.TypeText("Hallo Welt");
Dieser Code tippt den angegeben Text in das jeweils oberste Dokument der Documents Aufzählung.

Formatierungen vornehmen Ebenfalls über die Selection Eigenschaft können Formatierungen vorgenommen werden. Werden diese vor einem TypeText Befehl durchgeführt, greifen sie beim geschriebenen Text. Es stehen alle bekannten Formatierungsoptionen zur Verfügung, z.B.:
WordApp.Selection.Font.Size = 20;
Dokument speichern Ein Dokument kann entweder über die parameterlose Funktion Save() oder über SaveAs2() gespeichert werden. Letztere erwartet den Speicherpfad.

Word Instanz beenden
WordApp.Quit();

Mittwoch, 19. September 2012

Systemwiederherstellungspunkt erstellen

Im heutigen Post möchte ich zeigen, wie man mit C# einen Systemwiederherstellungspunkt anlegt.
Dafür benutzen wir Management Klassen, welche sich mit der Windows Management Instrumentation (WMI) verbinden und so Informationen über den PC auslesen.
Damit das Programm läuft, muss mittels Projekt - Verweis hinzufügen System.Management eingebunden werden und dises zusätzlich mittels using. Außerdem muss das Programm mit Administratorrechten ausgeführt werden.
Zentral ist eine Instanz der Klasse ManagementClass.
Deren Konstruktor erwartet 3 Parameter:
Zuerst einen Scope, der hier auf den lokalen PC festgelegt wird, dann einen Pfad, welcher die auszuführende Operation defininiert (hier Wiederherstellungspunkt erstellen) und zuletzt eine Klasse mit Optionen, hierfür übergeben wir die Standardoptionen eines WMI Aufrufs.
Von der erzeugten Instanz wird die Funktion GetMethodParameters() mit Parameter "CreateRestorePoint" aufgerufen. Dieses weist die Anwendung an, die Parameter der WMI Funktion "CreateRestorePoint" zu laden, sodass diese dann belegt werden können. CreateRestorePoint erwartet 3 Parameter:
  • Description: Beschreibung des Wiederherstellungspunkts.
  • RestorePointType: Typ des Wiederherstellungspunkts. Genaueres zu den verfügbaren Optionen (auch zum nächsten Parameter) gibt es z.B. auf dieser Seite. Wir übergeben hier 0, was bedeuten soll, dass eine Anwendung installiert wurde, eine 10 bedeutet beispielsweise, dass ein Treiber installiert wurde.
  • EventType: Typ des Ereignisses. Wir übergeben hier 100, was bedeutet, dass im System eine Veränderung begonnen wurde, 101 hieße beispielsweise, dass die Veränderung abgeschlossen ist.
Mit InvokeMethod() rufen wir schließlich die ganze Aktion auf und erstellen den Wiederherstellungspunkt.
Zum Schluss der Code:

                // lokalen Computer auswählen
                ManagementScope ManScope = new ManagementScope(@"\\localhost\root\default");
                // Systemwiederherstellung auswählen
                ManagementPath ManPath = new ManagementPath("SystemRestore");
                // Standardoptionen auswählen
                ObjectGetOptions ManOptions = new ObjectGetOptions();
                // Management Klasse aus vorigen Auswahlen erstellen
                ManagementClass ManClass = new ManagementClass(ManScope, ManPath, ManOptions);
                // Methodenparameter laden
                ManagementBaseObject ManBaseObject = ManClass.GetMethodParameters("CreateRestorePoint");
                // Beschreibung 
                ManBaseObject["Description"] = "Mein C# Wiederherstellungspunkt";
                // Typ des Wiederherstellungspunkts
                ManBaseObject["RestorePointType"] = 0;
                // Typ des Events
                ManBaseObject["EventType"] = 100;

                ManagementBaseObject OutParam = ManClass.InvokeMethod("CreateRestorePoint", ManBaseObject, null);

Dienstag, 18. September 2012

Layer Ads

Ich habe mich entschlossen, Layer Ads auf diesem Blog zu schalten (also diese Popup Werbung). Ich weiß, das ist wahrscheinlich etwas aufdringlich, aber ein kleiner Verdienst nebenbei ist natürlich auch was schönes. Sagt Bescheid, wie ihr es findet, und ob es zu sehr stört.

Mittwoch, 12. September 2012

Prüfen ob aktueller Benutzer bestimmte Rolle (z.B. Administrator) hat

Eine einfache Lösung, um zu prüfen, ob der aktuelle Benutzer bestimmte Rollen (wie Adminstrator oder Gast) innehat, lautet folgendermaßen (im Beispiel wird geprüft, ob der Benutzer Gast ist):
WindowsIdentity CurrentIdentity = WindowsIdentity.GetCurrent();
WindowsPrincipal CurrentPrincipal = new WindowsPrincipal(CurrentIdentity);
bool UserIsAdmin = CurrentPrincipal.IsInRole(WindowsBuiltInRole.Guest);
Hierbei ergibt sich aber ab Windows Vista ein Problem, falls die zu prüfende Rolle Administrator ist. Obwohl der ausführende Benutzer eventuell Administrator ist, wird die Anwendung erst einmal ohne Administratorrechte ausgeführt, sodass fälschlicherweise false zurückgegeben wird.
Nur beim expliziten Ausführen der Anwendung als Administrator wird true zurückgegeben, allerdings logischerweise auch, wenn der Benutzer gar kein Administrator ist.

Um dieses in Windows 7 richtig umzusetzen, habe ich keine (einfache) Lösung gefunden, bei Gelegenheit werde ich etwas weiter probieren, aber vielleicht kommen ja auch ein paar gute Vorschläge von euch?

Sonntag, 9. September 2012

MD5 Hash einer Datei ermitteln

Im vorigen Post habe ich Grundlegendes zum Hashing und zum Hashen von Zeichenketten erläutert, dieses setze ich nun voraus. Daher poste ich nun einfach den Code, um die Hashsumme einer ganzen Datei zu berechnen:
MD5 Md5Hash = MD5.Create();
System.IO.FileStream HashStream = new System.IO.FileStream(@"C:\Users\User\Documents\c#.txt", System.IO.FileMode.Open, System.IO.FileAccess.Read);
byte[] Data = Md5Hash.ComputeHash(HashStream);
string Hash =  System.BitConverter.ToString(Data);

Donnerstag, 6. September 2012

MD5 Hash einer Zeichenkette berechnen

Im heutigen Post möchte ich vorstellen, wie man mit C# den MD5-Hashwert einer Zeichenkette berechnet.
Kurz etwas allgemeines zum Prinzip des Hashings:
Eine Hashfunktion ist eine Funktion, die aus einer Eingabe variabler Länge eine Ausgabe fixer Länge erzeugt.
Die Funktion sollte einerseits nicht bzw. nur schwer invertierbar sein, das heißt, aus der Ausgabe darf kein Rückschluss auf die Eingabe möglich sein.
Andererseits soll die Funktion möglichst wenige Kollisionen erzeugen, das heißt, verschiedene Eingabe sollen verschiedene Ausgaben erzeugen und außerdem sollen kleine Änderungen in der Eingabe zu großen Änderungen in der Ausgabe führen.

Wofür nun das Ganze?
Ein Beispiel ist die Speicherung von Passwörtern auf einem Webserver. Die Passwörter werden nicht im Klartext gespeichert sondern gehasht. So kann einerseits der Administrator selber nicht die Passwörter der Kunden einsehen, da er den Hashwert ja nicht zurückberechnen kann, gleichzeitig können natürlich auch Eindringlinge selbiges nicht tun.
Ein weiteres Beispiel ist die Hashsummen Berechnung von Dateien, etwa um korrekte Übertragungen zu überprüfen. Die ganze Datei mit dem Original zu vergleichen wäre zu aufwending, also vergleicht man die Hashwerte. Stimmen diese überein, sind die Dateien wegen der Kollisionsarmut der Hashfunktion mit hoher Wahrscheinlichkeit identisch, ist bereits ein kleiner Teil der Datei inkorrekt, ist der Hashwert wahrscheinlich erheblich anders.

Nun zum Code. using System.Security.Cryptography vorausgesetzt berechnet folgender Code den Hashwert einer Zeichenkette:
MD5 Md5Hash = MD5.Create();
byte[] Data = Md5Hash.ComputeHash(Encoding.Default.GetBytes("Zu hashende Zeichenkette"));
string Hash =  System.BitConverter.ToString(Data);
Die 1. Zeile erzeugt ein MD5 Objekt. In der 2. Zeile wird die Zeichenkette per MD5 gehasht und der Hash als byte - Array zurückgegeben. Die Funktion ToString() in der 3. Zeile von BitConverter wandelt dieses Array schließlich in einen Hexadezimalstring um, die meist genutzte Darstellung eines Hashwerts.

Montag, 3. September 2012

Programm automatisch mit Windows starten

In diesem Post möchte ich zeigen, wie man ein C# Programm per Code dem Autostart von Windows hinzufügt. Hierfür gibt es 2 Möglichkeiten: Entweder kann man eine Verknüpfung auf das Programm im Autostart Ordner erstellen, oder einen entsprechenden Eintrag in der Registry anlegen.

1. Methode: Verknüpfung erstellen
Wie man allgemein eine Verknüpfung anlegt, habe ich in diesem Post beschrieben. Wir müssen nun als Verknüfungsziel unser Programm angeben und als Pfad den Autostartordner von Windows, dieser befindet sich bei Windows 7 in C:\Users\User\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup. Den Pfad zur eigenen Anwendung gibt es über den Befehl Application.ExecutablePath.ToString() - also führt folgender Code dazu, dass das Programm in den Autostart kopiert wird (als Icon lässt sich etwas beliebiges einsetzen):
CreateShortcut(@"C:\Users\User\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup" + "\\CAutoStart.url",  Application.ExecutablePath.ToString(), "C:\\MeinIcon.ico");


2. Methode: Eintrag in der Registry erstellen
Das Analogon zum obigen Pfad findet sich unter HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run in der Registry. Wie man generell mit der Registry umgeht, habe ich in diesem Tutorial beschrieben. Hier zeige ich nur den fertigen Code, welcher den passenden Eintrag in oben genanntem Pfad anlegt:
RegistryKey AutostartKey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Run", true);
AutostartKey.SetValue("CAutoStart", Application.ExecutablePath.ToString());
AutostartKey.Close();