我什至没有提出问题我认为这是某种确认,我正确理解了这个主题。
我正在做一些逆向工程研究,这就是我所拥有的。
假设我们有结构/类,如下所示:
struct {
char str[n]
int x
float a
}
我们正在查看的进程内存中有这些结构的数组。
所以,我拥有的是指向结构指针数组的指针。
如果我错了,现在请你纠正我。要读取此数组第一个元素的 x 值(实际结构,而不是指针),我必须遵循以下步骤:
- 读取指针指向的值(4字节)。
- 没有任何偏移量读取先前读取值指向的值,也是 4 个字节(这将引导我到结构开始的地址)
- 现在我必须添加等于 n 的偏移量。并从第2步的地址中读取值(step2result+n+1)。
我说的对吗?我会得到第一个结构包含的实际 X 吗?要从第二个中获取 X 值,我只需要在步骤 2 中添加偏移量(+4 字节)?
我认为我这样做是对的,但实际上我无法从指针访问结构。我会说指向数组的指针是 100% 正确的。
感谢阅读,期待答案。如果您需要更多信息,请提出要求。
附注不要为了教育目的而破解任何东西或任何东西
添加:
好的,我试图简化它只会让解释和理解变得更加困难。现在我要尝试修复它。
一种结构描述了游戏中的 NPC 参数。整个结构的大小为 0x1200。前 16 个字节只是 ID 信息,然后在这个信息变成 64 个字节的字符串之后,就是名称。然后是 X/Y/Z 的坐标。这些之后的一切都不重要。
并不难找,下面是截图:
/
所以我可以通过在该结构开始的地址上加上或减去 0x1200 来找到其他结构。
我搜索了结构开始的地址并找到了指向它的指针。
然后我扫描了对找到的指针的访问并得到了类似的东西:
mov [eax+edx*4+00320], ecx
然后我搜索了eax
的值,找到了指向eax
的指针
这就是为什么我认为这是指针数组。
希望我只是更具体地解释了这一点。
最佳答案
你的问题实际上充满了地雷,这将以不幸的方式证明为什么 assembly 的准确性如此重要。
So, what I have is ...
你展示了语法错误的匿名结构,突然间你有了一些指针?它不是那样工作的。您有匿名结构和一些语法错误,仅此而已。
现在我真的觉得可以停止回答了,因为如果没有数据的实际定义,你的问题的其余部分就毫无意义。但是假设您有这样的想法:
struct STRUCT_A {
char str[17];
int x;
float a;
};
STRUCT_A testA[3]{
{"a1", 1111, 1.111},
{"a2", 2222, 2.222},
{"a3", 3333, 3.333}
};
int foo(unsigned index) {
return testA[index].x;
}
所以,我这里有数组 testA
。数组不仅仅是指针,它在编译期间在 C++ 中多了一点点,尽管它在使用时很乐意“退化”成指针,但它并不完全相同。
当我将使用 testA
作为指针时,它不指向任何进一步的指针,它直接指向数据。
因此您在 OP 中没有一层,而是两层额外的间接寻址。要读取第一个元素的 x
,您只需执行 mov eax,[testA + 20]
。未加载指针(示例来自 x86 32b 目标,在其他目标上 +20
可能不同)。
你会不会:
STRUCT_A* testA_alias = testA;
// now this ^^ alias is no more array, it's just pointer
// (array silently decays into pointer during compilation, when asked to)
STRUCT_A** testA_indirect = &testA_alias;
然后获取第二个元素的x
:
mov eax,[testA_indirect] ; eax = &testA_alias
mov eax,[eax] ; eax = testA (or &testA .. not sure how to write it, "address of data")
mov eax,[eax + 28*1 + 20] ; eax = testA[1].x
我设法创建了两个间接级别(实际上我不得不在这部分编辑答案,因为我错误地从 C++ 读取程序集,不完整的 Intel 语法让我感到困惑)。
我仍然不确定您从哪里获得所有这些指示以及为什么?它不是 Java,它是 C++,您只需将数据直接存储在内存中即可。如您所见,我不得不付出相当多的努力来获得两个间接级别。
现在您可能想知道为什么 x
位于 +20
而不是 +17
。因为填充,C++ 会根据结构成员的类型对齐结构成员,int
喜欢对齐,所以它就是。
这也应该解释 28
,它是该结构的大小。
在你的问题中你还有:
step2result+n+1
+1
从何而来?也许你对此感到困惑:
char str[]{"abc"}; // str[4]
但那是因为 "abc"
就像 db 'a', 'b', 'c', 0
= 定义了四个字节。当你只定义它像 a, b, c 三个字节时,数组将是 3 个字节:
char str2[]{'a', 'b', 'c'}; // str2[3]
当您通过 [n]
定义 char
数组时,不涉及 +1,该数组恰好有 n
个字符。如果将 C 字符串文字放入其中,它们最多可能有 (n-1) 个字符长,因为第 n 个字节将被零终止符占用。
您可以检查源代码在编译后的样子here .
这可能会以最好的方式回答您的问题。
您可能需要特别注意内存内容定义,我在 testA
数组定义的初始行添加了一些注释:
testA:
.string "a1" ; three bytes 'a', '1', 0 defined
.zero 14 ; remaining 14 zeroed to have char[17]
.zero 3 ; padding for "int x"
.long 1111 ; int x
.long 1066284351 ; float a
.string "a2" ; char[17] of second element
...
关于c++ - 指向结构指针数组的指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41732727/