在shellcode中调用函数

时间:2017-01-01 13:18:40

标签: c++ assembly x86-64 shellcode

我想将小double(...)函数编译为x64 shellcode。我已经有了一个工作程序来为a + b / a之类的简单数学运算生成编码汇编,其中ab是函数的double参数。

生成的代码被加载到可执行的mmap缓冲区中,稍后可以调用。

我遇到以下问题:我想在生成的shellcode中调用math.h等函数,如sinexp等。由于所有call操作码都以某种方式使用32位地址或相对跳转,因此我无法轻易使用这些指令。因此我尝试以这种方式实现我自己的call - 指令:

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的有趣方式,不应该太认真:)

1 个答案:

答案 0 :(得分:1)

我发现了三个错误。 jmp指令不是绝对的,而是afaik RIP - 相对的。我使用push + ret作为替代,因为ret跳转到堆栈上的绝对地址。

此外,我不知道调用者必须在堆栈上保留4 * 8字节的阴影空间。详细信息可以在here找到。

最后,将函数指针插入指令代码的代码是错误的。我不小心插入了函数代码的前8个字节而不是指针的值:

code.insert(code.end(),reinterpret_cast<uint8_t*>(&fabs),reinterpret_cast<uint8_t*>(&fabs) + 8);

这是完成的工作代码:

//add rsp,0x20  --> shadow space of 4*8 bytes
insertAll(code,std::list<uint8_t>{ 0x48, 0x83, 0xC4, 0x20 } );
//lea rax, [rip+0x0]
insertAll(code,std::list<uint8_t>{ 0x48, 0x8D, 0x05, 0x00, 0x00, 0x00, 0x00 });
//add rax, 18
insertAll(code,std::list<uint8_t>{ 0x48, 0x83, 0xC0, 18 });
//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 });
void* address = reinterpret_cast<void*>(&my_abs);
code.insert(code.end(),reinterpret_cast<uint8_t*>(&address),reinterpret_cast<uint8_t*>(&address) + sizeof(address));

//push rax
code.push_back(0x50);
//retq
code.push_back(0xC3);
//sub rsp,0x20  --> shadow space of 4*8 bytes
insertAll(code,std::list<uint8_t>{ 0x48, 0x83, 0xEC, 0x20 } );