我的蹦床不会弹跳(迂回,C + +,GCC) [英] My trampoline won't bounce (detouring, C++, GCC)

查看:229
本文介绍了我的蹦床不会弹跳(迂回,C + +,GCC)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

感觉像我滥用Stackoverflow与我的所有问题,但它是一个Q& A论坛毕竟:)无论如何,我一直使用detours一段时间,但我还没有实现我自己的我之前使用过包装器)。因为我想完全控制我的代码(谁不?)我决定实现一个完全功能的detour'er我自己,所以我可以理解我的代码的每一个字节。



代码(下面)尽可能简单,但问题是,不是。我已经成功地实现了绕行(即钩子到我自己的功能),但我没有能够实现蹦床



我称之为蹦床,取决于我使用的偏移量,我得到一个分段故障或非法指令。两种情况都结束了; 'core dumped'。我认为这是因为我混淆了相对地址(注意:我是Linux的新手,所以我远没有掌握GDB)。



在代码中,根据 sizeof(jmpOp)(在第66行)我得到一个非法指令或分段错误。对不起,如果是显而易见的,我太累了...

  //头文件
#include< stdio.h>
#include< sys / mman.h>
#include< unistd.h>
#includeglobal.h//包含字节,ulong,ushort等的类型定义...
#include< cstring>

bool ProtectMemory(void * addr,int flags)
{
//保持页大小值的常量
const size_t pageSize = sysconf(_SC_PAGE_SIZE);

//计算相对页偏移
size_t temp =(size_t)addr;
temp - = temp%pageSize;

//更新地址
addr =(void *)temp;

//更新内存区域保护
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 ****** \\\
);
return 9;
}

typedef int(* TestType)(void);

int main(int argc,char * argv [])
{
//获取地址
byte * test =(byte *)&
byte * myTest =(byte *)& MyTest;

//调用原始
Test();

//为'test'函数更新内存访问
ProtectMemory((void *)test,PROT_EXEC | PROT_WRITE | PROT_READ);

//为trampoline分配内存
byte * trampoline = new byte [sizeof(jmpOp)* 2];

//复制操作
memcpy(trampoline,test,sizeof(jmpOp));
memcpy(test,jmpOp,sizeof(jmpOp));

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

//我认为这个地址不正确,我该怎么计算呢?使用当前
//状态(注释'sizeof(jmpOp)'),编译器会提示非法指令。
//如果我取消注释,并使用+或 - ,会出现分段错误...
*(uint *)(trampoline + 1)=((uint)test - (uint)蹦床)/ * + sizeof(jmpOp)* /;
trampoline - = sizeof(jmpOp);

//使蹦床可执行(和读/写)
ProtectMemory((void *)trampoline,PROT_EXEC | PROT_WRITE | PROT_READ);

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

//调用'detoured'func
Test();

//调用trampoline(崩溃)
((TestType)trampoline)();
return 0;
}

在感兴趣的情况下,这是正常运行期间的输出确切的代码如下):

 
这是测试
这是 **
非法指令b

这是如果我在第66行使用+/- sizeof(jmpOp)的结果:

这是测试
这是******
分段故障(内核转储)

注意:我运行的是Ubuntu 32位并用 g ++ global.cpp main.cpp -o main -Iinclude

解决方案

你不能将Test()的前5个字节不加区别地复制到你的蹦床中,然后跳转到Test()的第6个指令字节,因为你不知道第一个5字节包括整数个x86可变长度指令。为了做到这一点,你必须至少做一个最小量的自动反汇编Test()函数,以找到一个指令边界超过函数的开头5个或更多的字节,然后复制一个适当的数字的字节到你的蹦床,然后附加你的跳跃(这将不是在你的蹦床固定偏移)。注意,在典型的RISC处理器(如PPC)上,你不会有这个问题,因为所有的指令宽度相同。


It feels like I'm abusing Stackoverflow with all my questions, but it's a Q&A forum after all :) Anyhow, I have been using detours for a while now, but I have yet to implement one of my own (I've used wrappers earlier). Since I want to have complete control over my code (who doesn't?) I have decided to implement a fully functional detour'er on my own, so I can understand every single byte of my code.

The code (below) is as simple as possible, the problem though, is not. I have successfully implemented the detour (i.e a hook to my own function) but I haven't been able to implement the trampoline.

Whenever I call the trampoline, depending on the offset I use, I get either a "segmentation fault" or an "illegal instruction". Both cases ends the same though; 'core dumped'. I think it is because I've mixed up the 'relative address' (note: I'm pretty new to Linux so I have far from mastered GDB).

As commented in the code, depending on sizeof(jmpOp)(at line 66) I either get an illegal instruction or a segmentation fault. I'm sorry if it's something obvious, I'm staying up way too late...

// 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;
}

In case of interest, this is the output during a normal run (with the exact code above):

This is testing
This is **
Illegal instruction (core dumped)

And this is the result if I use +/- sizeof(jmpOp) at line 66:

This is testing
This is ******
Segmentation fault (core dumped)

NOTE: I'm running Ubuntu 32 bit and compile with g++ global.cpp main.cpp -o main -Iinclude

解决方案

You're not going to be able to indiscriminately copy the first 5 bytes of Test() into your trampoline, followed by a jump to the 6th instruction byte of Test(), because you don't know if the first 5 bytes comprise an integral number of x86 variable-length instructions. To do this, you're going to have to do at least a minimal amount of automated disassembling of the Test() function in order to find an instruction boundary that's 5 or more bytes past the beginning of the function, then copy an appropriate number of bytes to your trampoline, and THEN append your jump (which won't be at a fixed offset within your trampoline). Note that on a typical RISC processor (like PPC), you wouldn't have this problem, as all instructions are the same width.

这篇关于我的蹦床不会弹跳(迂回,C + +,GCC)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