EAX und Stack



  • Hallo nochmal!

    Ich habe mir jetzt folgenden Code zusammengeschrieben:

    PUSH EAX
       MOV EAX, zahl1
       ADD EAX, zahl2
       MOV ergebnis, EAX
       POP EAX
    

    zahl1 und zahl2 sind zwei Variablen aus meinem C++ Programm. Das funktioniert auch soweit. EAX ist ein CPU Register. Wird mittels der ersten Anweisung EAX (also ein komplettes Register) auf den Stack gelegt? Dann wird in EAX gearbeitet und zum Schluss mit POP wieder vom Stack genommen?

    Aber warum muss ich hier überhaupt den Stack verwenden? Das verstehe ich nicht so richtig. Kann ich die Variablen nicht gleich in ein Register stopfen? Dafür sind die doch da. Wenn ich PUSH und POP weglasse, dann kommt es aber zum Laufzeitfehler. Warum?

    Vielen Dank euch
    lg, freakC++



  • Wie haste den Assembler-Code im C++-Programm aufgerufen?
    Funktionsaufruf (nebst Zugriff auf globale Variablen) vermutlich nicht. Dann würde der Compiler auch nicht erwarten, daß EAX danach noch den alten Wert hat und es wäre kein Absturz zu befürchten.

    Haste den irgendwie geschafft, in deinen C++-Code zu injizieren? Beim gcc müßtest Du angeben, daß Du EAX veränderst. Dann wüßte der Compiler das.

    MSCV erkennt, welche Register ich im inline-asm-Block verwende und sichert sie von alleine, wenn er das braucht.

    Also eigentlich müßte es klappen.

    Oder verwendest Du kein inline-asm, sondern hast per hand assembliert und führst jetzt String-Literale aus? Nee, dann hättest Du ja kaum die Adressen der Variablen zur Verfügung.



  • Ich hab den Code im Borland Builder inline eingebunden. Das geht da recht schön mit der Funktion asm.

    Aber die Stackgeschichte hat doch damit eigentlich nichts zu tun oder? Danke



  • freakC++ schrieb:

    Ich hab den Code im Borland Builder inline eingebunden. Das geht da recht schön mit der Funktion asm.

    Aber die Stackgeschichte hat doch damit eigentlich nichts zu tun oder? Danke

    Da http://docs.google.com/viewer?a=v&q=cache:J5Etx6N3-74J:www.krucker.ch/Skripten-Uebungen/InfUeb/Assembler%20in%20C-CPP%20Programmen%20BCB.pdf+c%2B%2B+builder+inline+asm&hl=de&gl=de&pid=bl&srcid=ADGEESiy3tlDMd5nLRmUkqRZcwZpKzK_aj3FAjb5NQ-GChxXjLPkmkXDJ9vdNwtLTy_cFW_cdglzIpbwhAErxc36I5Z52EvTxwaML2IMeZqIu-61S0TtuuzMG_vFLDGK-lIG-Wuo5y62&sig=AHIEtbSr1YxuBwrSZAI8sp5DKlsfJCO0uQ (auf Seite 5) macht er das genau wie Du.
    Ohne push und pop.
    Es müßte klappen, sag ich mal.



  • Ich habe vergessen, den POP Befehl rauszunehmen. Klar, dass dann ein Fehler kommt. Kein PUSH aber POP...

    Ich habe eben aus Spaß ein kleines C++ Programm geschrieben mit einem Eingabefeld und einem Button (mit Borland Builder). Nur wenn man das richtige Passwort eingibt, kommt eine Meldung, die "Willkommen" ausgibt. Mithilfe eines Disassemblers habe ich den Assemblercode erhalten und habe den entsprechenden "jne" Befehl modifiziert, wodurch ich jetzt kein Passwort mehr eingeben muss. Dazu habe ich ein paar Fragen:

    Das Passwort heißt "Auto". An der entsprechenden Stelle steht:

    mov edx, dword ptr [00454DC0]
    call 00404258
    jne 00453812
    

    Der C++ lautet

    if (Eingabe == Passwort)
          ShowMessage("Willkommen");
    

    1.) Warum ist der entscheidenen Jump ein jne Befehl. Er steht ja für "jump if not equal". Aber eigentlich soll der Jump doch nur erfolgen, wenn es equal ist. Es gibt keinen else Teil.

    2.) Wenn ich nun den JUMP Befehl austausche, sodass immer "Willkommen" beim Buttondruck ausgegeben wird, muss ich folgendes machen:

    Intern sieht der JUMP Befehl wohl so aus (Original Bytes):

    75 0A B8 3C 38 45 00 E8 ...

    Nun weiß ich, dass ich einfach die 75 in eine 74 ändern muss. Warum eigentlich? ASCII Code ist das sicherlich nicht. Was ändert die 74 am Jump Befehl?

    3.) Wie werden Strings in Assembler abgespeichert? Ich habe nämlich versucht, den String "Willkommen" durch "Hallo" zu ersetzen.

    Vielen Dank euch.

    lg, freakC++



    1. Du solltest dir mal ansehen, wo die Zieladressen im Programm liegen. Ich würde ja vermuten, daß der jne-Befehl die nächsten Anweisungen überspringt, die den ShowMessage-Call überspringt.

    2. 75 bzw. 74 sind die Codes für verschiedene Assembler-Anweisungen, vermutlich steht die 74 für eine andere Sprunganweisung, da müsstest du dir mal den modifizierten Code ansehen.

    3. normalerweise sollten die Literale irgendwo in ACSII-Format stehen, da solltest du mal mit einem Hex-Editor oder im Dissassembler nach dem Willkommens-String suchen.



  • Konstante Strings liegen in der Regel im Datanbereich der Executable. Mit einem normalen Editor solltest du den Text finden. Zu dissamblieren gibt es da nicht viel, weil da einfach nur Daten drin stehen. Du musst natürlich beim Editieren auch beachten das die Datenlänge gleich bleibt, da sich sonst die Adressen der folgenden Daten verändert und nicht mehr mit dem Code übereinstimmen.



  • freakC++ schrieb:

    if (Eingabe == Passwort)
          ShowMessage("Willkommen");
    

    1.) Warum ist der entscheidenen Jump ein jne Befehl. Er steht ja für "jump if not equal". Aber eigentlich soll der Jump doch nur erfolgen, wenn es equal ist. Es gibt keinen else Teil.

    Ich kenne den Code nicht.

    Aber ich kann mir vorstellen, daß der Compiler aus

    tuwas1();
    if (Eingabe == Passwort)
          ShowMessage("Willkommen");
    tuwas2();
    

    das hier macht:

    tuwas1();
    int tmp = strcmp(Eingabe.data,Passwort.data)
    if(tmp!=0) goto hinten; //jne
    ShowMessage("Willkommen");
    hinten: tuwas2();
    


  • freakC++ schrieb:

    75 0A B8 3C 38 45 00 E8 ...

    Nun weiß ich, dass ich einfach die 75 in eine 74 ändern muss. Warum eigentlich? ASCII Code ist das sicherlich nicht. Was ändert die 74 am Jump Befehl?

    3.) Wie werden Strings in Assembler abgespeichert? Ich habe nämlich versucht, den String "Willkommen" durch "Hallo" zu ersetzen.

    Bei den Sprungbefehl handelt es sich um einen short jump (8Bit relativ-Adresse zum nächten Befehl) -> 75 0A -> je $+2+10

    Wenn du eines String ersetzen möchtest, ist es sinnvoll, an der entsprechenden Stelle[n] den/die Zeiger zu ändern. Den neuen String hängt man z.B. ans Daten Segment an.



  • volkard schrieb:

    Aber ich kann mir vorstellen, daß der Compiler aus

    tuwas1();
    if (Eingabe == Passwort)
          ShowMessage("Willkommen");
    tuwas2();
    

    Bei mir gibt es aber kein tuwas2(). Nach der if-Abfrage ist Schluss. Das Programm beinhaltet ausschließlich diese Fallunterscheidung.

    Tobiking2 schrieb:

    Konstante Strings liegen in der Regel im Datanbereich der Executable. Mit einem normalen Editor solltest du den Text finden.

    Ich benutze den Disassembler "ursoft w32dasm". Darin gibt es eine Funktion, die nennt sich "String Data References". Dort kann ich tatäschlich nach einem String suchen und ich finde ihn auch. Angenommen ich gebe "Auto" (das Passwort) ein, dann lande ich bei folgender Stelle:

    * Possible StringData Ref from Code Obj -> "Auto"
    mov edx, dword ptr[00454DC0]
    call 00404258
    jne 00453812
    

    Für mich erscheint die Zeile mit dem Wort "Auto" wie ein Kommentar, da diese in Grün geschrieben ist. Ich finde aber keine Stelle, wo das Wort nun wirklich abgelegt also gespeichert ist und wo ich dieses dann durch ein gleichlanges ersetzen kann. Mir geht es ja um das Ersetzen. Damit möchte ich erreichen, dass ich im Nachhinein mittels Assembler das Kennwort ersetzen kann. Beispielsweise soll "Auto" zu "Sofa" werden. Kennt jemand den Disassembler den ich nutze oder könnt ihr mir einen besseren raten? Ich kenne ihn selbst nicht.

    masm schrieb:

    Bei den Sprungbefehl handelt es sich um einen short jump (8Bit relativ-Adresse zum nächten Befehl) -> 75 0A -> je $+2+10

    Vielleich ist das Grundwissen, aber wofür steht "$+2+10"?

    Vielen Dank und bis bald



  • freakC++ schrieb:

    volkard schrieb:

    Aber ich kann mir vorstellen, daß der Compiler aus

    tuwas1();
    if (Eingabe == Passwort)
          ShowMessage("Willkommen");
    tuwas2();
    

    Bei mir gibt es aber kein tuwas2(). Nach der if-Abfrage ist Schluss. Das Programm beinhaltet ausschließlich diese Fallunterscheidung.

    Es gibt immer ein tuwas2() - und wenn es das implizite return 0; am Ende der main() ist 😉

    Tobiking2 schrieb:

    Konstante Strings liegen in der Regel im Datanbereich der Executable. Mit einem normalen Editor solltest du den Text finden.

    Ich benutze den Disassembler "ursoft w32dasm". Darin gibt es eine Funktion, die nennt sich "String Data References". Dort kann ich tatäschlich nach einem String suchen und ich finde ihn auch. Angenommen ich gebe "Auto" (das Passwort) ein, dann lande ich bei folgender Stelle:

    * Possible StringData Ref from Code Obj -> "Auto"
    mov edx, dword ptr[00454DC0]
    call 00404258
    jne 00453812
    

    Für mich erscheint die Zeile mit dem Wort "Auto" wie ein Kommentar, da diese in Grün geschrieben ist. Ich finde aber keine Stelle, wo das Wort nun wirklich abgelegt also gespeichert ist und wo ich dieses dann durch ein gleichlanges ersetzen kann. Mir geht es ja um das Ersetzen. Damit möchte ich erreichen, dass ich im Nachhinein mittels Assembler das Kennwort ersetzen kann. Beispielsweise soll "Auto" zu "Sofa" werden. Kennt jemand den Disassembler den ich nutze oder könnt ihr mir einen besseren raten? Ich kenne ihn selbst nicht.

    Hast du irgendeine Möglichkeit, die Adressen der einzelnen Anweisungen herauszufinden? Wenn ja, würde ich mal unter Adresse 00454DC0 nachsehen, was dort steht.

    masm schrieb:

    Bei den Sprungbefehl handelt es sich um einen short jump (8Bit relativ-Adresse zum nächten Befehl) -> 75 0A -> je $+2+10

    Vielleich ist das Grundwissen, aber wofür steht "$+2+10"?

    Vielen Dank und bis bald

    $ - aktuelle Position des Instruction Pointers, +2 - nächster Befehl, +10 steht in dem Srpungbefehl (0A)



  • freakC++ schrieb:

    Bei mir gibt es aber kein tuwas2(). Nach der if-Abfrage ist Schluss. Das Programm beinhaltet ausschließlich diese Fallunterscheidung.

    Dein Code ist ja trotzdem nicht wirklich freistehend. Da passiert einiges wie z.B. Parameterübergabe bevor die main Funktion aufgerufen wird, und am Ende wird aufgeräumt. Man kann also durchaus hinter deinen Code springen.

    freakC++ schrieb:

    Für mich erscheint die Zeile mit dem Wort "Auto" wie ein Kommentar, da diese in Grün geschrieben ist.

    Ja, das ist nur ein Kommentar. Ich kenne aber gerade auch keinen Disassembler der direkt das editoeren von Strings erlaubt. Selbst die kostenlose Version von IDA Pro scheint die Strings nur anzuzeigen.

    freakC++ schrieb:

    Vielleich ist das Grundwissen, aber wofür steht "$+2+10"?

    Das $ wird (zumindest bei nasm) als Platzhalter für die Anfangsadresse des aktuellen Befehls verwendet. Die 10 kommt aus dem Befehl, weil man 10 Byte (0A) (Vom Ende des Befehls) weiter springen will. Die +2 kommen weil der Sprungbefehl 2 Byte lang ist, und man vom Ende aus weiter springen will.

    Edit: Da hab ich wohl zu lange zum Tippen gebraucht :p



  • Danke für eure Antworten. Ich denke, dass ich erstmal besser in Assembler werden sollte, bevor ich anfange bei .exe Programmen die Strings auszutauschen. Ich merke nämlich, dass Assembler gar nicht so einfach ist.

    Ihr habt mir wieder mal geholfen.


Anmelden zum Antworten