1

我编写了一个与进程挂钩的 dll 应用程序。它有效,但它只显示第一个字母。
我想得到整个字符串。该字符串可以从 2 个字母到 32 个字母不等。

//READING MEMORY
HANDLE ExeBaseAddress = GetModuleHandleA(0);

char uNameAddr = *(char*)((char*)ExeBaseAddress + 0x34F01C);
printf("%c \n", uNameAddr);

我还想了解这些部分:

 *(char*)((char*) //<-- what this is for.

如果使用多级指针可以使用它:

char multipoint = *(char*)((char*)ExeBaseAddress + 0x34F01C + 0x123 + 0x321 + 0x20);

更新

我想这里出了点问题:

if(uNameAddr == "omnicient")
    cout << "YOU ARE OMNI" << endl;

我使用了用户名omnicient,但没有 cout YOU ARE OMNI。我想我的比较是错误的?

4

2 回答 2

2

char uNameAddr 是一个字符,您需要一个字符列表(或 char*)

试试这个:

char* name= (char*)((char*)ExeBaseAddress + 0x34F01C);
printf("%s \n", name);

是什么*(char*)((char*)意思?

(char*)ExeBaseAddress将 ExeBaseAddress 视为指向某些 char 类型数据的指针

((char*)ExeBaseAddress + 0x34F01C)表示将 0x34F01C 添加到上述指针以将其偏移 0x34F01C 字符

(char*)((char*)ExeBaseAddress + 0x34F01C)意味着将此新地址视为指向某些字符的指针

*(char*)((char*)ExeBaseAddress + 0x34F01C)获取该位置第一个字符的内容

char uNameAddr = *(char*)((char*)ExeBaseAddress + 0x34F01C);表示将该字符放入名为 uNameAddr 的 char 大小的变量中。

所以基本上你有一个指针,你偏移它,然后取第一个字符并打印它。

在示例中,我注意了我如何不使用 firat 字符,并将其放在指针变量中。

然后我在 printf 中使用 %s 让它打印出所有按名称填充的字符。

于 2013-04-18T00:02:39.390 回答
2

%c显示chars(单个字符),%s显示以 NULL 结尾char*的 s(字符串):

HANDLE ExeBaseAddress = GetModuleHandleA(0);

char *uNameAddr = (char*) ExeBaseAddress + 0x34F01C;
printf("%s \n", uNameAddr);

请注意,我还整理了指针转换,但重要的是我摆脱了最终的取消引用(*在前面)并将其分配给char*(pointer) 而不是 a char

如果您的字符串不是以 NULL 结尾的(不太可能),您也需要使用%.*s并传递字符串的长度。

至于你问题的第二部分:

*(char*)((char*) ExeBaseAddress + 0x34F01C)

让我们分解一下。括号内(因此要评估的第一件事)是:

(char *) ExeBaseAddress + 0x34F01C

嗯,这是一个 C 转换(将 a 转换HANDLE为 a char*),然后是一个加法。换句话说,它说“将此事物视为指向某个内存的指针,然后向前看 0x34F01C 字节的内存”(char始终为 1 字节)。它现在是指向内存中新位置的指针。

然后我们退出括号并char*再次投射到......不必要的。它可能是:

*((char*) ExeBaseAddress + 0x34F01C)

最后我们取消引用(*前面的),上面写着“现在告诉我你指向的内存是什么”。但是在这种情况下,您不希望这样,因为您想要整个字符串,而不仅仅是第一个字母(在 内部printf,它会沿着您发送给它的内存循环,打印每个字符,直到找到 a 0,又名\0aka NULL)。

于 2013-04-18T00:06:12.393 回答