C++ 重新定义的Winapi结构与其原始状态的连接?
我的目标是理解WinApi结构重定义。但我在任何地方都找不到任何文档、参考或手册。请解释一下,在下面的示例中,如何将struct重新定义为其原始形式。编译器是否理解重新定义的结构的名称并与PEB_LDR_数据结构建立关系 以下是原始的PEB_LDR_数据结构:C++ 重新定义的Winapi结构与其原始状态的连接?,c++,winapi,struct,C++,Winapi,Struct,我的目标是理解WinApi结构重定义。但我在任何地方都找不到任何文档、参考或手册。请解释一下,在下面的示例中,如何将struct重新定义为其原始形式。编译器是否理解重新定义的结构的名称并与PEB_LDR_数据结构建立关系 以下是原始的PEB_LDR_数据结构: typedef struct _PEB_LDR_DATA { BYTE Reserved1[8]; PVOID Reserved2[3]; LIST_ENTRY InMemoryOrderModuleLi
typedef struct _PEB_LDR_DATA {
BYTE Reserved1[8];
PVOID Reserved2[3];
LIST_ENTRY InMemoryOrderModuleList;
} PEB_LDR_DATA, *PPEB_LDR_DATA;
这是重新定义的PEB_LDR_数据结构MY_PEB_LDR_数据:
typedef struct _MY_PEB_LDR_DATA {
ULONG Length;
BOOL Initialized;
PVOID SsHandle;
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
} MY_PEB_LDR_DATA, * PMY_PEB_LDR_DATA;
请向我解释一下,如何将struct重新定义为其原始形式
在内存中,两个结构具有相同的布局,假设它们对各自的字段使用相同的数据对齐设置
PEB_LDR_DATA::Reserved1
是一个包含8个字节的数组ULONG
和BOOL
各为4个字节,因此MY\u PEB\u LDR\u DATA::Length
的偏移量与PEB\u LDR\u DATA::Reserved1[0]
相同,MY\u PEB\u LDR\u DATA::Initialized
的偏移量与PEB\u LDR\u DATA::Reserved1[4]
相同
PEB_LDR_DATA::Reserved2
是一个包含3个void*
指针的数组。MY\u PEB\u LDR\u DATA::SsHandle
的偏移量与PEB\u LDR\u DATA::Reserved2[0]
相同。是一个包含2个LIST\u ENTRY*
指针的结构,因此MY\u PEB\u LDR\u DATA::InLoadOrderModuleList::Flink的偏移量与PEB\u LDR\u DATA::Reserved2[1]
相同,MY\u PEB\u LDR\u DATA::InLoadOrderModuleList::Blink
的偏移量与PEB\u LDR\u DATA::Reserved2[2]相同
因此,将MY_PEB_LDR_DATA::InMemoryOrderModuleList
的偏移量保留为与PEB_LDR_DATA::InMemoryOrderModuleList
相同的偏移量
对于其余的PEB_LDR_数据
和MY_PEB_LDR_数据
字段,依此类推
编译器是否理解重新定义的结构的名称并与PEB_LDR_数据结构建立关系
不。就编译器而言,它们是独立的、不同的类型,它们之间根本没有关系。但是,如果它们设置正确,然后给出一个指向包含PEB\u LDR\u数据的内存块的指针
,则您可以键入该指针并访问数据,就像内存包含MY\u PEB\u LDR\u数据
一样。这是类型转换指针的强度(和危险)
请向我解释一下,如何将struct重新定义为其原始形式
在内存中,两个结构具有相同的布局,假设它们对各自的字段使用相同的数据对齐设置
PEB_LDR_DATA::Reserved1
是一个包含8个字节的数组ULONG
和BOOL
各为4个字节,因此MY\u PEB\u LDR\u DATA::Length
的偏移量与PEB\u LDR\u DATA::Reserved1[0]
相同,MY\u PEB\u LDR\u DATA::Initialized
的偏移量与PEB\u LDR\u DATA::Reserved1[4]
相同
PEB_LDR_DATA::Reserved2
是一个包含3个void*
指针的数组。MY\u PEB\u LDR\u DATA::SsHandle
的偏移量与PEB\u LDR\u DATA::Reserved2[0]
相同。是一个包含2个LIST\u ENTRY*
指针的结构,因此MY\u PEB\u LDR\u DATA::InLoadOrderModuleList::Flink的偏移量与PEB\u LDR\u DATA::Reserved2[1]
相同,MY\u PEB\u LDR\u DATA::InLoadOrderModuleList::Blink
的偏移量与PEB\u LDR\u DATA::Reserved2[2]相同
因此,将MY_PEB_LDR_DATA::InMemoryOrderModuleList
的偏移量保留为与PEB_LDR_DATA::InMemoryOrderModuleList
相同的偏移量
对于其余的PEB_LDR_数据
和MY_PEB_LDR_数据
字段,依此类推
编译器是否理解重新定义的结构的名称并与PEB_LDR_数据结构建立关系
不。就编译器而言,它们是独立的、不同的类型,它们之间根本没有关系。但是,如果它们设置正确,然后给出一个指向包含PEB\u LDR\u数据的内存块的指针
,则您可以键入该指针并访问数据,就像内存包含MY\u PEB\u LDR\u数据
一样。这就是类型转换指针的强度(和危险性)。在运行时,结构中只有字节和字节偏移量。假设有8个字节的指针,两者正好匹配。可能最简单的方法是创建这两个结构,并在调试程序中检查它们,而不使用任何原始形式。在c/c++中,您可以定义PEB\u LDR\u数据(来自winternl.h)和MY\u PEB\u LDR\u数据(来自pdb的截断\u PEB\u LDR\u数据
)。从编译器的角度来看,这是不同的结构。但是InMemoryOrderModuleList
在运行时两者(在32位和64位代码中)的偏移量相同,结构中只有字节和字节偏移量。假设有8个字节的指针,两者正好匹配。可能最简单的方法是创建这两个结构,并在调试程序中检查它们,而不使用任何原始形式。在c/c++中,您可以定义PEB\u LDR\u数据(来自winternl.h)和MY\u PEB\u LDR\u数据(来自pdb的截断\u PEB\u LDR\u数据
)。从编译器的角度来看,这是不同的结构。但是在memoryordermodulelist
中两者的偏移量相同(在bot 32和64位代码中),“但是,如果它们设置正确,然后给定一个指向包含PEB\u LDR\u数据的内存块的指针,您可以键入cast该指针并访问数据,就像内存包含MY\u PEB\u LDR\u数据一样。”-这在实践中通常是正确的,尽管这个演员的行为是严格未定义的。“在内存中,两个结构都有相同的布局,假设它们各自的字段都使用相同的数据对齐设置。”-您可以让编译器使用static\u assert
和offsetof
表达式强制执行这些假设。谢谢