I have the following assembly lines:

 PUSH 4                                   ; CreationFlags = CREATE_SUSPENDED
 PUSH program.0040163B                    ; start address of thread 
 CALL DWORD PTR DS:[402428]               ; kernel32.CreateThread 
 MOV DWORD PTR DS:[4023F8], EAX           ; store handle to created thread to [4023F8]
 PUSH ESI                                 ; [402000] will be the location where we store the context of the thread
 PUSH DWORD PTR DS:[4023F8]               ; handle to created thread
 CALL DWORD PTR DS:[402424]               ; kernel32.GetThreadContext
 MOV [ESI+B0], program.004010E9           ; [ESI+B0] = [4020B0] = 0040163B (starting address of the created thread will be replaced by 004010E9, I guess)
 PUSH ESI                                 ; ESI points to 402000 where the thread context is stored, but now with a modified starting address of the thread
 PUSH DWORD PTR DS:[4023F8]               ; handle to thread
 CALL DWORD PTR DS:[402418]               ; kernel32.SetThreadContext
 CALL DWORD PTR DS:[402410]               ; kernel32.ResumeThread

So, to sum up: We create a thread in suspended state. Its starting address is 0040163B. Then we get the thread context and store it into 402000. By adding the offset of B0 to 402000, we reach the place where the starting address of the thread is stored in the context structure. We change it to 004010E9 and set the modified context using SetThreadContext.

So, my question would be: When I reach/call ResumeThread(), then will be 0040163B the starting address of the the thread, or 004010E9 ? Because of the combination of Get-and SetThreadContext, it would make sense that the starting address of my thread must be 004010E9, but I wanted to be sure.


In short my question is
(1) if I create a suspended thread
(2) Change its entry-point via SetThreadContext  
(3) Resume the suspended thread

will the thread begin execution at the original entry-point as specified by CreateThread or at the newly modified one ?


Your intuition is correct. Changing the starting address of the Thread via SetThreadContext will change the entry point. Here is a C++ snippet to verify our claims

#include <Windows.h>
#include <WinNT.h>

DWORD WINAPI orig_entry( LPVOID param)
    MessageBoxA(0, "Original Thread Entrypoint called", "", MB_OK);
    return 0;   

DWORD WINAPI new_entry(LPVOID param)
    MessageBoxA(0, "Modified Thread Entrypoint called", "", MB_OK);
    return 0;   

int main()
    HANDLE tHand;
    CONTEXT ctx;

    //Thread created with orig_entry as starting address
    tHand = CreateThread(NULL, 0, orig_entry, NULL, CREATE_SUSPENDED, NULL);

    ctx.ContextFlags = CONTEXT_INTEGER; //We only want to get/set register eax
    GetThreadContext(tHand, &ctx);

    //Entry point is stored in register eax (ctx + 0xB0)
    ctx.Eax = (DWORD) new_entry;    
    ctx.ContextFlags = CONTEXT_INTEGER;

    //Comment the line below to see the difference
    SetThreadContext(tHand, &ctx);

    Sleep(-1);  //Pause main thread permanently
    return 0;

Running the code, you will notice that function new_entry is called, which justifies that the entry-point was changed by SetThreadContext

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.