2010-12-03 20 views
5

Je travaille sur un émulateur Xbox1 dans Delphi, et parce que je cours les jeux sur le processeur local, je dois créer une sécurité intégrée pour les instructions ring0 qui peuvent se produire dans le code du jeu. J'ai appris que SetUnhandledExceptionFilter peut enregistrer une fonction qui va être appelée sur des exceptions non-Delphi (à condition de mettre JITEnable à une valeur supérieure à 0). La signature de la fonction de rappel enregistrée se lit comme suit:SetUnhandledExceptionFilter: Continuer l'exécution 1 opcode plus loin

function ExceptionFilter(E: LPEXCEPTION_POINTERS): Integer; stdcall; 

A l'intérieur de cette fonction, je peux tester pour obtenir des instructions illégales comme ceci:

// STATUS_PRIVILEGED_INSTRUCTION = $C0000096 
if E.ExceptionRecord.ExceptionCode = STATUS_PRIVILEGED_INSTRUCTION then 

L'une des instructions incriminées est WVINDB (0F $, 09 $) qui Je peux détecter comme ceci:

// See if the instruction pointer is a WBINVD opcode : 
if (PAnsiChar(E.ExceptionRecord.ExceptionAddress)[0] = #$0F) 
and (PAnsiChar(E.ExceptionRecord.ExceptionAddress)[1] = #$09) then 

tout cela fonctionne (à condition que je lance ce en dehors le débogueur) mais je ne peux pas obtenir le code à exécuter au-delà de l'instruction défaillante - Je l'ai essayé comme ceci:

begin 
    // Skip the WBINVD instruction, and continue execution : 
    Inc(DWORD(E.ExceptionRecord.ExceptionAddress), 2); 
    Result := EXCEPTION_CONTINUE_EXECUTION; 
    Exit; 
    end; 

Hélas, cela ne fonctionne pas. En fait, j'aurais utilisé le vrai pointeur d'instruction (E.ContextRecord.Eip), mais en quelque sorte l'ensemble ContextRecord ne semble pas peuplé.

Que puis-je faire de sorte que est-ce que fonctionne comme prévu? PS: lors de l'exécution avec le débogueur, je m'attendrais à ce que ce code se retrouve dans ma routine ExceptionFilter, mais ce n'est pas le cas - cela ne fonctionne que sans le débogueur; Pourquoi ça?

DebugHook := 0; // Act as if there's no debugger 
// Trigger a privileged instruction exception via this ring0 instruction : 
asm 
    WBINVD 
end; 
// Prove that my exception-filter worked : 
ShowMessage('WBINVD succesfully ignored!'); 

Répondre

3

SetUnhandledExceptionFilter semble être une sorte de wrapper Delphi, peut-être avez-vous plus de chance si vous le faites directement?

Vous pouvez enregistrer votre propre gestionnaire d'exceptions avec AddVectoredExceptionHandler, cela s'appellera une fonction callback qui vous donnera une structure EXCEPTION_POINTERS. Le membre Context de cette structure retourne ao EIP que vous pouvez modifier.

Si vous renvoyez EXCEPTION_CONTINUE_EXECUTION dans l'appel de rappel, l'exécution se poursuit à l'EIP indiqué.

+1

En outre, SetUnhandledExceptionFilter est une API de noyau: http://msdn.microsoft.com/en-us/library/ms680634(VS.85).aspx – PatrickvL

+0

Oh, et en lisant la documentation, on dirait que vous avez raison à propos du membre Context, mais comme je l'ai déjà dit, il n'est pas peuplé! Seul ExceptionRecord semble sain d'esprit - ContextRecord ne semble pas initialisé. – PatrickvL

+0

@PatrickvL: il est disponible pour XP et supérieur (voir MSDN). En ce qui concerne SetUnhandledExceptionFilter, les documents MSDN indiquent: pointeur vers une fonction de filtre d'exception de niveau supérieur qui sera appelée chaque fois que la fonction UnhandledExceptionFilter obtient le contrôle et que le processus n'est pas en cours de débogage. AddVectoredExceptionHandler fonctionne dans le débogueur alors essayez-le! – Remko