News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Interesting TIB member

Started by donkey, May 08, 2011, 08:05:29 AM

Previous topic - Next topic

donkey

Recently I was looking to store some information but could not keep the pointer to my VirtualAlloc'ed memory in the data section. It seems like a trivial task until you decide to actually do it. If you can't store the pointer how do you retrieve the information ? Storing it in a register was not an option since it had to be available throughout the run of the application, obviously storing it in the code or constant section was out of the question. Using TLS is the normal answer but I would have had to store the index of the slot somewhere, it presents the same problem. So how do you store a pointer that you can retrieve at any time without using the data section ?

The answer lies in a little used member of the TIB (Thread Information Block) that is common to all versions of Windows, TIB.pvArbitrary at offset 0x14 bytes. It is a DWORD sized slot that is available for application use, in X64 it is defined as NT_TIB.ArbitraryUserPointer, a QWORD found at offset 0x28 bytes. Since it is always at the exact same location and is accessible at any time using the FS segment override it fits my needs perfectly. In GoAsm syntax (for 32 bit):

fs mov [0x14],eax
fs mov eax,[0x14]

Quote from: Under The Hood -- MSJ May 1996The 14h DWORD pvArbitrary field is theoretically available for applications to use however they want. It's almost like an extra thread local storage slot for you to use, although I've never seen an application use it.

You might ask what in the heck would I need this for, well I found that in monitoring guard pages if I stored information in the data section it would sometimes end up in the guarded page and that would present some interesting if not confusing race conditions. The solution was to move the information I needed completely out of the data section, including the pointer to the data. No data section access meant no possibility of a race condition.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

dedndave

that's cool
i have need of a place to store the ESP value for later verification and possibly restoration
this is just what i need   :U

you could even use it to store a pointer to an array, eliminating all the overhead of TLS

jj2007

Want some more space, Dave?

assume fs:nothing
mov eax, 123456789
mov fs:[14h], eax
mov edi, 200h
mov ecx, 100h
.Repeat
mov fs:[edi], eax
add edi, 4
dec ecx
.Until Zero?

donkey

I don't think I would be comfortable writing to undocumented memory locations especially since you're dealing with the very high end of the 2GB user area when writing to the TIB. For now there doesn't seem to be an issue but Microsoft may expropriate that memory for something in the future and that could cause some very nasty bugs. For my programs I think I'll stick to using allocated memory and a pointer stored in an area that is documented as for application use.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

jj2007

Just kidding, Edgar. Although the whole TIB is kind of undocumented, of course :bg

dedndave

Jochen - trying to mislead me, again - lol
i didn't fall for it   :P

btw - there is some documentation

http://en.wikipedia.org/wiki/Win32_Thread_Information_Block

reminds me of the PSP segment from days of old   :bg

MichaelW

This is from WinNT.h in the PSDK:

typedef struct _NT_TIB {
    struct _EXCEPTION_REGISTRATION_RECORD *ExceptionList;
    PVOID StackBase;
    PVOID StackLimit;
    PVOID SubSystemTib;
    union {
        PVOID FiberData;
        DWORD Version;
    };
    PVOID ArbitraryUserPointer;
    struct _NT_TIB *Self;
} NT_TIB;
typedef NT_TIB *PNT_TIB;

eschew obfuscation