2016-08-06 9 views
0

関数をフックするとき、元の関数の5バイトを上書きする必要があります。シグネチャと呼び出し規約は元の関数と置き換え関数と同じであるため、スタックフレームの初期設定は重要ではありません私が得られないことは、元の関数の最初の数バイトを上書きしていることです。 55(push ebp)8B EC(mov ebp、esp)、もう2つ必要ですか?関数に重大な2バイトを上書きしても問題にならないのはなぜですか?関数をフックするとき、最初の5バイトを上書きするとどうして問題になりませんか?

00440112       ; int __cdecl function(int, FILE *) 
.text:00440112       var_410   = byte ptr -410h 
.text:00440112       var_310   = byte ptr -310h 
.text:00440112       var_210   = byte ptr -210h 
.text:00440112       var_110   = byte ptr -110h 
.text:00440112       var_10   = byte ptr -10h 
.text:00440112       var_4   = dword ptr -4 
.text:00440112       arg_0   = dword ptr 8 
.text:00440112       arg_4   = dword ptr 0Ch 
.text:00440112 
.text:00440112 55          push ebp 
.text:00440113 8B EC         mov  ebp, esp 
.text:00440115 81 EC 10 04 00 00      sub  esp, 410h 
.text:0044011B 53          push ebx 
.text:0044011C 56          push esi 
.text:0044011D 8B 75 0C        mov  esi, [ebp+arg_4] 
.text:00440120 80 7E 04 00        cmp  byte ptr [esi+4], 0 
.text:00440124 57          push edi 
.text:00440125 C7 86 10 01 00 00 63 00+    mov  dword ptr [esi+110h], 63h 
.text:0044012F 74 0F         jz  short loc_440140 
.text:00440131 83 3D 7A 4E 4B 00 00     cmp  dword_4B4E7A, 0 
.text:00440138 7F 06         jg  short loc_440140 
.text:0044013A 83 65 FC 00        and  [ebp+var_4], 0 
.text:0044013E EB 07         jmp  short loc_440147 

上記のアセンブリを取る。 'E9 ?? ?? ?? ?? ' '55 8B EC 81 EC '(ジャンプする関数のアドレス)を置き換えるので、ローカル変数のスタック上に0x410の割り当てが発生することはありません新しい関数が呼び出されて0x44011Bの元に戻ります。なぜこれは問題ではないのですか?私は何が欠けているのか分かりません。

、あなたが気づいたとして、あなたは、元のコードを実行できるようにするつもりであれば、MyUsername112358の答えHERE

+1

フックが元の関数にジャンプしない場合は、5バイトの 'jmp rel32'の後のすべてが重要ではありません。あなたがそれらを*あなたのフックとしても実行しようとしているならば、元の指示が何だったかだけが重要です。 –

+1

ええ、私はフックの後に元の関数を呼び出す必要があります。上記の例では、元の関数を呼び出していますが、2つの余分なバイトを上書きしているとは思われません。 – MikeO

+2

私は彼が余分なバイトをオーバーライドしていることを知っていると思うし、元の関数を呼び出すときに考慮に入れているとか、幸運なことに何も壊れていない。 DLLによってエクスポートされたルーチンのほとんどがプロローグ 'mov edi、edi;を使用していたので、5バイトのフックは普及していました。プッシュebp; mov ebp、esp'(おそらくstdcallの規約のために)はちょうど5バイトの長さなので、あなたはジャンプで置き換えても害はありません。 –

答えて

2

を参照して、その後、このメソッドを使用して機能をフックすることができます機能コードを再現したい場合は、 5バイト境界で切断することはできません。最初の5バイトをカバーする命令を逆アセンブルしてコピーする必要があります。

私のia32hookは、OllyDbgdisassemblerを使用して、どこから切り取るかを調べることができます。 The relevant snippet

#include "ollydisasm/disasm.h" 

static inline unsigned long CleanBiteOff(const unsigned char *ptr, size_t amount) 
{ 
    static t_disasm disasm; 
    unsigned long size = 0; 
    do {size += Disasm(ptr+size, 16, ptr+size, &disasm, DISASM_SIZE);} while(size < amount); 
    return size; 
} 

返さsizeをコピーする必要があるバイト数です。これらのバイトをコピーするトランポリンの終わりには(char*)func+sizeにジャンプし、すべてがうまくいきます。

あなたがリンクした答えは、命令キャッシュをフラッシュせず、命令ポインタがあなたがパッチしようとしているバイトを指し示した場合に深刻な問題を引き起こします。スレッドを一時停止して、eipがパッチしようとしているバイトを指していないと主張してください。

これは学習目的でない場合は、代わりにMicrosoft Detoursのようなソリューションの使用を検討してください。

+1

detoured関数はトランポリンと同じ署名と呼び出し規約を持つため、最初の3バイトは必要ありません。それ以外はあなたの答えをありがとう、それはうまく説明された。 – MikeO

+0

3番目のパラメータ 'ip'はハードコードされたアドレスですか? '0x00401AAC' – MikeO

+0

@MikeO私はなぜその値で 'ip'を設定したのか思い出すことはできません。あなたは命令サイズを知ることに興味があるので、あなたはそれを無視することができます。ディスアセンブラが0に気をつけなければ、ゼロでなければ意味がないことを示すべきです。 – a3f

関連する問題