Vereinfachte Updatefunktion

  • VB.NET

Es gibt 14 Antworten in diesem Thema. Der letzte Beitrag () ist von Springbok.

    Vereinfachte Updatefunktion

    Hallo und alles Gute im neuen Jahr!

    Ich hab eine Frage bezüglich meines Programms was ich gerade dabei bin zu verfeinern. Es geht um die Updatefunktion, sprich das Programm soll (automatisch oder durch einen Userklick) auf eine neue Version prüfen. Um etwas jedoch vorweg zu nehmen: Das updateSystem.NET kommt nicht in Frage. Der Grund dazu ist dass ich keinen Server habe und ich mir auch keinen anlegen will. Ich veröffentliche mein Programm über ein Supportforum einer Firma und stelle da einen Dropboxlink rein wo jeder User selber herunterladen muss und selbst das Programm extrahieren/installieren muss (Ich möchte das jedem User selber überlassen damit sie sehen was an ihrem PC gewerkelt wird!). Auf derm Server der Firma wollte ich eigentlich nur eine .txt anlegen. Sozusagen so:
    Serverpfad: w w w . d i e f i r m a . d e / V e r s i o n . t x t (sorry für die Schreibweise aber die Website gibt es wirklich und ich will keine Zusammenhängigkeit hervorrufen)
    In der Datei Version.txt steht dann folgendes: X.X.X.X
    mit X={0,1,2,3,4,5,6,7,8,9}

    Mein Programm macht also folgendes: Nach dem Userklick (das automatische lassen wir mal weg) geht mein Programm hin lädt diese Version.txt Datei runter, vergleicht was in der Datei steht mit der Versionsnummer des Programms. Falls die Version.txt-Versionsnummer grösser als die des Programms ist geht eine Messagebox auf und das Programm fragt ob es den Browser öffnen soll um die neueste Version zu laden. Falls die Versionsnummern identisch sind gibt es nur eine Messagebox die sagt, dass das Programm aktuell ist.

    Das ist meine theoretische Lösung zur Frage. Nur wollte ich jetzt mal von euch wissen ob das eine gute Idee ist. Wo wären die eventuellen Schwachstellen? (Wenn wir mal das kapern des Dropboxaccounts und des Servers weglassen.) Gibt es Optimisationsmöglichkeiten oder sogar alternative Wege?

    Ich bedanke mich jetzt schon bei eurer Kritik!
    cheers Kevin
    Hy ich habe ein Update System erstellt du brauchst nur ein Ftp Server. Du kannst Updates ganz einfach durch das Managment Studio Hochladen [Beta] Freesoft Auto Updater
    Meine Projekte Genesis Game Engine | GFX | smartli.me - Der smarte URL shortener

    @Andy16823:

    Springbok schrieb:

    etwas jedoch vorweg zu nehmen: [...] Der Grund dazu ist dass ich keinen Server habe und ich mir auch keinen anlegen will. Ich veröffentliche mein Programm über ein Supportforum einer Firma und stelle da einen Dropboxlink rein wo jeder User selber herunterladen muss und selbst das Programm extrahieren/installieren muss [...]


    Afaik arbeitet dein Management-Studio automatisch, genauso, wie nUpdate, sodass dies nicht in Frage kommt.
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:
    Ich frage mich ob die in VS integrierte Publish/Update-Funktion sich nicht schon mit nem Dropbox Ordner versteht.
    Hast du das mal getestet?

    Ich benutze die Funktion hier mit nem Netzwerk-Ordner... Das funktioniert ganz schön.

    PS. Andy... er schreibt er hat keinen Server und du schreibst "brauchst nur nen Server"... naja
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    ... Nun solltest es selber wissen. :'D

    Springbok schrieb:

    Wo wären die eventuellen Schwachstellen?

    Jemand könnte den Internetverkehr des Users umleiten (zum Beispiel über Manipulation der hosts-Datei), sodass statt des Firmenservers ein "bösartiger" Server angesteuert wird, auf dem auch eine Version.txt liegt. Die ist dann auf einen Wert wie 9.9.9.9 eingestellt, sodass immer die neue Exe vom Server heruntergeladen wird. Und schon hat der User ein ungewünschtes Programm auf seinem PC. Wenn sein Internetverkehr umgeleitet wird, hatte er das vmtl. vorher auch schon, aber das ist ja erstmal egal ^^
    Lösen könnte man das durch eine Authentifizierung oder ein Zertifikat, da können dir andere bestimmt mehr zu erzählen.

    Ein paar praktische Dinge zur Umsetzung:
    Nutze die Version-Klasse. Die hat einen Constructor, dem du einen String in der Form X.X.X.X übergeben kannst, das ist praktisch. Vor allem, weil die Version-Klasse den < und > Operator definiert. Damit lassen sich zwei Versions-Objekte also super vergleichen.
    Deinen Versions-String bekommst du am einfachsten mit einem WebClient und dessen DownloadString oder DownloadStringAsync Methode. Dazu gibt's auch genug Beispiele.

    Skybird schrieb:

    Das sind ja Ubisoftmethoden hier !

    @vb-checker: Jo, Authentifizierung durch eine Signierung, am Besten mit RSA (4096 bit), das ist sehr sicher. Dabei wird einfach der Hash des Archives berechnet, in dem sich das Update befindet, oder auch nur der Hash der Datei, wenn es so ist.

    Diese Gefahren gehen meist nicht nur von Umleitungen (an Flughäfen o. ä. Orten) aus, sondern auch von gekaperten Webspaces.

    Hierbei verweise ich mal auf den RSA-Wrapper von nUpdate (ursprünglich mit timmi31061 entworfen):
    github.com/ProgTrade/nUpdate/b…ature/SignatureManager.cs
    ist GPL v3, es müssen also die Urheber drinnen bleiben und Änderungen auskommentiert werden.

    Ansonsten dazu eben:
    msdn.microsoft.com/de-de/library/aa331388(v=vs.71).aspx
    msdn.microsoft.com/de-de/library/55yk5665(v=vs.110).aspx
    de.wikipedia.org/wiki/Asymmetrisches_Kryptosystem
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:
    Also erstmal Danke an alle hier für die zahlreichen Antworten. Ich geh sie mal der Reihe nach durch:

    @Andy16823:
    Danke für deinen Vorschlag aber Freesoft Auto Updater scheint (mehr oder weniger) das selbe zu sein wie updateSystem.NET. Da ich keinen FTP-Server hab fällt das weg. Ausserdem will ich den User zwingen die Datei selbst zu entpacken und alles zu ersetzen damit er weiss was da abläuft (nachher sagt noch einer dass wegen meinem automatischen Extrahieren der PC kaputt ist - ist ja üblicherweise immer der Dev nie der User).

    @MemoAnMichSelbst:
    Daran dachte ich auch schon, das Problem ist aber auch wieder hier dass es automatisch installiert wird oder? Ausserdem will ich nur dass der User ja eine Benachrichtigung bekommt dass ein Update da ist. Somit käme das nicht in Frage.

    @vb-checker:
    Das mit der hosts-Datei ist dann wirklich ein Problem. Aber dazu müsste er wissen dass der User genau den Server ansteuert von wo ich die Datei lade somit wäre sein Rechner ja schon "kaputt" bevor ich überhaupt was mache. Ausserdem bin ich mir sicher dass dieses Programm <10000 Leute verwenden. Ich denke solche agressiven Methoden kommen für solche Randgruppen nicht vor oder?

    Das mit der Versionsklasse hab ich mir angeschaut und es scheint sicher viel besser zu sein als den Stringvergleich den ich anstellen wollte. Aber bevor ich das benutzen kann muss ich mich da rein arbeiten. Weitere Fragen folgen also wahrscheinlich erst später :)

    @Trade:
    Das mit diesem RSA meinst du ja so: Ich soll die Datei Version.txt mit einem RSA-4096bit signieren. Den Grund dazu verstehe ich nicht ganz. Falls ich das ja einlese weiss ich wie die Datei aussieht. Besteht ja nur aus "X.X.X.X". Ich könnte ja einfach ein paar Checks einbauen die das was in der Datei steht anguckt und sagt ob es das richtige Format hat und keine unzulässigen characters enthält oder wäre das falsch? Ich würde dann ne Iterationsschleife laufen lassen die erst mal schaut ob das "X.X.X.X" 7 Characters lang ist. Falls ja läuft eine weitere Iterationsschleife von 0 bis 6 und schaut ob 0,2,4,6 Zahlen (0...9) sind und ob 1,3,5 Punkte (".") sind. Damit hätte ich doch alle möglichen Probleme aus der Welt geschafft oder irre ich hier? Falls ja würde es mich interessieren wieso und warum (will ja was dazulernen). Ausserdem verstehe ich nicht wieso ich nur eine "normale" Datei mit "X.X.X.X" so arg "verschlüsseln" muss. Ich lade ja nur diese Datei herunter checke ob das was drin steht aktueller ist oder nicht und gebe dementsprechend einfach nur eine Message aus die sagt: "Kollege es gibt ein Update" oder halt "Hast du gut gemacht - ist die aktuelle Version".

    Nochmals vielen Dank an alle für die Hilfe :)
    cheers Kevin
    Es scheint mir, als meinst du eine Integritätsprüfung. Die nützt aber im Ernstfall nichts, da man das ja alles austauschen kann. Bei einer RSA-Verschlüsselung hast du ein asymmetrisches Kryptosystem, also eins mit zwei Keys und das ist bei einer Schlüsselstärke von 4096bit völlig unknackbar.

    Eine Signierung ist nötig, da Updatepakete ausgetauscht werden können. Du musst zudem die .exe bzw das .zip signieren, nicht die Versionsdatei. Denn die is ja egal, der Angreifer möchte auf das Archiv oder die ausführbare Datei zugreifen und das Ganze manipulieren. Beispielsweise am Flughafen (öffentlichen Netzwerken) ist es so, dass mehrere Leute im gleichen LAN sind und somit der Verkehr umgeleitet werden kann. Dann tauscht der Angreifer das Paket einfach aus und du hast nen Virus statt dem Paket dabei. Das Ganze ist natürlich auch wichtig, wenn dein Webspace gekapert wird. Zwar kann der potenzielle Angreifer dann die Art des Updatesystems ausfindig machen und das Ganze angreifen, da er die Macht hat, aber im Ernstfall bist du mit einer Signierung vorbereitet.
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:
    Ah ihr redet alle von dem .zip-Archiv in der Dropbox und nicht von der Version.txt-Datei. Nun wird mir einiges klarer.

    Aber der User muss ja erst einmal dann meine Daten von der Dropbox abgreifen können und dann das Archiv finden und dann alles abändern. Die Wahrscheinlichkeit dass genau das passiert tendiert doch wirklich gegen Null oder? Ich weiss dass es immer Leute gibt die für so etwas Zeit und den nötigen Biss haben jedoch muss der ja dann meinen Dropbox Account bekommen. Er könnte den ja nur über meinen PC bekommen und das wird doch immer unwahrscheinlicher dass das passiert oder irre ich hier?

    Falls dies mit diesem Austausch der Datenpakete wirklich so easy geht an Airports und dergleichen hat dann jede Website eine RSA-Verschlüsselung/Signierung oder? Weil sonst könnte man ja alles abfischen und die Leute auf Virusseiten bekommen oder?
    cheers Kevin
    Hi,

    um das richtig zu stellen. Die integrierte Update-Funktion unterstützt ein automatisches Update. Das ist aber mitnichten ein Muss!
    Du kannst sehr wohl selber Programmieren, dass der User aufs Knöpfchen drückt... Die Routine unterstützt auch die Abfrage ob ein Update vorhanden ist. Sprich du kannst es so programmieren, dass der User beim Start im Falle einer neuen Version gefragt wird und auch dass er via Knopfdruck ein Update durchführen kann.

    Das ist alles so vorgesehen.
    Die Einzige Problematik ist... Dass das Programm immer vom gleichen Pfad aus installiert werden will. Aber das wäre ja bei dir kein Problem, da der Pfad zur Dropbox sich (userbezogen wohl gemerkt) nicht ändern wird.

    Ich hänge mal von mir den Code an, den ich in nem Programm benutzt habe.
    Spoiler anzeigen

    VB.NET-Quellcode

    1. SchreibeLogeintrag("Ein Update des Programms wird gesucht.", TraceEventType.Start)
    2. Dim info As UpdateCheckInfo = Nothing
    3. If (ApplicationDeployment.IsNetworkDeployed) Then
    4. Dim AD As ApplicationDeployment = ApplicationDeployment.CurrentDeployment
    5. Try
    6. info = AD.CheckForDetailedUpdate()
    7. Catch dde As DeploymentDownloadException
    8. MessageBox.Show("Eine neue Version der Anwendung kann zum jetzigen Zeitpunkt nicht heruntergeladen werden. " + ControlChars.Lf & ControlChars.Lf & "Bitte überprüfen Sie. Error: " + dde.Message)
    9. SchreibeLogeintrag("Eine neue Version der Anwendung kann zum jetzigen Zeitpunkt nicht heruntergeladen werden. Error: " + dde.Message, TraceEventType.Stop)
    10. Return
    11. Catch ioe As InvalidOperationException
    12. MessageBox.Show("Dieses Programm kann nicht aktualisiert werden. Es ist wahrscheinlich keine ClickOnce-Anwendung. Error: " & ioe.Message)
    13. SchreibeLogeintrag("Dieses Programm kann nicht aktualisiert werden. Es ist wahrscheinlich keine ClickOnce-Anwendung. Error: " & ioe.Message, TraceEventType.Stop)
    14. Return
    15. End Try
    16. If (info.UpdateAvailable) Then
    17. Dim doUpdate As Boolean = True
    18. If (Not info.IsUpdateRequired) Then
    19. Dim dr As DialogResult = MessageBox.Show("Eine neue Version des Programms ist verfügbar. Wollen Sie das Programm jetzt aktualisieren?", "Update verfügbar", MessageBoxButtons.OKCancel)
    20. If (Not System.Windows.Forms.DialogResult.OK = dr) Then
    21. doUpdate = False
    22. End If
    23. Else
    24. MessageBox.Show("Das Programm hat festgestellt, dass eine neue Version verfügbar ist. " & _
    25. "Die verfügbare Version lautet: " & info.MinimumRequiredVersion.ToString() & _
    26. ". Das Update wird nun installiert und das Programm anschließend neugestartet.", _
    27. "Update verfügbar", MessageBoxButtons.OK, _
    28. MessageBoxIcon.Information)
    29. End If
    30. If (doUpdate) Then
    31. Restart = True
    32. SchreibeLogeintrag("Das Programm wird neugestartet.", TraceEventType.Stop)
    33. Application.Restart()
    34. Return
    35. End If
    36. Else
    37. MessageBox.Show("Das Programm ist auf dem aktuellsten Stand.", "Update nicht nötig", MessageBoxButtons.OK, MessageBoxIcon.Information)
    38. SchreibeLogeintrag("Das Programm ist auf dem aktuellsten Stand.", TraceEventType.Stop)
    39. End If
    40. End If
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    ... Nun solltest es selber wissen. :'D

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „MemoAnMichSelbst“ ()

    @MemoAnMichSelbst:
    Falls ich es so mache wie in deinem Code geschrieben wird doch aber die aktuelle Version immer (!) auch installiert (sofern der User OK klickt und nicht abbricht) oder nicht?
    Der Grund warum ich unbedingt den User dazu bringen will das Update selbst aufzuspielen ist, dass ich nachher keine Beschwerden bekomme wie: "Dein Programm hat meinen PC kaputt gemacht" usw..
    Ich weiss dass ich nur das .zip-Archiv extrahiere jedoch hab ich solche Anschuldigungen schon des öfteren gesehen und möchte sie wirklich vermeiden. Wenn der User das dann falsch extrahiert hat er selber Pech gehabt und hätte mal besser die ReadMe Datei zu studieren. Ich probiere die Tage über mal den Code für meine (gewünschte) Updatefunktion zu bauen, damit wir dann mal zusammen schauen können wo es haken könnte und was ich verbessern könnte.

    Vielen Dank an alle nochmal!
    cheers Kevin
    Richtig, der Code spielt das Update ein wenn der Benutzer es bestätigt. Aber es ist auch kein Copy-Paste-Code.
    Du kannst den ja in nen eigenen Button packen und die Abfrage "Soll das Update installiert werden" raus lassen.
    Es zwingt dich schließlich keiner :P
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    ... Nun solltest es selber wissen. :'D

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „MemoAnMichSelbst“ ()

    Wenn der Nutzer es manuell runterlädt, dann brauchst du keine Signierung, ansonsten ist es absolut nötig und ohne eine riesige Sicherheitslücke. War nur so nen Gedanke, falls du das doch mit Server o. ä. machen wollen würdest. Einbauen könntest du es für 100%igen Schutz schon, falls dein DropBox-Account gekapert wird :P
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Trade“ ()

    Hey Leute,
    sorry für die Verspätung aber ich hatte viel zu tun in den letzten Tagen. Dann hier mal meine "Updatefunktion" wie sie bisher im Programm verwendet wird. Anregungen/Verbesserungsvorschläge/... nehme ich sehr gerne an:

    VB.NET-Quellcode

    1. Private Sub CheckForUpdate()
    2. Dim Checked As Boolean = True
    3. Dim FileReader As String = ""
    4. Dim ApplicationVersion As String = My.Application.Info.Version.ToString
    5. Dim ApplicationPath As String = My.Application.Info.DirectoryPath.ToString
    6. ApplicationPath = ApplicationPath + "\Update.txt"
    7. If File.Exists(ApplicationPath.ToString) Then
    8. File.Delete(ApplicationPath.ToString)
    9. End If
    10. Dim DownloadCheckerFile As New System.Net.WebClient
    11. DownloadCheckerFile.DownloadFile("URL-Zur-Datei-Auf-dem-Server", ApplicationPath)
    12. DownloadCheckerFile.Dispose()
    13. If File.Exists(ApplicationPath.ToString) Then
    14. Dim TextReader As IO.TextReader = New IO.StreamReader(ApplicationPath.ToString)
    15. FileReader = TextReader.ReadToEnd
    16. If FileReader.Length = 7 Then
    17. For I = 1 To 7
    18. If (I Mod 2 = 0) And (I <> 1) Then
    19. If FileReader(I - 1) = "." Then
    20. Else
    21. MsgBox("Parser error - " & FileReader(I - 1).ToString & " should be a point "".""")
    22. Checked = False
    23. End If
    24. Else
    25. Dim TempCharacter As Integer = Asc(FileReader(I - 1).ToString)
    26. If (TempCharacter > 47) And (TempCharacter < 58) Then
    27. Else
    28. MsgBox("Parser error - " & FileReader(I - 1).ToString & " should be a number between 0 and 9!")
    29. Checked = False
    30. End If
    31. End If
    32. Next
    33. End If
    34. Else
    35. MsgBox("There was a proble while downloading the file...", MsgBoxStyle.Critical)
    36. End If
    37. If Checked = True Then
    38. If FileReader = ApplicationVersion Then
    39. MsgBox("No newer version available!", MsgBoxStyle.OkOnly)
    40. Else
    41. Select Case MsgBox("There is a newer version available! Do you want to visit the forum to install it?", MsgBoxStyle.YesNo)
    42. Case MsgBoxResult.Yes
    43. Process.Start("URL-zum-Forum")
    44. Case MsgBoxResult.No
    45. MsgBox("Please remember that not updateing the application may result in errors. We can also only provide support for the newest version of our application!")
    46. End Select
    47. End If
    48. End If
    49. End Sub


    Danke nochmal an die Hilfe von allen!
    cheers Kevin