2011-11-11 12 views
3

私は関数の最初の数バイトをメモリに上書きして、それを自分の関数に迂回させました。私は現在、実際の機能に制御を戻すトランポリン機能を作成する際に問題を抱えています。トランポリン関数を書く

これは私の質問hereの2番目の部分です。

BYTE *buf = (BYTE*)VirtualAlloc(buf, 12, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); 
void (*ptr)(void) = (void (*)(void))buf; 

vm_t* VM_Create(const char *module, intptr_t (*systemCalls)(intptr_t *), vmInterpret_t interpret) 
{ 
    MessageBox(NULL, L"Oh Snap! VM_Create Hooked!", L"Success!", MB_OK); 

    ptr(); 

    return NULL;//control should never get this far 
} 

void Hook_VM_Create(void) 
{ 
    DWORD dwBackup; 
    VirtualProtect((void*)0x00477C3E, 7, PAGE_EXECUTE_READWRITE, &dwBackup); 

    //save the original bytes 
    memset(buf, 0x90, sizeof(buf)); 
    memcpy(buf, (void*)0x00477C3E, 7); 

    //finish populating the buffer with the jump instructions to the original functions 
    BYTE *jmp2 = (BYTE*)malloc(5); 
    int32_t offset2 = ((int32_t)0x00477C3E+7) - ((int32_t)&buf+12); 
    memset((void*)jmp2, 0xE9, 1); 
    memcpy((void*)(jmp2+1), &offset2, sizeof(offset2)); 
    memcpy((void*)(buf+7), jmp2, 5); 

    VirtualProtect((void*)0x00477C3E, 7, PAGE_EXECUTE_READ, &dwBackup); 
} 

0x00477c3eは、上書きされた関数のアドレスです。元の関数のasmは、書き込む前にbufに保存されています。次に、5バイトのjmp命令がbufに追加され、元の関数の残りの部分に戻ります。

問題は、ptr()が呼び出され、プログラムがクラッシュすると発生します。ときに私のptr()機能のように見えないが、私のオフセット計算をダブルチェック正しいように見えるサイトをデバッグするときにクラッシュします。 NOTE

:余計なコードが簡単にすべてのものを読ん作るために省略されている

EDIT:これはptr()機能は私のオフセット計算が間違っているかのようにollydbg

0FFB0000 55    PUSH EBP 
0FFB0001 57    PUSH EDI 
0FFB0002 56    PUSH ESI 
0FFB0003 53    PUSH EBX 
0FFB0004 83EC 0C   SUB ESP,0C 
0FFB0007 -E9 F1484EFD  JMP 0D4948FD 

でだから、見えるように見えるものです。

+0

ここで、VM_Createにジャンプするには0x00477C3Eのコードを上書きしますか? 0x00477C3Eでコードをどこに復元しますか?元のコードに戻るときにレジスターなどを保存するために何らかの措置を講じていますか? –

+0

元のVM_Createは、VM_Hook_Createの先頭で上書きされます。コードが復元されず、欠落しているasm命令を含む迂回機能がバッファにロードされて呼び出され、バッファの最後に、元のvm_createの残りの部分へのジャンプが「呼び出されました」(?) – Adam

答えて

3

だからあなたbufが[] 2つの物事含む終わる:次に、あなたはBUFに制御を移す元の命令の

  • 7最初のバイト
  • JMP

を。最初の7バイトには命令全体のみが含まれていることが保証されていますか?そうでない場合、これらの7バイトで始まる最後の不完全な命令の実行中または実行後にクラッシュする可能性があります。

これらの7バイトの命令では、EIP相対的な計算が行われないことが保証されていますか(これには、主にジャンプやコールなどのEIP相対アドレス指定が含まれます)。そうでない場合は、元の関数の継続が正しく機能せず、プログラムがクラッシュする可能性があります。

元の関数にはパラメータがありますか?そうであれば、単にptr();を実行することで、元のコードはレジスタやスタックから取り込まれたガベージ(呼び出し規約によります)で動作し、クラッシュする可能性があります。

EDIT:もう1つです。 &buf+12の代わりにbuf+12を使用してください。あなたのコードでbufは配列ではなくポインタです。

+0

はい、最初の7バイトは命令全体です。実際、それらはptr()関数で最初に見られる7バイトです。元の関数のパラメータはスタックにプッシュされ、eip相対的な計算は行われません。だからすべてが有効であるはずです。 – Adam

+1

@Adam:bufの前にアンパサンドを削除します。 –

+0

roflmao、omg私はそんなにばかだ。どのように私はそれが恋しいのですか?あなたはポインタでそれ以外のことが起こっても、そのような間違いはないと思います。 tyvm – Adam

関連する問題