注意这些 C++ 局部变量指令长度是红框中的 8 个字节
48 c7 45 f8 00 00 00 00
...
但是,绿框中的指令长度为 11 字节
48 c7 85 78 ff ff ff 00 00 00 00
...
https://godbolt.org/z/bTsxx63rT
我正在编写一些需要修补 API 地址的 shellcode,但注意到错误,因为局部变量指令长度从 8 字节跳到了 11 字节。不管怎样,通过反复试验,为了强制所有指令都是 11 字节,我添加了一个本地数组
char enforce_mov_long_form[128];
避免访问
[rbp-0x8]
到 [rbp-0x80]
范围内的当地人
DWORD WINAPI shellcode_start(void)
{
char enforce_mov_long_form[128];
// ------------------------------------------------------------
QWORD start_shellcode = 0xAAAAAAAAAAAAAAAA;
DWORD sizeofshellcode = 0xAAAAAAAA;
QWORD start_shellcode_injector = 0xAAAAAAAAAAAAAAAA;
DWORD pid_injector = 0xAAAAAAAA;
QWORD WinExec = 0xAAAAAAAAAAAAAAAA;
QWORD Sleep = 0xAAAAAAAAAAAAAAAA;
QWORD CreateToolhelp32Snapshot = 0xAAAAAAAAAAAAAAAA;
QWORD Process32First = 0xAAAAAAAAAAAAAAAA;
QWORD Process32Next = 0xAAAAAAAAAAAAAAAA;
QWORD CloseHandle = 0xAAAAAAAAAAAAAAAA;
QWORD OpenProcess = 0xAAAAAAAAAAAAAAAA;
QWORD VirtualAllocEx = 0xAAAAAAAAAAAAAAAA;
QWORD VirtualFreeEx = 0xAAAAAAAAAAAAAAAA;
QWORD WriteProcessMemory = 0xAAAAAAAAAAAAAAAA;
QWORD CreateRemoteThread = 0xAAAAAAAAAAAAAAAA;
QWORD CompareStringA = 0xAAAAAAAAAAAAAAAA;
QWORD GetCurrentProcessId = 0xAAAAAAAAAAAAAAAA;
// ------------------------------------------------------------
为什么局部变量的指令长度突然从 8 字节转变为 11 字节?
通过将局部变量限制在
[rbp-0x8]
到 [rbp-0x80]
之间是否可以获得任何微观优化?
推动评论回复:
x86-64 寻址模式将位移编码为有符号 8 位(1 字节)或有符号 32 位(4 字节)值,在任何一种情况下都会被符号扩展为 64 位。由于有符号 8 位整数的范围是
[-128..127]
或 [-0x80..0x7f]
,因此超出此范围的位移必须改用 32 位形式,从而使指令长三个字节。
有关如何编码寻址模式的更多信息,请参阅 https://wiki.osdev.org/X86-64_Instruction_Encoding 和 引用内存位置的内容。 (x86 寻址模式).