Stack overwrite when calling GetThreadContext in 64bit application

G

George Hicken

I'm seeing a stack overwrite when I call GetThreadContext in a 64bit
application XP/Server 2003 systems with SP2.

Is this a known problem, does anyone know a workaround?

Test case follows:
#include
#include
#include
#include
#include
#include


unsigned __stdcall SecondThreadFunc( void* pArguments )
{
HANDLE handle = *(HANDLE*)pArguments

printf( "In second thread...\n" )


WaitForSingleObject( handle, INFINITE )


_endthreadex( 0 )
return 0
}


int main()
{
HANDLE hThread, currentThread, thread_handle
unsigned threadID
char buffer[600]
CONTEXT tmpContext
STACKFRAME64 stackFrame = {0}
int frameNumber = 0
int rc = 1
int i = 0
BOOLEAN damaged = FALSE

currentThread = GetCurrentThread()

printf( "Creating second thread...\n" )

printf( "&buffer=%p - %p, &tmpContext=%p - %p\n", buffer, buffer +
sizeof(buffer), &tmpContext, (char*)&tmpContext + sizeof(tmpContext))
// Create the second thread.
hThread = (HANDLE)_beginthreadex( NULL, 0, &SecondThreadFunc,
&currentThread, 0, &threadID )

if (hThread == (HANDLE)-1L) {
printf ("error creating thread\n")
goto cleanup
}

Sleep(1000)

if (SuspendThread(hThread) == -1) {
printf ("error suspending thread\n")
goto cleanup
}

thread_handle = OpenThread(THREAD_GET_CONTEXT|THREAD_QUERY_INFORMATION,
FALSE, GetThreadId(hThread))
tmpContext.ContextFlags = CONTEXT_FULL

memset(buffer, 0xFF, sizeof(buffer))


for (i = 0 i < sizeof(buffer) i++) {
if (buffer != (char)0xFF) {
printf ("sanity failed at buffer[%i], = %i\n", i, buffer)
goto cleanup
}
}

if (GetThreadContext(thread_handle , &tmpContext) == FALSE) {
printf ("error getting context, %i\n", GetLastError())
goto cleanup
}


for (i = sizeof(buffer) - 1 i >= 0 i--) {
if (buffer != (char)0xFF) {
printf ("overflowed %i bytes of buffer, total overflow is %i
bytes\n", i+1, (size_t)&buffer - (size_t)&tmpContext - sizeof(tmpContext))
goto cleanup
}
}



/* initialize the stackframe */
stackFrame.AddrPC.Mode = AddrModeFlat
stackFrame.AddrStack.Mode = AddrModeFlat
stackFrame.AddrFrame.Mode = AddrModeFlat

stackFrame.AddrPC.Offset = tmpContext.Rip
stackFrame.AddrStack.Offset = tmpContext.Rsp
stackFrame.AddrFrame.Offset = tmpContext.Rbp


/* now walk the stack and maintain a count of the frames */
for (frameNumber = 0 rc != FALSE frameNumber++) {
DWORD64 disp64
BYTE buffer[256]
PSYMBOL_INFO symbol_info = (PSYMBOL_INFO)buffer
memset(symbol_info, 0, sizeof(buffer))
symbol_info->SizeOfStruct = sizeof(SYMBOL_INFO)
symbol_info->MaxNameLen = sizeof(buffer) - sizeof(SYMBOL_INFO)

rc = StackWalk64(
IMAGE_FILE_MACHINE_AMD64,
GetCurrentProcess(),
thread_handle,
&stackFrame,
&tmpContext,
NULL,
SymFunctionTableAccess64,
SymGetModuleBase64,
NULL )

if (rc == 0) {
printf ("stack walk failed\n")
break
}

if (SymFromAddr(GetCurrentProcess(), tmpContext.Rip, &disp64,
symbol_info) == FALSE) {
printf("failed to get symbol for %p\n", tmpContext.Rip)
} else {
printf("%s\n", symbol_info->Name)
}

printf ("got frame %i\n", frameNumber)
}

cleanup:
// Destroy the thread object.
ResumeThread( hThread )
CloseHandle( hThread )
CloseHandle(thread_handle)
}
 
Back
Top Bottom