检查程序是否通过另一个程序运行

时间:2015-01-09 07:37:20

标签: c++ windows

所以我的问题如下:我有一个程序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添加命令行参数,因为它受到严重保护......

1 个答案:

答案 0 :(得分:1)

标准Windows API不允许您直接查找进程的父级。但希望根据this other SO question,您还有其他2个解决方案(前提是父进程尚未终止......):

  • 使用本机API。函数NtQueryInformationProcess可以直接为您提供信息。但要注意:

    • 您没有导入库,因此您必须明确地使用LoadLibraryGetProcAddress
    • 父进程ID是Microsoft SDK
    • 中引用为Reserved3的未记录字段
    • Microsoft警告此功能不是公共API的一部分,可能会在以后的版本中更改。

    如果您仍想使用它,这里是获取父进程可执行文件名的完整示例(您必须与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创建所有正在运行的进程的快照,您可以使用Process32FirstProcess32Next。希望您获得(记录的)PROCESSENTRY32结构,其中包含可执行文件名,进程ID和进程父ID。它有大量文档记录,您可以在StackOverflow上轻松找到许多示例(参见参考问题)