Log in

View Full Version : unknown TEB fields


Neitsa
August 17th, 2004, 18:25
Hello,

Can somebody explain me what are those fields in the TEB structure on Win NT environment (start of TEB located at FS:[0]):

Code:

LastStatusValue: offset 38h
Count Owned Locksffset 3Ch
HardErrorsMode: offset 40h


'LastStatusValue' is surely related to LastErrorValue, which is the last error done by the thread, but Status of what ?

Count Owned Locks: maybe this field is about mutual-exclusion locks for threads, but I'm not sure...

HardErrorsMode: So, Hard errors are critical errors done by hardware (Am I right ?) but what is the 'Mode' ? and why Threads should deal with Hard errors (I was thinking that was the job of the Kernel) ?.


Thank you very much. Regards, Neitsa.


Damn, First post Here and registred since Feb. ! So , I'm very happy to be here and I like to see and read posts by great coders and reversers

Keep up the good work !

Woodmann
August 17th, 2004, 18:50
Howdy,

I have read this post a few times now and I am not quite sure what you are asking.

If you are looking for a basic explanation as to what those 3 mean,
MS has all the documentation you could ever want.

Woodmann

Neitsa
August 17th, 2004, 20:12
Hello Woodmann,

Thank you for your answer, and sorry if my question wasn't clear.

Yes I'm searching for an explanation of what those fields mean.

I've searched through the MSDN but the PEB and TEB aren't documented by MS, and I've also googled for them but can't find an answer for those fields...
(searched also in WINTERNL.H, but found nothing to explain what they are)

All I've wrote in my previous post is what I guess they are...

I've found those fields in the "inside MS win2k" book, but they aren't explained either...

And Soory for my bad english

Regards, Neitsa.

Woodmann
August 17th, 2004, 20:50
Howdy,

Your English is fine

Try looking for Matt Pietreks (I think the spelling is correct)
book. He is the "MAN" when it comes to MSDN.

Woodmann

Kayaker
August 17th, 2004, 23:12
Hi

These 3 fields are pretty well undocumented AFAIK. Sven Schrieber in his 2001 work doesn't even acknowledge their existence, the TEB structure described there ends with the field LastErrorValue at [TEB + 34h].


The exact use for these 3 fields are anybody's guess. The TEB is the only part of the ETHREAD block which exists in the process address space, so any of the fields must be important from a user mode perspective (like the PEB pointer). Windows may use the fields somewhere in ntdll code, an examination with IDA might reveal something.


Possible explanations of the fields:

LastErrorValue [TEB + 34h] - will be 0 or a C000xxxx error code.

LastStatusValue [TEB + 38h] - may indicate the Wait status of the thread, as used in synchronization. A guess.


Count Owned Locks [TEB + 3Ch] - the question is what type of locks are we talking about here? There are resource locks, critical section locks, spin locks, other wait events...

There is a structure SYSTEM_LOCK_INFORMATION used with ZwGetSystemInformation (class SystemLockInformation), which may or may not be associated with this particular TEB field.
This structure is identical to the one used with RtlQueryProcessDebugInformation
PDI_LOCKS 0x20 // The locks created by the process (DEBUG_MODULE_INFORMATION)

-------------------------------
typedef struct _SYSTEM_LOCK_INFORMATION { // Information Class 12
PVOID Address;
USHORT Type;
USHORT Reserved1;
ULONG ExclusiveOwnerThreadId;
ULONG ActiveCount;
ULONG ContentionCount;
ULONG Reserved2[2];
ULONG NumberOfSharedWaiters;
ULONG NumberOfExclusiveWaiters;
} SYSTEM_LOCK_INFORMATION, *PSYSTEM_LOCK_INFORMATION;

Address
The address of the lock structure.
Type
The type of the lock. This is either RTL_CRITSECT_TYPE (0) or RTL_RESOURCE_TYPE (1).
ActiveCount
The number of threads granted access to the lock. Critical sections count from -1, and
resources count from 0.
ContentionCount
The number of times a thread had to wait for the lock.
--------------------------------------

I have seen a couple of TEB variations which declare this field as a count of owned CriticalSection locks, but it may include any Resource locks as well.



