2013-06-10 7 views
5

ich einen Artikel x86 API hooking demystified über x86 Haken lesen, und ich kam in diesem Code:Funktion Opcode in C

if(*function_A == 0xe9) { 
    printf("Hook detected in function A.\n"); 
} 

Es scheint, dass dieser Code prüft, ob der Operationscode der Funktion ein Sprung ist. Meine Frage betrifft die Syntax *function_A. Was ist diese Syntax? Gibt es den Opcode einer Funktion in C zurück? Ich habe eine Menge Forschung, aber ich fand keine Dokumentation zu dieser Funktion

EDIT

Ich dachte, ich den Link zu dem Artikel hinzugefügt, aber ich gerade bemerkte ich es hinzuzufügen vergessen. Link hinzugefügt, falls es hilft.

+1

Was ist der Typ von 'function_A'? Woher kam sein Wert? – interjay

+0

Dies ist der Prototyp 'void function_A (int Wert, int Wert2);' – Mansuro

+2

Dann ist dieser Code falsch, es wird den Funktionszeiger und nicht den Opcode vergleichen. – interjay

Antwort

5

Nein, Sie können einen Funktionszeiger nicht dereferenzieren, um den zugrunde liegenden Code zu erhalten.

Dies wird wahrscheinlich getan, indem man einen anderen Zeiger einführt, und sich auf die bestimmte Plattform verlässt, die "das Richtige tut", wo "richtig" bedeutet, "was ich machen will".

Etwas wie:

const unsigned char *function_A = (unsigned char *) printf; /* Any function. */ 

Dies ist nicht tragbar, und Compiler-Warnungen erzeugen, da Funktion und Datenzeiger nicht kompatibel sind. Auf z.B. x86, wird es wahrscheinlich "funktionieren".

+0

Nun, wo die ABI etwas anderes als das Standard sagt, sollten wir noch Sprachanwälte bleiben und darauf bestehen, dass es nicht korrekt ist? (Ich meine, die Leute schreiben Shell-Code, der mit einer vernünftigen Erklärung funktioniert.) (Und ich versuche nicht hier zu trollen, interessiert mich nur.) –

+2

Und +1 sowieso. Aus einem anderen Blickwinkel: "void *" ist unter POSIX sowohl mit Daten- als auch Funktionszeigern kompatibel. Dies bedeutet, dass 'void * tmp = & printf; const unsigned char * funcPtr = tmp; 'funktioniert ohne Warnung. –

+0

Die Zuweisung funktioniert möglicherweise ohne eine Warnung, aber wird sie ausgeführt, was ein Leser des Codes denkt, sollte es tun? – Devolus

3

Wenn Sie so etwas tun:

unsigned char *pf; 

pf = (unsigned char *)function_A; 

if (*pf == 0xE9) 
{ 
... 
} 

dann würden Sie diesen Effekt erhalten (die Architektur unter der Annahme erlaubt im allgemeinen Code zu lesen, und der Compiler hat das Recht, nicht definiertes Verhalten, dies zu erreichen).

Wenn Sie jedoch nicht die gesamte Funktion in Ihrem Code scannen, könnte man ein solches Erkennungsschema ganz einfach umgehen, indem Sie die Sprunganweisung (0xe9 ist ein Sprung zu einer relativen Adresse) irgendwo anders eingibt oder eine andere Form des Sprungs verwendet B. (0x66 0xe9, und ein 16- oder 32-Bit-Offset in einer 32- bzw. 16-Bit-Architektur). Und natürlich, wenn Sie nur die Scoring-Funktion innerhalb einer längeren Funktion überschreiben möchten, wäre es nicht zu schwer, einige Bytes innerhalb dieser Funktion zu ändern, um score += 10 zu score += 120 zu ändern. Es ist möglich, dass die Änderung zu score += 10000 schwieriger sein kann, da es oft "kleine Anzahl" und "große Anzahl" Varianten der Anweisungen zum Hinzufügen und Subtrahieren gibt.