Laden...

Forensuche

Ergebnisse (271)
vor 12 Jahren

Mit Google relativ schnell zu finden:
Babel Obfuscator
EDIT: Soll keine Werbung sein. Kannte den hier bis vor 5 Minuten nicht und es gibt sicherlich auch andere 😉

Wichtig ist auch zu wissen, dass das Gleiche auch für Html/Javascript Apps gilt. Auch hier müsste man den Quellcode obfuscieren.

Gruß
Roland

vor 12 Jahren

Das Thema ist doch bereits ein klassiker oder?
Da du weißt wie der aktuelle Stand mit einsehen von Code ist, ist das Thema an sich doch beantwortet oder?

Da .Net so oder so auf dem IL Code arbeitet wirst du deinen Code nicht zu 100% unlesbar machen.
Ein Obfuscator erschwert zwar das lesen aber es gibt auch dafür Mittel und Wege um den Code wieder lesbar zu machen.

Wenn du deinen Code unlesbar machen willst entwickle mit nativem Sprachen wie C/C++.
Da ist man besser beraten.

T-virus

vor 12 Jahren

Hallo Andy,

ich würde doch zuerst einen Obfuscator (für die EXE) benutzen und anschließend daraus (z.B. mit Reflector mittels "Export") dann wieder den C#-SourceCode generieren lassen.
Danach kannst du ja einige der Original-Klassen wieder darüberkopieren und hast ein teilweise "obfusciertes" Projekt.

Project Obfuscation: Gezielte Obfuscation der Quellcode-Dateien, nicht erst der Assembly(EXE/DLL)

Hallo,

kurze Frage. Ich suche eine Möglichkeit, einen Obfuscator für die Quelltexte, z.B. für eine Weitergabe an Dritte zu nutzen, um bspw. bestimmte Klassen oder Codeabschnitte zum Schutz unlesbar zu machen, aber dennoch andere Teilbereiche lesbar zu lassen.
Eine komplette Obfuscation des Projekts wäre allerdings auch ok. Wichtig ist nur dass nachher nicht die Executable durchgejagt wird. Vielmehr geht es dabei um das Visual Studio Projekt.

Danke und LG
Andy

Passwort im Klartext speichern

verwendetes Datenbanksystem: MS Sql-Server 2008 R2

Hallo Forum,

ich habe folgendes Problem, mein Dienst verwendet die Microsft "Managed Exchange API", um mit dem Exchange-Server zu kommunizieren. Um eine Verbindung mit dem Webservice herzustellen, benötige ich den Benutzernamen, Passwort und Domäne des Postfaches.
Dies ist auch alles kein Problem, nur ich bin mit nicht sicher, wie ich die Passwörter, welche ja später im Klartext benötigt werden in meiner Datenbank speichern soll. Zur Zeit gibt es für jeden Benutzer eine Hidden-Procedure mit den Logindaten. Von dieser wird dann mit Hilfe eines bestimmten Parameters ein select gemacht, so dass ich die Anmeldeinformationen bekomme.

Allerdings bin ich mit der Lösung nicht sonderlich zufrieden, da sobald jemand den Schlüssel hat, an alle Passwörter kommen kann.

Gibt es überhaupt einen sicheren Weg, die Passwörter einigermaßen sicher zu speichern? Der Schlüssel für die Prozeduren liegt im C#-Code, also kommt man an diesen auch echt leicht dran (trotz Obfuscator).

Oder ist mein Weg ein komplett falscher?

MfG

Sicherheit bei kompilierten Passwort

Mir ist bewusst, dass man .NET-Anwendungen sehr einfach Reverse Engineering betreiben kann (mit ILSpy kann man mit ein paar Klicks in den Quellcode schauen).

Nur wie ist das bei C/C++-Anwendungen? Ist das da genauso einfach?
Ich gehe mal stark davon aus, dass ein Kenner kaum Probleme haben wird, den Dekompilierten Code zu durchforsten.

Jetzt ists so, dass ich Dateien verschlüsseln will (mit AES). Die Anwendung soll dabei ohne extra Passwort-Angabe in der Lage sein, die Dateien zu entschlüsseln (um den Inhalt zu laden). Für aussenstehende soll aber durch die Verschlüsselung eine zusätzliche Hürde eingebaut werden.
Mir ist klar, dass das nur eine kleine Hürde wird. Sobald das Passwort irgendwie reinkompiliert wird, kann man auch drankommen (deswegen sollte man ja auch Datenbank-Zugangsdaten niemals in die Assembly hardcoden, sondern immer ne Middleware dazwischenklemmen, über die man Kontrolle hat).
Aber wie viel an Schutz bringt es, wenn man das Passwort hardcoded (OHNE die Exe durch einen Obfuscator zu jagen)? Wie sehr ist dekompilierter C++-Code lesbar?

Hi talla,

danke für den Hinweis, das war mir neu. InstallShield ist dabei, aber nur in der Limited Version. Wenn das so ist, wie die CommunityVersion vom Obfuscator, dann nützt es mir nicht viel.

Der Vorteil vom Microsoft-Setup war ja die prima Integration in VisualStudio. Gibt es soetwas auch für WIX und/oder InnoSetup?

Christian

WPF-Anwendungen zu einer Assembly mergen

Hallo allerseits,

bekanntlich ist es ja unmöglich, eine WPF-Anwendung oder -Bibliothek mit ILMerge in eine Assembly zu mergen.

Der von Microsoft vorgeschlagene Weg, die Unter-Assemblys in die Haupt-Assembly als Resourcen einzubetten, hat sich auch nicht als zufriedenstellend erwiesen, weil man dadurch verhindert, daß (a) die Assembly im Ganzen obfusziert werden kann und (b) dadurch in einigen Fällen Ringverweise entstehen können, wenn sich die einzelnen Assemblys auch gegenseitig referenzieren.

Was spricht dafür, eine Anwendung in eine Assembly zu mergen?

  • Obfuscation: Man kann den Quellcode der gesamten Anwendung schützen, selbst die Namen der öffentlichen Klassen und Member können verschlüsselt werden, da man keinen Zugriff mehr von außen auf die Assembly benötigt. Bei einer Bibliothek müssen nur die öffentlichen Klassen und Member der Haupt-DLL unverschlüsselt bleiben.
  • Einfachere Distribution

