2

私はすべての質問で Stackoverflow を悪用しているように感じますが、結局のところ Q&A フォーラムです :) とにかく、私はしばらく回り道を使用してきましたが、まだ独自のものを実装していません (ラッパーを使用しました)。ついさっき)。私は自分のコードを完全に制御したいので (そうでない人はいないでしょうか?)、完全に機能する detour'er を自分で実装することにしました。これにより、コードのすべてのバイトを理解できるようになります。

コード (以下) は可能な限り単純ですが、問題はそうではありません。迂回路 (つまり、自分の関数へのフック) を正常に実装しましたが、トランポリンを実装できませんでした。

トランポリンを呼び出すたびに、使用するオフセットに応じて、「セグメンテーション違反」または「不正な命令」のいずれかが表示されます。ただし、どちらの場合も同じように終了します。「コアダンプ」。「相対アドレス」を混同したためだと思います(注:私はLinuxにかなり慣れていないため、GDBを習得するにはほど遠いです)。

sizeof(jmpOp)コードでコメントされているように、 (66 行目) に応じて、不正な命令またはセグメンテーション違反が発生します。当たり前のことでしたらすみません、夜更かししてしまいました...

// Header files
#include <stdio.h>
#include <sys/mman.h>
#include <unistd.h>
#include "global.h" // Contains typedefines for byte, ulong, ushort etc...
#include <cstring>

bool ProtectMemory(void * addr, int flags)
{
    // Constant holding the page size value
    const size_t pageSize = sysconf(_SC_PAGE_SIZE);

    // Calculate relative page offset
    size_t temp = (size_t) addr;
    temp -= temp % pageSize;

    // Update address
    addr = (void*) temp;

    // Update memory area protection
    return !mprotect(addr, pageSize, flags);
}

const byte jmpOp[] = { 0xE9, 0x00, 0x00, 0x00, 0x00 };

int Test(void)
{
    printf("This is testing\n");
    return 5;
}

int MyTest(void)
{
    printf("This is ******\n");
    return 9;
}

typedef int (*TestType)(void);

int main(int argc, char * argv[])
{
    // Fetch addresses
    byte * test = (byte*) &Test;
    byte * myTest = (byte*) &MyTest;

    // Call original
    Test();

    // Update memory access for 'test' function
    ProtectMemory((void*) test, PROT_EXEC | PROT_WRITE | PROT_READ);

    // Allocate memory for the trampoline
    byte * trampoline = new byte[sizeof(jmpOp) * 2];

    // Do copy operations
    memcpy(trampoline, test, sizeof(jmpOp));
    memcpy(test, jmpOp, sizeof(jmpOp));

    // Setup trampoline
    trampoline += sizeof(jmpOp);
    *trampoline = 0xE9;

    // I think this address is incorrect, how should I calculate it? With the current
    // status (commented 'sizeof(jmpOp)') the compiler complains about "Illegal Instruction".
    // If I uncomment it, and use either + or -, a segmentation fault will occur...
    *(uint*)(trampoline + 1) = ((uint) test - (uint) trampoline)/* + sizeof(jmpOp)*/;
    trampoline -= sizeof(jmpOp);

    // Make the trampoline executable (and read/write)
    ProtectMemory((void*) trampoline, PROT_EXEC | PROT_WRITE | PROT_READ);

    // Setup detour
    *(uint*)(test + 1) = ((uint) myTest - (uint) test) - sizeof(jmpOp);

    // Call 'detoured' func
    Test();

    // Call trampoline (crashes)
    ((TestType) trampoline)();
    return 0;
}

参考までに、これは通常の実行中の出力です (上記の正確なコードを使用)。

これはテスト中です
これは**です
不正な命令 (コアダンプ)
これは、66 行目で +/- sizeof(jmpOp) を使用した場合の結果です。

これはテスト中です
これは ******
セグメンテーション違反 (コアダンプ)

注:Ubuntu 32ビットを実行しており、コンパイルしますg++ global.cpp main.cpp -o main -Iinclude

4

1 に答える 1

10

Test() の最初の 5 バイトを無差別にトランポリンにコピーし、続いて Test() の 6 番目の命令バイトにジャンプすることはできません。 x86 可変長命令の整数。これを行うには、Test() 関数の自動逆アセンブルを少なくとも最小限実行して、関数の先頭から 5 バイト以上離れた命令境界を見つけ、適切な数値をコピーする必要があります。のバイトをトランポリンに追加し、ジャンプを追加します (トランポリン内の固定オフセットにはなりません)。典型的な RISC プロセッサ (PPC など) では、すべての命令が同じ幅であるため、この問題は発生しないことに注意してください。

于 2012-05-05T01:57:39.807 に答える