HardErrorsMode [TEB + 40h] - The last TEB field may be an indicator of this (DDK):

-------------
IoSetThreadHardErrorMode enables or disables hard error reporting for the current thread. If hard errors are disabled for a given thread, calls to IoRaiseHardError will not display a message to the user indicating that a serious error has occurred.

IoRaiseHardError causes a popup to be displayed that warns the user that a device I/O error has occurred, which might indicate that a physical device is failing.
------------

The popup of IoRaiseHardError is created via a kernel APC, and APC handler code resides in ntdll.dll. Ntdll may make use of the HardErrorsMode flag in the TEB field somewhere in its code.


Since WinDbg returns 0 for these 3 !teb fields for a normal process, one would have to try to code a situation where they would return a value, identifying their use.

If anyone has any other ideas... cough it up! ;-)

Kayaker

Opcode
August 18th, 2004, 06:20
Alex Ionescu has made a excellent job in his
"Introduction to NT Internals".

Take a look about the TEB in his PDF:
http://www.relsoft.net/Articles/Process/part1.pdf

Regards,
Opcode

dELTA
August 18th, 2004, 07:35
Very nice document Opcode, thanks! Strange though that only one of those fields (LastStatusValue) is mentioned, and the offset for that one doesn't seem to be consistent with the value mentioned above either, or am I wrong?

Neitsa
August 18th, 2004, 08:23
Hello,

I wish to thank you all for your answers.

Here's what M.Russinovich and A Solomon are telling us about TEB struct in the "inside MS windows 2000 - third edition" book, using KD program to display those fields:

Code:

kd> !teb
TEB at 7FFDE000
ExceptionList: 0
Stack Base: +4
Stack Limit: +8
SubSystemTib: +0Ch
FiberData: +10h
ArbitraryUser: +14h
Self: +18h
EnvironmentPtr: +1Ch
ClientId: +20h
Real ClientId: +24h
RpcHandle: +28h
Tls Storage: +2Ch
PEB Address: +30h
LastErrorValue: +34h
LastStatusValue: +38h
Count Owned Locks:+3Ch
HardErrorsMode: +40h


In my windows 2k SP4, the +38h and +3Ch fields are always set to 0 with "normal" user-mode programs, and the last fields has always the same value:

Code:

7FFDE040 E42238C8


Anyway, with all the informations you've provided, I'll try to see if can reverse ntdll (maybe ntoskernel also) to see where those fields can be used.

Thank you very much !

Regards, Neitsa.

Kayaker
August 18th, 2004, 10:49
Yeah, the TEB in that (albeit very nice) Relsoft doc is the same as initially proposed elsewhere, such as
http://pulhas.org/xploitsdb/NT/5966.html

Code:

typedef struct _NT_TEB
{
NT_TIB Tib; // 00h
PVOID EnvironmentPointer; // 1Ch
CLIENT_ID Cid; // 20h
PVOID ActiveRpcInfo; // 28h
PVOID ThreadLocalStoragePointer; // 2Ch
PPEB Peb; // 30h
ULONG LastErrorValue; // 34h
ULONG CountOfOwnedCriticalSections; // 38h
PVOID CsrClientThread; // 3Ch
PVOID Win32ThreadInfo; // 40h
ULONG Win32ClientInfo[0x1F]; // 44h
PVOID WOW32Reserved; // C0h
...


In The Assembly-Programming-Journal, (2004)
Detecting operating systems without Microsoft Advanced Programming Interface
http://www.Assembly-Journal.com
the fields in question are defined in their own substructure,
which isn't a bad "working" hypothesis:

Code:

The last entry of TEB is the pointer to process database.
On NT-based operating systems this value will point to the address
of Process Environment Block.

Additional data following TEB - this additional data has no logical structure
and differs on each non NT-based operating system. On Windows
NT, 2000, XP and 2003 this additional Data is defined as follows:

NT_TEB_ADDON struct
LastErrorValue DWORD ? ; 00h (34h TEB)
LastStatusValue DWORD ? ; 04h (38h TEB)
CountOwnedLocks DWORD ? ; 08h (3Ch TEB)
HardErrorsMode DWORD ? ; 0Ch (40h TEB)
NT_TEB_ADDON ends


I did a bit of exploration last night of ntdll.dll in IDA, trying text searches for the relevant bits of

mov eax, fs:18h ; TEB

then searches for code indicating the fields being used

mov reg, [eax+34h]
+38h]
+3Ch]
+40h]

