我的蹦床不会反弹(绕路,C ++,GCC)

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

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

每当我打电话给蹦床,根据我使用的偏移量,我得到“分段错误”或“非法指令”。 尽pipe两个案件都结束了。 “核心倾销”。 我认为这是因为我混淆了“相对地址”(注:我对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; } 

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

这是testing
这是**
非法指令(核心倾弃)

如果我在第66行使用+/- sizeof(jmpOp),结果如下:

 这是testing
这是 ******
分割故障(核心转储)

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

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