Warum kann man WPF-Assemblies nicht mergen?
Laut Microsoft liegt es an der Zuordnung der Namespaces zu den XAML-Dateien. Die Assemblies lassen sich zwar mergen, aber man bekommt zur Laufzeit eine Exception, sobald das erste Mal auf eine XAML-Datei zugegriffen wird.

Was kann man machen?
Der einfachste Weg ist es, die einzelnen Projekte und Projektdateien zu mergen, statt der binäre Ausgabe. Man führt also den Quellcode zusammen, nicht den IL-Code.

Wie funktioniert es?
Ich habe eine kleine Klasse geschrieben, die das Prinzip veranschaulicht. Die MergeProjects-Methode bekommt die Pfade des Ausgangsprojektes und des Zielprojektes übergeben. Das Ausgangsprojekt wird mit allen abhängigen Projekten gemeinsam in das Zielprojekt gemerged. Dazu wird die Projektmappen-Datei (*.csproj) geparst und eine neue mit den gleichen Einstellungen erzeugt. Alle Quellcode-, Resourcen- und XAML-Dateien werden in den Ordner des Zielprojektes kopiert, da die z.T. noch angepaßt werden müssen.

Am Ende hat man ein neues Projekt, daß man mit einem Skript per MSBuild kompilieren und dann bei Bedarf obfuszieren kann. Man kann das Ausgabeprojekt aber auch in VisualStudio öffnen und debuggen. Das ganze ist auch erfreulich schnell und hat bei meinen Projekten bisher ganz gut funktioniert.

Known Issues:

  • Eingebettete Resourcen in XAML-Dateien (z.B. Bilder) sollten immer relativ zur XAML-Datei referenziert werden. Also immer <Image Source="../MyImages/MyIcon.png" /> anstatt <Image Source="/MyLibrary;component/MyImages/MyIcon.png" />. Die Namespaces der URIs werden derzeit noch nicht angepaßt, aber das läßt sich noch implementieren.
  • Bei den referenzierten Namespaces in den XAML-Datei könnte es zu Problemen können, da die bisherige Anpassung sehr naiv ist. Es wird bisher einfach für alle gemergten Assemblys das ";assembly=MyAssemblyName" aus der Referenzierung gelöscht.
  • Die Ausgabedateien müssen immer gelöscht werden, bevor man ein Projekt erneut im gleichen Ordner erstellt.
  • Ansonsten halt bei Interesse einfach ausprobieren und Feedback geben 😃

