GetThreadContext() returning 87

Viewed 1186

I'm trying to get the thread context of suspended WordPad. However, no matter what changes I make to the code, it returns 87.

STARTUPINFO si = { 0 };
PROCESS_INFORMATION pi = { 0 };
CONTEXT ctx;

if (CreateProcess(L"C:\\Windows\\write.exe", NULL, NULL, NULL, false, CREATE_SUSPENDED, NULL, NULL, &si, &pi))
{
    cout << "-> Success <-" << endl;
}

else
{
    cout << GetLastError();
}

if (GetThreadContext(pi.hThread, &ctx))
{
    cout << "-> Success <-" << endl;
}

else
{
    cout << GetLastError();
}
1 Answers

the CONTEXT structure contains processor-specific register data. so it definition depend from target architecture. say for x86 and amd64 the different CONTEXT definitions.

here exist 32-64 bit issue in 64bit windows:

  • 64-bit application can get 64-bit context of any thread by call GetThreadContext
  • 64-bit application can get 32-bit context of WOW64 thread by call Wow64GetThreadContext. note in this case you need use WOW64_CONTEXT.
  • 32-bit application can get only 32-bit context of WOW64 thread by call GetThreadContext
  • when 32-bit application try get context of thread in 64-bit application - the GetThreadContext always failed with ERROR_INVALID_PARAMETER

so based on your error i can say that you running on 64-bit windows. here write.exe is 64-bit process and your code is 32-bit. you can not get context in this case.

also, as general note we always must init ContextFlags member of ctx. this is mandatory:

The function retrieves a selective context based on the value of the ContextFlags member of the context structure.

so when ContextFlags is undefined - GetThreadContext return undefined result

so code must be next:

    STARTUPINFO si = { sizeof(si) };
    PROCESS_INFORMATION pi ;

    if (CreateProcess(L"C:\\Windows\\write.exe", NULL, NULL, NULL, false, CREATE_SUSPENDED, NULL, NULL, &si, &pi))
    {
        union {
            CONTEXT ctx;
#ifdef _WIN64
            WOW64_CONTEXT wow_ctx;
#endif
        };

        BOOL fOk = FALSE;
        BOOL Wow;
#ifdef _WIN64
        if (IsWow64Process(pi.hProcess, &Wow))
        {
            if (Wow)
            {
                wow_ctx.ContextFlags = WOW64_CONTEXT_DEBUG_REGISTERS|WOW64_CONTEXT_CONTROL|WOW64_CONTEXT_INTEGER;
                fOk = Wow64GetThreadContext(pi.hThread, &wow_ctx);
            }
            else
            {
                ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS|CONTEXT_INTEGER|CONTEXT_CONTROL;
                fOk = GetThreadContext(pi.hThread, &ctx);
            }
        }
#else
        BOOL MyWow;
        if (IsWow64Process(NtCurrentProcess(), &MyWow) && IsWow64Process(pi.hProcess, &Wow))
        {
            if ((MyWow != 0) ^ (Wow != 0))
            {
                //32-bit app can not got context of 64-bit app
                SetLastError(ERROR_GEN_FAILURE);
            }
            else
            {
                ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS|CONTEXT_INTEGER|CONTEXT_CONTROL;
                fOk = GetThreadContext(pi.hThread, &ctx);
            }
        }

        if (!fOk)
        {
            DbgPrint("error=%u\n", GetLastError());
        }
#endif
        ResumeThread(pi.hThread);
        CloseHandle(pi.hThread);
        CloseHandle(pi.hProcess);
    }
Related