防止loader的一種技術 (2千字)

看雪資料發表於2001-08-19

透過檢查程式的父程式,可以防止loader方式的破解。一般情況下普通Win32程式的父程式是explorer.exe。如果不是,則很可能是被其它loader載入了。

在NT/2K下,可以利用native API獲得程式的父程式的PID,進而可獲得父程式的程式名。

#include <windows.h>
#include <psapi.h>
#include <iostream.h>

#define NTAPI              __stdcall
typedef long                NTSTATUS;
#define NT_SUCCESS(Status)  (((NTSTATUS)(Status)) >= 0)

enum PROCESS_INFO_CLASS    { ProcessBasicInformation  = 0  };

typedef struct _PROCESS_BASIC_INFORMATION
{
    NTSTATUS  ExitStatus;
    ULONG      PebBaseAddress;
    ULONG      AffinityMask;
    ULONG      BasePriority;
    ULONG      UniqueProcessId;
    ULONG      InheritedFromUniqueProcessId;
} PROCESS_BASIC_INFORMATION, *PPROCESS_BASIC_INFORMATION;

typedef NTSTATUS  (NTAPI *ZW_QUERY_INFORMATION_PROCESS)(IN HANDLE ProcessHandle, IN PROCESS_INFO_CLASS ProcessInformationClass, OUT PVOID ProcessInformation, IN ULONG ProcessInformationLength, OUT PULONG ReturnLength);

ULONG GetParentPID(HANDLE hProcess)
{
    ULONG ParentPID = (ULONG)(-1);

    __try
    {
        HMODULE hModule = GetModuleHandle("ntdll.dll");
        if (! hModule)
            __leave;

        ZW_QUERY_INFORMATION_PROCESS ZwQueryInformationProcess;
        ZwQueryInformationProcess = (ZW_QUERY_INFORMATION_PROCESS)GetProcAddress(hModule, "ZwQueryInformationProcess");
        if (!ZwQueryInformationProcess)
            __leave;

        PROCESS_BASIC_INFORMATION ProcessInfo;
        NTSTATUS Status = ZwQueryInformationProcess(hProcess, ProcessBasicInformation, &ProcessInfo, sizeof(ProcessInfo), NULL);
        if (NT_SUCCESS(Status))
        {
            ParentPID = ProcessInfo.InheritedFromUniqueProcessId;
        }
    }
    __finally
    {
        //empty
    }

    return ParentPID;
}

void main(void)
{
    LONG ParentPID = GetParentPID(GetCurrentProcess( ));
    cout << "Parent PID: " << ParentPID << endl;
    HANDLE hParentProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, ParentPID);
    if (hParentProcess)
    {
        char FileName[MAX_PATH];
        DWORD Len = GetModuleFileNameEx(hParentProcess, NULL, FileName, MAX_PATH);
        if (Len)
        {
            cout << "Parent EXE name: " << FileName << endl;
        }
        CloseHandle(hParentProcess);
    }
}

在NT/2K下,普通Win32程式的父程式還可能是cmd.exe;對於Win32服務程式,其父程式則為service.exe。

相關文章