Hi
You could also get the offset of the CLIENT_ID structure dynamically in a separate IOCTL call, without the use of hard-coded version specific offsets. This is just a variation on the code snippet popularized by Hoglund/Russinovich to get the offset of EProcess->ImageFileName during DriverEntry.
For reference, here's the latter method
Code: Select all/***********************************************************
GetOffsetOfProcessName
Find offset of EProcess->ImageFileName, irrespective of OS version
(Hoglund/Russinovich)
When called from DriverEntry we are in the System context,
so we simply search the current EPROCESS structure
for the process string "system"
***********************************************************/
ULONG GetOffsetOfProcessName()
{
ULONG ul_offset;
PEPROCESS CurrentEProcess;
////////////////////////////////////////////////////
CurrentEProcess = PsGetCurrentProcess();
// EPROCESS considered no larger than a page size.
for(ul_offset = 0; ul_offset < PAGE_SIZE; ul_offset++)
{
if( !strncmp( "System", (PCHAR) CurrentEProcess + ul_offset,
strlen("System")))
{
return ul_offset;
}
}
return 0;
}
Here's a similar method to get the Cid, except called through an IOCTL, not DriverEntry:
Code: Select all/***********************************************************
GetOffsetOfCid
Obtain offset of EThread->Cid
http://computer.forensikblog.de/
_ETHREAD version 5.0.2195.7045 Microsoft Windows 2000.
+0x1e0 Cid : struct _CLIENT_ID
+0x000 UniqueProcess
+0x004 UniqueThread
_ETHREAD Version 5.1.2600.0 Windows XP.
+0x1ec Cid : struct _CLIENT_ID
_ETHREAD Version 5.2.3790.0 Microsoft Windows Server 2003
+0x1f4 Cid : struct _CLIENT_ID
***********************************************************/
ULONG GetOffsetOfCid()
{
ULONG ul_offset;
ULONG CurrentProcessId;
PETHREAD CurrentEThread;
////////////////////////////////////////////////////
CurrentProcessId = (ULONG)PsGetCurrentProcessId();
CurrentEThread = PsGetCurrentThread();
// ETHREAD considered no larger than a page size.
for(ul_offset = 0; ul_offset < PAGE_SIZE; ul_offset++)
{
if( *(ULONG*) ( (BYTE*)CurrentEThread + ul_offset) == CurrentProcessId )
{
// found _CLIENT_ID.UniqueProcess
return ul_offset;
}
}
return 0;
}
You can develop similar routines to get the offsets of other fields as well, where possible. Here's one for Win32StartAddress:
Code: Select all/***********************************************************
GetOffsetOfWin32StartAddress
Obtain offset of EThread->Win32StartAddress by scanning
for our own GUI image Entry Point (EP)
This gives us an OS version independant way of obtaining
the absolute offset in the ETHREAD structure to locate
the starting address of a thread.
ZwQueryInformationThread/ThreadQuerySetWin32StartAddress
might work but is not exported by Win2K.
***********************************************************/
ULONG GetOffsetOfWin32StartAddress()
{
ULONG ul_offset;
PEPROCESS CurrentEProcess;
PETHREAD CurrentEThread;
PIMAGE_NT_HEADERS NtHeaders; // "PE"
ULONG BaseAddress;
ULONG lpStartAddress;
////////////////////////////////////////////////////
__try {
// Get the Entry Point from our own GUI app
CurrentEProcess = PsGetCurrentProcess();
BaseAddress = (ULONG) CurrentEProcess->Peb->ImageBaseAddress;
NtHeaders = RtlImageNtHeader((PVOID) BaseAddress);
lpStartAddress = BaseAddress + NtHeaders->OptionalHeader.AddressOfEntryPoint;
////////////////////////////////////////////////////
// Find offset of ETHREAD.Win32StartAddress
CurrentEThread = PsGetCurrentThread();
// ETHREAD considered no larger than a page size.
for(ul_offset = 0; ul_offset < PAGE_SIZE; ul_offset++)
{
if( *(ULONG*) ( (BYTE*)CurrentEThread + ul_offset) == lpStartAddress )
{
// found Win32StartAddress
return ul_offset;
}
}
//=============================================================
} __except (EXCEPTION_EXECUTE_HANDLER) {
DbgPrint ("HOOK: ERROR ExceptionCode: %x\n", GetExceptionCode() );
} // end __try{
return 0;
}
btw, nice board guys, glad to see it's established itself ;)
Regards,
Kayaker