Ist eine VB Exe sicher vor Codeauslesung?

Hallo Wissende,

in Excel ist nichts sicher. Weder der Paßwortschutz für die Mappe oder Blätter noch der Paßwortschutz für den Vba-Code der drin steht.

Nun gibt es Compiler die eine xls-datei in eine Exe wandeln. Z.B. hier:

http://doneex.com/index.php?option=com_content&task=…

Nun hat da jmd. eine Exceldatei damit kompiliert und in einem anderen Forum hochgeladen:

http://www.badongo.com/file/9883108

mit halt der Frage, ob jemand da es schafft den darin enthaltenen Vba-Code auszulesen.

Ich bin da sehr gespannt ob es da jmd. schafft und werde berichten.
Andererseits, wenn ich davon lebe daß mein Code geschützt bleibt würde ich den Teufel tun und sagen wie man meinen Schutz umgeht.

Mein bzw. der Hintergrund ist, z.B. dort sind Profi Excel-Vba Programmierer, die leben davon, und natürlich haben sie keinerlei Interesse daran, daß sie einem Kunden eine Trialversion für 30 Tage anbieten, dem gefällt die Software, er surft ein bißchen im Internet und hat dann den Code quasi gratis und zahlt nix.

Also sind sie bemüht, ihren Code, für den sie vielleicht 60 Tage gebraucht haben auch zu schützen.
manche benutzen da DLLs *gehört hab*.

Jetzt wäre es natürlich auch genial die Exceltabelle samt Vba-Code in eine Exe-datei zu wandeln. Weil da klappen die bekannten Paßwortknackprogramme für Excel nicht.

Irgendwie kam ich darauf, daß diese Problematik auch für VBler besteht.

Jetzt meine Frage,

Kann man aus einer mit VB erstellten Exe den VB-Code auslesen?

Wenn ja,

a) können das nur ganz wenige weltweit?

b) kann das auch jeder Hirni wie ich der auf dunklen Seiten surft?

Ich habe mir die o.g. Datei runtergeladen und gestartet. Mein Hackversuch sie als einfache xls-Datei abzuspeichern ging schief.
Denn dann hätte ich hacken/cracken was weiß ich , können.
Okay, dann wurde das gesperrt.
Ergo steht irgendwo in der Exe, unterbinde die Möglichkeit eine offenen Datei mittels „Speichern unter“ zu speichern.
Könnte jmd. der sich mit Disassemblern auskennt mit dieser Information die entsprechenden Assemblerbefehle in der Exe durch 0 o.ä. ersetezen sodaß man dann die durch die exe angezeigte xls-Datei „normal“ speichern könnte?

Ich hoffe ich konnte mich verständlich machen.

Gruß
Reinhard

Hallo Reinhard,

Kann man aus einer mit VB erstellten Exe den VB-Code auslesen?

nein. Bis VB4 wurde noch wie bei VBA interpretiert, das war lesbar.
Bei .NET wird nicht kompiliert, sondern ein P-Code geschrieben. In wie weit der lesbar ist, weiß ich nicht.

VB5 / VB6 wird aber tatsächlich zu einem Assemblerprogramm kompiliert, da bleibt vom Quellcode nur noch der Gedankengang übrig.

Ergo steht irgendwo in der Exe, unterbinde die Möglichkeit eine :offenen Datei mittels „Speichern unter“ zu speichern.
Könnte jmd. der sich mit Disassemblern auskennt mit dieser :Information die entsprechenden Assemblerbefehle in der Exe durch 0 :o.ä. ersetezen sodaß man dann die durch die exe angezeigte xls-Datei :„normal“ speichern könnte?

Jein. :smile: Assembler ist etwas schwerer zu lesen. Auch wenn man es kann dauert es noch länger, verstehen ist noch schwerer. Nun stell Dir vor, das Programm wird ein paar tausend Seiten lang.

