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

Check if program is runned trough another one

本文关键字:程序 运行 另一个 是否 检查程序      更新时间:2023-10-16

所以我的问题如下:我有一个程序Main.exe(启动游戏),我有一个dll附加到它,所以我可以加载一些函数。我有另一个程序叫做 StartGame.exe(launcher+autoupdater),现在的问题是,当客户端按下 START 时.exe我如何创建一个函数来确保 Main.exe 仅从 StartGame 运行?我无法修改主.exe或启动游戏.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因为它受到严格保护...

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

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

    • 您没有导入库,因此必须显式调用 LoadLibraryGetProcAddress
    • 父进程 ID 是 SDK 中引用的未记录字段 Reserved3 Microsoft
    • 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 进行浏览。希望您能获得(记录的)包含可执行文件名称、进程 ID 和进程父 ID 的PROCESSENTRY32结构。它有大量的文档,你可以很容易地在StackOverflow上找到很多例子(见参考问题)