机器代码中的 sizeof() 等价物是什么?
What is the sizeof() equivalent in machine code?
我目前正在对一款游戏进行逆向工程,我遇到了一个问题,我需要调用 GetRawInputData
,它需要 pcbSize
作为其参数之一。
通常在 C 中我会写 sizeof(pData)
但我不知道如何用机器代码来处理这个问题。
sizeof
纯粹是 C 类型系统的构造,并且在编译时完全解析为普通数字;机器代码中没有这样的东西,您可能只会在 push
或 mov
中找到一个与 pData
.
的大小相对应的立即值
比如我们的一个程序中,序列
RAWINPUT raw;
UINT dwSize = sizeof(raw);
GetRawInputData((HRAWINPUT)lparam, RID_INPUT, &raw, &dwSize, sizeof(RAWINPUTHEADER));
被 gcc 4.8 翻译为
0x005f351d <+125>: lea eax,[ebp-0x48] // eax = &dwSize
0x005f3520 <+128>: mov DWORD PTR [esp+0xc],eax // pcbSize = eax = &dwSize
0x005f3524 <+132>: lea eax,[ebp-0x38] // eax = &raw
0x005f3527 <+135>: mov DWORD PTR [ebp-0x48],0x28 // dwSize = sizeof(raw) i.e. 38
0x005f352e <+142>: mov DWORD PTR [esp+0x10],0x10 // cbSizeHeader = sizeof(RAWINPUTHEADER) i.e. 16
0x005f3536 <+150>: mov DWORD PTR [esp+0x8],eax // pdata = eax = &raw
0x005f353a <+154>: mov DWORD PTR [esp+0x4],0x10000003 // uiCommand = RID_INPUT
0x005f3542 <+162>: mov DWORD PTR [esp],ecx // hRawInput = lparam
0x005f3545 <+165>: call DWORD PTR ds:0x20967fc // call GetRawInputData
没有任何等价物。 sizeof 是编译时构造,它在汇编中被翻译成一个数字。 IE。 sizeof(pcbSize) 将类似于 48 或 1024 等等。如果需要,您必须手动计算大小或在反汇编代码中找到它。
在 assembly 源代码中,您可以让 assembler 计算 assemble-时间常数,例如
msg: db "hello world", 10 ; 10 = ASCII newline
msglen equ $-msg
然后当你写 mov edx, msglen
时,它 assembles 到 mov edx, imm32
并替换为常量。请参阅 How does $ work in NASM, exactly? 了解一些示例。
但是在最后的机器码中,assemble-time constants都变成了immediates或者data constants。 (e.g. ptr_and_length: dq msg, msglen
in the data or rodata 部分 assembles 变成一个地址和一个 qword 整数,它就在目标文件中,不是在运行时从任何东西计算出来的。)
(Assemble-时间常量也可以用作宏或其他指令中的重复计数。(例如
times power imul eax, ecx
assemble 到那么多 imul
指令的块。
power
是用 EQU 定义的整型常量。或 NASM %rep n
/ ... / %endrep
)
或用在 assemble 时间表达式中,因此大小本身并不实际存在于目标文件中,只是基于它的一些计算结果。 (例如 mov edx, msglen+2
或 mov ecx, arrbytes/4
,后者可能作为按双字而不是字节计数的循环的边界)。
我目前正在对一款游戏进行逆向工程,我遇到了一个问题,我需要调用 GetRawInputData
,它需要 pcbSize
作为其参数之一。
通常在 C 中我会写 sizeof(pData)
但我不知道如何用机器代码来处理这个问题。
sizeof
纯粹是 C 类型系统的构造,并且在编译时完全解析为普通数字;机器代码中没有这样的东西,您可能只会在 push
或 mov
中找到一个与 pData
.
比如我们的一个程序中,序列
RAWINPUT raw;
UINT dwSize = sizeof(raw);
GetRawInputData((HRAWINPUT)lparam, RID_INPUT, &raw, &dwSize, sizeof(RAWINPUTHEADER));
被 gcc 4.8 翻译为
0x005f351d <+125>: lea eax,[ebp-0x48] // eax = &dwSize
0x005f3520 <+128>: mov DWORD PTR [esp+0xc],eax // pcbSize = eax = &dwSize
0x005f3524 <+132>: lea eax,[ebp-0x38] // eax = &raw
0x005f3527 <+135>: mov DWORD PTR [ebp-0x48],0x28 // dwSize = sizeof(raw) i.e. 38
0x005f352e <+142>: mov DWORD PTR [esp+0x10],0x10 // cbSizeHeader = sizeof(RAWINPUTHEADER) i.e. 16
0x005f3536 <+150>: mov DWORD PTR [esp+0x8],eax // pdata = eax = &raw
0x005f353a <+154>: mov DWORD PTR [esp+0x4],0x10000003 // uiCommand = RID_INPUT
0x005f3542 <+162>: mov DWORD PTR [esp],ecx // hRawInput = lparam
0x005f3545 <+165>: call DWORD PTR ds:0x20967fc // call GetRawInputData
没有任何等价物。 sizeof 是编译时构造,它在汇编中被翻译成一个数字。 IE。 sizeof(pcbSize) 将类似于 48 或 1024 等等。如果需要,您必须手动计算大小或在反汇编代码中找到它。
在 assembly 源代码中,您可以让 assembler 计算 assemble-时间常数,例如
msg: db "hello world", 10 ; 10 = ASCII newline
msglen equ $-msg
然后当你写 mov edx, msglen
时,它 assembles 到 mov edx, imm32
并替换为常量。请参阅 How does $ work in NASM, exactly? 了解一些示例。
但是在最后的机器码中,assemble-time constants都变成了immediates或者data constants。 (e.g. ptr_and_length: dq msg, msglen
in the data or rodata 部分 assembles 变成一个地址和一个 qword 整数,它就在目标文件中,不是在运行时从任何东西计算出来的。)
(Assemble-时间常量也可以用作宏或其他指令中的重复计数。(例如
times power imul eax, ecx
assemble 到那么多 imul
指令的块。
power
是用 EQU 定义的整型常量。或 NASM %rep n
/ ... / %endrep
)
或用在 assemble 时间表达式中,因此大小本身并不实际存在于目标文件中,只是基于它的一些计算结果。 (例如 mov edx, msglen+2
或 mov ecx, arrbytes/4
,后者可能作为按双字而不是字节计数的循环的边界)。