我试图为子功能重新分配堆栈。我试图通过混合程序集和Linux,x86_64架构上的C实现它。
以下是我计划的方式:
1.通过mmap
系统调用获取一段内存。
2.将映射的内存传递给asm func,然后将其分配给RSP寄存器并跳转到该函数。
C函数:
typedef struct Context
{
uint64_t rbx; // 0
uint64_t rsp; // 8
uint64_t rbp; // 16
uint64_t r12; // 24
uint64_t r13; // 32
uint64_t r14; // 40
uint64_t r15; // 48
uint64_t rip; // 56
uint64_t break_point; // 64
} Context_st;
main_func()
{
...
Context_st contexts[1];
Context_st mainContexts;
// inittialize main stack and the function's stack. This should make the func return to main function, which is this one.
_init_contexts(contexts);
// This should backup main function's context and jump to another function with customized stack
_run_contexts(&mainContexts, contexts);
printf("Successfully returned\n"); // This could not be executed.
...
}
static void _init_contexts(Context_st pContexts[1])
{
int mmapFlags = MAP_PRIVATE | MAP_ANONYMOUS;
const size_t STACK_SIZE = 512;
asm_init_context(&(pContexts[0]));
pContexts[0].rip = (uint64_t)_some_func;
pContexts[0].break_point = (uint64_t)_func_to_go;
pContexts[0].rsp = (uint64_t)mmap(NULL, STACK_SIZE, PROT_READ | PROT_WRITE, mmapFlags, -1, 0);
pContexts[0].rsp += STACK_SIZE;
return;
}
static void _run_contexts(Context_st *pMainCtx, Context_st *pSubCtx)
{
asm_save_main_and_go(pMainCtx, pSubCtx);
return;
}
和汇编函数:
#################################################
##
.text
.align 4
.globl asm_init_context
.type asm_init_context, @function
asm_init_context:
movq %rbx, (%rdi)
movq %rsp, 8(%rdi)
movq %rbp, 16(%rdi)
movq %r12, 24(%rdi)
movq %r13, 32(%rdi)
movq %r14, 40(%rdi)
movq %r15, 48(%rdi)
retq
#################################################
##
.text
.align 4
.globl asm_save_main_and_go
.type asm_save_main_and_go, @function
asm_save_main_and_go:
movq %rbx, (%rdi)
movq %rsp, 8(%rdi)
movq %rbp, 16(%rdi)
movq %r12, 24(%rdi)
movq %r13, 32(%rdi)
movq %r14, 40(%rdi)
movq %r15, 48(%rdi)
movl %esi, %eax
movq (%rsi), %rbx
movq 8(%rsi), %rsp # This is the code which causes SIGSEGV
movq 16(%rsi), %rbp
movq 24(%rsi), %r12
movq 32(%rsi), %r13
movq 40(%rsi), %r14
movq 48(%rsi), %r15
movq 56(%rsi), %rdx
push %rdx
jmp 64(%rsi)
我已经标记了导致SIGSEGV的asm代码。如果我将其注释掉,程序可能会正确运行并返回shell。但我不知道为什么。
我做错了吗?或者如果还需要做些什么来使mmapped内存部分能够将RSP注册为自定义堆栈空间?
先谢谢你们!
11月22日更新:
非常奇怪:当我切换到另一台虚拟机时,成功调用了_func_to_go()。虽然返回后还有另一个分段错误,但由于错误堆栈,可能会出现问题......
如果我复制问题,我会不断更新。但我希望这仍然是“WorksForMe”。
特别感谢@AjayBrahmakshatriya和@Ped7g。您的讨论指出了我的一些错误,我已在项目here中更正或纠正了这些错误。 : - )