Lots of hits, but no home runs yet...

Kayaker

disavowed
August 18th, 2004, 21:29
LastStatusValue is the STATUS_* equivalent of the ERROR_* value returned by GetLastError(). In other words, LastStatusValue == RtlNtStatusToDosError(GetLastError()). Neitsa, this value is "always set to 0" for you becuase you've been checking it when your thread's last error is ERROR_SUCCESS (STATUS_SUCCESS)

Neitsa
August 18th, 2004, 23:17
Hello Disavowed,

Maybe I've misanderstood something but I think you're talking about LastErrorValue.

From Kernel32.dll:

Code:

.text:77ED390F ; DWORD GetLastError(void)
.text:77ED390F GetLastError db 'NTDLL.RtlGetLastWin32Error',0


from ntdll:

Code:

.text:77F51502 public RtlGetLastWin32Error
.text:77F51502 RtlGetLastWin32Error proc near
.text:77F51502 mov eax, large fs:18h
.text:77F51508 mov eax, [eax+34h]
.text:77F5150B retn
.text:77F5150B RtlGetLastWin32Error endp


doing a little error in a program:

Code:

PUSH 0 ;no control ID / error
PUSH DWORD PTR SS:[EBP+8] ; |hWnd
CALL <JMP.&user32.GetDlgItem> ; \GetDlgItem


returned : ERROR_CONTROL_ID_NOT_FOUND (0000058D)

TEB fields :

Code:

7FFDE034 0000058D (Last error = ERROR_CONTROL_ID_NOT_FOUND)
7FFDE038 00000000 ; this damn field always at 0
7FFDE03C 00000000
7FFDE040 E4559888


Searching through ntdll with dead-listing, I've found nothing trully interesting bout this +38h field, but sometimes it's hard to find those things without a live approach. (Got to code a little program to see..)

Thank you for your answer Disavowed, all comments , criticisms and helps are always appreciated ! Just tell me if I've made a mistake or if you can find/see something.

Regards, Neitsa.

Kayaker
August 19th, 2004, 03:01
Hi

I question the use of the label HardErrorsMode at [TEB+40h] by WinDbg for Win2Ksp3. A check of the TEB in the context of a user thread in Softice indicates the value there (Neitsa recorded it as E4559888) is a pointer to the address of an ETHREAD structure. DISPATCHER_HEADER at + 0, LIST_ENTRY beginning at +8, Teb pointer at + 20h...

The "other" TEB definition appears to be more correct
PVOID Win32ThreadInfo; // 40h


On the other point, disavowed is correct. There seems to be a distinction between Win32 and NTSTATUS error codes, clarified by the WinDbg function !error.

0:000> !error 58d
Error code: (Win32) 0x58d (1421) - Control ID not found.

0:000> !error c0000034
Error code: (NTSTATUS) 0xc0000034 (3221225524) - Object Name not found.


I also found this telling output at
http://www.codeproject.com/debug/cdbntsd4.asp

LastErrorValue: 0
LastStatusValue: c0000034
Count Owned Locks: 0
HardErrorMode: 0

Cheers,
Kayaker

Neitsa
August 19th, 2004, 07:10
Hello,

