Log in

View Full Version : Server Handle Table Funtions.


BanMe
June 29th, 2009, 02:17
new source for the handle table.. commented for your further enjoyment...

Code:

//The Usage of a Handle Table in my opinion is basiclly a
//global lookup for handles so that no Global Handles
//are needed to pass from thread to thread..
//this "can" and eventually will be used
//to reduce the amount of the Local Parameters inheritant
//in alot of functions used by the my "Subsystem"

typedef enum _SIN32_OBJECT_TYPE
{
ObProcess,//remote process's are stored here no sense to store and handle to self..
ObThread,//Type Specifier for Internal Threads
ObThread_Remote,//Type Specifier for Remote Thread
ObEvent_Comm,//Type Specifier for the Handle to The Internal "Permanent" Event for Notification
ObEvent_Sync,//...for the Internal "Permanent" Event for Synchronization
ObCrit_Section,//..critical sections for later usage..
ObMem_Heap,//Heap Type(Base or Part is determined by Object State)..so read carefully
ObMem_Virtual,//Virtual Memory Type
ObMem_Section,//Section Type
ObMem_Mapped,//Mapped Section Type
ObLpc,
ObLpc_Message
}SIN32_OBJECT_TYPE;

typedef enum _SIN32_OBJECT_STATE
{
ObPSuspended,//Process is Suspended..(All Threads!!)
ObPRunning,//Process is Running
ObTSuspended,//Thread Suspended
ObTRunning,//..Running..
ObSignaled,//Event Signaled
ObWaiting,//Event Waiting..
ObMemBase,//Heap or Virtual Memory or Section or Mapped Base Address
//this must be set to discern between Base Address and Part Address!!
ObMemPart,//Part:A RVA, what RtlAllocateHeap returns so on so forth..
ObLpcConnect,
ObDeadAndGone//Object Type for a handle that should no longer be in the table...
}SIN32_OBJECT_STATE;
//Native_InitHandleTable
//1 parameter poiner to the memory that will hold the handle table..
//returns true is table not equal 0..
//false if it does...
__checkReturn bool Native_InitHandleTable(__inout RTL_HANDLE_TABLE* HandleTable)
{
//Initialiaze the A HandleTable
//1st parameter for RtlInitializeHandleTable is the
//max of number of entries 0x4096/10 = 0x409 = 1033 entries max
//2nd parameter is the size of each entry.
//3rd is ptr to the region where the table will be initialized.
RtlInitializeHandleTable(0x4096/sizeof(SIN32_HANDLE_TABLE_ENTRY),sizeof(SIN32_HANDLE_TABLE_ENTRY),HandleTable);
if(HandleTable != 0)
{
return true;
}
return false;
}
__checkReturn bool Native_DestroyHandleTable(__in void* ServerHeap)
{
if(NT_SUCCESS(RtlDestroyHeap(ServerHeap)))
{ return true;
}
return false;
}
//This Function Add's the first Entry into the HandleTable and links it with the next
//This was designed with the notion that I was going to able to use RtlIsValidIndexHandle
//for the querying of the table but that didnt go as planned and
//I just left these 2 function like this..the problem was with test byte ptr[eax],1
//as I discussed in further detail in my post "A Snippet of Time..Unedited"
//after that discussion I whipped these out in order to bypass my problem with RtlIsValidHandle
//which is internally called by RtlIsValidIndexHandle, I also did a few other little experiment's
//in order to bypass this hurdle. the first was I changed the structure around
//a bit and added a BYTE union dword at the head of the structure then while adding them
//i changed the first BYTE to 1.. this actually bypassed RtlIsValidHandleIndex
//on the first queryloop but failed on the next..so that was useless to me
//so i changed the structre back.the next thing i tried was these 2 functions,
//with the 'idea' that these should be able to give me what I wanted.
//I wanted to do it properly. but that failed..numerous times(including with these.)