Wer da einen Befehl suchen und finden kann, der könnte in der Zeit, die ihn das kostet, das Programm in VBA zwei mal selbst schreiben. :smile:

Gruß Rainer

Hallo Reinhard,

also mir ist definitiv keine Möglichkeit bekannt, den direkten Source auszulesen! Mit ein wenig Wissen und kann man zwar EXE oder DLL Files disamsemblieren und dort auch ergo abaendern. Aber das Bedarf grosses Wissen und der der das hat, schreibt sich in der Zeit die er dazu benötigt, selbst das proggi nach.

Unter .NET wird zum Bsp. gleich ein Disambler mit ausgeliefert. Dort kann man zu bsp. EXE Files laden und sich dann gewisse Sachen anzeigen lassen.

Mal ein kleines Demo :wink:

\_\_\_[MOD] D:\Projecte\VB9\Lernen Demos\WerteTypen Structur\ConsoleApplication1\ConsoleApplication1\bin\Release\ConsoleApplication1.exe
 | M A N I F E S T
 |\_\_\_[NSP] ConsoleApplication1
 | |\_\_\_[NSP] ConsoleApplication1.My
 | | |\_\_\_[NSP] ConsoleApplication1.My.Resources
 | | | |\_\_\_[CLS] ConsoleApplication1.My.Resources.Resources
 | | | | | .class private auto ansi sealed 
 | | | | | .custom instance void [System]System.CodeDom.Compiler.GeneratedCodeAttribute::.ctor(string, ...
 | | | | | .custom instance void [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.StandardModuleAttribute::.ctor() = ( 01 00 00 00 ) ...
 | | | | | .custom instance void [Microsoft.VisualBasic]Microsoft.VisualBasic.HideModuleNameAttribute::.ctor() = ( 01 00 00 00 ) ...
 | | | | | .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) ...
 | | | | | .custom instance void [mscorlib]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) ...
 | | | | |\_\_\_[STF] resourceCulture : private static class [mscorlib]System.Globalization.CultureInfo
 | | | | |\_\_\_[STF] resourceMan : private static class [mscorlib]System.Resources.ResourceManager
 | | | | |\_\_\_[STM] get\_Culture : class [mscorlib]System.Globalization.CultureInfo()
 | | | | |\_\_\_[STM] get\_ResourceManager : class [mscorlib]System.Resources.ResourceManager()
 | | | | |\_\_\_[STM] set\_Culture : void(class [mscorlib]System.Globalization.CultureInfo)
 | | | | |\_\_\_[PTY] Culture : class [mscorlib]System.Globalization.CultureInfo()
 | | | | |\_\_\_[PTY] ResourceManager : class [mscorlib]System.Resources.ResourceManager()
 | | | |
 | | |
 | | |\_\_\_[CLS] ConsoleApplication1.My.MyApplication
 | | | | .class private auto ansi 
 | | | | extends [Microsoft.VisualBasic]Microsoft.VisualBasic.ApplicationServices.ConsoleApplicationBase 
 | | | | .custom instance void [System]System.ComponentModel.EditorBrowsableAttribute::.ctor(valuetype [System]System.ComponentModel.EditorBrowsableState) = ( 01 00 01 00 00 00 00 00 ) ...
 | | | | .custom instance void [System]System.CodeDom.Compiler.GeneratedCodeAttribute::.ctor(string, ...
 | | | |\_\_\_[MET] .ctor : void()
 | | |
 | | |\_\_\_[CLS] ConsoleApplication1.My.MyComputer
 | | | | .class private auto ansi 
 | | | | extends [Microsoft.VisualBasic]Microsoft.VisualBasic.Devices.Computer 
 | | | | .custom instance void [System]System.ComponentModel.EditorBrowsableAttribute::.ctor(valuetype [System]System.ComponentModel.EditorBrowsableState) = ( 01 00 01 00 00 00 00 00 ) ...
 | | | | .custom instance void [System]System.CodeDom.Compiler.GeneratedCodeAttribute::.ctor(string, ...
 | | | |\_\_\_[MET] .ctor : void()
 | | |
 | | |\_\_\_[CLS] ConsoleApplication1.My.MyProject
 | | | | .class private auto ansi sealed beforefieldinit 
 | | | | .custom instance void [Microsoft.VisualBasic]Microsoft.VisualBasic.HideModuleNameAttribute::.ctor() = ( 01 00 00 00 ) ...
 | | | | .custom instance void [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.StandardModuleAttribute::.ctor() = ( 01 00 00 00 ) ...
 | | | | .custom instance void [System]System.CodeDom.Compiler.GeneratedCodeAttribute::.ctor(string, ...
 | | | |\_\_\_[CLS] MyWebServices
 | | | | | .class nested assembly auto ansi sealed 
 | | | | | .custom instance void [System]System.ComponentModel.EditorBrowsableAttribute::.ctor(valuetype [System]System.ComponentModel.EditorBrowsableState) = ( 01 00 01 00 00 00 00 00 ) ...
 | | | | | .custom instance void [Microsoft.VisualBasic]Microsoft.VisualBasic.MyGroupCollectionAttribute::.ctor(string, ...
 | | | | |\_\_\_[MET] .ctor : void()
 | | | | | Create\_\_Instance\_\_ : !!T (!!T)
 | | | | | Dispose\_\_Instance\_\_ : void (!!T&amp:wink:
 | | | | |\_\_\_[MET] Equals : bool(object)
 | | | | |\_\_\_[MET] GetHashCode : int32()
 | | | | |\_\_\_[MET] GetType : class [mscorlib]System.Type()
 | | | | |\_\_\_[MET] ToString : string()
 | | | |
 | | | | ThreadSafeObjectProvider`1
 | | | | | .class nested assembly auto ansi sealed 
 | | | | | .custom instance void [System]System.ComponentModel.EditorBrowsableAttribute::.ctor(valuetype [System]System.ComponentModel.EditorBrowsableState) = ( 01 00 01 00 00 00 00 00 ) ...
 | | | | | .custom instance void [mscorlib]System.Runtime.InteropServices.ComVisibleAttribute::.ctor(bool) = ( 01 00 00 00 00 ) ...
 | | | | |\_\_\_[STF] m\_ThreadStaticValue : private static !0
 | | | | |\_\_\_[MET] .ctor : void()
 | | | | |\_\_\_[MET] get\_GetInstance : !T()
 | | | | |\_\_\_[PTY] GetInstance : instance !0()
 | | | |
 | | | |\_\_\_[STF] m\_AppObjectProvider : private static initonly class ConsoleApplication1.My.MyProject/ThreadSafeObjectProvider`1
 | | | |\_\_\_[STF] m\_ComputerObjectProvider : private static initonly class ConsoleApplication1.My.MyProject/ThreadSafeObjectProvider`1
 | | | |\_\_\_[STF] m\_MyWebServicesObjectProvider : private static initonly class ConsoleApplication1.My.MyProject/ThreadSafeObjectProvider`1
 | | | |\_\_\_[STF] m\_UserObjectProvider : private static initonly class ConsoleApplication1.My.MyProject/ThreadSafeObjectProvider`1
 | | | |\_\_\_[STM] .cctor : void()
 | | | |\_\_\_[STM] get\_Application : class ConsoleApplication1.My.MyApplication()
 | | | |\_\_\_[STM] get\_Computer : class ConsoleApplication1.My.MyComputer()
 | | | |\_\_\_[STM] get\_User : class [Microsoft.VisualBasic]Microsoft.VisualBasic.ApplicationServices.User()
 | | | |\_\_\_[STM] get\_WebServices : class ConsoleApplication1.My.MyProject/MyWebServices()
 | | | |\_\_\_[PTY] Application : class ConsoleApplication1.My.MyApplication()
 | | | |\_\_\_[PTY] Computer : class ConsoleApplication1.My.MyComputer()
 | | | |\_\_\_[PTY] User : class [Microsoft.VisualBasic]Microsoft.VisualBasic.ApplicationServices.User()
 | | | |\_\_\_[PTY] WebServices : class ConsoleApplication1.My.MyProject/MyWebServices()
 | | |
 | | |\_\_\_[CLS] ConsoleApplication1.My.MySettings
 | | | | .class private auto ansi sealed beforefieldinit 
 | | | | extends [System]System.Configuration.ApplicationSettingsBase 
 | | | | .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) ...
 | | | | .custom instance void [System]System.CodeDom.Compiler.GeneratedCodeAttribute::.ctor(string, ...
 | | | | .custom instance void [System]System.ComponentModel.EditorBrowsableAttribute::.ctor(valuetype [System]System.ComponentModel.EditorBrowsableState) = ( 01 00 02 00 00 00 00 00 ) ...
 | | | |\_\_\_[STF] defaultInstance : private static class ConsoleApplication1.My.MySettings
 | | | |\_\_\_[STM] .cctor : void()
 | | | |\_\_\_[MET] .ctor : void()
 | | | |\_\_\_[STM] get\_Default : class ConsoleApplication1.My.MySettings()
 | | | |\_\_\_[PTY] Default : class ConsoleApplication1.My.MySettings()
 | | |
 | | |\_\_\_[CLS] ConsoleApplication1.My.MySettingsProperty
 | | | | .class private auto ansi sealed 
 | | | | .custom instance void [mscorlib]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) ...
 | | | | .custom instance void [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.StandardModuleAttribute::.ctor() = ( 01 00 00 00 ) ...
 | | | | .custom instance void [Microsoft.VisualBasic]Microsoft.VisualBasic.HideModuleNameAttribute::.ctor() = ( 01 00 00 00 ) ...
 | | | | .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) ...
 | | | |\_\_\_[STM] get\_Settings : class ConsoleApplication1.My.MySettings()
 | | | |\_\_\_[PTY] Settings : class ConsoleApplication1.My.MySettings()
 | | |
 | |
 | |\_\_\_[CLS] ConsoleApplication1.Module1
 | | | .class private auto ansi sealed 
 | | | .custom instance void [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.StandardModuleAttribute::.ctor() = ( 01 00 00 00 ) ...
 | | |\_\_\_[VCL] NumberSystems
 | | | | .class value nested public sequential ansi sealed 
 | | | | extends [mscorlib]System.ValueType 
 | | | |\_\_\_[STF] myDigits : private static char[]
 | | | |\_\_\_[FLD] myNumberSystem : private int32
 | | | |\_\_\_[FLD] myUnderlyingValue : private uint64
 | | | |\_\_\_[STM] .cctor : void()
 | | | |\_\_\_[MET] .ctor : void(uint64)
 | | | |\_\_\_[MET] .ctor : void(uint64,int32)
 | | | |\_\_\_[MET] .ctor : void(int32)
 | | | |\_\_\_[STM] Parse : valuetype ConsoleApplication1.Module1/NumberSystems(string,int32)
 | | | |\_\_\_[MET] ToString : string()
 | | | |\_\_\_[MET] get\_NumberSystem : int32()
 | | | |\_\_\_[MET] get\_Value : uint64()
 | | | |\_\_\_[MET] set\_NumberSystem : void(int32)
 | | | |\_\_\_[MET] set\_Value : void(uint64)
 | | | |\_\_\_[PTY] NumberSystem : instance int32()
 | | | |\_\_\_[PTY] Value : instance uint64()
 | | |
 | | |\_\_\_[STM] KonstruktorUndStandInstanzierungen : void()
 | | |\_\_\_[STM] Main : void()
 | | |\_\_\_[STM] NimmWerteTyp : void(valuetype ConsoleApplication1.Module1/NumberSystems)
 | | |\_\_\_[STM] NimmtReferenzTyp : void(class ConsoleApplication1.ReferenzTyp)
 | | |\_\_\_[STM] NimmtWerteTypByref : void(valuetype ConsoleApplication1.Module1/NumberSystems&amp:wink:
 | | |\_\_\_[STM] TesteByrefinSubs : void()
 | | |\_\_\_[STM] TesteReferenz : void()
 | | |\_\_\_[STM] TesteReferenzInSubs : void()
 | | |\_\_\_[STM] TesteWerte : void()
 | | |\_\_\_[STM] TesteZahlenSystem : void()
 | |
 | |\_\_\_[CLS] ConsoleApplication1.ReferenzTyp
 | | | .class private auto ansi 
 | | |\_\_\_[FLD] vRet : private int32
 | | |\_\_\_[MET] .ctor : void(int32)
 | | |\_\_\_[MET] get\_sValue : int32()
 | | |\_\_\_[MET] set\_sValue : void(int32)
 | | |\_\_\_[PTY] sValue : instance int32()

Wenn wir uns nun folgenden Eintrag mal anschauen

TesteReferenzInSubs : void() So erkennen wir das es sich um eine Sub handelt. Nur was macht diese? Also schauen wir und das auch noch einmal an :smile:

.method /\*06000017\*/ public static void TesteReferenzInSubs() cil managed
{
 // Code size 58 (0x3a)
 .maxstack 2
 .locals /\*1100000E\*/ init ([0] class ConsoleApplication1.ReferenzTyp/\*02000008\*/ WerteTyp2,
 [1] valuetype ConsoleApplication1.Module1/\*02000007\*//NumberSystems/\*02000009\*/ WerteType1)
 IL\_0000: ldloca.s WerteType1
 IL\_0002: ldc.i4.s 10
 IL\_0004: call instance void ConsoleApplication1.Module1/\*02000007\*//NumberSystems/\*02000009\*/::.ctor(int32) /\* 0600001F \*/
 IL\_0009: ldloc.1
 IL\_000a: call void ConsoleApplication1.Module1/\*02000007\*/::NimmWerteTyp(valuetype ConsoleApplication1.Module1/\*02000007\*//NumberSystems/\*02000009\*/) /\* 06000012 \*/
 IL\_000f: ldloc.1
 IL\_0010: box ConsoleApplication1.Module1/\*02000007\*//NumberSystems/\*02000009\*/
 IL\_0015: call void [mscorlib/\*23000001\*/]System.Console/\*01000019\*/::WriteLine(object) /\* 0A000020 \*/
 IL\_001a: ldc.i4.s 10
 IL\_001c: newobj instance void ConsoleApplication1.ReferenzTyp/\*02000008\*/::.ctor(int32) /\* 0600001B \*/
 IL\_0021: stloc.0
 IL\_0022: ldloc.0
 IL\_0023: call void ConsoleApplication1.Module1/\*02000007\*/::NimmtReferenzTyp(class ConsoleApplication1.ReferenzTyp/\*02000008\*/) /\* 06000013 \*/
 IL\_0028: ldloc.0
 IL\_0029: callvirt instance int32 ConsoleApplication1.ReferenzTyp/\*02000008\*/::get\_sValue() /\* 0600001C \*/
 IL\_002e: call void [mscorlib/\*23000001\*/]System.Console/\*01000019\*/::WriteLine(int32) /\* 0A000021 \*/
 IL\_0033: call valuetype [mscorlib/\*23000001\*/]System.ConsoleKeyInfo/\*0100001A\*/ [mscorlib/\*23000001\*/]System.Console/\*01000019\*/::ReadKey() /\* 0A00001F \*/
 IL\_0038: pop
 IL\_0039: ret
} // end of method Module1::TesteReferenzInSubs

Hier kann man mit tiefergehenden Kenntnissen erkennen, was da gemacht wird und koennte nun einfach das proggi nach basteln!

Ich selbst verstehe davon zwar nicht alles, aber ca. 70% schon :wink: Da man nicht drum herum kommt, es auch ab und wann mal zu nutzen :smile:

MfG Alex

OT Danke euch beiden für die Informationen
Hallo Alex und Rainer,

siehe Betreff.

@Alex, sorry, wie du in der Email sehen kannst habe ich wieder mal Alex mit Axel vertauscht, sorry dafür :frowning:

Gruß
Reinhard

mit halt der Frage, ob jemand da es schafft den darin
enthaltenen Vba-Code auszulesen.

Er hätte nur die FAQ lesen müssen:

„Is it possible to extract the XLS file from the compiled EXE?“

Yes, it is possible. Also you can find this file in temporary folder on you disk when compiled EXE is started. This xls file DOESN’T contain any formulas in cells. NONE OF THEM! This file is a data provider between compiled EXE and Excel. It is used to format calculated values and to reflect them into Excel. After compilation all xls formulas are stored in EXE file (in binary, unreadable format) but not in xls. You can try this file to figure out that it doesn’t work as original xls.


Das ist nun ein wenig neblig und mehrdeutig, ob aus Gründes des Schutzes von Geschäftsgeheimnissen oder weil hier wieder mal nur ein drittklassiger Pseudo-Schutz zum Einsatz kommt ist ohne die Details zu kennen nicht ersichtlich.

Also mal das was sich ablesen lässt: die Formeln werden aus der Original-XLS Datei entfernt und in der externen exe gespeichert. Ob sie da tatsächlich mehr sind als „getarntes VBA“ kann man nicht sagen, die betont neblige Ausdrucksweise „binary form“ der FAQ ließe das aber durchaus zu. Wenns so wäre, und man annähme dass niemand diese „binary form“ zu interpretieren in der Lage wäre, würden die Formeln in jedem Fall von der exe im Hauptspeicher „entschleiert“, an Excel übergeben mit der freundlichen Bitte um Berechnung, Excel würde das Ergebnis an die exe liefern, und diese würde es in die temporäre xls schieben zwecks Darstellung. Diese Taktik wäre angreifbar, indem man den Hauptspeicher beobachtet, oder indem man die Formeln am Übergabepunkt an Excel (wo auch immer der zu suchen ist - ich würde das vba Debugger Interface verdächtigen) abfängt.

Alternativ könnte der Anbieter in seiner exe natürlich alle Makrobefehle von Excel/vba als eigenen Maschinencode neu programmieren, und dann wäre der Angreifer gezwungen, den Code auf binärer Basis zu entschlüsseln. Eine irre Arbeit - allerdings für beide. Ich meine, dass der günstige Preis des Produkts das niemals hergibt. Also handelt es sich m.E. „nur“ um eine - zugegebener Maßen offenbar recht schlau eingefädelte - Verschleierung des vba Codes. Er kann also höchst wahrscheinlich sichtbar gemacht werden, wenn jemand die Abfangmethode („Man in the Middle“) implementieren kann.

Meine derzeitigen Systemkenntnisse würden dazu allerdings - ebenfalls zugegebener Maßen - nicht ausreichen. Daher kann ich nur vermuten, aber nicht sicher wissen.

Und wenn das Posting im Forum niemals entschlüsselt wird, heißt das erst mal garnichts. Zwei Gegenargumente: die Belohnung für die Mühe lohnt den Aufwand nicht, und wenn jemand wirklich einen erfolgreichen Hack findet und - wie die meisten hier - kein absolut immateriell eingestellter Idealist ist - warum sollte er das an die große Glocke hängen? Am Besten ist es doch, einen Hack für ein System zu haben, und niemand weiß es. Sonst wird das System geändert, und die Mühe war - abgesehen von etwas Bewunerung in der Community - für die Katz.

…Armin