【发布时间】:2021-03-22 16:23:04
【问题描述】:
所以在 64 位进程中创建远程线程后,我正在映射我的 shellcode:
push rax
push r9
push r8
push rdx
push rcx
push r11
push 0x00000000
push 0x00000000
mov r9, 0
mov r8, StartRoutine
mov rdx, 0
mov rcx, 0
mov rax, CreateThread
call rax
add rsp, 8*2 ;clear shadow space
pop r11
pop rcx
pop rdx
pop r8
pop r9
pop rax
mov r15, PreviousRip
jmp r15 ;return to previous instruction pointer
您在上面看到的名称是占位符,在我映射我的 shellcode 之前被 替换:
-
StartRoutine是远程进程内存中现有函数的地址 -
CreateThread是CreateThread在虚拟内存中的地址 -
PreviousRip是之前的Instruction Pointer取自线程上下文
但是,在 shellcode 运行后,由于 ret 指令转到错误的 rip,我收到了 Access violation 错误。
对我来说,这表明堆栈已损坏/不平衡,但是我仔细检查了 shellcode 之前和之后的堆栈地址是相同的,我还检查了我的 shellcode 之前和之后的所有通用寄存器,它们是成功的已恢复。
【问题讨论】:
-
add rsp, 8*2- 影子空间是 32 个字节,而不是 16 个字节,高于调用前允许被调用者踩的 RSP。 (任何堆栈参数都高于此值。)您可能只是破坏了返回地址,而不是不平衡堆栈,直接或通过破坏其他代码存储的寄存器。 -
这是 NASM 语法,其中
mov rax, CreateThread是地址的mov reg, imm64,而不是负载? -
r10在 Windows x64 中被调用破坏:docs.microsoft.com/en-us/cpp/build/…。 RFLAGS 和 XMM0..5(以及带有 AVX 的 YMM0..15)也是如此,如果您尝试在两个任意指令之间异步执行此操作,而不是在代码期望这些 regs 被破坏的地方挂钩函数调用。您需要保存所有内容,例如中断处理程序,但 DLL 函数必须保存/恢复的注册表除外。 (中断处理程序通过 iret 恢复 RFLAGS,但您需要 pushf / popf 手动保存它。) -
@PeterCordes 使进程崩溃的
ret在返回后位于主线程内。另外,你说得对,我忘了保留r10,但是在这种情况下,r10在 shellcode 前后始终为零,所以我认为这不是原因。我将尝试保留RFLAGS寄存器。 -
@PeterCordes 保存 rflags 寄存器成功了,谢谢!
标签: windows assembly x86-64 code-injection shellcode