ForeverLearning
ForeverLearning

Reputation: 6685

Weird callstack leading up to CreateRemoteThread

I am having a hard time understanding the callstack below.

ntdll!NtCreateThreadEx+0xc
KERNELBASE!CreateRemoteThreadEx+0x1f0
kernel32!CreateThreadStub+0x27
MyModule!_beginthreadex+0x87

Sorry I cannot reveal any more of it because of proprietory issues but I believe we should be able to make at least partial sense just with this. That was the state of one the threads spawned by a third party library inside a crash dump I was looking at. (the thread itself had nothing to do with the problem I was investigating.)

What condition can possibly cause a call to _beginthreadex to end up in CreateRemoteThread? The MSDN doc for the API does not give me any clues (the word 'remote' doesn't even appear on that page.)

I have symbols for the third party library and the callstack is definitely legit.

Update:

Interesting. If I disassemble backwards from the spot CreateThreadStub is supposed to return to, I see the following instructions:

call    dword ptr [MyModule!_imp__CreateThread (573701a0)]
cmp     eax,ebx

When I do:

0:048> dds MyModule!_imp__CreateThread l1
573701a0  75b5cf30 kernel32!CreateThreadStub

and when I disassemble CreateThreadStub, I do see it calling CreateRemoteThread. This is all very confusing!

Upvotes: 0

Views: 528

Answers (2)

Ben Voigt
Ben Voigt

Reputation: 283803

The function description on MSDN is a bit misleading:

Creates a thread that runs in the virtual address space of another process.

The first line of remarks is a much better summary of CreateRemoteThread:

The CreateRemoteThread function causes a new thread of execution to begin in the address space of the specified process.

At least with this description, it's clear that you can create a thread in the local process using CreateRemoteThread, merely by specifying the current process. Also note this in CreateRemoteThreadEx remarks:

The CreateRemoteThreadEx function causes a new thread of execution to begin in the address space of the specified process. The thread has access to all objects that the process opens. The lpAttribute parameter can be used to specify extended attributes such as processor group affinity for the new thread. If lpAttribute is NULL, the function's behavior is the same as CreateRemoteThread.

When you think about the transition to kernel-mode, and the fact that CreateRemoteThreadEx, by choice of parameters, can do everything that CreateThread or CreateRemoteThread can do, and the maintenance cost of testing correctness and security of each syscall, it makes sense to provide only one syscall with a superset of all the abilities, and have all these functions use it.

Upvotes: 1

Thomas Weller
Thomas Weller

Reputation: 59513

The stack you posted is the normal stack. Compile the following C++ code:

#include "stdafx.h"
#include <iostream>
#include <process.h>
#include <Windows.h>
using namespace std;

void test(void *param)
{
    Sleep(1000);
    _endthread();
}

int main()
{
    HANDLE hThread;
    hThread = (HANDLE)_beginthread(test, 0, NULL);
    WaitForSingleObject(hThread, INFINITE);
    return 0;
}
  1. Start WinDbg
  2. Open the executable
  3. At the initial breakpoint, set a breakpoint

    0:000> bp KERNELBASE!CreateRemoteThreadEx
    0:000> bl
         0 e Disable Clear  7485b060     0001 (0001)  0:**** KERNELBASE!CreateRemoteThreadEx
    0:000> g
    
  4. See that the main() method calls CreateRemoteThreadEx() when it hits the _beginthread() method:

    0:000> k
     # ChildEBP RetAddr  
    WARNING: Stack unwind information not available. Following frames may be wrong.
    00 00f7f714 0f7ba3cd KERNELBASE!CreateRemoteThreadEx
    01 00f7f758 000f255f ucrtbased!_beginthread+0xed [d:\rs1\minkernel\crts\ucrt\src\appcrt\startup\thread.cpp @ 174] 
    02 00f7f844 000f2cbe ThreadStartStack!main+0x2f [c:\users\t\documents\visual studio 2015\projects\threadstartstack\threadstartstack\threadstartstack.cpp @ 19] 
    03 00f7f858 000f2b20 ThreadStartStack!invoke_main+0x1e [f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl @ 64] 
    04 00f7f8b0 000f29bd ThreadStartStack!__scrt_common_main_seh+0x150 [f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl @ 253] 
    05 00f7f8b8 000f2cd8 ThreadStartStack!__scrt_common_main+0xd [f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl @ 296] 
    06 00f7f8c0 752362c4 ThreadStartStack!mainCRTStartup+0x8 [f:\dd\vctools\crt\vcstartup\src\startup\exe_main.cpp @ 17] 
    07 00f7f8d4 77370fd9 KERNEL32!BaseThreadInitThunk+0x24
    08 00f7f91c 77370fa4 ntdll!__RtlUserThreadStart+0x2f
    09 00f7f92c 00000000 ntdll!_RtlUserThreadStart+0x1b
    

Upvotes: 3

Related Questions