您可以像这样编码(gcc 风格/AT&T 汇编语法):
jmp *.Ltgtaddr
.Ltgtaddr: .long absoluteAddrOfFunctionToCall
这会汇编成 10 个字节(在 32 位 x86 上)-ff 25
对于具有 32 位内存操作数的绝对 jmp,然后是带有下一个字的地址的四个字节,后面是代码的(绝对)目标地址的内容。
编辑:我已经用编译和测试的示例更新了下面的部分。
您可以从 C 源代码动态创建这样的蹦床。示例源(需要 32 位 x86,留给读者练习如何将蹦床转换为 64 位):
#include <sys/mman.h>
#include <stdio.h>
void oneWay(char *str, int arg)
{ printf("string is \"%s\", int is %d\n", str, arg); }
void otherWay(char *str, int arg)
{ printf(str, arg); printf("\n"); }
void *trampGen(void *tgtAddr)
{
char *trampoline = mmap(NULL, 10, PROT_EXEC | PROT_WRITE | PROT_READ,
MAP_PRIVATE | MAP_ANON, -1, 0);
trampoline[0] = (char)0xff; trampoline[1] = (char)0x25;
*(char**)(trampoline+2) = trampoline + 6;
*(void**)(trampoline+6) = tgtAddr;
return trampoline;
}
int main(int argc, char **argv)
{
void * (*funcptr)(char*, int) = trampGen(oneWay);
*funcptr("Test %d String", 12345);
*(void **)(((char *)funcptr) + 6) = otherWay;
*funcptr("Test %d String", 12345);
munmap(funcptr, 10);
return 0;
}
对我来说输出:
$ ./tt
string is "Test %d String", int is 12345
Test 12345 String
请注意,留出整个 MMU 页以仅使用其中的 10 个字节的效率稍低。如果您需要多个蹦床,请实现您自己的内存管理器......