Kompilierte exe Datei crypten / schützen

  • VB.NET

Es gibt 27 Antworten in diesem Thema. Der letzte Beitrag () ist von BiedermannS.

    Kompilierte exe Datei crypten / schützen

    Hallo,

    ich habe eine kleine Application geschrieben.
    Wie gut oder wie hoch ist die Wahrscheinlichkeit, dass man diese exe Datei (in VB 2010 geschrieben) dekompilieren kann?

    Kennt jemand ein Programm womit man die .exe Dateien schützen kann? - sollte wenn möglich max. 150€ kosten (nicht kommerziell, das Programm ist frei).


    Vielen Dank!

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „grex“ () aus folgendem Grund: Rechtschreibfehler ausgebssert

    Hallo,

    danke für die rasche Antwort.
    Eig. dachte ich eher an crypten, solche Programme wie Themida (oreans.com/themida.php)
    Jedoch ist mir das Programm zu teuer. Die Suche habe ich schon verwendet, aber ich weiß ehrlich gesagt nicht, nach was genau gesucht wird.
    Im prinzip ja "exe verschlüsseln", "exe crypting" oder?
    Es gibt bestimmt mehrere Programme...

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „grex“ () aus folgendem Grund: Rechtschreibfehler ausgebessert

    grex schrieb:

    Wie gut oder wie hoch ist die Wahrscheinlichkeit, dass man diese exe Datei (in VB 2010 geschrieben) deckmpilieren kann?
    Stell dir erstmal die Frage: Wie gut oder wie hoch ist die Wahrscheinlichkeit, dass man diese exe Datei dekompilieren will?

    ...sollte wenn möglich max. 150€ kosten (nicht kommerziell, das Programm ist frei).
    Was soll das? Du verschenkst dein Programm, aber den Code soll niemand angugge dürfen - würdeste sogar 150€ für abdrücken??

    versteh ich nicht.

    ErfinderDesRades schrieb:

    Was soll das? Du verschenkst dein Programm, aber den Code soll niemand angugge dürfen - würdeste sogar 150€ für abdrücken??

    versteh ich nicht.

    ErfinderDesRades schrieb:

    Stell dir erstmal die Frage: Wie gut oder wie hoch ist die Wahrscheinlichkeit, dass man diese exe Datei dekompilieren will?



    Ich dachte mir schon, dass so eine Frage kommt. Die Gegenfrage ist es, musst du es wissen? - Die Frage im ersten Post wurde gestellt ;)
    Aber ich erklärs mal ganz kurz:

    Ich betreibe einen Gameserver, jedoch gibts schon ziemlich viele Hacks dafür, die den Spielspaß rauben. Nun habe ich einen Loader / Anti Cheat geschrieben, der im Spieleverzeichnis die MD5s mit der Whitelist bzw. Blacklist vom Server abgleicht.
    Der Client ist mit Visual Basic geschrieben, die Serverversion in C++ und wird betrieben auf Linux.
    Wir haben eine Betaphase eingeführt, jetzt kommen natürlich schon die ersten Spieler, die den Loader dekompilieren. Dagegen möchte ich vorgehen. Ein anderes Projektteam hat es mit Themida abgesichert. 150€ ist schon viel da gebe ich dir recht, aber ist im Projektbudget enthalten.
    Die Lösung von big-d funktioniert leider nicht, es lässt sich mit dem Telerik JustDecompile dekompilieren, zwar werden die Variablen anders angezeigt, aber mit z.B. themida kann der Dekompiler erst garnicht öffnen.


    Natürlich bin ich für jeden weiteren Rat von dir/euch dankbar!

    EDIT: @ Annoxoli Danke dir für den Tipp, hast du damit schon Erfahrung gemacht? - Die SW + Jahreslizenz für Updats hat einen stolzen Preis :/

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „grex“ () aus folgendem Grund: Kurze Ergänzung

    nein, du hast natürlich recht: ich musses nicht wissen. Aber ich bin erst recht froh, dassich gefragt hab, weilich deine Ausführungen interessant finde, unds gefällt mir einfach, wenn ich Zusammenhänge verstehe :).

    Vlt. geht die GrundIdee deines Sicherheitskonzepts nicht auf:
    Also statt eines AntiCheat-Loaders, der abfragt: "Bin ich gesperrt?", sollte die Sperr-Logik auffm Server liegen, also dass wer gesperrt ist, eben nicht mehr bedient wird.
    @ErfinderDesRades
    Das ist schon richtig das die Sperr-Logik auf dem Server sein muss, doch die Erkennung ob Dateien geändert wurden, muss beim Spieler sein.

    @grex
    Am wichtigsten ist erst mal, dass du keine pdb Dateien mitgibst. Alles was man nicht zum ausführen der EXE braucht, hat beim "Spieler" nichts zu suchen. Denn dotPeek kann auch pdb Dateien lesen, wodurch das ganze Obfuskieren nutzlos wird...

    Am einfachsten wäre ein Obfuskator und wenn du ein paar Dinge in native DLL's auslagerst.

    Man kann natürlich auch händisch obfuskieren (nicht so sicher wie ein Obfuskator, nicht leicht umzusetzen, aber gratis):
    Achtung: Dadurch wird der nicht nur der Code nach dem dekompilieren unleserlich, sonder auch der echte Sourcecode wird ziemlich verwirrend...
    Spoiler anzeigen
    Verwende viele Statische Variablen, diese werden nämlich so unleserlichen benannt das nur der Compiler das schön lesen kann.
    Verwende viele Anonyme Methoden, selbes Spiel wie mit den Variablen
    Baue unnötige Jumps und Labels ein, Funktionen die Nichts bewirken aber so heißen als währen sie wichtig.
    Benenne Funktionen mit namen wie "X", "F" usw..
    Brich so ziemlich jede regel die du dir normalerweise für das Programmieren gesetzt hast, sei kreativ.


    Du musst halt nur aufpassen das die Performance nicht zu sehr darunter leidet.

    Hier mal ein kleines Beispiel:

    Ein von mir erstellte "For-Schleife", mit Telerik JustDecompile dekompiliert (wenn man nicht weiß, dass dieser Code die Funktionalität einer For-Schleife hat, findet man das von selber nie raus):

    Spoiler anzeigen

    VB.NET-Quellcode

    1. <StandardModule> _
    2. Friend NotInheritable Class obfuskiert
    3. <AccessedThroughProperty("o")> _
    4. Private Shared _o As x
    5. Private Property Shared o As x
    6. Get
    7. Return obfuskiert._o
    8. End Get
    9. Set(ByVal value As x)
    10. obfuskiert._o = WithEventsValue
    11. End Set
    12. End Property
    13. Shared Sub New()
    14. obfuskiert.o = New x()
    15. End Sub
    16. Public Shared Sub m(ByVal a As Integer)
    17. obfuskiert.o.q()
    18. Console.WriteLine(a)
    19. End Sub
    20. <STAThread> _
    21. Public Shared Sub Main()
    22. obfuskiert.o.q()
    23. obfuskiert.o.add_d(New dEventHandler(Nothing.obfuskiert.m))
    24. obfuskiert.o.q()
    25. Dim num As Long = CLng(100).y(num, Conversions.ToString(2000), 1, 0)
    26. Console.ReadLine()
    27. End Sub
    28. End Class
    29. Public Class x
    30. Private Shared __ENCList As List(Of WeakReference)
    31. Private dEvent As dEventHandler
    32. Private FALSCH As Boolean
    33. Private r As Delegate
    34. Private WAHR As Boolean
    35. <DebuggerNonUserCode> _
    36. Shared Sub New()
    37. x.__ENCList = New List(Of WeakReference)()
    38. End Sub
    39. Public Sub New()
    40. MyBase.New()
    41. x.__ENCAddToList(Me)
    42. Me.FALSCH = True
    43. Me.r = New VB$AnonymousDelegate_0(Of Integer)(Me._Lambda$__1)
    44. Me.WAHR = False
    45. Me.$STATIC$y$204110AE88$a$Init = New StaticLocalInitFlag()
    46. Me.$STATIC$y$204110AE88$b$Init = New StaticLocalInitFlag()
    47. Me.$STATIC$y$204110AE88$c$Init = New StaticLocalInitFlag()
    48. Me.$STATIC$y$204110AE88$e$Init = New StaticLocalInitFlag()
    49. Me.$STATIC$y$204110AE88$l$Init = New StaticLocalInitFlag()
    50. Me.$STATIC$y$204110AE88$d$Init = New StaticLocalInitFlag()
    51. End Sub
    52. <DebuggerNonUserCode> _
    53. Private Shared Sub __ENCAddToList(ByVal value As Object)
    54. Dim _ENCList As List(Of WeakReference) = x.__ENCList
    55. SyncLock _ENCList
    56. If (x.__ENCList.Count = x.__ENCList.Capacity) Then
    57. Dim num1 As Integer = 0
    58. Dim count As Integer = Dim num2 As Integer = x.__ENCList.Count - 1
    59. While (Dim num3 As Integer = num2) <= num3
    60. Dim item As WeakReference = x.__ENCList(count)
    61. If (item.IsAlive) Then
    62. If (flag) Then
    63. x.__ENCList.Item = num1
    64. End If
    65. num1 = num1 + 1
    66. End If
    67. count = count + 1
    68. End While
    69. x.__ENCList.RemoveRange(num1, x.__ENCList.Count - num1)
    70. x.__ENCList.Capacity = x.__ENCList.Count
    71. End If
    72. x.__ENCList.Add(New WeakReference(RuntimeHelpers.GetObjectValue(value)))
    73. End SyncLock
    74. End Sub
    75. Public Sub q()
    76. Me.FALSCH = Me.FALSCH Xor 1
    77. Me.WAHR = Me.WAHR Xor 1
    78. End Sub
    79. Public Sub y(ByRef k As Long, ByVal x As String, ByVal f As Integer, ByVal s As Integer)
    80. Dim dateTime As DateTime
    81. Dim millisecond As Integer
    82. Dim objArray As Object()
    83. Dim num As Long
    84. Me.q()
    85. Dim flag1 As Boolean = False
    86. Try
    87. Monitor.Enter(Me.$STATIC$y$204110AE88$a$Init, flag1)
    88. If (Me.$STATIC$y$204110AE88$a$Init.State = 0) Then
    89. Me.$STATIC$y$204110AE88$a$Init.State = 2
    90. Me.$STATIC$y$204110AE88$a = s
    91. Else
    92. If (Me.$STATIC$y$204110AE88$a$Init.State = 2) Then
    93. Throw New IncompleteInitialization()
    94. End If
    95. End If
    96. Finally
    97. Me.$STATIC$y$204110AE88$a$Init.State = 1
    98. If (flag1) Then
    99. Monitor.Exit(Me.$STATIC$y$204110AE88$a$Init)
    100. End If
    101. End Try
    102. Me.q()
    103. Dim flag2 As Boolean = False
    104. Try
    105. Monitor.Enter(Me.$STATIC$y$204110AE88$b$Init, flag2)
    106. If (Me.$STATIC$y$204110AE88$b$Init.State = 0) Then
    107. Me.$STATIC$y$204110AE88$b$Init.State = 2
    108. Me.$STATIC$y$204110AE88$b = Conversions.ToInteger(x)
    109. Else
    110. If (Me.$STATIC$y$204110AE88$b$Init.State = 2) Then
    111. Throw New IncompleteInitialization()
    112. End If
    113. End If
    114. Finally
    115. Me.$STATIC$y$204110AE88$b$Init.State = 1
    116. If (flag2) Then
    117. Monitor.Exit(Me.$STATIC$y$204110AE88$b$Init)
    118. End If
    119. End Try
    120. Dim flag3 As Boolean = False
    121. Try
    122. Monitor.Enter(Me.$STATIC$y$204110AE88$c$Init, flag3)
    123. If (Me.$STATIC$y$204110AE88$c$Init.State = 0) Then
    124. Me.$STATIC$y$204110AE88$c$Init.State = 2
    125. Me.$STATIC$y$204110AE88$c = f
    126. Else
    127. If (Me.$STATIC$y$204110AE88$c$Init.State = 2) Then
    128. Throw New IncompleteInitialization()
    129. End If
    130. End If
    131. Finally
    132. Me.$STATIC$y$204110AE88$c$Init.State = 1
    133. If (flag3) Then
    134. Monitor.Exit(Me.$STATIC$y$204110AE88$c$Init)
    135. End If
    136. End Try
    137. If ((k Mod CLng(2) = CLng(0) Xor Me.WAHR) <> 0) Then
    138. Me.$STATIC$y$204110AE88$a = s
    139. Me.$STATIC$y$204110AE88$b = Conversions.ToInteger(x)
    140. Me.$STATIC$y$204110AE88$c = f
    141. Else
    142. s = s
    143. End If
    144. Dim flag4 As Boolean = False
    145. Try
    146. Monitor.Enter(Me.$STATIC$y$204110AE88$e$Init, flag4)
    147. If (Me.$STATIC$y$204110AE88$e$Init.State = 0) Then
    148. Me.$STATIC$y$204110AE88$e$Init.State = 2
    149. millisecond = dateTime.Millisecond.$STATIC$y$204110AE88$e = New Random(Conversions.ToInteger(Convert.ChangeType(millisecond.ToString(), s.GetType())))
    150. Else
    151. If (Me.$STATIC$y$204110AE88$e$Init.State = 2) Then
    152. Throw New IncompleteInitialization()
    153. End If
    154. End If
    155. Finally
    156. Me.$STATIC$y$204110AE88$e$Init.State = 1
    157. If (flag4) Then
    158. Monitor.Exit(Me.$STATIC$y$204110AE88$e$Init)
    159. End If
    160. End Try
    161. Me.q()
    162. Dim flag5 As Boolean = False
    163. Try
    164. Monitor.Enter(Me.$STATIC$y$204110AE88$l$Init, flag5)
    165. If (Me.$STATIC$y$204110AE88$l$Init.State = 0) Then
    166. Me.$STATIC$y$204110AE88$l$Init.State = 2
    167. millisecond = dateTime.Millisecond.$STATIC$y$204110AE88$l = New Random(Conversions.ToInteger(Convert.ChangeType(millisecond.ToString(), Me.$STATIC$y$204110AE88$c.GetType())))
    168. Else
    169. If (Me.$STATIC$y$204110AE88$l$Init.State = 2) Then
    170. Throw New IncompleteInitialization()
    171. End If
    172. End If
    173. Finally
    174. Me.$STATIC$y$204110AE88$l$Init.State = 1
    175. If (flag5) Then
    176. Monitor.Exit(Me.$STATIC$y$204110AE88$l$Init)
    177. End If
    178. End Try
    179. Me.q()
    180. Dim flag6 As Boolean = False
    181. Try
    182. Monitor.Enter(Me.$STATIC$y$204110AE88$d$Init, flag6)
    183. If (Me.$STATIC$y$204110AE88$d$Init.State = 0) Then
    184. Me.$STATIC$y$204110AE88$d$Init.State = 2
    185. millisecond = dateTime.Millisecond.$STATIC$y$204110AE88$d = New Random(Conversions.ToInteger(Convert.ChangeType(millisecond.ToString(), Me.$STATIC$y$204110AE88$b.GetType())))
    186. Else
    187. If (Me.$STATIC$y$204110AE88$d$Init.State = 2) Then
    188. Throw New IncompleteInitialization()
    189. End If
    190. End If
    191. Finally
    192. Me.$STATIC$y$204110AE88$d$Init.State = 1
    193. If (flag6) Then
    194. Monitor.Exit(Me.$STATIC$y$204110AE88$d$Init)
    195. End If
    196. End Try
    197. Me.q()
    198. Me.q()
    199. If ((Me.$STATIC$y$204110AE88$c <> 0 Xor Me.WAHR) <> 0) Then
    200. Me.q()
    201. If ((Me.$STATIC$y$204110AE88$c > 0 Xor Me.FALSCH) <> 0) Then
    202. Me.q()
    203. If ((Me.$STATIC$y$204110AE88$a - Me.$STATIC$y$204110AE88$b >= 0 And Me.$STATIC$y$204110AE88$a <> Me.$STATIC$y$204110AE88$b Xor Me.WAHR) <> 0) Then
    204. Throw New Exception("Exception 2")
    205. End If
    206. Me.q()
    207. Me.r.DynamicInvoke(New Object() { Me.$STATIC$y$204110AE88$a })
    208. Me.$STATIC$y$204110AE88$a = Me.$STATIC$y$204110AE88$a + Me.$STATIC$y$204110AE88$c
    209. Me.q()
    210. If ((Me.$STATIC$y$204110AE88$a <= Me.$STATIC$y$204110AE88$b Xor Me.FALSCH) <> 0) Then
    211. Me.q()
    212. num = CLng(15).y(num, Conversions.ToString(Me.$STATIC$y$204110AE88$e.Next()), Me.$STATIC$y$204110AE88$d.Next(), Me.$STATIC$y$204110AE88$l.Next())
    213. Else
    214. Me.q()
    215. Me.q()
    216. Me.q()
    217. End If
    218. Else
    219. Me.q()
    220. If ((Me.$STATIC$y$204110AE88$a - Me.$STATIC$y$204110AE88$b < 0 And Me.$STATIC$y$204110AE88$a <> Me.$STATIC$y$204110AE88$b Xor Me.WAHR) <> 0) Then
    221. Throw New Exception("Exception 6")
    222. End If
    223. Me.r.DynamicInvoke(New Object() { Me.$STATIC$y$204110AE88$a })
    224. Me.$STATIC$y$204110AE88$a = Me.$STATIC$y$204110AE88$a + Me.$STATIC$y$204110AE88$c
    225. Me.q()
    226. If ((Me.$STATIC$y$204110AE88$a <= Me.$STATIC$y$204110AE88$b Xor Me.FALSCH) <> 0) Then
    227. num = CLng(9).y(num, Conversions.ToString(Me.$STATIC$y$204110AE88$d.Next()), Me.$STATIC$y$204110AE88$l.Next(), Me.$STATIC$y$204110AE88$e.Next())
    228. End If
    229. End If
    230. End If
    231. Throw New Exception("Exception 32")
    232. End Sub
    233. Public Event d As dEventHandler
    234. Public NotInheritable Class dEventHandler
    235. Inherits MulticastDelegate
    236. Public Sub New(ByVal TargetObject As Object, ByVal TargetMethod As IntPtr)
    237. Public Overridable Function BeginInvoke(ByVal a As Integer, ByVal DelegateCallback As AsyncCallback, ByVal DelegateAsyncState As Object) As IAsyncResult
    238. Public Overridable Sub EndInvoke(ByVal DelegateAsyncResult As IAsyncResult)
    239. Public Overridable Sub Invoke(ByVal a As Integer)
    240. End Class
    241. End Class



    Hier eine normale For-Schleife, dekompiliert:

    Spoiler anzeigen

    VB.NET-Quellcode

    1. <StandardModule> _
    2. Friend NotInheritable Class original
    3. Public Shared Sub test()
    4. Dim i As Integer = 0
    5. Do
    6. Console.WriteLine(i)
    7. i = i + 1
    8. Loop While (Dim num As Integer = 100) <= num
    9. End Sub
    10. End Class


    Zu Schluss noch:
    Verwende bitte keine MD5 Hashes.

    MD5 ist für so etwas schon sehr veraltet. Und jeder der sich etwas auskennt und Zeit investiert kann dir ne EXE machen die den selben MD5 hat. Da gibt es einfach zu wenig Zeichen ^^

    Habt ihr auch eine Überprüfung ob von aussen was in den Prozess injected wird?


    Mfg Steve
    SWYgeW91IGNhbiByZWFkIHRoaXMsIHlvdSdyZSBhIGdlZWsgOkQ=

    Weil einfach, einfach zu einfach ist! :D
    Danke erstmal für die super Antworten.

    pdb Dateien habe ich bis jetzt keine weitergegeben und hätte es auch nicht vorgehabt. Eine native DLL habe ich bis jetzt noch nie etwas gemacht, aber es soll eine einfache Exe sein die am Desktop dann liegt, daher zusätzliche Files wären nicht so ideal.
    Leider kann man ja noch den Code auch noch mittels Obfuskator auslesen,... auch wenn jetzt nurnoch steth string1, string2, int1,int2 usw.
    Ich suche aber ein Programm womi das erst garnicht möglich ist.

    Themida schlägt leider bei einigen Antivirenprogrammen an Begründung: themida
    Im Prinzip nix schlimmes, aber dennoch ärgerlich.
    Zum Thema MD5: Bist du dir da sicher, dass man den MD5 Wert einer Datei beliebig ändern kann? Das wäre ja mal interessant.
    Was würdest du dann nehmen SHA1, oder SHA256/SHA512?

    Nochmals danke!

    grex schrieb:

    Leider kann man ja noch den Code auch noch mittels Obfuskator auslesen,... auch wenn jetzt nurnoch steth string1, string2, int1,int2 usw.
    Ich suche aber ein Programm womi das erst garnicht möglich ist.!

    Sowas kann es für eine .NET-Assembly nicht geben. Spätestens im Arbeitsspeicher landet beim Ausführen der IL-Code.
    Wenn dir das so wichtig ist, kannst du - wie dir auch bereits empfohlen wurde - eigentlich nur einen anderen Compiler benutzen.
    Es ist im Prinzip auch möglich, das nur mit ein paar Teilen deines Programms zu machen.
    Hallo,

    @Renati: Falls es dich interessiert, kannst du mal die Trial Version von Themida (Link steht oben) runterladen, du brauchst es nicht installieren, ist eine portable Version. Damit kann ich mit keinem Dekompiler etwas anfangen. Nat. kenn ich mich mit dem Dekompilieren nicht wirklich aus (siehe Fragestellung oben ;)).

    Ich habe denen angeschrieben, aber leider antworten die nicht, warum auch immer. Eventuell ausgestorben. - Seite sieht mir aber auch nicht wirklich seriös aus, muss ich zugeben.
    Ich glaube ich werde es wirklich mit einem Obfuskator probieren. Ob den Free oder den um 200€ muss ich mir noch überlegen.

    Ich werde das Tool noch ein bisschen umschreiben, da ihr gute Einwände hattet mit MD5 + überprüfen ob etwas in dem Gameprozess "injeziert" wurde. Das Problem ist, einige "Hacks" sind erlaubt (z.B. dass man seine eigenen Koordinaten sieht, usw.). Es gibt aber auch Tools, die komplett von uns verboten werden.

    Ich danke euch für eure Mithilfe :)
    ... erst recht mit einem budget von 150€. so eine kleinigkeit erledigt euch in einem C++ forum sicher jemand für <30€. macht doch ne ausschreibung mit abgabetermin und nehmt den kleinstbietenden. :thumbup:
    Jungs ihr vergesst das der IL Code zur Laufzeit IMMER plain in der CRL liegt ... also könnt ihr obfuskieren bis ihr blöd werdet ... per Simulation komme ich trotzdem an den ganzen Code :)!

    ... ich hatte Renati übersehen ,wie er schon richtig erkannte zur Runtime liegt der gesamte IL-Code in der CRL und damit im Arbeitsspeicher :=)

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „(Ger)Foley“ () aus folgendem Grund: hab was übersehen :=)

    Renati ist ne Frau und du solltest nochmal nachlesen was IL Code ist. Bei einem nativen C++-Programm (nicht eins das nur ein .NET-Proggie in den RAM entschlüsselt) wirste den wohl kaum finden.