【问题标题】:Calling functions inside shellcode在 shellcode 中调用函数
【发布时间】:2017-01-01 13:18:40
【问题描述】:

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

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

我有以下问题:我想在我生成的 shellcode 中调用 math.h 函数,如 sinexp 等。由于所有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 错误。我的汇编代码或指令编码有问题吗? &lt;offset-to-return-to&gt; 应该有什么值,才能让函数回到正确的位置?

免责声明:我知道,这不是处理代码动态生成的最佳方式...我可以编译一个动态库并使用dlsym 加载它。这只是学习汇编/shellcode 的一种有趣方式,不应该太认真:)

【问题讨论】:

  • 乍一看很有意义,使用调试器查看故障的位置和原因。 PS:您当然可以将add rax 合并到lea 中。确保使用正确的偏移量。
  • 什么是“x64 shellcode”?? C 和 C++ 是不同的语言。不要垃圾标签。
  • @Olaf :我想说,我对代码使用 x86-64 指令。这对于 jmp 指令可能很重要,因为地址大小是 64 位。

标签: c++ assembly x86-64 shellcode


【解决方案1】:

我发现了三个错误。 jmp 指令不是绝对的,而是 afaik RIP-relative。我使用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 } );

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-26
    相关资源
    最近更新 更多