我的蹦床不会弹跳(绕道,C++,海湾合作委员会)

My trampoline won't bounce (detouring, C++, GCC)

本文关键字:C++ 委员会 绕道 我的      更新时间:2023-10-16

感觉就像我在滥用Stackoverflow的所有问题,但它毕竟是一个问答论坛:)无论如何,我已经使用弯路一段时间了,但我还没有实现我自己的一个(我之前使用过包装器(。因为我想完全控制我的代码(谁不想?我决定自己实现一个功能齐全的绕行器,这样我就可以理解代码的每个字节。

代码(下面(尽可能简单,但问题并非如此。我已经成功地实现了绕道(即钩到我自己的功能(,但我无法实现蹦床

每当我调用蹦床时,根据我使用的偏移量,我都会得到"分段错误"或"非法指令"。不过,这两种情况的结局都是一样的;"核心倾销"。我认为这是因为我混淆了"相对地址"(注意:我对 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 testingn");
    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编译

你无法

不分青红皂白地将 Test(( 的前 5 个字节复制到你的蹦床上,然后跳转到 Test(( 的第 6 个指令字节,因为你不知道前 5 个字节是否包含整数个 x86 可变长度指令。 为此,您必须至少对 Test(( 函数进行最少量的自动反汇编,以便找到比函数开头多 5 个或更多字节的指令边界,然后将适当数量的字节复制到您的蹦床上,然后附加您的跳跃(不会在您的蹦床内固定偏移(。 请注意,在典型的RISC处理器(如PPC(上,您不会遇到此问题,因为所有指令的宽度都相同。