2017-01-01 78 views
0

我想编译小型double(...)作为x64 shellcode。我已经有一个工作程序来生成用于简单数学运算的编码程序集,如a + b/a,其中abdouble函数的参数。shellcode内调用函数

生成的代码被加载到可执行文件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,不应该太认真:)

+2

乍一看有道理,使用调试器看在哪里以及为什么会发生故PS:你当然可以将'add rax'合并到'lea'中。确保你使用正确的偏移量。 – Jester

+2

什么是“x64 shellcode”?而C和C++是不同的语言。不要垃圾标签。 – Olaf

+0

@Olaf:我想说,我使用x86-64指令代码。这对于jmp指令可能很重要,因为地址大小是64位。 – tly

回答

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 });