C++ 强制转换内存位置以获取字符串

C++ 强制转换内存位置以获取字符串,c++,winapi,C++,Winapi,我正在尝试从Win32应用程序访问变量,该应用程序具有基于源代码的已知变量: Foo foo; // Class foo foo.mystring = "All your base are belong to us"; // where this is defined as: 'string mystring' 现在,我试图用拆卸器拆卸PE,我发现了这个 .rdata:00446074 aAllYourBaseAre db 'all your base are belong to us',0

我正在尝试从Win32应用程序访问变量,该应用程序具有基于源代码的已知变量:

Foo foo; // Class foo
foo.mystring = "All your base are belong to us"; // where this is defined as: 'string mystring'
现在,我试图用拆卸器拆卸PE,我发现了这个

.rdata:00446074 aAllYourBaseAre db 'all your base are belong to us',0
现在,我有了另一个win32进程,该进程获取前win32应用程序的映像基址,该应用程序具有我需要的类变量

我使用以下代码获取进程地址:

HMODULE parent = ::GetModuleHandle(NULL);
if (parent) {
   const BYTE* imageBase = reinterpret_cast<const BYTE*> ( parent );
   const char* strMemberValue = *reinterpret_cast<const char**>((unsigned char*)imageBase + 0x00446074); 
            std::cout << "Value=" << strMemberValue;
}

但是我仍然不确定这一点。

好的,首先要注意的是:当使用外部进程内存进行解编译时,如果重新编译其他可执行文件,您可能再也找不到任何数据了。链接器可以自由地将数据和代码放在任何地方并重新排列。要重新查找某些值或函数,必须搜索二进制模式

接下来要注意的是:您实际上有一个成员变量。这意味着每个对象的it内容实际上可能不同。您当前正在搜索默认分配给它的字符串(不是直接分配给成员,而是在std::string类中的某个位置)

最后但并非最不重要的一点:当您试图访问外部进程的内容时,您必须使用。考虑使用共享内存来进行进程间通信。命名管道也可以

访问真实值的最简单方法是将
Foo
对象(例如
&Foo
的地址)传递到读取过程,并将
Foo
类放在两个项目都可以访问的公共项目库中。
然后将整个对象读入地址空间(请参见上文的
ReadProcessMemory
),并像访问任何其他成员一样访问该成员。但请注意,您实际上处理的是真实对象的副本。共享内存可以使两个进程都可以访问单个对象()

好的,首先要注意的是:当使用外部进程内存卸载时,如果重新编译其他可执行文件,则可能再也找不到任何数据。链接器可以自由地将数据和代码放在任何地方并重新排列。要重新查找某些值或函数,必须搜索二进制模式

接下来要注意的是:您实际上有一个成员变量。这意味着每个对象的it内容实际上可能不同。您当前正在搜索默认分配给它的字符串(不是直接分配给成员,而是在std::string类中的某个位置)

最后但并非最不重要的一点:当您试图访问外部进程的内容时,您必须使用。考虑使用共享内存来进行进程间通信。命名管道也可以

访问真实值的最简单方法是将
Foo
对象(例如
&Foo
的地址)传递到读取过程,并将
Foo
类放在两个项目都可以访问的公共项目库中。
然后将整个对象读入地址空间(请参见上文的
ReadProcessMemory
),并像访问任何其他成员一样访问该成员。但请注意,您实际上处理的是真实对象的副本。共享内存可以使两个进程都可以访问单个对象()

您通过一个间接寻址以错误的方式访问进程内存
.rdata:00446074
是字符串所在的地址,而不是指向实际位置的指针。您应该像这样访问它:

HMODULE parent = ::GetModuleHandle(NULL);
if (parent) {
   const BYTE* imageBase = reinterpret_cast<const BYTE*> ( parent );
   const char* strMemberValue = (const char *)imageBase + 0x00446074; 
   std::cout << "Value=" << strMemberValue;
}
hmoduleparent=::GetModuleHandle(NULL);
如果(家长){
常量字节*imageBase=重新解释强制转换(父级);
常量字符*strMemberValue=(常量字符*)imageBase+0x00446074;

std::cout您通过一个间接寻址以错误的方式访问进程内存。
。rdata:00446074
是字符串所在的地址,而不是指向实际位置的指针。您应该像以下方式访问它:

HMODULE parent = ::GetModuleHandle(NULL);
if (parent) {
   const BYTE* imageBase = reinterpret_cast<const BYTE*> ( parent );
   const char* strMemberValue = (const char *)imageBase + 0x00446074; 
   std::cout << "Value=" << strMemberValue;
}
hmoduleparent=::GetModuleHandle(NULL);
如果(家长){
常量字节*imageBase=重新解释强制转换(父级);
常量字符*strMemberValue=(常量字符*)imageBase+0x00446074;

STD::哦,天啊,你在做什么?我正在用一种明智的方式来做这件事。基本上,你正在尝试做链接器所做的事情。你可以使用C++的动态链接;你可能想查找如何进行DLL调用。这是因为你需要加载DLL才能得到精确的地址。(通常为高位地址+对象文件中指定的地址)哦,天哪,地址是不可用的。哦,你在做什么?我正在用一种明智的方式来做这件事。基本上,你正在尝试做链接器所做的事情。你可以使用C++的动态链接;你可能想查找如何进行DLL调用。这是因为你需要加载DLL才能得到精确的地址。(通常为高位地址+对象文件中指定的地址)。按原样,地址不可用。好的,我没有领会我的意思。我无法重新编译目标Win32应用程序,因为它已经在生产中。但是我需要访问该可执行文件上的一些变量。我这里的代码只是概念的证明。是的,在这种情况下,您实际上进行了反向工程。但上述方法适用。复制mem如果您创建了一个外部应用程序(DLL注入可以克服这个问题,那么您可以直接访问外部地址空间的内容)并使用二进制模式再次查找某些代码段。还请注意,您可以定义一个与外部类具有相同布局的类并将其强制转换。使用
char[]
跳过未知内容。这正是我想要做的,将内存位置强制转换到我需要的类中。但是很难获得要强制转换的偏移量。顺便说一句,我的情况是“DLL注入”,也就是说,我需要访问内存的应用程序实际加载了DLLI多次编写的Ansare:1.如果是真实结构,则创建一个POD结构;如果是多态类,则创建一个类(在这种情况下,您必须定义CLA