Roadmap:

  • Einfaches CommandLine-Programm zur Verwendung in Post-Build-Anweisungen oder Batch-Dateien.
  • Am Ende könnte ein VisualStudio-Plugin entstehen, mit dem man seine Anwendungen mit einem Klick mergen und verschlüsseln kann.

	using System.IO;
	using Path = System.IO.Path;
	using Microsoft.Build.Evaluation;
	using Microsoft.Build.Execution;

	public static class ProjectMerger
	{

		/// <summary>
		/// Used to create projects with.
		/// </summary>
		private static readonly ProjectCollection projectCollection = new ProjectCollection();


		/// <summary>
		/// Loads a project file (*.csproj) from file and merges it together with all dependend
		/// projects into a new project on disk. All files will be copyied in the merged project's
		/// folder. In XAML files (*.xaml) all namespaces of the merged projects will be adjusted.
		/// </summary>
		/// <param name="projectToMergePath">The path of the project file to merge.</param>
		/// <param name="mergedProjectPath">The path of the project to merge all files into.</param>
		public static void MergeProjects(string projectToMergePath, string mergedProjectPath)
		{
			Project project = projectCollection.LoadProject(projectToMergePath);

			string destPath = Path.GetDirectoryName(mergedProjectPath);
			ConvertProjectItems(project, destPath);

			using (StreamWriter writer = new StreamWriter(mergedProjectPath))
				project.Save(writer);

			projectCollection.UnloadAllProjects();
		}


		/// <summary>
		/// Converts all needed paths and namespaces of the original project's items, 
		/// saving them to a new project, and create a physical copy on the file system.
		/// </summary>
		/// <param name="projectToMerge">The project to merge.</param>
		/// <param name="mergedProjectPath">The path of the merged project file.</param>
		private static void ConvertProjectItems(Project projectToMerge, string mergedProjectPath)
		{
			HashSet<string> processedSubProjects = new HashSet<string>();

			Queue<Tuple<Project, ProjectItem>> items = new Queue<Tuple<Project, ProjectItem>>(projectToMerge.Items.Count);
			foreach (ProjectItem item in projectToMerge.Items)
				items.Enqueue(new Tuple<Project, ProjectItem>(projectToMerge, item));

			while (items.Count != 0)
			{
				Tuple<Project, ProjectItem> tuple = items.Dequeue();
				Project project = tuple.Item1;
				ProjectItem item = tuple.Item2;
				string projectFolder = project.DirectoryPath;
				switch (item.ItemType)
				{
					case "ProjectReference": // References projects
						// Copy all elements to main project instead of creating ProjectReference item
						string originalProjectPath = MakeAbsolute(item.EvaluatedInclude, projectFolder).LocalPath;
						item.UnevaluatedInclude = ConvertToTargetPath(project, item.EvaluatedInclude, projectFolder, mergedProjectPath);
						
						// Remove Reference from main project
						if (project == projectToMerge)
							projectToMerge.RemoveItem(item);

						// Only copy file on first reference found
						if (!processedSubProjects.Contains(originalProjectPath))
						{
							// Enqueue all items of referenced project and handle them later
							Project subProject = projectCollection.LoadProject(originalProjectPath);
							foreach (ProjectItem subProjectItem in subProject.Items)
								items.Enqueue(new Tuple<Project, ProjectItem>(subProject, subProjectItem));
							processedSubProjects.Add(originalProjectPath);
						}

						break;
					
					case "Reference": // Referenced assemblies
						// Convert path to referenced assembly
						foreach (ProjectMetadata metadata in item.Metadata)
							if (metadata.Name == "HintPath")
								metadata.UnevaluatedValue = MakeAbsolute(metadata.EvaluatedValue, projectFolder).LocalPath;

						// Include file into main project
						if (project != projectToMerge)
							AddItem(projectToMerge, item);
						break;
					
					case "Compile": // Code file
						// Files to skip
						if (Path.GetFileName(item.EvaluatedInclude) == "AssemblyInfo.cs" && (project != projectToMerge))
							break;

						// Copy file
						item.UnevaluatedInclude = CopyFile(project, item.EvaluatedInclude, projectFolder, mergedProjectPath);

						// Include file into main project
						if (project != projectToMerge)
							AddItem(projectToMerge, item);
						break;

					case "Page": // XAML
						// Copy file and convert XAML-Namespaces
						item.UnevaluatedInclude = CopyXamlFile(project, item.EvaluatedInclude, projectFolder, mergedProjectPath, processedSubProjects);

						// Include file into main project
						if (project != projectToMerge)
							AddItem(projectToMerge, item);
						break;

					case "Resource": // Images
					case "EmbeddedResource": // Resource files (*.resx)
					case "None": // Settings files (*.settings; app.config)
						// Copy file
						item.UnevaluatedInclude = CopyFile(project, item.EvaluatedInclude, projectFolder, mergedProjectPath);

						// Include file into main project
						if (project != projectToMerge)
							AddItem(projectToMerge, item);
						break;
					
					default:
						break;
				}
			}
		}


		/// <summary>
		/// Returns the path of a file relative to the merged project.
		/// </summary>
		/// <param name="project">The source project that is beeing merged.</param>
		/// <param name="relativePath">The path of the file relative to the source project's folder.</param>
		/// <param name="originalProjectFolder">The source project's folder.</param>
		/// <param name="targetProjectFolder">The folder of the merged project.</param>
		private static string ConvertToTargetPath(Project project, string relativePath, string originalProjectFolder, string targetProjectFolder)
		{
			string projectPath = Path.GetFileNameWithoutExtension(project.FullPath);
			targetProjectFolder = Path.Combine(targetProjectFolder, projectPath);
			string targetPath = MakeAbsolute(relativePath, EnsureFinalDirectorySeparator(targetProjectFolder)).LocalPath;
			return targetPath;
		}


		/// <summary>
		/// Copies a XAML file from a source project to the merged project by adjusting all namespaces of the merged projects.
		/// </summary>
		/// <param name="project">The source project that is beeing merged.</param>
		/// <param name="relativePath">The path of the file relative to the source project's folder.</param>
		/// <param name="originalProjectFolder">The source project's folder.</param>
		/// <param name="targetProjectFolder">The folder of the merged project.</param>
		/// <param name="mergedAssemblies">The paths of the assemblies that are beeing merged into the
		/// project, used to adjust namespaces in the XAML file.</param>
		/// <returns>Returns the path of the duplicated file.</returns>
		private static string CopyXamlFile(Project project, string relativePath, string originalProjectFolder, string targetProjectFolder, HashSet<string> mergedAssemblies)
		{
			string originalPath = MakeAbsolute(relativePath, EnsureFinalDirectorySeparator(originalProjectFolder)).LocalPath;
			string targetPath = ConvertToTargetPath(project, relativePath, originalProjectFolder, targetProjectFolder);

			string markup = File.ReadAllText(originalPath);

			foreach (string assemblyPath in mergedAssemblies)
			{
				string assemblyName = projectCollection.LoadProject(assemblyPath).GetProperty("AssemblyName").EvaluatedValue;
				string removeNameSpace = string.Format(";assembly={0}", assemblyName);
				markup = markup.Replace(removeNameSpace, string.Empty);
			}

			CreateFolders(targetPath); // Ensure directory exists
			File.WriteAllText(targetPath, markup);
			return targetPath;
		}


		/// <summary>
		/// Copies a file from a source project to the merged project.
		/// </summary>
		/// <param name="project">The source project that is beeing merged.</param>
		/// <param name="relativePath">The path of the file relative to the source project's folder.</param>
		/// <param name="originalProjectFolder">The source project's folder.</param>
		/// <param name="targetProjectFolder">The folder of the merged project.</param>
		/// <returns>Returns the path of the duplicated file.</returns>
		private static string CopyFile(Project project, string relativePath, string originalProjectFolder, string targetProjectFolder)
		{
			string originalPath = MakeAbsolute(relativePath, EnsureFinalDirectorySeparator(originalProjectFolder)).LocalPath;
			string targetPath = ConvertToTargetPath(project, relativePath, originalProjectFolder, targetProjectFolder);

			CopyFile(originalPath, targetPath);
			return targetPath;
		}


		/// <summary>
		/// Creates all folders needed to copy a file to the position specified by <paramref name="filename"/>.
		/// </summary>
		/// <param name="filename">The file that is beeing copied.</param>
		private static void CreateFolders(string filename)
		{
			string folder = Path.GetDirectoryName(filename);
			string file = Path.GetFileName(filename);
			string baseFolder = folder;

			Stack<string> foldersToCreate = new Stack<string>();
			while (!Directory.Exists(baseFolder))
			{
				string parent = Path.GetDirectoryName(baseFolder);
				foldersToCreate.Push(baseFolder.Substring(parent.Length + 1));
				baseFolder = parent;
			}

			while (foldersToCreate.Count != 0)
			{
				string newFolder = Path.Combine(baseFolder, foldersToCreate.Pop());
				Directory.CreateDirectory(newFolder);
				baseFolder = newFolder;
			}
		}

		/// <summary>
		/// Copys a file from a source to a destination path.
		/// </summary>
		/// <param name="source">The path to the source file.</param>
		/// <param name="dest">The file's destination path.</param>
		private static void CopyFile(string source, string dest)
		{
			CreateFolders(dest); // Ensure directory exists
			File.Copy(source, dest, true);
		}
		

		/// <summary>
		/// Adds a <see cref="ProjectItem"/> to a <see cref="Project"/> by making sure not to create any duplicates.
		/// </summary>
		/// <param name="project">The project.</param>
		/// <param name="item">The property item.</param>
		private static void AddItem(Project project, ProjectItem item)
		{
			if (!project.Items.Any(existingItem => existingItem.ItemType == item.ItemType && existingItem.EvaluatedInclude == item.EvaluatedInclude))
				project.AddItem(item.ItemType, item.EvaluatedInclude, item.Metadata.Select(metaItem => new KeyValuePair<string, string>(metaItem.Name, metaItem.UnevaluatedValue)));
		}
		

		/// <summary>
		/// Converts a relative into an absolute <see cref="Uri"/>.
		/// </summary>
		/// <param name="relativePath">The relative path to convert.</param>
		/// <param name="basePath">The path the relative path is relative to.</param>
		private static Uri MakeAbsolute(string relativePath, string basePath)
		{
			Uri relativeUri = new Uri(relativePath, UriKind.Relative);
			Uri baseUri = new Uri(EnsureFinalDirectorySeparator(basePath), UriKind.Absolute);
			Uri result = MakeAbsolute(relativeUri, baseUri);
			return result;
		}

		/// <summary>
		/// Converts a relative into an absolute <see cref="Uri"/>.
		/// </summary>
		/// <param name="relativeUri">The relative path to convert.</param>
		/// <param name="basePathUri">The path the relative path is relative to.</param>
		private static Uri MakeAbsolute(Uri relativeUri, Uri basePathUri)
		{
			Uri filePath = new Uri(basePathUri, relativeUri);
			return filePath;
		}


		/// <summary>
		/// Converts an absolute into a relative <see cref="Uri"/>.
		/// </summary>
		/// <param name="basePathUri">The base path.</param>
		/// <param name="absoluteUri">The Uri to convert.</param>
		private static Uri MakeRelative(Uri basePathUri, Uri absoluteUri)
		{
			Uri filePath = basePathUri.MakeRelativeUri(absoluteUri);
			return filePath;
		}


		/// <summary>
		/// Makes sure a path ends with a final "\". This is necessary in order
		/// to achieve correct results when converting absolute to relative paths.
		/// </summary>
		/// <param name="relativePath">The path to fix.</param>
		/// <returns>Returns the fixed path</returns>
		private static string EnsureFinalDirectorySeparator(string relativePath)
		{
			if (relativePath[relativePath.Length - 1] != System.IO.Path.DirectorySeparatorChar)
				return relativePath + System.IO.Path.DirectorySeparatorChar;
			else
				return relativePath;
		}

	}

