64bit Kernelbase Problematik: kernelbase.GetTickCount() modifiziert ein Register, was kernel32.GetTickCount() nicht tut



  • Hey!

    Ein älteres Spiel stürzt leider immer an einer bestimmten Stelle ab, wenn es auf einem neueren Betriebssystem als XP 32 läuft.
    Zunächst dachte ich an Vista/Windows7, doch das Problem besteht auch auf XP 64.

    Dann habe ich herausgefunden, dass ein Aufruf von GetTickCount() schuld sein muss.
    Auf einem 32bit OS wird die kernel32.GetTickCount() Implementierung aufgerufen.
    Doch auf einem 64bit OS wird nach kernelbase weitergeleitet, wo dann schließlich eine neue Implementierung abgearbeitet wird.

    Ein Bild dazu:
    http://www.bilder-hochladen.net/files/e1jx-2.png

    Das Problem der neuen Implementierung ist, dass das Register ECX modifiziert wird. In dem steckt allerdings ein Wert, der auch nach dem Aufruf von GetTickCount() erhalten sein muss, davon geht das Spiel eben aus.

    Das Spiel speichert also einen Wert in ECX und ruft dann GetTickCount() auf. Unter 32bit kein Problem, die Implementierung dort modifiziert ECX nicht. Doch unter 64bit wird ECX durch die neue Implementierung modifiziert.

    Der Wert von ECX geht verloren, deshalb stürzt das Spiel ab.

    Jetzt weiß ich nicht weiter.

    Warum ist das eigentlich so? Ich dachte, eine Abwärtskompatibilität wäre von Windows aus gegeben.
    Wie kommt dieses Problem zustande? Also dass das Spiel ECX braucht, es aber von der neuen GetTickCount()-Implementierung verändert wird?
    Müsste die neue Implementierung nicht die Register sichern & wiederherstellen (Habe leider nur wenig Ahnung von Assembler)?

    Was kann ich tun, um diesen crash zu verhindern?



  • Rayden Wins schrieb:

    Was kann ich tun, um diesen crash zu verhindern?

    Aufhören Spiele in Assembler zu programmieren?



  • What?

    Rayden Wins schrieb:

    Ein älteres Spiel stürzt leider immer an einer bestimmten Stelle ab, ...



  • Falsches Board -> WinAPI



  • Rayden Wins schrieb:

    Warum ist das eigentlich so? Ich dachte, eine Abwärtskompatibilität wäre von Windows aus gegeben.
    Wie kommt dieses Problem zustande? Also dass das Spiel ECX braucht, es aber von der neuen GetTickCount()-Implementierung verändert wird?

    de.wikipedia.org/wiki/Aufrufkonvention#stdcall schrieb:

    Die stdcall-Aufrufkonvention ist de facto die Standard-Aufrufkonvention für die Microsoft Win32-API. Funktionsparameter werden von rechts nach links übergeben. Die Register EAX, ECX, und EDX sind reserviert für die Verwendung innerhalb der Funktion, werden also unter Umständen verändert.



  • Rayden Wins schrieb:

    Was kann ich tun, um diesen crash zu verhindern?

    Es gibt da so perversen Injection- & Hook-Krams, mit dem man den Aufruf von Kernel-Funktionen umleiten kann; in der Umleitung könntest du vielleicht ECX speichern, GetTickCount aufrufen und ECX wieder herstellen. Kenne mich damit nicht aus, im WinAPI-Forum wird über sowas aber manchmal debattiert.



  • Dieser Thread wurde von Moderator/in SideWinder aus dem Forum Themen rund um den PC in das Forum WinAPI verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • Okay, wenns nicht einfacher geht. Werde wohl eine code cave erstellen und hoffen, dass es nicht noch mehr Stellen gibt.

    Aber: Wie kommt dieser Konflikt zustande? Ich hab das Spiel ja nicht gemacht, es ist schon viele Jahre alt und wurde halt 32bit kompiliert. Aber es sollte doch trotzdem auf einem 64bit OS laufen?



  • Rayden Wins schrieb:

    Das Problem der neuen Implementierung ist, dass das Register ECX modifiziert wird. In dem steckt allerdings ein Wert, der auch nach dem Aufruf von GetTickCount() erhalten sein muss, davon geht das Spiel eben aus.

    Füg ein kleines Stück code hinzu das die Register sichert (ist kein Problem mit Olly). Den Sprung/Aufruf musst du dann entsprechend umleiten.


Anmelden zum Antworten