Nice post Kayaker, now I understand my error about different win errors (I've searched through my headers files and found NTSTATUS.h with all Status error codes). So, please forgive my mistakes in my previous post.

Also, there's a little more question, I dont't understand really where this stucture came from (see Kayaker's link: http://pulhas.org/xploitsdb/NT/5966.html ), and on the other hand why KD / Windbg doesn't diplay the same fields.

The previous post from Kayaker tends to tell us that Windbg is wrong when display some of those fields...

I wish to thank you all for your previous replies.

Regards, Neitsa

disavowed
August 19th, 2004, 17:24
Quote:
[Originally Posted by Neitsa]The previous post from Kayaker tends to tell us that Windbg is wrong when display some of those fields...
maybe microsoft is sick of people reversing their os, and decided to throw a red herring into windbg?

Elftor
August 20th, 2004, 01:29
Quote:
[Originally Posted by disavowed]maybe microsoft is sick of people reversing their os, and decided to throw a red herring into windbg?


heh heh ...

Neitsa
August 20th, 2004, 08:05


You got a point Disavowed ! Something rotten in the kingdom of MS...

Regards, Neitsa.

bilbo
August 24th, 2004, 04:04
Quote:
[Originally Posted by Neitsa]The previous post from Kayaker tends to tell us that Windbg is wrong when display some of those fields...

Quote:
[Originally Posted by disavowed]maybe microsoft is sick of people reversing their os, and decided to throw a red herring into windbg?


Come on, mates, do you think they are so smart, and what could be a bug is in fact an intelligent trick?

By the way, there is no sickness neither bugs from them. The command
!teb does not give you the offsets, but the correct values.

The correct citation from Solomon-Russinovich book is not the one Neitsa reported (where in the hell did you find it?), but
Code:

EXPERIMENT
--------------------------------------------------------------------------------
Examining the TEB
You can dump the TEB structure with the !teb command in the kernel debugger. The output looks like this:

kd> !teb
TEB at 7FFDE000
ExceptionList: 12ffb0
Stack Base: 130000
Stack Limit: 12d000
SubSystemTib: 0
FiberData: 1e00
ArbitraryUser: 0
Self: 7ffde000
EnvironmentPtr: 0
ClientId: 490.458
Real ClientId: 490.458
RpcHandle: 0
Tls Storage: 0
PEB Address: 7ffdf000
LastErrorValue: 0
LastStatusValue: 0
Count Owned Locks:0
HardErrorsMode: 0


Best regards, bilbo

Neitsa
August 24th, 2004, 09:24
Hello,

Yes you're right Bilbo , but I was thinking that each fileld was DWORD aligned. On the other hand Pegasus posted this little MASM struct:



NT_TEB_ADDON struct
LastErrorValue DWORD ? ; 00h (34h TEB)
LastStatusValue DWORD ? ; 04h (38h TEB)
CountOwnedLocks DWORD ? ; 08h (3Ch TEB)
HardErrorsMode DWORD ? ; 0Ch (40h TEB)
NT_TEB_ADDON ends


but from the kayaker's post we can see this:



ULONG LastErrorValue; // 34h
ULONG CountOfOwnedCriticalSections; // 38h
PVOID CsrClientThread; // 3Ch
PVOID Win32ThreadInfo; // 40h


from this link :http://pulhas.org/xploitsdb/NT/5966.html

I can't find either HardErrorMode or CountOwnedLocks but LastStatusValue is there:



NTSTATUS LastStatusValue; // BF4h


As Kayaker and disavowed said the LastStatusField at offset 38h is correct:

Quote:

On the other point, disavowed is correct. There seems to be a distinction between Win32 and NTSTATUS error codes, clarified by the WinDbg function !error.

0:000> !error 58d
Error code: (Win32) 0x58d (1421) - Control ID not found.

0:000> !error c0000034
Error code: (NTSTATUS) 0xc0000034 (3221225524) - Object Name not found.


So, Who's right who's wrong ? It's very strange...

disavowed
August 24th, 2004, 10:35
according to the leak from Mainsoft, i'm right

bilbo
August 24th, 2004, 11:36
Quote:
[Originally Posted by disavowed]according to the leak from Mainsoft, i'm right

Of course you're right, disavowed, but as usually things go in this strange world of human beings, everyone is right!

To make more light in this matter, let's do some reverse engineering...
Kernel debugger will help us a lot...
In all M$ operating systems the command !teb is contained in an extension debugger DLL. Let's see...

NT4: F88 bytes are read for TEB structure. Disasm from NT4FRE\NTSDEXTS.DLL follows.
Code:

push [ebp+var_F54] ; var_F88-var_F54: +34
push offset aLasterrorval_0 ; " LastErrorValue: %u\n"
call dword_4EE92EB4
add esp, 8

push [ebp+var_394] ; var_F88-var_394: +BF4
push offset aLaststatusva_0 ; " LastStatusValue: %x\n"
call dword_4EE92EB4
add esp, 8

push [ebp+var_F50] ; var_F88-var_F50: +38
push offset aCountOwnedLock ; " Count Owned Locks:%u\n"
call dword_4EE92EB4
add esp, 8

push [ebp+var_60] ; var_F88-var_60: +F28
push offset aHarderrorsmode ; " HardErrorsMode: %u\n"
call dword_4EE92EB4


Win2K: FA4 bytes are read for TEB structure. Disasm from W2KFRE\NTSDEXTS.DLL follows.
Code:

push [ebp+var_F70] ; var_FA4-var_F70: +34
push offset aLasterrorval_0 ; " LastErrorValue: %u\n"
call dword_4EE95024
pop ecx
pop ecx

push [ebp+var_3B0] ; var_FA4-var_FB0: +BF4
push offset aLaststatusva_0 ; " LastStatusValue: %x\n"
call dword_4EE95024
pop ecx
pop ecx

push [ebp+var_F6C] ; var_FA4-var_F6C: +38
push offset aCountOwnedLock ; " Count Owned Locks:%u\n"
call dword_4EE95024
pop ecx
pop ecx

push [ebp+var_7C] ; var_FA4-var_7C: +F28
push offset aHarderrorsmode ; " HardErrorsMode: %u\n"
call dword_4EE95024


WinXP: since I'm playing on an XP box, there is no need to disasm; command dt may be used!
Code:

kd> dt _TEB
+0x000 NtTib : _NT_TIB
+0x01c EnvironmentPointer : Ptr32 Void
+0x020 ClientId : _CLIENT_ID
+0x028 ActiveRpcHandle : Ptr32 Void
+0x02c ThreadLocalStoragePointer : Ptr32 Void
+0x030 ProcessEnvironmentBlock : Ptr32 _PEB
+0x034 LastErrorValue : Uint4B
+0x038 CountOfOwnedCriticalSections : Uint4B
+0x03c CsrClientThread : Ptr32 Void
+0x040 Win32ThreadInfo : Ptr32 Void
+0x044 User32Reserved : [26] Uint4B
+0x0ac UserReserved : [5] Uint4B
+0x0c0 WOW32Reserved : Ptr32 Void
+0x0c4 CurrentLocale : Uint4B
+0x0c8 FpSoftwareStatusRegister : Uint4B
+0x0cc SystemReserved1 : [54] Ptr32 Void
+0x1a4 ExceptionCode : Int4B
+0x1a8 ActivationContextStack : _ACTIVATION_CONTEXT_STACK
+0x1bc SpareBytes1 : [24] UChar
+0x1d4 GdiTebBatch : _GDI_TEB_BATCH
+0x6b4 RealClientId : _CLIENT_ID
+0x6bc GdiCachedProcessHandle : Ptr32 Void
+0x6c0 GdiClientPID : Uint4B
+0x6c4 GdiClientTID : Uint4B
+0x6c8 GdiThreadLocalInfo : Ptr32 Void
+0x6cc Win32ClientInfo : [62] Uint4B
+0x7c4 glDispatchTable : [233] Ptr32 Void
+0xb68 glReserved1 : [29] Uint4B
+0xbdc glReserved2 : Ptr32 Void
+0xbe0 glSectionInfo : Ptr32 Void
+0xbe4 glSection : Ptr32 Void
+0xbe8 glTable : Ptr32 Void
+0xbec glCurrentRC : Ptr32 Void
+0xbf0 glContext : Ptr32 Void
+0xbf4 LastStatusValue : Uint4B
+0xbf8 StaticUnicodeString : _UNICODE_STRING
+0xc00 StaticUnicodeBuffer : [261] Uint2B
+0xe0c DeallocationStack : Ptr32 Void
+0xe10 TlsSlots : [64] Ptr32 Void
+0xf10 TlsLinks : _LIST_ENTRY
+0xf18 Vdm : Ptr32 Void
+0xf1c ReservedForNtRpc : Ptr32 Void
+0xf20 DbgSsReserved : [2] Ptr32 Void
+0xf28 HardErrorsAreDisabled : Uint4B
+0xf2c Instrumentation : [16] Ptr32 Void
+0xf6c WinSockData : Ptr32 Void
+0xf70 GdiBatchCount : Uint4B
+0xf74 InDbgPrint : UChar
+0xf75 FreeStackOnTermination : UChar
+0xf76 HasFiberData : UChar
+0xf77 IdealProcessor : UChar
+0xf78 Spare3 : Uint4B
+0xf7c ReservedForPerf : Ptr32 Void
+0xf80 ReservedForOle : Ptr32 Void
+0xf84 WaitingOnLoaderLock : Uint4B
+0xf88 Wx86Thread : _Wx86ThreadState
+0xf94 TlsExpansionSlots : Ptr32 Ptr32 Void
+0xf98 ImpersonationLocale : Uint4B
+0xf9c IsImpersonating : Uint4B
+0xfa0 NlsCache : Ptr32 Void
+0xfa4 pShimData : Ptr32 Void
+0xfa8 HeapVirtualAffinity : Uint4B
+0xfac CurrentTransactionHandle : Ptr32 Void
+0xfb0 ActiveFrame : Ptr32 _TEB_ACTIVE_FRAME


So we can see that the TEB structure is grown from F88 to FA4 to FB4 with the evolution (involution?) of M$ systems, but the offsets of the four fields are always the same

Code:

LastErrorValue: +34h
LastStatusValue: +BF4h
Count Owned Locks:+38h
HardErrorsMode: +F28h


Well, what about the structure NT_TEB_ADDON described by Thomas Kruse (Pegasus?) in Assembling Programming Journal Vol.1 No.1? He seems the only guy to be wrong! He correctly located only the first field, LastErrorValue, at bias +34, but the structure NT_TEB_ADDON is not existing, and the TEB is a lot bigger than 44h bytes, as we saw!

Regards, bilbo

Neitsa
August 24th, 2004, 11:53


Thanks a lot Bilbo (from the Shire ?), that's definitly solve some trouble, at least for me.

Now...hmmm I got to search what's the meaning of all those fields maybe something interesting on there...

I wish to thank you all for your replies !

JMI
August 24th, 2004, 15:51
That wandering Hobbit has picked up some really useful informations in his wanderings. Glad he made it out of the cave and back to Middle Earth to share his findings with us.

Regards,

Kayaker
August 24th, 2004, 17:19
... and the RingBearer shall wield clarity of thought..


I suppose the lack of a structure definition should have been a clue?

0: kd> .load kdex2x86
0: kd> !strct teb
Structure is not in database.

..slaps forehead...

Regards,
Kayaker

Woodmann
August 24th, 2004, 19:05
Hi,


The person of bilbo seems extremely intelligent.
He knows much about TEB that seems to be hidden
from some of us
He as also contributed some "deep" info's from the
nether regions of coding.

I am very grateful he is among us

Woodmann

bilbo
August 25th, 2004, 02:40
Quote:
[Originally Posted by Neitsa]Now...hmmm I got to search what's the meaning of all those fields maybe something interesting on there...

Just to quote... myself (or, better, Tolkien): All who wander are not lost.
Something very interesting, by the way...
Quote:
[Originally Posted by Woodmann]The person of bilbo seems extremely intelligent

I do not understand well what you are saying, you know, human language is so complicated, sometime they say black and they are meaning white... Anyway, I'm just a seeker...

Regards, bilbo

JMI
August 25th, 2004, 11:17
In any case we are glad to have you among us and sharing your knowledge.

Regards,

Woodmann
August 25th, 2004, 16:10
Hi,

Quote:
quote:
Originally Posted by Woodmann
The person of bilbo seems extremely intelligent

I do not understand well what you are saying, you know, human language is so complicated, sometime they say black and they are meaning white... Anyway, I'm just a seeker..



I thank you for sharing your knowledge.

Woodmann