vor 13 Jahren
Security: Wie Passwörter sicher hinterlegen?

Hallo,

ich habe bei mir grade folgende Problemstellung:

Angenommen eine Anwendung (Service) benötigt zum Zugriff auf ein System, das keine integrierte Windowsauthentifizierung unterstützt, Zugangsdaten. Diese müssen dem Service in irgendeiner Form bereitgestellt werden.

Den Ansatz, die Zugangsdaten mit einem eincodierten Passwort zu verschlüsseln, habe ich verworfen, da es ja Tools wie .Net Reflector oder ILSpy gibt, die trotz Obfuscator einige ungewollte Daten ans Licht bringen können.

Nächster Ansatz wäre es jetzt, die Daten mit der Klasse ProtectedData zu verschlüsseln. D.h. string in byte[] konvertieren, durch die Protect()-Methode jagen und lokal ablegen. Damit wären die verschlüsselten Daten nur an dem einen Rechner wieder entschlüsselbar und auch nur dann, wenn man einen zusätzlichen byte[] (optionalEntropy), der dann fest hinterlegt würde, kennt.

Kennt jemand Gründe, die gegen eine solche Umsetzung sprechen (Risiken, die ich nicht bedacht habe...)? Oder hat vielleicht jemand andere / bessere Ideen? Ich bin ja sicher nicht der erste, der vor diesem Problem steht 😉

Über Anregungen wäre ich sehr dankbar!

P.S.: Mit der Crypto API von Windows habe ich schon gespielt, allerdings ist mir das ganze Handling zu umständlich (Außer es kennt jemand einen Wrapper für die Crypto API, der es einfach erlaubt Keys in einem Store zu speichern und wieder abzurufen - so was konnte ich bisher leider nicht in funktionsfähiger Form finden). CNG fällt auch flach, weil das ganze unter Windows XP auch noch laufen muss...

Hallo Kalle1970,

