问题描述
所以在 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 运行后,由于 Access violation
指令指向错误的 ret
,我收到一个 rip
错误。
对我来说,这表明堆栈已损坏/不平衡,但是我仔细检查了shellcode前后的堆栈地址相同,我还检查了shellcode前后的所有通用寄存器,它们成功了恢复了。
解决方法
如果您在现有程序中的任意两条指令之间异步运行它,您需要确保保存/恢复ALL未调用保留的架构状态,例如中断处理程序会。
您错过了 r10
、rflags
和 XMM0..5
1。 https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-160
为了安全起见,您还需要确保保留完整的 32 字节的影子空间,以便 DLL 函数不会占用您保存的任何寄存器值。您说您的测试表明现在这不是问题,但未来的某些 Windows 版本可能具有 DLL 函数,可以利用该阴影空间。
脚注 1:还有 x87 st0..7 或 MM0..7。和 AVX YMM0..15,虽然 Windows API 函数不太可能通过运行 vzeroupper 或任何东西来影响它们的上半部分。或触摸 AVX-512 ZMM0..31 或 k0..7。因此,您可能无需执行 xsave
/ xrstor
,而只需保存 XMM0..5。