SIN32_HANDLE_TABLE_ENTRY *Native_AddFirstEntry(__in void* ServerHandleTable,__in HANDLE hObject,__in unsigned short HandleType,__in unsigned short HandleState)
{
//Native_AddFirstEntry
//1st parameter is a void * to the ServerHandleTable
//2nd Parameter is the Handle of the object to store in the Table
//3rd parameter is a USHORT used to describe the TYPE of the Handle
//4th parameter is a USHORT used to describe the STATE of the Handle
ULONG HandleIndex = 0;
SIN32_HANDLE_TABLE_ENTRY* HandleEntry = {0};
//add first entry
HandleEntry = (SIN32_HANDLE_TABLE_ENTRY*)RtlAllocateHandle((RTL_HANDLE_TABLE*)ServerHandleTable,&HandleIndex);
HandleEntry->Handle = hObject;
HandleEntry->HandleState = HandleState;
HandleEntry->HandleType = HandleType;
HandleEntry->HandleIndex = HandleIndex;
//add entry for Next Handle
HandleEntry->Next = (_SIN32_HANDLE_TABLE_ENTRY*)RtlAllocateHandle((RTL_HANDLE_TABLE*)ServerHandleTable,&HandleIndex);
__asm push HandleEntry;
HandleEntry = (SIN32_HANDLE_TABLE_ENTRY*)HandleEntry->Next;
//fill out the next entries HandleIndex
HandleEntry->HandleIndex = HandleIndex;
__asm pop HandleEntry;
//return the Entry to pass to the Next Function.
return HandleEntry;
}
SIN32_HANDLE_TABLE_ENTRY *Native_AddNextEntry(__in void* ServerHandleTable,__in HANDLE hObject,__in unsigned short HandleType,__in unsigned short HandleState,__inout SIN32_HANDLE_TABLE_ENTRY* HandleEntry)
{
ULONG HandleIndex = 0;
SIN32_HANDLE_TABLE_ENTRY* TempEntry = {0};
//make temp = the 2nd entry
TempEntry = (SIN32_HANDLE_TABLE_ENTRY*)HandleEntry->Next;
//if not TempEntry->Next or the 3rd Entry allocate one
if(!TempEntry->Next)
{
TempEntry->Next = (_SIN32_HANDLE_TABLE_ENTRY*)RtlAllocateHandle((RTL_HANDLE_TABLE*)ServerHandleTable,&HandleIndex);
}
//fill out the passed in HandleEntry->Next
TempEntry->Handle = hObject;
TempEntry->HandleState = HandleState;
TempEntry->HandleType = HandleType;
TempEntry->HandleIndex = HandleIndex;
//return the Next "Clean" entry to pass back into AddNextEntry
TempEntry = (SIN32_HANDLE_TABLE_ENTRY*)HandleEntry->Next;
return TempEntry;
}
//this needs work..
__checkReturn BOOLEAN Native_DeleteHandleEntry(__in void* ServerHandleTable,__in ULONG HandleIndex)
{
RTL_HANDLE_TABLE_ENTRY* RtlEntry = {0};
if(RtlIsValidIndexHandle((RTL_HANDLE_TABLE*)ServerHandleTable,HandleIndex,&RtlEntry))
{
return RtlFreeHandle((RTL_HANDLE_TABLE*)ServerHandleTable,RtlEntry);
}
return FALSE;
}
//see Indirect __stdcall thread on woodmann forums for further info..
__declspec(naked) void CallOutRecaptureRoutine(__in void* FunctionPtr,__in_opt void* ...)
{
__asm
{
POP ECX //;pop return address
POP EDX //;pop function pointer
PUSH ECX //;place function return back on stack
CALL EDX //;call function
XOR ECX,ECX //;zero ecx
ADD ECX,18 //;add 18
MOV EBX,DWORD PTR FS:[ECX] //;NtCurrentTeb to ebx
//;return the value of call of call to a generally
//;read/writable area Teb.NtTib.ArbritraryUserPointer
MOV DWORD PTR DS:[EBX+14],EAX
PUSH 0
PUSH -2
CALL NtSuspendThread
}
}
//this function is supposed to emulate behavior similar to RtlRemoteCall but it still needs a little work.
NTSTATUS Native_DispatchRecaptureThread(__in void* ServerHandleTable,__in ULONG CallSite,__in void *Param)
{
ULONG HandleIndex = 0;
PVOID HeapPart = 0;
NTSTATUS Status = 0;
HANDLE DormantThread = INVALID_HANDLE_VALUE;
CONTEXT Context = {0};
DormantThread = Native_GetHandleTableHandle(ServerHandleTable,ObThread,ObTSuspended);
if(DormantThread != INVALID_HANDLE_VALUE)
{
Context.ContextFlags = CONTEXT_FULL;
Status = NtGetContextThread(DormantThread,&Context);
Status = NtSetContextThread(DormantThread,&Context);
if(NT_SUCCESS(Status))
{
return NtResumeThread(DormantThread,0);
}
}
return STATUS_UNSUCCESSFUL;
}
//needs work.
__checkReturn bool Native_UpdateHandleState(__in void *ServerHandleTable,__in ULONG HandleIndex,__in unsigned short HandleState)
{
SIN32_HANDLE_TABLE_ENTRY * HandleEntry = {0};
if(RtlIsValidIndexHandle((RTL_HANDLE_TABLE*)ServerHandleTable,HandleIndex,(PRTL_HANDLE_TABLE_ENTRY*)&HandleEntry))
{
HandleEntry->HandleState = HandleState;
return true;
}
return false;
}
//I explained this above in some ways..
HANDLE Native_GetHandleTableHandle(__in void* ServerHandleTable,__in unsigned short HandleType,__in unsigned short DesiredState)
{
ULONG HandleIndex = 0;
void *Reusable = 0;
SIZE_T SizeRegion = 0x4096;
CLIENT_ID ClientId = {0};
RTL_HANDLE_TABLE *TempTable ={0};
SIN32_HANDLE_TABLE_ENTRY *HandleEntry = {0};
CollectEntry:
//this always fails
if(RtlIsValidIndexHandle((RTL_HANDLE_TABLE*)ServerHandleTable,HandleIndex,(PRTL_HANDLE_TABLE_ENTRY*)&HandleEntry))
{
if(HandleEntry->HandleType == HandleType && HandleEntry->HandleState == DesiredState)
{
return HandleEntry->Handle;
}
else
{
HandleIndex++;
__asm jmp CollectEntry;
}
}
HandleIndex = 0;
//Get our HandleTable
TempTable = CONTAINING_RECORD(ServerHandleTable,RTL_HANDLE_TABLE,MaximumNumberOfHandles);
//get the First entry
HandleEntry = CONTAINING_RECORD(TempTable->CommittedHandles+(HandleIndex*sizeof(SIN32_HANDLE_TABLE_ENTRY)),SIN32_HANDLE_TABLE_ENTRY,Next);
ForceCollectEntry:
//check if we succeeded..somewhat..
if(HandleEntry)
{
//check the type and desired state of current Entry
if(HandleEntry->HandleType == HandleType && HandleEntry->HandleState == DesiredState)
{
//if matched return the handle..
return HandleEntry->Handle;
}
else
{
//get the next Entry and jump back to recheck it..
HandleEntry = (SIN32_HANDLE_TABLE_ENTRY*)HandleEntry->Next;
__asm jmp ForceCollectEntry;
}
}
//if all else fails just try to return something that can be used..
switch(HandleType)
{
case ObMem_Virtual:
{
HandleIndex = NtAllocateVirtualMemory(NtCurrentProcess(),&Reusable,0,&SizeRegion,MEM_COMMIT,PAGE_READWRITE);
if(NT_SUCCESS(HandleIndex))
{
return Reusable;
}
else
{
return INVALID_HANDLE_VALUE;
}
}
case ObMem_Heap:
{
if(DesiredState == ObMemPart)
{
Reusable = RtlAllocateHeap(RtlProcessHeap(),HEAP_GENERATE_EXCEPTIONS,SizeRegion);
return Reusable;
}
else
{
return RtlProcessHeap();
}
}
case ObThread:
{
if(DesiredState == ObTSuspended)
{
HandleIndex = RtlCreateUserThread(NtCurrentProcess(),0,true,0,0,0,(PUSER_THREAD_START_ROUTINE)Native_AcceptConnect ionRequest,0,&Reusable,&ClientId);
if(NT_SUCCESS(HandleIndex))
{
return Reusable;
}
}
else
{
return INVALID_HANDLE_VALUE;
}
}
default:
return INVALID_HANDLE_VALUE;
}
return INVALID_HANDLE_VALUE;
}

BanMe
July 1st, 2009, 17:07
*update* See Above...