Patcher erstellen

  • Kann man mit AutoIt eigentlich exe-Patches erstellen?
    Da ich meist nur meine exe-Dateien verbessern muss, währe es nicht schlecht, wenn ich einen Patch erstellen könnte, der die alte exe aktualisiert.

    In C++ geht das ja irgendwie mit dem HexOffset und durch binäres Einlesen der exe. Das HexOffset kann ich finden, wie man es mit eine Hexeditor ändert weiß ich auch, allerdings kann ich nicht mit C++ gut genug umgehen.

    Deshalb würde ich das gerne über AutoIt realisieren.

    Wär schön, wenn mir jemand helfen kann.

    • Offizieller Beitrag

    Hi!

    Inzwischen kann AutoIt Binärdateien lesen und schreiben, müsste als grundsätzlich gehen. Die Änderungen zu erkennen, dürfte allerdings nicht wirklich trivial sein, weil man check muss, ob etwas verschwunden, hinzugefügt oder verändert worden ist.

    peethebee

  • Zitat

    Inzwischen kann AutoIt Binärdateien lesen und schreiben,


    Danke, ich glaub, ich sollte mein AutoIt öfters updaten, war noch bei Version 3.2.2.0.

    Zitat

    Die Änderungen zu erkennen, dürfte allerdings nicht wirklich trivial sein, weil man check muss, ob etwas verschwunden, hinzugefügt oder verändert worden ist.

    Wär ja auch zu schön gewesen. Aber sehen wirs doch positiv: An Herausforderungen wächst man.

  • Mit welchen Funktionen geht das den?

    Die einzigen Dinge, die ich gefunden hab sind:

    [autoit]

    Binary

    [/autoit]

    -> gibt mir nen String als Binary

    [autoit]

    BinaryLen

    [/autoit]

    -> gibt mir die Länge

    [autoit]

    BinaryMid

    [/autoit]

    -> gibt mir ein paar Bytes aus dem String

    [autoit]

    BinaryToString

    [/autoit]

    ->binär nach String

    Mit all diesen Funktionen komm ich kein bischen weiter, da ich die exe dann über FileRead einlesen müsste, was zu Fehlern führt(guckt euch mal ne exe mit nem Texteditor an *lo*) .

    • Offizieller Beitrag

    Hallo,

    Du musst die Datei im Binary-Mode, mit FileOpen, öffnen!

  • Ah danke, hab die Funktion noch nie benutzt. Das müsste dann wohl so aussehen:

    [autoit]

    FileOpen("test.exe", 16)

    [/autoit]

    .
    Sollte es nicht stimmen, kann man mich gerne verbessern.

    Funktioniert perfekt, allerdings hab ich ein Problem. Scite zeigt mir folgende Fehlermeldung:
    F:\selbst programmierte programme\scripts\patcher\patcher.au3 (24) : ==> Array variable has incorrect number of subscripts or subscript dimension range exceeded.:
    If $array_alt[$i] = $array_neu[$i] Then
    If $array_alt[$i] = ^ ERROR

    Hier mein Code

    Spoiler anzeigen
    [autoit]

    #include <Array.au3>

    [/autoit] [autoit][/autoit] [autoit]

    Global $array_alt = _ArrayCreate(""), $array_neu = _ArrayCreate(""), $array_unterschied = _ArrayCreate("");erstellt 3 Arrays

    [/autoit] [autoit][/autoit] [autoit]

    $datei = FileOpen("test.txt", 16);öffnet Datei binär
    $read = FileRead($datei);liest Datei ein
    If @error Then
    Exit;beendet bei Fehler
    Else
    $alt = $read;lagert um
    $neu = Binary("boot");Vergleichswert
    For $i = 1 To StringLen($alt) Step 2
    _ArrayAdd($array_alt, StringMid($alt, $i, 2));liest paarweise ein und speichert in Array
    Next
    For $i = 1 To StringLen($neu) Step 2
    _ArrayAdd($array_neu, StringMid($neu, $i, 2));liest paarweise ein und speichert in Array
    Next
    vergleich()
    EndIf
    FileClose($datei)

    [/autoit] [autoit][/autoit] [autoit]

    Func vergleich();sucht Unterschiede
    For $i = 1 To _ArrayMax($array_alt)
    If $array_alt[$i] = $array_neu[$i] Then
    Else
    _ArrayAdd($array_unterschied, $array_neu[$i])
    EndIf
    _ArrayDisplay($array_unterschied, "test")
    Next
    EndFunc

    [/autoit]

    Die Datei test.txt enthält nur das Wort test. Das Prog arbeitet die Unterschiede heraus und gibt mir ein Array mit den Werten, die im neuen Wort anders sind, dann erscheint die Fehlermeldung.

    Einmal editiert, zuletzt von penta.phoenix (23. Juni 2007 um 10:34)

    • Offizieller Beitrag
    Zitat

    If $array_alt[$i] = ^ ERROR


    Weist darauf hin, dass $array_neu[$i] kein gültiger Parameter für dieses Array ist.
    Vermutlich ist $array_neu kleiner als $array_alt, somit verweist [$i] auf ein nicht existierendes Element.
    Mach doch mal ne Consolenausgabe für $i ( $i markieren, Alt+D ). Dann siehst du an welcher Stelle es crasht.

    • Offizieller Beitrag

    Hallo,

    der Fehler liegt an der For-Schleife, _ArrayMax gibt den größten Wert im Array zurück und nicht die Anzahl der Element!

    Schreib mal die For-Anweisung so:

    [autoit]

    For $i = 0 To Ubound($array_alt) - 1

    [/autoit]


    @1: Ausserdem muss sichergestellt sein das $array_neu mindesten soviel element hat wie $array_alt, ansonsten gibt die Schleife immer den Fehler zurück!

  • Das Problem ist, dass beide gleich groß sind.
    test -->8 Bytes
    boot --> 8 Bytes

    Je 2 Bytes pro Array-Element, macht 4 Elemente, also müsste es bis $array_alt[4] bzw. $array_neu[4] funtkionieren und danach ist eh Schluss.

    Hab mir die Array anzeigen lassen, beide haben mit dem nullten Element 6 Elemente, 0-5.

    Das mit dem Debuggen versteh ich nicht ganz, wo genau muss ich $i markieren, habs ja öfters im Code?

    Bernd:
    Danke, hab durch _ArrayMaxIndex ersetzt. Jetzt findet es allerdings nur einen unterschied, das b.
    t e s t
    b o o t
    Man sieht eindeutig, es müssten 3 sein, wo liegt mein Fehler?

    Bernd, 2. Edit:
    Mit deinem Tipp geht es, auch wenn ichs nicht verstehe. Jetzt interessiert mich eigentlich nur noch, warum es über meinen _ArrayMaxIndex nicht geht.

    3 Mal editiert, zuletzt von penta.phoenix (23. Juni 2007 um 11:04)

    • Offizieller Beitrag

    _ArrayMin, _ArrayMax, _ArrayMinIndex und _ArrayMaxIndex beziehen sich auf den Inhalt eines Array nicht auf dien Anzahl der Elemente!

    _ArrayMin gibt den kleinsten Wert im Array zurück
    _ArrayMax gibt den grössten Wert m Array zurück

    _ArrayMinIndex gibt die Nummer des Elements mit dem kleinsten Wert im Array zurück
    _ArrayMaxIndex gibt die Nummer des Elements mit dem grössten Wert im Array zurück

    • Offizieller Beitrag
    Zitat

    Das mit dem Debuggen versteh ich nicht ganz, wo genau muss ich $i markieren, habs ja öfters im Code?


    Ich hatte es auf die Schleife in deiner Func vergleich() bezogen, dort war der Fehler ja aufgetreten.

    Zitat

    Jetzt interessiert mich eigentlich nur noch, warum es über meinen _ArrayMaxIndex nicht geht.

    Zitat

    _ArrayMaxIndex
    Returns the index where the highest value occurs in the array.

    _ArrayMaxIndex() liefert den Index zurück an dem der größte Wert steht. Das kann also auch 0 sein.

  • Ok, jetzt hab ichs verstanden. Zurück zum eigentlichen Problem: Patcher.
    Im Normalfall kommen durch einen Patch Dinge hinzu, in meinem Beispiel Buchstaben.

    Nun habe ich test.txt mit dem Wort test und test2.txt mit dem Wort Fußball.
    Nun bricht mein Script natürlich am Ende des ersten Array($array_alt) ab, also nach 4 Buchstaben. all auß Fußball geht also verloren. Was muss ich ändern?

  • Spoiler anzeigen
    [autoit]

    #include <GUIConstants.au3>
    #include <dph.au3>
    #include <Array.au3>
    #include <File.au3>

    [/autoit] [autoit][/autoit] [autoit]

    Global $array_patch = _ArrayCreate(""), $array_datei_orginal_inhalt = _ArrayCreate(""), $datei_orginal, $datei_patch

    [/autoit] [autoit][/autoit] [autoit]

    GUICreate("Patch - created with c.a.p. - visit https://autoit.de/www.penta.ph%C3%B6nix.de.vu", 500, 200)

    [/autoit] [autoit][/autoit] [autoit]

    GUISetState(@SW_SHOW)
    $button_patch = GUICtrlCreateButton("Patchen", 200, 50, 100)

    [/autoit] [autoit][/autoit] [autoit]

    While 1
    $msg = GUIGetMsg()

    If $msg = $GUI_EVENT_CLOSE Then
    Exit
    EndIf

    If $msg = $button_patch Then

    $datei_orginal = FileOpen("test.txt", 16);~ Original einlesen vorbereiten
    $datei_orginal_lesen = FileRead($datei_orginal);~ Original einlesen, aufteilen
    For $i = 1 To StringLen($datei_orginal_lesen) Step 2;~ Original einlesen, aufteilen
    _ArrayAdd($array_datei_orginal_inhalt, StringMid($datei_orginal_lesen, $i, 2));~ Original einlesen, aufteilen
    Next
    _ArrayDisplay($array_datei_orginal_inhalt, "test1");~ zeigt das Array mit Inhalt von test.txt

    $datei_patch = FileOpen("test3.txt", 0);~ Patch-Datei einlese
    $datei_patch_lesen = FileRead($datei_patch);~ Patch-Datei einlese
    $datei_patch_lesen_bearbeiten1 = StringTrimLeft($datei_patch_lesen, 2);~ die ersten 2 Kommata abschneiden
    $datei_patch_lesen_bearbeiten2 = StringTrimRight($datei_patch_lesen_bearbeiten1, 1);~ das letzte Komma abschneiden
    MsgBox(0, "", $datei_patch_lesen_bearbeiten2);~ zeigt den bearbeiteten Inhalt von test3.txt
    $datei_patch_lesen_split = StringSplit($datei_patch_lesen_bearbeiten2, ",");~ splittet den Inhalt und speichert in $datei_patch_lesen_split
    _ArrayDisplay($datei_patch_lesen_split, "test");~ zeigt das Array mit bearbeitetem Inhalt von test3.txt

    For $i = 1 To UBound($datei_patch_lesen_split) - 1
    $a = $i + 1
    MsgBox(0, "test", "An Position " & $datei_patch_lesen_split[$i] & " gehört: " & BinaryToString($datei_patch_lesen_split[$a]));zeigt an, an welche Position was gehört
    $i = $i + 1
    Next

    ;~ Datei test1.txt bearbeiten
    EndIf
    FileClose($datei_orginal)
    FileClose($datei_patch)

    WEnd

    [/autoit]

    Kann mir jemand sagen, warum

    MsgBox(0, "test", "An Position " & $datei_patch_lesen_split[$i] & " gehört: " & BinaryToString($datei_patch_lesen_split[$a]));zeigt an, an welche Position was gehört

    nicht funktioniert. Eigentlich sollte BinaryToString ja den String ausgeben. Ich bekomme aber immer noch den Binärwert angezeigt.
    Z.B. binär 75, nach BinaryToString bekomm ich immer noch 75 angezeigt.

  • Mich würde so ein Patcher auch interessieren allerdings wurde hier jetzt über 1 jahr nichts mehr geschrieben.
    Deswegen frage ich mal: Bisher wurde nur die Datei binär ausgelesen und die Größe verglichen.
    Aber:
    1. wie findet man heraus welcher Code-Teil erneuert wurde
    und
    2.wie macht man das ganze wieder zue .exe? Ginge das mit FileWrite?

    eagle

  • Mich würde so ein Patcher auch interessieren allerdings wurde hier jetzt über 1 jahr nichts mehr geschrieben.
    Deswegen frage ich mal: Bisher wurde nur die Datei binär ausgelesen und die Größe verglichen.
    Aber:
    1. wie findet man heraus welcher Code-Teil erneuert wurde
    und
    2.wie macht man das ganze wieder zue .exe? Ginge das mit FileWrite?

    eagle

    Ich habe es inzwischen geschafft, bin noch beim Betatesten, weil ich nicht mehr so viel damit gemacht habe.
    1. Orginal-Datei und neue Datei in Arrays einlesen und diese dann vergleichen.
    2. Über ne Spezialfunktion von mir, die automatisch herausfindet, was verändert wurde und vor allem auch wo. Dann wird die ungepatchte VErsion(z.B. bei nem Kumpel) abgefragt und der Patcher kann an den jeweiligen Positionen die Bytes ändern.

  • mh könntest du, wenn du fertig bist vielleicht mal den code posten?
    das wäre nett weil so richtig komm ich nicht drauf.
    Zumal ich Dateien nicht richtig binär auslesen kann da kommen bei mir immer so komische Zeichen und Nummern aber kein binärer code

  • Wieso machst du es nicht so. EXE herunterladen und dann die Version überprüfenund evtl. die vorhandene EXE überschreiben

  • Wieso machst du es nicht so. EXE herunterladen und dann die Version überprüfenund evtl. die vorhandene EXE überschreiben

    Weil es nicht darum geht die exe zu ersetzen. Es soll ein Patcher erstellt werden, und er hat nach der UDF geragt. Vielleicht könntest du zuerst mal lesen.