所以我的问题如下:我有一个程序Main.exe(开始游戏),我有一个dll连接到它所以我可以加载一些功能。我有另一个名为StartGame.exe(启动器+ autoupdater)的程序,现在的问题是,如何在客户端按下START时确保只从StartGame.exe运行Main.exe的功能? 我不能修改Main.exe,也不能修改StartGame.exe ......我做了一些简单的检查,如下所示:
if(FindWindow(NULL,"LiveMU") == NULL) //LiveMU is the name of window StartGame.exe
{
MessageBoxA(0,"English: Please use the Launcher! \nRomanian: Va rugam sa folositi Launcher-ul!", TitleMsgBox,MB_ICONERROR);
ExitProcess(0);
}
问题是,如果他们打开startgame.exe并将其留在托盘中,他们可以毫无问题地加载Main.exe。主要的问题是,如果我无法以某种方式保护Main.exe在没有启动器的情况下启动,客户/玩家使用一个作弊程序加载Main.exe(注入它或其他东西,我真的不知道它只是消失了,我可以'找到它)
LE:我无法向StartGame.exe添加命令行参数,因为它受到严重保护......
答案 0 :(得分:1)
标准Windows API不允许您直接查找进程的父级。但希望根据this other SO question,您还有其他2个解决方案(前提是父进程尚未终止......):
使用本机API。函数NtQueryInformationProcess
可以直接为您提供信息。但要注意:
LoadLibrary
和GetProcAddress
如果您仍想使用它,这里是获取父进程可执行文件名的完整示例(您必须与psapi.lib
链接):
#include <windows.h>
#include <psapi.h>
#include <TCHAR.h>
typedef struct _PROCESS_BASIC_INFORMATION {
PVOID Reserved1;
PVOID PebBaseAddress;
PVOID Reserved2[2];
ULONG_PTR UniqueProcessId;
PVOID Reserved3;
} PROCESS_BASIC_INFORMATION;
DWORD getParentProcessId(HANDLE process) {
LONG (WINAPI *NtQueryInformationProcess)(HANDLE ProcessHandle,
ULONG ProcessInformationClass, PVOID ProcessInformation,
ULONG ProcessInformationLength, PULONG ReturnLength) = NULL;
HMODULE ntDll = ::LoadLibrary(_T("NTDLL.DLL"));
FARPROC ntQueryInformationProcess = ::GetProcAddress(ntDll,
"NtQueryInformationProcess");
NtQueryInformationProcess =
(LONG (WINAPI *)(HANDLE,ULONG,PVOID,ULONG,PULONG))ntQueryInformationProcess;
if (NtQueryInformationProcess == NULL) {
::FreeLibrary(ntDll);
return -1;
}
PROCESS_BASIC_INFORMATION pi;
ULONG piLen;
NtQueryInformationProcess(process, 0, &pi, sizeof(pi), & piLen);
DWORD ppid = (DWORD) pi.Reserved3;
::FreeLibrary(ntDll);
return ppid;
}
int main() {
DWORD cr;
HANDLE proc = ::GetCurrentProcess();
DWORD ppid = getParentProcessId(proc);
HANDLE pproc = ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, ppid);
TCHAR pFile[MAX_PATH];
cr = ::GetModuleFileNameEx(pproc, NULL, pFile, sizeof(pFile));
::CloseHandle(pproc);
if (cr == 0) {
LPTSTR pBuff;
DWORD error = ::GetLastError();
::FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, error, 0,
(LPWSTR) &pBuff, 1, NULL);
::MessageBox(NULL, pBuff, _T("Error"), MB_OK | MB_ICONERROR);
}
::MessageBox(NULL, pFile, _T("Parent process"), MB_OK);
return 0;
}
如果您不喜欢使用记录不良的本机API函数,可以使用toolhelp32库:CreateToolhelp32Snapshot
创建所有正在运行的进程的快照,您可以使用Process32First
和Process32Next
。希望您获得(记录的)PROCESSENTRY32
结构,其中包含可执行文件名,进程ID和进程父ID。它有大量文档记录,您可以在StackOverflow上轻松找到许多示例(参见参考问题)