laut Ordnerstruktur hast du eine ClickOnce Veröffentlichung gemacht.
Dementsprechend erhält man durch ändern der Dateienung direkt die dll, bzw exe. Aus dieser kann man dann auch mit einem Disassembler den Code herausbekommen. Um den Code zu schützen verwendet man einen Obfuscator.
Generell ist jede Klasse, wenn man es richtig macht mit einem entsprechenden Copyright Header versehen, und dadurch schon geschützt.
Dementsprechend sehe ich keinen Sinn Code mit einem Obfuscator zu verschleiern. (Ausgenommen evtl die Lizenzierungsprüfung.

Gruß
Michael

Hallo!

Dieses Thema wurde schon oft besprochen, u.a. in [FAQ] NET Assembly vor Disassembling schützen (Obfuscator)

vor 13 Jahren

[FAQ] NET Assembly vor Disassembling schützen (Obfuscator)
Warum meinst du das Du sowas benötigst?

Hallo kom2006,

wahrscheinlich kann der Eazfuscator.net nicht mit richtig mit Component umgehen. In Eazfuscator.NET – Free .NET Obfuscator steht auch etwas von einem Fix dafür - nähere weiß ich aber nicht.

Wie äußern sich die Probleme? Bitte beachte [Hinweis] Wie poste ich richtig? Punkt 5.

mfG Gü

vor 13 Jahren

Mir ist das Icon selbst völlig egal 😉

Was mir aber nicht egal ist, dass sich diese Klasse offenbar nicht mit dem eazfuscator.NET verträgt.

Schalte ich den Obfuscator aus, kann ich ein Release erstellen, welches fehlerfrei läuft - ist der Obfuscator eingeschaltet, dann läuft das Programm genau solange, bis intern auf diese Klasse zugegriffen wird.

Hallo moelski,

in den Threads, die aus der FAQ verlinkt werden, sind schon alle (relevanten) Tools besprochen: [FAQ] .net Assembly vor Disassembling schützen (Obfuscator). Das müssen wir nicht nochmal wiederholen.

herbivore

vor 13 Jahren

Ich habe im Prinzip ein ähnliches Problem wie Hirnhamster.

Ich habe eine .net 3.5 Anwendung mit .NET Reactor geschützt. Obfuscator. Und nutze dann ein hardwarebasiertes Lizenzensierungssystem.

Dennoch wurde meine Software geknackt, indem ein Programm vorgeschaltet wird, welches im Prinzip den Speicher von meinem Programm manipuliert. Im Prinzip wird da einfach der Wert der Variablen, welche den Lizenzstatus speichert geändert. Leider funktioniert das.

Hat irgend jemand eine Idee, wie ich dagegen vorgehen kann, um eine derartige Speichermanipulation zu verhindern?

Hallo burkut,

ansonsten ist alles was du wissen musst, schon oft und lange im Forum beschrieben. Siehe [FAQ] .net Assembly vor Disassembling schützen (Obfuscator). Dort und über die Forensuche gibt es z.B. auch Hinweise auf kostenlose Werkzeuge und deren Qualität.

herbivore

Babel Obfuscator 4.0 erschienen

Babel.NET - Features

Zitat von: Babel Obfuscator 4.0 Released - Babel Obfuscator
After quite long time, Babel 4.0 has been released.
The features available with this new release are:
Supported Silverlight for Windows Phone 7, XBOX360 XNA Framework and .NET Micro Framework

XAML and BAML Obfuscation

Merging Support for WPF and Silverlight Assemblies

Dynamic Proxy Calls to External and Internal Methods

Code Instrumentation

Custom Character Set Obfuscation

New and Improved Control Flow Obfuscation

Debug PDB Symbol File Generation

Merging Support for Debug PDB Symbol Files

Code Optimizations

Improved Renaming of Compiler Generated Code

Support x64 .NET Images

Also note that starting from this version, the Free edition will not be more available. It will be substituted by the Flexible edition that has a variable price licensing according the number of features purchased. I hope you will understand that this change was introduced to support future product investment that we want to carry out soon.

Wie schon der Reflector ist Babel.NET in der neuen Version 4.0 aber nicht mehr frei verfügbar. Mit der neuen Flexible Edition ist man ab 20€ wieder dabei.
Die freie Version 3.5 steht auch nicht mehr als Download zur Verfügung.

Flexible edition license is very simple indeed.
With Flexible licensing you can choose any features from the one listed below:
Overloaded Renaming

Custom Character Set Obfuscation

Advanced Hash String Encryption

Protections Against Disassemblers

Dead Code Removal

Code Optimizations (automatic class sealing and attribute removal)

Debug PDB Symbol File Support

Resign with PFX Files

Assembly Embedding

Parallel Execution

Each feature costs 20 €, so if you want to purchase only Protection Against Disassembler feature you will pay only 20 €.

If you want to purchase Overloaded Renaming and Protections Against Disassemblers you will pay 40 €.
Note that babel is licensed per user and license discounts are available on purchasing multiple licenses.
We provide a discount for Flexible edition when purchasing more then 3 features.

Also all the licensed product have one year of free upgrades.

To unlock the time expiration of the obfuscated assemblies you have to buy at least one feature.

Hallo Nokinger,

suche mal nach Obfuscation bzw. Obfuscator.
So bezeichnet man derartige Programme im Allgemeinen - gibt noch einige andere.

Hallo P.K.,

ein Hash ist eine Zeichenkette, die nicht wieder entschlüsselt werden kann. Auf der von dir genannten Seite findest du einfach eine Datenbank, mehr nicht. Es gibt auch anderere Verschlüsselungstechniken.

Siehe auch [FAQ] .net Assembly vor Disassembling schützen (Obfuscator). Stichwort: Obfuscator, Packer.

zero_x

Hallo zusammen,

leider habe ich erst jetzt gesehen, dass wir die Umfrage schon mal hatten. Und die ist auch noch nicht so lange her, dass zu erwarten wäre, dass die Ergebnisse nicht mehr zutreffend sind:

**Umfrage: **Nutzt ihr einen Obfuscator?

Ich sags ja immer wieder: Erst suchen, dann posten. 😃

herbivore

Außerdem kann man durch einen Obfuscator nicht verhindern, dass man das Konzept einer Anwendung erkennt.

Ist zwar nur durch den Source Code schwer zu beurteilen aber geht durchaus. Da öffentliche Namen ja nicht geändert werden ist das kein Problem.

Ich finde das also total sinnlos.

Bei uns im Unternehmen werden ebenfalls keine Obfuscator eingesetzt. Ich denke auch dass es bei Anwendungen für die Industrie sowieso ohne Bedeutung ist ob der Quellcode schnell mal eingesehen werden kann. - Wird sowieso keiner machen.

Ob ich einen einsetzen würde, wenn ich eine Anwendung vermarkten möchte, die was revolutionäres kann, kann ich momentan nicht sagen, aber ich denke nicht.

vor 14 Jahren

Wir setzen bei uns auch keinen Obfuscator ein. Stand aber bisher einfach nicht zur Debatte und hat nichts mit einer konkreten Entscheidung dafür oder dagegen zu tun.

Obfuscatoren - Setzt ihr welche ein?

Hallo Leute,

in einem anderen Thread meinte ein Benutzer ganz selbstverständlich, dass er natürlich den Client obfuskiert hätte. Das machte mich etwas stutzig, da ich in meiner Praxis noch nie einen Obfuscator für das Endprodukt verwendet habe.

Wie sieht das bei euch aus? Verwendet ihr Obfuscator oder andere Mittel um euren Code zu schützen?

PS: Bitte nicht auf Threads verlinken wie "Wie schütze ich meinen Code" - denn mich interessiert in erster Linie wieviele von uns solche Techniken verwenden.

vor 14 Jahren

Hallo Regenwurm,

Sprich auch wenn ich bspw das komplette App-Byte Array mittels XOR verschlüssle, ist der Cracker im Stande sich an dem Punkt einzuhacken wo das entschlüsselte Programm in die Assembly geladen wird?

Es spielt keine Rolle welche Verschlüsselung du nimmst, alle Synchronen Verschlüsselungen kann man mittels dissassembler (in .Net) einfach wieder umgehen.

Ich würde eine einmalige asynchrone Authentifizierung verwenden.
Und den Code mit einem Obfuscator schützen.

Gruß André

Hallo zusammen,

@inflames
Ich gehe davon aus dass das Programm nicht mehr als 50 MB RAM in Anspruch nehmen wird.
Danke schonmal für den Assembly Typ.

@TheGear
Sprich auch wenn ich bspw das komplette App-Byte Array mittels XOR verschlüssle, ist der Cracker im Stande sich an dem Punkt einzuhacken wo das entschlüsselte Programm in die Assembly geladen wird?

@der-schlingel
Es ist ein reines "Sicherheitsbedürfnis".
Ich habe dies nur mal so gesehen und wollte mich mal informieren wo der Sinn des Ganzen liegt & wie das überhaupt funktioniert.

Ja, die Ressourcen wären immer vorhanden & es handelt sich um das Internet. 😉

Was gäbe es sonst noch für Möglichkeiten ausser einem Server / Client Login, seine Applikation zu schützen?
Ausser natürlich das übliche à la obfuscator etc.

cheers 😃

Hallo Ayke,

ich kann dir das so aus dem Stehgreif nicht sagen. Hier das Projekt baut auch auf Mono.Cecil auf. Das wird die bestimmt weiterhelfen. Es ist ein fertiger Obfuscator, da kannst du bestimmt den ein oder anderen Code-Snippet verwenden.

zero_x

vor 14 Jahren
Mono.Cecil Alle referenzen eines Types.

Ich schreibe grade einen Obfuscator. Hab schon einiges gelöst aber leider nicht so wie ich es mir vorstelle. Gibt es eine möglichkeit mit Mono.Cecil alle referenzen (Abhängigkeiten) eines Types zu bekommen.

Hallo,

solange die Debug-Informationen *.pdb greifbar sind kann auch der Code angezeigt werden.

Wie kann ich die DLL so erstellen das wirklich nur die öffentlichen Methoden sichtbar sind?

Siehe [FAQ] .net Assembly vor Disassembling schützen (Obfuscator)
Den Reflektor kennst du auch?

mfG Gü

vor 14 Jahren

Aber wirklich geschützt ist deine DLL aber trotzdem nicht.

Das ist ja nur der anfang 😃

Schon mal was von einen Obfuscator gehört?

Ja nur wuste ich nicht was das sein soll. Gibt bestimmt paar sources im Netz,
jetzt weiss ich ja was ich suchen muss. Danke

Hallo Ayke

Weil ich das automatisieren möchte um meine Projekt zu schützen.

Schon mal was von einen Obfuscator gehört?
Diese machen im Prinzip auch das was du willst. Aber wirklich geschützt ist deine DLL aber trotzdem nicht.

Gruss
Michael

Der Eazfuscator.NET obfuscator sollte an dieser Stelle ebenfalls genannt werden.
Eazfuscator.NET

Ich habe nun schon mehrere Obfuscatoren ausprobiert, meiner Ansicht nach sind der Phoenix Protector und der Eazfuscator.NET obfuscator die beiden besten.

Wobei der Eazfuscator.NET obfuscator die Namespaces, Klassen und Methoden stärker verschlüsselt, wohingegen der Phoenix Protector meinen Disassembler öfter zum Abstürzen bringt.

Viele Grüße.

FYI:
Nachfolgend mal meine Vorlage für den MSBuild-Task (einfach wie in Doku in die *.csproj integrieren). Wenn man als <BabelOutputFile>$(TargetPath)<BabelOutputFile> angibt, wird automatisch die kompilierte Assembly mit der obfuskierten ersetzt.
Aber aufpassen mit Setup-Projekten, die packen die Assemblies aus dem obj-Ordner. Dort dann <BabelOutputFile>$(ProjectDir)$(IntermediateOutputPath)$(TargetFileName)</BabelOutputFile> verwenden. Sonst hat man ein Setup mit nicht obfuskierten Assemblies!


<!-- Babel.NET Obfuscator -->
<Import Project="C:\Program Files\Babel\MSBuild\Babel.Build.targets" />
<Choose>
	<When Condition="'$(Configuration)' == 'Debug'">
		<PropertyGroup>
			<EnableObfuscation>false</EnableObfuscation>
			<GenerateDebug>true</GenerateDebug>
		</PropertyGroup>
	</When>
	<Otherwise>
		<PropertyGroup>
			<EnableObfuscation>true</EnableObfuscation>
			<ShowStatistics>false</ShowStatistics>
			<BabelOutputFile>$(TargetPath)</BabelOutputFile>
			<FlattenNamespaces>true</FlattenNamespaces>
			<UnicodeNormalization>true</UnicodeNormalization>
			<ObfuscateTypes>true</ObfuscateTypes>
			<ObfuscateEvents>true</ObfuscateEvents>
			<ObfuscateMethods>true</ObfuscateMethods>
			<ObfuscateProperties>true</ObfuscateProperties>
			<ObfuscateFields>true</ObfuscateFields>
			<VirtualFunctions>true</VirtualFunctions>
			<OverloadedRenaming>true</OverloadedRenaming>
			<ControlFlowObfuscation>true</ControlFlowObfuscation>
			<EmitInvalidOpcodes>false</EmitInvalidOpcodes>
			<StringEncryption>true</StringEncryption>
			<MsilEncryption>false</MsilEncryption>
			<SuppressIldasm>true</SuppressIldasm>
			<DeadCodeElimination>false</DeadCodeElimination>
		</PropertyGroup>
	</Otherwise>
</Choose>

Hat es eigentlich einen bestimmten Grund, warum du nur Kontrollflussobfuskierung machst?

Gruß,
dN!3L

Du kannst doch eigentlich bei jedem Obfuscator einstellen, welche Elemente verändert werden dürfen. Wenn die DLL öffentliche Methoden usw. hat, dann sollten die beibehalten werden.

vor 14 Jahren

WPF lebt davon, dass per Reflection(warscheinlich) direkter Zugriff(dynamisch) auf Member genommen wird? ...somit sind dependecy properties etc. möglich?

...

ViewModel: Gibt es Probleme bei der Typkonvertierung, genauer bei der Übersetzung der Properties auf Controls (Databinding)?

Nun wie du bereits gesagt hast basieren Verweise von XAML auf Code (Bindings, x:Static...) auf Reflection. Probleme damit gibts es sobald du Obfuscation einsetzt. Ein guter Obfuscator benennt die ganzen Properties/Methoden/Klassen und alle aufrufenden Stellen um. Verweise von XAML aus werden allerdings nicht erkannt. Dabei kommt es schon mal vor dass die Properties deiner ViewModel-Klassen einfach entfernt werden da der Obfuscator denkt 'die benutzt je eh keiner'. Im Obfuscator lassen sich natürlich div. Einstellungen vornehmen mit denen man das ganz genau regulieren kann. Es kommt dann allerdings immer wieder vor dass der ein oder andere Trigger im XAML-Code nicht funktioniert und man den beim Testen einfach mal vergisst.

Diese Probleme treten aber eh nur mit Obfuscation auf und die scheint ja so gut wie niemand zu benutzen.

vor 14 Jahren
Rekursiv Methode in Controls aufrufen - Problem mit Obfuscator

Hallo 😃

Ich bin grad dabei ein VFP konstrukt auf C# um zu schrieben.
Es geht darum alle Controls einer Form je nach zustand entweder zu disablen oder zu enablen.

in VFP sieht das ganze bei uns so aus:


local element
for each element IN  thisform.controls
	if pemstatus(element,"lock",5)
		element.lock(plwie)
	endif
next

^^ VFP... quickly und dirtyer 😃

Das ganze würde in etwa in C# wie folgt aussehen:


foreach (Control control in this.Controls)
{
    if (control.GetType().GetMethod("controls_lock") != null)
    {
        object[] parameter = new object[1]; 
        parameter[0] = sperren;
        control.GetType().GetMethod("controls_lock").Invoke(control, parameter);
    }
} 

Dies würde die Eigens definierte Methode "controls_lock" innerhalb der Controls aufrufen - falls vorhanden, welche sie dann je nach zustand disablen oder enablen würde.

Das problem ist, das dies mit Reflection gelöst ist.
Wenn ich mit jetzt einen Obfuscator nehme und die Assemby, welche daraus resultiert obfuskiere und sie dann ausführe, funktioniert das ganze Konstrukt nicht mehr, weil die Strings und methoden-namen auch mit unkenntlich gemacht werden.

Also muss irgendwie eine Möglichkeit her, die nicht mit Reflection arbeitet.
Meine Controls sind alle von den Basis-Controls abgeleitet, welche wiederum von "Controls" erben.
Ich hatte schon eine Idee über ExtensionMethods das "Controls" aufzubohren, aber das ist wohl nicht der elegante weg.

Ich steh mal wieder voll auf dem Schlauch.
Wie komme ich in der Schleife an die Methoden meiner Controls ohne die Schreibe für jedes Control neu bauen und aufrufen zu müssen? 😕

Hallo Komandar,

wofür ein Obfuscator sicher genug ist, hängt nicht davon ab, ob das zu schützende Programm kommerziell ist oder nicht, sondern wie hoch die Sicherheitsanforderungen (oder sollte ich besser sagen das Bedürfnis nach Sicherheit) sind. Das .NET-Framework und viele andere Programme sind auch kommerziell und trotzdem nicht mit Obfuscatoren bearbeitet.

Allerdings haben wir oft genug diskutiert, wie groß der Nutzen von Obfuscatoren ist. In aller Kürze: Die Masse der Nutzer wird sich überhaupt nicht für den Code interessieren und die, die sich wirklich dafür interessieren (Cracker, ernsthafte Konkurrenten), wirst du mit einem Obfuscatoren nicht davon abhalten, dein Programm zu analysieren. Das müssen wir also nicht noch mal diskutieren. Lies dir mal die Threads in [FAQ] .net Assembly vor Disassembling schützen (Obfuscator) an. Und entscheide dann selbst.

herbivore

vor 14 Jahren

Falls ich mal ein Lizenzierungssystem haben sollte... würde ich eine FloatingLizenz einbauen welche sagt
5 Benutzer wurden gekauft, 5 dürfen sich anmelden, x User können angelegt sein.
und die Lizenzdatei liegt am Server, in der Datenbank oder am Server selbst ist in diesem Fall irrelevant. Besser in der Datenbank, dann kann der Kunde das Programm schon nicht mehr so leicht weitergeben, da er dann ja auch seinen Daten weitergeben würde.
Gegen Hacker zu schützen ist einen "sinnlose" arbeit, denn wenn einer reinwill kommt einer rein. Obfuscator hält mal schon 90% (inkl. mich) auf und gegen den Rest kann man eh nichts machen also wäre es verschwendete Zeit.

Hallo Hirnhamster,

vorneweg: von dem Gedanken von (ständigen) Online-Prüfungen solltest du dich dringend verabschieden. Das stellt eine unangemessene Benachteiligung deiner Kunden da. Gerade wenn du nur eine kleine Firma hast oder sogar als Einzelunternehmer auftrittst, würden die Kunden bei Geschäftsaufgabe, Insolvenz o.ä. das bezahlte Programm nicht mehr nutzen können. Mal ganz abgesehen von den Regressansprüchen, die auf dich zukommen, wenn der Lizenz-Server mal nicht verfügbar ist.

Aber es geht eigentlich sehr einfach und effektiv:

zu 1-3:

Erstelle eine XML-Datei, in der die Daten den Kunden enthalten sind. Pack außerdem eine feste GUID mit in die Datei. "Verschlüssele" die Datei mit deinem privaten Schlüssel. Schick die "verschlüsselte" Datei (=Lizenzdatei) an den Kunden. Der kann sie dann im Programmverzeichnis ablegen.

Dein Programm enthält den öffentlichen Schlüssel und kann damit die XML-Datei entschlüsseln. Nun schaut es, ob die GUID stimmt und wenn ja ist alles gut.

Zwar kann dann der Kunde die Lizenzdatei weitergeben oder ins Internet stellen, aber dann stellt er ja automatisch seine Daten mit ins Netz und kann jederzeit zurückverfolgt werden. Das ist sehr abschreckend und der bestmögliche Schutz.

Ein weiterer Vorteil: Selbst wenn jemand durch Reenginieering die GUID und den öffentlichen Schlüssel ermittelt, kann er trotzdem keine gültige Lizenzdatei erstellen, weil er den privaten Schlüssel nicht kennt.

EDIT: Um das Ergebnis der nachfolgenden Diskussion zu meinem Vorschlag vorwegzunehmen: Auf der theoretischen Ebene von asymmetrischen Verfahren funktioniert mein Vorschlag so wie beschrieben. Damit er auch auf der praktischen Ebene von .NET funktioniert, sollte man nicht die Verschlüsselungs- sondern stattdessen die Signierfunktionen verwenden.

zu 4.

Siehe [FAQ] .net Assembly vor Disassembling schützen (Obfuscator)

Ansonsten wurde das ganze Thema schon öfter besprochen. Bitte benutze die Forumssuche und poste die besten Treffer hier. Vielen Dank!

herbivore

Hallo Lector,

Obfuscatoren für die Controls gibt es wohl nicht, da diese auch irgendwie gerendert werden müssen. Schützen kann man sich nur mit einen Obfuscator für XAML. Beachte bitte auch, dass sich in der Assembly auch der BAML-Code(Binary Application Markup Language) befindet, der dort fest einkompiliert ist.

Hallo winSharp93,

vielleicht möchte Lector einen aufwenig programmierten Style oder ähnliches schützen.

zero_x

Gelöschter Account
vor 14 Jahren

naja... garnicht?

Obfuscation habe ich schon ausprobiert jedoch lässt sich dadurch lediglich der .NET-Reflector aussperren

nicht ganz aussperren... lesen kann man den code auch so.. nur nciht ganz so sprechend.

zu dem ganzen thema siehe auch: [FAQ] .net Assembly vor Disassembling schützen (Obfuscator)

Hallo Locutus,

... nicht-.NET DLL (nennt man das native DLL?)

ja

Bei einer nativen(?) DLL ist es soweit ich weiss nicht bzw. nur schwer möglich, an die Interna zu gelangen.
Bei einer .NET-DLL (oder allgemein .NET-Software) hingegen meine ich mal gelesen zu haben, dass man relativ leicht an den Sourcecode kommt, da es sich ja bei .NET-Software um einen Zwischencode handelt, der erst zur Laufzeit übersetzt wird und daher der Zwischencode einsehbar ist. Ist das korrekt?

ja

Ich denke, die beste Variante wäre dann, die Zusatzfunktionen in einer nativen DLL zu lösen, und dann für diese DLL den Wrapper zu schreiben.

Entweder so oder du verwendest einen Obfuscator: [FAQ] .net Assembly vor Disassembling schützen (Obfuscator).

herbivore

Hallo Locutus,

das sicherste ist sicherlich wenn du diese Dinge direkt in der nativen DLL machst.

Aber Falls du das in .Net machst ist der Code (z.B: mit .net Reflector) einsehbar, da hast du recht.
Du kannst aber einen sog. Obfuscator verwenden welcher dir den Sourcecode schützt.
Danach kann man den SourceCode nicht mehr einsehen.
Wenn du hier im Forum nach Obfuscator suchst dann findest du bestimmt was.
Ich verwende oft den Phoenix Protector (oder so ähnlich) und dieser ist auch noch free 😃
Es ist zwar nciht Bombensicher aber meist wäre der Aufwand an den Sourcecode zu kommen größer als der Wert des Sourcecodes 😃

Gruss
Michael

selber kenn ich mich da nicht aus aber vielleicht hilft dir was im FAQ steht(wenn du es nich sowieso schon gelesen hast)

FAQ von mycsharp über Obfuscator

Mfg Campac

Suche .NET Obfuscator - Eure Ratschläge sind gefragt

Hallo,

Ich bin auf der Suche nach einer der besten Obfuscator für .NET. Habt ihr da paar Vorschläge? Welche benutzt ihr?

MfG

Gelöschter Account
vor 15 Jahren

[FAQ] .net Assembly vor Disassembling schützen (Obfuscator)

das tool das eure "gegner" verwendet haben nennt sich: [Artikel] .NET Reflector

Also dann mal los. Zunächst einmal, wenn deine exe die du starten willst, keine .net exe ist, hast du schlicht und ergreifend pech. Denn mit .net kannst du nur .net Assemblies aus dem Speicher heraus starten. Für eine native exe bliebe dir nur C/C++ (oder auch andere Sprachen mit gleicher Funktionalität). Dazu wie man eine .net Assemblie aus dem Speicher heraus startest, solltest du hier im Forum massig Threads finden.
Zum Packen/Entpacken im Arbeitsspeicher:
Wenn du mit Packen/Entpacken komprimieren meinst, dann nutzt du am besten die ICSharpCode.ZipLib dafür. Um damit im Arbeitsspeicher zu arbeiten, kannst auf MemoryStreams zurückgeifen. Ansonsten gäbe es da noch SevenZipSharp. Damit kann man auch direkt auf byte[]'s arbeiten.
Die Daten, also das auszuführende Programm und die dazu ehörenden ordner kannst du in gezippter oder in welcher Form auch immer, direkt an deine Assembly/Exe hängen (wirklich einfach dahinter schreiben). Auch dazu gibt es hier im Forum irgendwo etwas (habs leider grade nicht mehr im Kopf). Die daten kannst du im Code dann per Filestream auslesen, in dem du dir z.B. die Position merkst, an der der Code aufhört und die Daten anfangen.
Zum Thema Reflector: Da könnte dir ein Obfuscator zumindest etwas mehr Sicherheit bieten. Ich persönlich kenne als ordentliche, kostenlose Variante da nur den Phoenix Protector.
Hoffentlich hilft dir das etwas.
Greetz, der Chicken

Hallo

Ich würde eine asymmetrisch verschlüsselte Datei verwenden. Den dazugehörigen öffentlichen Schlüssel legst du mit in deinem Programm ab (als Resource) und mit Hilfe des privaten Schlüssels (Natürlich schön sicher aufbewahren) erzeugst du nun entsprechende Lizenzen. So kann zwar jeder jederzeit die Lizenzdatei auslesen, aber halt keine neue generieren. Wie du die unverschlüsselte Datei aufbaust ist dann dir überlassen z. B. halt Benutzername, Firma, Kaufdatum, ... als XML, Text oder binär.
Und dann wie gesagt, ist sie nicht vorhanden oder ungültig -> Demo, wenn gültig -> alles frei.

Wichtig ist allerdings dann auch, dass du deine Anwendung durch einen guten Obfuscator schickst, damit erschwerst du, dass jemand deinen Programmcode einsehen kann. Dazu auch [FAQ] .net Assembly vor Disassembling schützen (Obfuscator)

Grüße