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,
¤tThread, 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)
}
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,
¤tThread, 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)
}