这远不是你的全部问题(C#...),但它可以给你一些线索。
这个例子是用 C 语言在 Linux-64 上用 gcc 完成的;你可能需要适应它
你的平台。
第一步是用一些内联汇编(gnu-asm
语法)以查看它与 objdump 的外观(它从未被调用
实际上)。
在这里找到了跳转到常量地址的技巧:
https://stackoverflow.com/a/53876008/11527076
之后我们必须创建一个可执行内存段并填充
它具有受前一个函数启发的字节(感谢 objdump)。
如果唯一可能改变的是地址,那么我们只需覆盖
这个地址在前面的代码中。
在此示例中,另一个函数的地址用于此目的。
那么这个可执行内存段可以看成是一个函数
(嗯……希望如此)我们通过函数指针来使用它。
而且它似乎有效!
我能看到的唯一问题是指令movb $0xff,0xa(%ecx,%ebx,4)
这样做不好,因为我不确切知道寄存器是什么
应该包含。
我决定用六个nop 替换这条指令以占据相同的位置
并保持此示例与原始问题相似。
(我想在你的问题的上下文中,这些寄存器将有一个
相关值)。
/**
gcc -std=c99 -o prog_c prog_c.c \
-pedantic -Wall -Wextra -Wconversion \
-Wc++-compat -Wwrite-strings -Wold-style-definition -Wvla \
-g -O0 -UNDEBUG -fsanitize=address,undefined
**/
#undef __STRICT_ANSI__ // for MAP_ANONYMOUS
#include <sys/mman.h>
#include <stdio.h>
#include <string.h>
#include <stddef.h>
void
target_function(void)
{
printf("~~~~ %s ~~~~\n", __func__);
}
void
inline_asm_example(void)
{
__asm__ __volatile__(
"\tnop\n"
"\tmovb $0xff,0xa(%ecx,%ebx,4)\n"
"\tjmpq *0x0(%rip)\n"
".quad 0xAA00BB11CC22DD33\n");
// the jump relative to rip is inspired from
// https://stackoverflow.com/a/53876008/11527076
}
int
main(void)
{
// create an executable page
void *page=mmap(NULL, 6+6+8,
PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
if(page==MAP_FAILED)
{
fprintf(stderr, "cannot allocate memory page\n");
return 1;
}
// initialise code pattern
// objdump --disassemble=inline_asm_example prog
char *code_pattern=(char *)page;
#if 0 // this instruction causes something wrong
memcpy(code_pattern+0,
"\x67\xc6\x44\x99\x0a\xff", 6); // movb $0xff, 10(%ecx,%ebx,4)
#else // use some useless instructions instead
memcpy(code_pattern+0,
"\x90\x90\x90\x90\x90\x90", 6); // 6x nop
#endif
memcpy(code_pattern+6,
"\xff\x25\x00\x00\x00\x00", 6); // jmpq *0x0(%rip)
// insert into the pattern the address we want to jump to
ptrdiff_t target_address=(ptrdiff_t)target_function;
memcpy(code_pattern+6+6, &target_address, sizeof(target_address));
// consider the code pattern as a function
void (*fnct_ptr)(void)=NULL;
memcpy(&fnct_ptr, &code_pattern, sizeof(code_pattern));
// here we go
printf("about to do something I will probably regret...\n");
fnct_ptr();
printf("ah? it was not so painful after all!\n");
// let's forget everything about that
munmap(code_pattern, 6+6+8);
return 0;
}