C++ 如何从注入过程重构数据结构';内存空间?

C++ 如何从注入过程重构数据结构';内存空间?,c++,memory,code-injection,C++,Memory,Code Injection,我有我制作的DLL。它被注入到另一个进程中。在另一个过程中, 我使用以下功能从其内存空间进行搜索: void MyDump(const void *m, unsigned int n) { const char *p = reinterpret_cast(m); for (unsigned int i = 0; i < n; ++i) { // Do something with p[i]... } }

我有我制作的DLL。它被注入到另一个进程中。在另一个过程中, 我使用以下功能从其内存空间进行搜索:


void MyDump(const void *m, unsigned int n)
{
        const char *p = reinterpret_cast(m);

        for (unsigned int i = 0; i < n; ++i) {
                // Do something with p[i]...
        }
}

void MyDump(常量void*m,无符号整数n)
{
const char*p=重新解释(m);
for(无符号整数i=0;i
现在我的问题。如果目标进程使用数据结构,比如


结构
{
无符号字符a;
无符号字符b;
无符号字符c;
};

在过程的记忆中,它总是以同样的方式呈现吗?我的意思是,如果S.a=2(总是跟在b=3,c=4后面),那么这个结构在进程的内存空间中是连续的一行吗


抵消
---------------------
0x0000 | 0x02 0x03 0x04

或者这些变量可以在不同的地方,比如


抵消
---------------------
0x0000 | 0x00 0x02 0x00
0x03fc | 0x00 0x03 0x04

如果是后者,如何从内存中的各个点重构数据结构

非常感谢,

nhaa123

成员顺序始终相同,结构将占用一个连续的内存块


根据编译器的不同,可以在成员之间添加填充,但如果使用相同的编译器和相同的设置重新编译程序,则填充仍然相同。如果添加了填充,而您不知道它,那么在运行时就不能可靠地检测到它——编译器的所有信息都丢失到那个时刻,而剩下的只是分析模式和猜测。

如果您的受害者是用C或C++编写的,而且所使用的数据类型确实是那么简单,然后,您将始终在内存中以单个字节块的形式找到它们

但只要你有C++类型,比如<代码> STD::String ,这个观察就不再成立了。首先,C++编译器的精确布局会不同,甚至不同版本的编译器也是不同的。std::string的字节可能不在连续数组中,但有时它们是连续的。如果他们一分为二,找到下半部分可能不会帮助你找到上半部分


不要把它放在更复杂的环境中,比如运行Java应用程序的JIT'ting JVM。你在记忆中遇到的类型非常复杂;人们可以写一本关于解码它们的书。

这取决于结构的对齐

如果你有这样的东西:

struct A
{
  int16_t a;
  char    b;
  int32_t c;
  char    d;
}
然后默认情况下,在32位平台上(我不知道64位的情况是否如此),c的偏移量是4,因为在b之后填充了一个字节,在d之后,在末尾填充了3个字节(如果我没记错的话)

如果结构具有指定的对齐方式,则会有所不同

现在我的问题。如果目标进程使用数据结构[…],它在进程内存中是否总是以相同的方式显示?我的意思是,如果S.a=2(总是跟在b=3,c=4后面),那么这个结构在进程的内存空间中是连续的一行吗

是的,但是它通常会被填充,以便以您可能不期望的方式对齐成员。因此,只需重新创建数据结构,以便通过代码注入与之交互

我强烈推荐使用或两个开源程序,专门用于从内存中重构数据结构并生成可用的C++代码!查看屏幕截图:


那么,应用程序本身如何找到拆分的std::string呢?我的意思是,信息必须在某个地方保存,对吗?应用程序本身将加载适当的C++运行时。该运行时不需要找到前半部分(程序逻辑将处理该部分,例如,将该部分放在堆栈上)。上半部分是由C++运行时创建的,因此同一运行时可以使用它来查找另一部分。对于您来说,主要的问题是,这是std::string的第二部分,它通常保存字符本身,因此是搜索特定字符串时唯一可以找到的部分。 Offset --------------------- 0x0000 | 0x02 0x03 0x04 Offset --------------------- 0x0000 | 0x00 0x02 0x00 0x03fc | 0x00 0x03 0x04
struct A
{
  int16_t a;
  char    b;
  int32_t c;
  char    d;
}