PDA

View Full Version : where is the best definition of NtCurrentTeb()->Win32ThreadInfo...


BanMe
July 2nd, 2010, 13:06
Found it..
regards BanMe

Kayaker
July 2nd, 2010, 18:27
Shame on you BanMe, you know that's not allowed.

"Never mind, I found it"

C'mon, give up the good stuff...

BanMe
July 2nd, 2010, 21:51
lol I found it and its useless to me I think.. :[
Im getting returned the address 0x00000000 from fs:18h + 0x40....

so I resorted to type?
Code:

//This Structure is written to base of shared sections a code header..it contains function
//address and data for function calls..)
typedef struct _SUSPEND_OTHERS
{
RTLALLOCATEHEAP AllocateHeap;
NTQUERYSYSTEMINFORMATION sQuerySystemInformation;
NTSUSPENDTHREAD sSuspendThread;
NTOPENTHREAD sOpenThread;
ULONG Len;
NTSTATUS Status;
PVOID Buffer;
HANDLE TargetThread;
CLIENT_ID ClientId;
OBJECT_ATTRIBUTES oa;
SYSTEM_PROCESS_INFORMATION_EX *pProcesses;
}SUSPEND_OTHERS,*PSUSPEND_OTHERS;

//this code is then transfered using Rick Vielers parsex86.c from professional rootkits(2k7)...
//this can be accomplished in other ways but this is interesting...
void SuspendNormalExecution(SUSPEND_OTHERS SuspendThreads)
{
if(SuspendThreads.TargetThread != 0 && SuspendThreads.ClientId.UniqueProcess != 0)
{
SuspendThreads.Buffer = SuspendThreads.AllocateHeap(NtCurrentTeb()->ProcessEnvironmentBlock->ProcessHeap,HEAP_ZERO_MEMORY,0x40000);
SuspendThreads.pProcesses = (SYSTEM_PROCESS_INFORMATION_EX *)SuspendThreads.Buffer;
SuspendThreads.Status = SuspendThreads.sQuerySystemInformation(SystemProcessInformation,(PVOID)SuspendThreads.pProcesses,Sus pendThreads.Len,&SuspendThreads.Len);
for(;
{
if(SuspendThreads.ClientId.UniqueProcess != SuspendThreads.pProcesses->UniqueProcessId)
{
SuspendThreads.pProcesses = (PSYSTEM_PROCESS_INFORMATION_EX)(((BYTE *)SuspendThreads.pProcesses)+SuspendThreads.pProcesses->NextEntryOffset);
}
else
{
for(SuspendThreads.Len = 0;SuspendThreads.Len < SuspendThreads.pProcesses->NumberOfThreads;SuspendThreads.Len++)
{
if(SuspendThreads.TargetThread != SuspendThreads.pProcesses->Threads[SuspendThreads.Len].ClientId.UniqueThread)
{
InitializeObjectAttributes(&SuspendThreads.oa,0,0,0,0);
SuspendThreads.ClientId.UniqueThread = SuspendThreads.pProcesses->Threads[SuspendThreads.Len].ClientId.UniqueThread;
SuspendThreads.Status = SuspendThreads.sOpenThread(&SuspendThreads.TargetThread,THREAD_ALL_ACCESS,&SuspendThreads.oa,&SuspendThreads.ClientId);
if(NT_SUCCESS(SuspendThreads.Status))
{
SuspendThreads.Status = SuspendThreads.sSuspendThread(SuspendThreads.TargetThread,(PULONG)&SuspendThreads.Status);
continue;
}
else
{
break;
}
}
}
}
}
}
return;
}


code in Server
Code:

case SIN_WAIT_SERVER:
{
ThisEntry = SinSrvLocateClientByPid(ApiRecvMessage.Header.ClientId.UniqueProcess);
ApiRecvMessage.ClientInfo = *ThisEntry;
if(getx86Instruction((PCHAR)SuspendNormalExecution,(PCHAR)((ULONG)ThisEntry->ClientView.ViewBase+0x4),(ULONG)GetFunctionLength(SuspendNormalExecution)))
{
memset(ThisEntry->ClientView.ViewBase,(ULONG)ApiRecvMessage.Header.ClientId.UniqueThread,sizeof(ULONG));
ApiRecvMessage.Data = ThisEntry->ClientView.ViewBase;
ApiRecvMessage.StartAddress = ((ULONG)ThisEntry->ClientView.ViewBase+0x4);
ApiRecvMessage.Status = 1;
ApiReplyMessage = ApiRecvMessage;
}
break;
}

sorry Kayaker the 'good stuff' takes time(for me at least)..But I'm at a stable server implementation and (testing\adding retesting) cycle but time is a precious thing also, and I want it to work and be usable under alot of circumstances for many different task..I've got tons of boring PE structure coding ahead of me and it's going....only if TitanEngine used Native Code but failing this it can be used anyways from the position I'm in now.

See updated Code Release page for a over all listing of the 'exe' test bed..still working on adding ApiCallTables like j00ru enumerated ...

regards BanMe

Kayaker
July 3rd, 2010, 00:31
Quote:
lol I found it and its useless to me I think.. :[
Im getting returned the address 0x00000000 from fs:18h + 0x40....

sorry Kayaker the 'good stuff' takes time


Hi BanMe. Sorry, I wasn't really pushing for a sneak preview of your stuph, I was actually hoping you'd stumbled upon a new uber-definitive definition for TEB.Win32ThreadInfo and wanted you to post it if so, since that was the original subject of the post

It's one of those oddball structs with not much info about. Zairon posted a bit about it here and here

http://www.woodmann.com/forum/showthread.php?10295-Mysteries-of-win32k-amp-GDI (Post #7)
http://zairon.wordpress.com/2006/12/06/any-application-defined-hook-procedure-on-my-machine/

No matter.

Cheers,
Kayaker

BanMe
July 3rd, 2010, 16:05
But upon testing this I got a return from 0x fs:18+0x40 as 2 dwords with 0x00000000 and a bunch of INVALID memory,I might need to do some digging to see where/when this field is filled out..my 'assumption' being that 'it failed during single thread execution' this field is probably filled out when multiple threads are running or maybe this is only for GUI as I've seen alot of 'hook chaining'
when searching the term "Win32ThreadInfo"..this seems to use SetWindowsHookEx(Message(ie Window(ie Win32k.sys..))) so this field may only be usable for GUI Processes.. too many vague facts involved in this one..maybe someone has some light for the subject?

p.s. 'The Title' didnt quite relay my course of action for the information supposedly provided in Win32ThreadInfo... I found a Pascal implementation that looks pretty precise in conjuction to zairons posting,as to why I wanted to use this info, the pointer should contain a a list of running thread strutures in the process and could therefor just collect the ID's without Native API's and forward them to server for suspension..I chose a shady style with the above code, but until this pans out that will suffice.

fixs to server code.. listed above..
Code:

case SIN_WAIT_SERVER:
{
ThisEntry = SinSrvLocateClientByPid(ApiRecvMessage.Header.ClientId.UniqueProcess);
ApiRecvMessage.ClientInfo = *ThisEntry;
SuspendThreads.ClientId.UniqueProcess = ApiRecvMessage.Header.ClientId.UniqueProcess;
SuspendThreads.TargetThread = ApiRecvMessage.Header.ClientId.UniqueThread;
if(hkHook::SinSrvSetupSuspension(&SuspendThreads))
{
memcpy(ThisEntry->ClientView.ViewBase,&SuspendThreads,sizeof(SUSPEND_OTHERS));
if(getx86Instruction((PCHAR)hkHook::SuspendNormalExecution,(PCHAR)((ULONG)ThisEntry->ClientView.ViewBase+sizeof(SUSPEND_OTHERS)),(ULONG)GetFunctionLength(hkHook::SuspendNormalExecution) ))
{
ApiRecvMessage.Data = ThisEntry->ClientView.ViewBase;
ApiRecvMessage.StartAddress = ((ULONG)ThisEntry->ClientView.ViewBase+sizeof(SUSPEND_OTHERS));
ApiRecvMessage.Status = 1;
ApiReplyMessage = ApiRecvMessage;
break;
}
}
break;
}


and a new 'setup' function
Code:

bool SinSrvSetupSuspension(__inout SUSPEND_OTHERS*SuspendThreads)
{
SuspendThreads->AllocateHeap = (RTLALLOCATEHEAP)Native_GetApi(L"ntdll.dll","RtlAllocateHeap";
SuspendThreads->sQuerySystemInformation = (NTQUERYSYSTEMINFORMATION)Native_GetApi(L"ntdll.dll","NtQuerySystemInformation";
SuspendThreads->sOpenThread = (NTOPENTHREAD)Native_GetApi(L"ntdll.dll","NtOpenthread";
SuspendThreads->sSuspendThread = (NTSUSPENDTHREAD)Native_GetApi(L"ntdll.dll","NtSuspendThread";
SuspendThreads->Len = 0x40000;
if(!SuspendThreads->AllocateHeap && !SuspendThreads->sQuerySystemInformation && !SuspendThreads->sOpenThread && SuspendThreads->sSuspendThread)
{
return false;
}
return true;
}

BanMe
July 4th, 2010, 13:04
http://www.i.u-tokyo.ac.jp/edu/training/ss/lecture/new-documents/Lectures/17-Win32K/Win32K.ppt#265,9,What is a GUI thread?

Key Information gleaned from this...

KTHREAD->Win32Thread pointer.
In user mode TEB->Win32ThreadInfo
Programmatically – IsGuiThread(fConvert) – Whistler only
KTHREAD->ServiceTable initialized to ntkrnlmp!KeServiceDescriptorTable, replaced with ntkrnlmp!KeServiceDescriptorTableShadow(alternative differentiator)
CSRSS creates First GUI Thread

this breaks my current flow, and causes a protection schema to be thought of..(idea?)
Code:

#define MAX_THREADS n
HANDLE ONLY_THESE_THREADS_SHOULD_BE_RUNNING [MAX_THREADS][1];
[0]//= Main Gui Thread
[0][1]//= Main ThreadId
...so on..

'update this with a waitable locking mechanism' on call leave lockon after MAX is reached hook 'thread' and remote thread creation 'allow only from specific retn addresses, this is only if internal apis 'need' it. do apc checks of this condition by location Main Gui checking ThreadCount and ThreadIds allowing a increase of MAX_THREADS only when conditions of call are met if returning to exit thats no good.. maybe a bit more code is necessary...

So to accomplish my original goal.. What I have to do is queue a lil code to each thread in a running process to check for GUI threads reap the information I want from it return that information or 0 for non GUI and take a different course for that process..

and hmm I could parse the threads handletable and determine 'GUI-ness'...that would be more information based but would enlarge code from a lil to some.. this would be much more heuristic and tedious..