Getting Process ID from Process Handle _1

1. Getting the ID by Creating a Remote Thread

If we want to find our own process ID, we call GetCurrentProcessId(). Intuitively it would be nice to make a target process to call it in its own context and to return us the result. To implement this, a remote thread creation technique can be used. Here is a prototype of CreateRemoteThread():

HANDLE CreateRemoteThread(

    HANDLE hProcess,        // handle to process to create thread in

 

    LPSECURITY_ATTRIBUTES lpThreadAttributes,  // pointer to security attributes

    DWORD dwStackSize,      // initial thread stack size, in bytes

    LPTHREAD_START_ROUTINE lpStartAddress, // pointer to thread function

 

    LPVOID lpParameter,     // argument for new thread

    DWORD dwCreationFlags,  // creation flags

 

    LPDWORD lpThreadId      // pointer to returned thread identifier

 

);

By setting lpStartAddress to the address of GetCurrentProcessId(), we cause this function to be executed as a thread routine in the context of a target process. Then it will remain, using the returned thread's handle, to get the thread exit code. One delicate thing is that GetCurrentProcessId() has no input parameters, whereas LPTHREAD_START_ROUTINE assumes one. Indeed, CreateRemoteThread() just passes execution to the code pointed by lpStartAddress not doing all necessary validations. In the majority of cases, it is rather a problem. Here we use it as an advantage: as GetCurrentProcessId() has been executed not using anything from the stack, the thread exits and then its stack is destroyed, causing no problem. Here is a full code of a function doing necessary steps:

DWORD WINAPI GetProcessIDbyProcessHandle(HANDLE hProcess)

{

    // [in]  process handle

    // [out] process ID, or 0xffffffff in case of failure

   

    if (hProcess == NULL)    return 0xffffffff;

    PTHREAD_START_ROUTINE lpStartAddress = (PTHREAD_START_ROUTINE)

        GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "GetCurrentProcessId");

    if (lpStartAddress == NULL) return 0xffffffff;

    // We do not know, whether process handle already has required access rights;

 

    // thus we have to duplicate it

    HANDLE hProcessAccAdj;

    BOOL bRes = DuplicateHandle(GetCurrentProcess(),

                                hProcess, GetCurrentProcess(), &hProcessAccAdj,

                                PROCESS_QUERY_INFORMATION|PROCESS_CREATE_THREAD|

                                PROCESS_VM_OPERATION|PROCESS_VM_WRITE,

                                FALSE, 0);

    if (!bRes || hProcessAccAdj == NULL)

    {

        UINT unError = GetLastError();

        return 0xffffffff;

    }

    // Create a remote thread; as its starting address

 

    // we specify GetCurrentProcessId() address,

    // which is the same for all processes. Note that GetCurrentProcessId() has no input

    // parameters, and we don't care about our thread stack cleanup,

    // as it will be destroyed right after this call

 

    DWORD dwThreadID;

    HANDLE hRemoteThread = CreateRemoteThread(hProcessAccAdj, NULL,

        0, lpStartAddress, 0, 0, &dwThreadID);

    CloseHandle(hProcessAccAdj);

    if (hRemoteThread == NULL) return 0xffffffff;

    // Wait until process ID is obtained

 

    // (replace INFINITE value below to a smaller value to avoid deadlocks);

    // then get the thread exit code, which is a value returned by GetCurrentProcessId()

    // in the context of the remote process

    WaitForSingleObject(hRemoteThread, INFINITE);

    DWORD dwExitCode;

    if (GetExitCodeThread(hRemoteThread, &dwExitCode) == 0)    dwExitCode = 0xffffffff;

    CloseHandle(hRemoteThread);

    return dwExitCode;

}

Unfortunately, this will fail if the security context of a target process does not allow us to open (duplicate) a handle to that process with required access rights. In particular, this will happen with low ID processes such as csrss.exewinlogon.exe and a few others. Getting debug privilege may or may not solve a problem, as we, by assumption, cannot control the way of getting an initial (available) handle. For instance, in the following sequence of calls...

    hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwProcessId);

    HANDLE hProcessAccessAdjusted;

    DuplicateHandle(GetCurrentProcess(), hProcess, GetCurrentProcess(),

                    &hProcessAccessAdjusted,

                    PROCESS_QUERY_INFORMATION|PROCESS_CREATE_THREAD|

                    PROCESS_VM_OPERATION|PROCESS_VM_WRITE,

                    FALSE, 0);

...the last call will fail with ERROR_ACCESS_DENIED if dwProcessId represents one of the above processes, whether or not the debug privilege is granted.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值