【发布时间】:2017-01-01 13:18:40
【问题描述】:
我想将小的 double(...) 函数编译为 x64 shellcode。我已经有一个工作程序可以为a + b / a 等简单的数学运算生成编码程序集,其中a 和b 是函数的double 参数。
生成的代码被加载到可执行的mmap 缓冲区中,以后可以调用。
我有以下问题:我想在我生成的 shellcode 中调用 math.h 函数,如 sin、exp 等。由于所有call 操作码都以某种方式使用 32 位地址或相对跳转,因此我无法轻松使用这些指令。因此我尝试以这种方式实现我自己的call-instruction:
lea rax, [rip+0x0] ;load instruction pointer into rax
add rax, <offset-to-return-to>
push rax
moveabs rax, <adress-of-function> ;load the function pointer to rax
jmp rax
这是我生成这些指令的代码:
//lea rax, [rip+0x0]
insertAll(code,std::list<uint8_t>{ 0x48, 0x8D, 0x05, 0x00, 0x00, 0x00, 0x00 });
//add rax, <offset-to-return-to>
insertAll(code,std::list<uint8_t>{ 0x48, 0x83, 0xC0, <offset-to-return-to>});
//push rax
code.push_back(0x50);
//moveabs rax, address-of-function
uint8_t reg = 0; //rax
uint8_t rexWPrefix = 0x48 + (reg > 8);
uint8_t opCode = 0xB8 + (reg % 8);
insertAll(code,std::list<uint8_t>{ rexWPrefix, opCode });
code.insert(code.end(),reinterpret_cast<uint8_t*>(&fabs),reinterpret_cast<uint8_t*>(&fabs) + 8);
//jmp rax
insertAll(code,std::list<uint8_t>{ 0xFF, 0xE0 });
不幸的是,以这种方式调用函数不起作用,程序崩溃并出现SIGSEGV 错误。我的汇编代码或指令编码有问题吗? <offset-to-return-to> 应该有什么值,才能让函数回到正确的位置?
免责声明:我知道,这不是处理代码动态生成的最佳方式...我可以编译一个动态库并使用dlsym 加载它。这只是学习汇编/shellcode 的一种有趣方式,不应该太认真:)
【问题讨论】:
-
乍一看很有意义,使用调试器查看故障的位置和原因。 PS:您当然可以将
add rax合并到lea中。确保使用正确的偏移量。 -
什么是“x64 shellcode”?? C 和 C++ 是不同的语言。不要垃圾标签。
-
@Olaf :我想说,我对代码使用 x86-64 指令。这对于 jmp 指令可能很重要,因为地址大小是 64 位。
标签: c++ assembly x86-64 shellcode