#pragma warning(push)
#pragma warning(disable : 4409)
DWORD64 __cdecl X64Call(DWORD64 func, int argC, ...)
{
if (!g_isWow64)
return 0;
va_list args;//VA_LIST 是在C语言中解决变参问题的一组宏,所在头文件:#include ,用于获取不确定个数的参数。
va_start(args, argC);//VA_START宏,获取可变参数列表的第一个参数的地址(ap是类型为va_list的指针,v是可变参数最左边的参数):
reg64 _rcx = { (argC > 0) ? argC--, va_arg(args, DWORD64) : 0 };
reg64 _rdx = { (argC > 0) ? argC--, va_arg(args, DWORD64) : 0 };//VA_ARG宏,获取可变参数的当前参数,返回指定类型并将指针指向下一参数(t参数描述了当前参数的类型):
reg64 _r8 = { (argC > 0) ? argC--, va_arg(args, DWORD64) : 0 };
reg64 _r9 = { (argC > 0) ? argC--, va_arg(args, DWORD64) : 0 };
reg64 _rax = { 0 };
reg64 restArgs = { (DWORD64)&va_arg(args, DWORD64) };//剩余成员用堆栈传递//conversion to QWORD for easier use in inline assembly
reg64 _argC = { (DWORD64)argC };
DWORD back_esp = 0;
WORD back_fs = 0;
__asm
{
;//reset FS segment, to properly handle RFG
mov back_fs, fs
mov eax, 0x2B
mov fs, ax
;//keep original esp in back_esp variable
mov back_esp, esp
;//align esp to 0x10, without aligned stack some syscalls may return errors !
;//(actually, for syscalls it is sufficient to align to 8, but SSE opcodes
;//requires 0x10 alignment), it will be further adjusted according to the
;//number of arguments above 4
;//对齐
and esp, 0xFFFFFFF0
X64_Start();
;//below code is compiled as x86 inline asm, but it is executed as x64 code
;//that's why it need sometimes REX_W() macro, right column contains detailed
;//transcription how it will be interpreted by CPU
;//fill first four arguments
REX_W mov ecx, _rcx.dw[0] ;//mov rcx, qword ptr [_rcx]
REX_W mov edx, _rdx.dw[0] ;//mov rdx, qword ptr [_rdx]
push _r8.v ;//push qword ptr [_r8]
X64_Pop(_R8); ;//pop r8
push _r9.v ;//push qword ptr [_r9]
X64_Pop(_R9); ;//pop r9
;// REX_W mov eax, _argC.dw[0] ;//mov rax, qword ptr [_argC]
;// ;//final stack adjustment, according to the ;// ;//number of arguments above 4 ;// test al, 1 ;//test al, 1
jnz _no_adjust ;//jnz _no_adjust
sub esp, 8 ;//sub rsp, 8 对齐对齐对齐!假如有单个参数 需要对齐!!!
_no_adjust: ;// ;// push edi ;//push rdi
REX_W mov edi, restArgs.dw[0] ;//mov rdi, qword ptr [restArgs]
;// ;//put rest of arguments on the stack ;// REX_W test eax, eax ;//test rax, rax
jz _ls_e ;//je _ls_e
REX_W ea edi, dword ptr [edi + 8*eax - 8] ;//lea rdi, [rdi + rax*8 - 8]取最后一个的地址
;//_ls: ;// REX_W test eax, eax ;//test rax, rax 判断是否为0
jz _ls_e ;//je _ls_e
push dword ptr [edi] ;//push qword ptr [rdi]
REX_W sub edi, 8 ;//sub rdi, 8
REX_W sub eax, 1 ;//sub rax, 1
jmp _ls ;//jmp _ls
_ls_e: ;// ;// ;//create stack space for spilling registers ;// REX_W sub esp, 0x20 ;//sub rsp, 20h
;// call func ;//call qword ptr [func]
;// ;//cleanup stack ;// REX_W mov ecx, _argC.dw[0] ;//mov rcx, qword ptr [_argC]
REX_W lea esp, dword ptr [esp + 8*ecx + 0x20] ;//lea rsp, [rsp + rcx*8 + 20h]
;// pop edi ;//pop rdi
;//
//set return value ;// REX_W mov _rax.dw[0], eax ;//mov qword ptr [_rax], rax
X64_End();
mov ax, ds
mov ss, ax
mov esp, back_esp
;//restore FS segment
mov ax, back_fs
mov fs, ax
}
return _rax.v;
}