如何绕过 Linux 上的函数?
How to detour a function on Linux?
我制作了一个 32 位测试程序,我试图绕过这个函数(内部):
void Function(int number)
{
std::cout << "Your number is: " << number << std::endl;
}
使用我制作的这个绕行函数(它在 memcpy 上抛出 SIGSEV 分段错误,即使内存有效并且受到 execute/read/write 保护):
bool Detour(byte_t* src, byte_t* dst, size_t size)
{
if(size < HOOK_MIN_SIZE) return false;
mprotect(src, size, PROT_EXEC | PROT_READ | PROT_WRITE);
mem_t jmpAddr = ((mem_t)dst - (mem_t)src) - HOOK_MIN_SIZE;
byte_t CodeCave[] = { JMP, 0x0, 0x0, 0x0, 0x0 };
*(mem_t*)((mem_t)CodeCave + sizeof(JMP)) = jmpAddr;
memcpy(src, CodeCave, sizeof(CodeCave));
return true;
}
它是这样调用的:
Detour((byte_t*)&Function, (byte_t*)&hkFunction, HOOK_SIZE);
HOOK_MIN_SIZE 等于 5,以适合汇编跳转 (0xE9 0x00 0x00 0x00 0x00) 并且 HOOK_SIZE 等于 7,因为它必须适合所有被覆盖的指令 (对于蹦床,但在这种情况下并不重要):
Dump of assembler code for function Function(int):
0x5655631d <+0>: push ebp
0x5655631e <+1>: mov ebp,esp
0x56556320 <+3>: push ebx
0x56556321 <+4>: sub esp,0x4
0x56556324 <+7>: call 0x56556220 <__x86.get_pc_thunk.bx>
GDB 错误:
Program received signal SIGSEGV, Segmentation fault.
0x565564c9 in Detour (
src=0x5655631d <Function(int)> "U15S34[=15=]407677137+",
dst=0x56556372 <hkFunction(int)> "U15S34[=15=]4026771â+", size=7) at main.cpp:51
51 memcpy(src, CodeCave, sizeof(CodeCave));
类型定义:
typedef unsigned int mem_t;
typedef unsigned char byte_t;
这个绕行功能有什么问题?我已经成功地在 Windows 上为 32 位和 64 位制作了自己的,但在 Linux.
上似乎有所不同
我做到了!问题是地址不是系统页面的倍数,我可以使用这个函数而不是 mprotect:
来修复它
int ProtectMemory(mem_t address, size_t size, int protection)
{
long pagesize = sysconf(_SC_PAGE_SIZE);
address = address - (address % pagesize);
return mprotect((void*)address, size, protection);
}
Detour 函数现在看起来像这样:
bool Detour(byte_t* src, byte_t* dst, size_t size)
{
if(size < HOOK_MIN_SIZE) return false;
//mprotect(src, size, PROT_EXEC | PROT_READ | PROT_WRITE);
int out = ProtectMemory((mem_t)src, size, PROT_EXEC | PROT_READ | PROT_WRITE);
//std::cout << out << std::endl;
mem_t jmpAddr = ((mem_t)dst - (mem_t)src) - HOOK_MIN_SIZE;
byte_t CodeCave[] = { JMP, 0x0, 0x0, 0x0, 0x0 };
*(mem_t*)((mem_t)CodeCave + sizeof(JMP)) = jmpAddr;
memcpy(src, CodeCave, sizeof(CodeCave));
return true;
}
我制作了一个 32 位测试程序,我试图绕过这个函数(内部):
void Function(int number)
{
std::cout << "Your number is: " << number << std::endl;
}
使用我制作的这个绕行函数(它在 memcpy 上抛出 SIGSEV 分段错误,即使内存有效并且受到 execute/read/write 保护):
bool Detour(byte_t* src, byte_t* dst, size_t size)
{
if(size < HOOK_MIN_SIZE) return false;
mprotect(src, size, PROT_EXEC | PROT_READ | PROT_WRITE);
mem_t jmpAddr = ((mem_t)dst - (mem_t)src) - HOOK_MIN_SIZE;
byte_t CodeCave[] = { JMP, 0x0, 0x0, 0x0, 0x0 };
*(mem_t*)((mem_t)CodeCave + sizeof(JMP)) = jmpAddr;
memcpy(src, CodeCave, sizeof(CodeCave));
return true;
}
它是这样调用的:
Detour((byte_t*)&Function, (byte_t*)&hkFunction, HOOK_SIZE);
HOOK_MIN_SIZE 等于 5,以适合汇编跳转 (0xE9 0x00 0x00 0x00 0x00) 并且 HOOK_SIZE 等于 7,因为它必须适合所有被覆盖的指令 (对于蹦床,但在这种情况下并不重要):
Dump of assembler code for function Function(int):
0x5655631d <+0>: push ebp
0x5655631e <+1>: mov ebp,esp
0x56556320 <+3>: push ebx
0x56556321 <+4>: sub esp,0x4
0x56556324 <+7>: call 0x56556220 <__x86.get_pc_thunk.bx>
GDB 错误:
Program received signal SIGSEGV, Segmentation fault.
0x565564c9 in Detour (
src=0x5655631d <Function(int)> "U15S34[=15=]407677137+",
dst=0x56556372 <hkFunction(int)> "U15S34[=15=]4026771â+", size=7) at main.cpp:51
51 memcpy(src, CodeCave, sizeof(CodeCave));
类型定义:
typedef unsigned int mem_t;
typedef unsigned char byte_t;
这个绕行功能有什么问题?我已经成功地在 Windows 上为 32 位和 64 位制作了自己的,但在 Linux.
上似乎有所不同我做到了!问题是地址不是系统页面的倍数,我可以使用这个函数而不是 mprotect:
来修复它int ProtectMemory(mem_t address, size_t size, int protection)
{
long pagesize = sysconf(_SC_PAGE_SIZE);
address = address - (address % pagesize);
return mprotect((void*)address, size, protection);
}
Detour 函数现在看起来像这样:
bool Detour(byte_t* src, byte_t* dst, size_t size)
{
if(size < HOOK_MIN_SIZE) return false;
//mprotect(src, size, PROT_EXEC | PROT_READ | PROT_WRITE);
int out = ProtectMemory((mem_t)src, size, PROT_EXEC | PROT_READ | PROT_WRITE);
//std::cout << out << std::endl;
mem_t jmpAddr = ((mem_t)dst - (mem_t)src) - HOOK_MIN_SIZE;
byte_t CodeCave[] = { JMP, 0x0, 0x0, 0x0, 0x0 };
*(mem_t*)((mem_t)CodeCave + sizeof(JMP)) = jmpAddr;
memcpy(src, CodeCave, sizeof(CodeCave));
return true;
}