Sunday, August 28, 2011

Hook Specials 21 : Reappear SSDT-HOOK shadow to compile succeed

Author:ASMHacker
Because need to hook a api, Write the article.

The way is usual used on Kingsoft and AVP about Hook shadow ssdt, The code passed compile ...... But some people do wrong that use it, So it cut something. Study ssdt or kernel can use it. I only cut a little .

//#include "ntddk.h"
//function and global varable of driver is default non-page.
#define HWND       ULONG
#define DWORD       ULONG
#define WORD       USHORT
#define BYTE       UCHAR
#define UINT       ULONG
#define ProcessNameOffset    0x174
//----------------------------------------------------------------------------------------------------------
#define NT_DEVICE_NAME L"\\Device\\hook" // device name and symbolic link name
#define DOS_DEVICE_NAME L"\\DosDevices\\hook"
#define ObjectNameInformation 1

#define BASE_PROCESS_PEB_OFFSET     0x01B0
#define BASE_PEB_PROCESS_PARAMETER_OFFSET 0x0010
#define BASE_PROCESS_PARAMETER_FULL_IMAGE_NAME 0x003C
//----------------------------------------------------------------------------------------------------------
#pragma pack(1)
typedef struct _SYSTEM_SERVICE_TABLE
{
unsigned int *ServiceTableBase;
unsigned int *ServiceCounterTableBase; //Used only checked build
unsigned int NumberOfServices;
unsigned char *ParamTableBase;
}
SYSTEM_SERVICE_TABLE,
*PSYSTEM_SERVICE_TABLE,
**PPSYSTEM_SERVICE_TABLE;
#pragma pack()
//-----------------------------------------------------------------------------------------------------------
#pragma pack(1)
typedef struct _SERVICE_DESCRIPTOR_TABLE_
{
SYSTEM_SERVICE_TABLE ntoskrnl; // ntoskrnl.exe ( native api )
SYSTEM_SERVICE_TABLE win32k;    // win32k.sys (gdi/user support)
SYSTEM_SERVICE_TABLE Table3;    // not used
SYSTEM_SERVICE_TABLE Table4;    // not used
}
SYSTEM_DESCRIPTOR_TABLE,
*PSYSTEM_DESCRIPTOR_TABLE,
**PPSYSTEM_DESCRIPTOR_TABLE;
#pragma pack()
//------------------------------------------------------------------------------------------------------------
#pragma pack(1)
typedef struct _SRVTABLE {
PVOID           *ServiceTable;
ULONG           LowCall;       
ULONG           HiCall;
PVOID           *ArgTable;
} SRVTABLE, *PSRVTABLE;
#pragma pack()
//--------------------------------------------------------------------------------------------------
#pragma pack(1)
typedef struct _SYSTEM_HANDLE_INFORMATION_EX
{
ULONG NumberOfHandles;
SYSTEM_HANDLE_INFORMATION Information[1];
}SYSTEM_HANDLE_INFORMATION_EX, *PSYSTEM_HANDLE_INFORMATION_EX;
#pragma pack()
//-------------------------------------------------------------------------------------------------------------------
NTKERNELAPI BOOLEAN KeAddSystemServiceTable (PULONG_PTR Base, PULONG Count OPTIONAL, ULONG Limit, PUCHAR Number, ULONG Index) ;
//------------------------------------------------------------------------------------------------------------
//////函数申明
VOID DrvUnload(PDRIVER_OBJECT);
NTSTATUS DriverEntry(PDRIVER_OBJECT, PUNICODE_STRING);
NTSTATUS IoDispatch(PDEVICE_OBJECT, PIRP);
HANDLE GetCsrPid();
PSYSTEM_DESCRIPTOR_TABLE FindShadowTable(void);
//------NtUserFindWindowEx------------------------------------------------------------------------------------------------------------------------------------------------------
ULONG NewNtUserFindWindowEx(HWND hwndParent,HWND hwndChild,PUNICODE_STRING pstrClassName OPTIONAL,PUNICODE_STRING pstrWindowName OPTIONAL,DWORD dwType);
typedef ULONG (*NTUSERFINDWINDOWEX)(HWND hwndParent, HWND hwndChild, PUNICODE_STRING pstrClassName OPTIONAL, PUNICODE_STRING pstrWindowName OPTIONAL, DWORD dwType);
//NTUSERFINDWINDOWEX OldNtUserFindWindowEx=(NTUSERFINDWINDOWEX *)ExAllocatePool(NonPagedPool, sizeof(NTUSERFINDWINDOWEX));
NTUSERFINDWINDOWEX OldNtUserFindWindowEx;
//--------------------------------------------------------------------------------------------------
//Global variable
PSYSTEM_DESCRIPTOR_TABLE ShadowTable = NULL;
//-----------------------------------------------------------------------------------------------------------
extern PSRVTABLE KeServiceDescriptorTable;
//__declspec(dllimport) KeAddSystemServiceTable(LPSSTAT,BOOL,DWORD,LPSSTPT,DWORD);
//-----------------------------------------------------------------------------------------------------------

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING RegistryPath)
{
KIRQL OldIrql;
PDEVICE_OBJECT pDeviceObject = NULL;
NTSTATUS ntStatus;
UNICODE_STRING uniNtNameString, uniWin32NameString;
int i;
PEPROCESS EProcess;

RtlInitUnicodeString( &uniNtNameString, NT_DEVICE_NAME );
ntStatus = IoCreateDevice (
   pDriverObject,
   0, // DeviceExtensionSize
   &uniNtNameString,
   FILE_DEVICE_UNKNOWN, //
   0,       // No standard device characteristics
   FALSE,      // not exclusive device
   &pDeviceObject
   );
if( !NT_SUCCESS(ntStatus) )
{
   return ntStatus;
}

// create dispatch points for create/open, close, unload
pDriverObject->DriverUnload = DrvUnload;

RtlInitUnicodeString( &uniWin32NameString, DOS_DEVICE_NAME );
ntStatus = IoCreateSymbolicLink( &uniWin32NameString, &uniNtNameString );
if (!NT_SUCCESS(ntStatus))
{
   IoDeleteDevice( pDriverObject->DeviceObject );
}

for( i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++ )
   pDriverObject->MajorFunction[i] = IoDispatch;

KeEnterCriticalRegion();
ShadowTable = (PSYSTEM_DESCRIPTOR_TABLE)FindShadowTable();
KeLeaveCriticalRegion();
if(ShadowTable==0)
{
   DbgPrint("Can't find ShadowTable");
   return STATUS_UNSUCCESSFUL;
}
else
{
   ntStatus = PsLookupProcessByProcessId(GetCsrPid(), &EProcess);
   if (!NT_SUCCESS( ntStatus ))
   {
    DbgPrint("PsLookupProcessByProcessId()\n");
    return ntStatus;
   }
   KeAttachProcess(EProcess);
   DbgPrint("ntoskrnl Address:\t 0x%08x\n", ShadowTable->ntoskrnl);
   DbgPrint("win32k   Address:\t 0x%08x\n", ShadowTable->win32k);
   DbgPrint("Table3   Address:\t 0x%08x\n", ShadowTable->Table3);
   DbgPrint("Table4   Address:\t 0x%08x\n\r\n", ShadowTable->Table4);
   DbgPrint("NtUserFindWindowEx Address: 0x%08x\n", ShadowTable->win32k.ServiceTableBase[0x17a]);
   //Lifting IRQ prevent break
   if(KeGetCurrentIrql() <= DISPATCH_LEVEL)
    KeRaiseIrql(DISPATCH_LEVEL,&OldIrql);
   //Disable memory protectiong mechanism
 
   __asm
   {
    push eax
     mov eax,CR0
     and eax,not 0x10000
     mov CR0,eax
     pop eax
     cli
   }
   ///
   ///hook something
   ///
   OldNtUserFindWindowEx=(NTUSERFINDWINDOWEX)ShadowTable->win32k.ServiceTableBase[0x17a];
   (NTUSERFINDWINDOWEX)ShadowTable->win32k.ServiceTableBase[0x17a]=NewNtUserFindWindowEx;
   //Start using memory protection mechanism
   __asm
   {
    sti
     push eax
     mov eax,CR0
     xor eax,0x10000
     mov CR0,eax
     pop eax
   }
   KeLowerIrql(OldIrql);
}
return STATUS_SUCCESS;
}

NTSTATUS IoDispatch(PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp)
{
NTSTATUS iStatus = STATUS_SUCCESS;

pIrp->IoStatus.Status = iStatus;
pIrp->IoStatus.Information = 0;
IoCompleteRequest( pIrp, IO_NO_INCREMENT );
return iStatus;
}

VOID DrvUnload(PDRIVER_OBJECT pDriverObject)
{
// KIRQL OldIrql;
PDEVICE_OBJECT pDeviceObject;
UNICODE_STRING uniWin32NameString;
pDeviceObject = pDriverObject->DeviceObject;

// if(KeGetCurrentIrql() <= DISPATCH_LEVEL)
// KeRaiseIrql(DISPATCH_LEVEL,&OldIrql);
//Disable memory protection mechanism
__asm
{
   push eax
    mov eax,CR0
    and eax,not 0x10000
    mov CR0,eax
    pop eax
    cli
}

///
///在这里做一些hook
(NTUSERFINDWINDOWEX)ShadowTable->win32k.ServiceTableBase[0x17a]=OldNtUserFindWindowEx;
//Use Interlocking to change value of pointer, safer?
//InterlockedExchangePointer(ShadowTable->win32k.ServiceTableBase[0x17a],&OldNtUserFindWindowEx);
//Start using memory protect mechanism
__asm
{
   sti
    push eax
    mov eax,CR0
    xor eax,0x10000
    mov CR0,eax
    pop eax
}
// KeLowerIrql(OldIrql);
RtlInitUnicodeString( &uniWin32NameString, DOS_DEVICE_NAME );
IoDeleteSymbolicLink( &uniWin32NameString );
IoDeleteDevice( pDriverObject->DeviceObject );
}
//--------------------------------------------------------------------------------------------------

PSYSTEM_DESCRIPTOR_TABLE FindShadowTable(void)
{
unsigned char *      pCheckArea = (unsigned char * ) KeAddSystemServiceTable;
int         i;
PSRVTABLE   pSrvTable = NULL;

for (i=0; i<100; i++)
{
   __try
   {
    pSrvTable = *(PSRVTABLE*)pCheckArea;
    if (
     !MmIsAddressValid(pSrvTable)            ||
     (pSrvTable == KeServiceDescriptorTable) ||
     (memcmp(pSrvTable, KeServiceDescriptorTable, sizeof (*pSrvTable)) != 0)
     )
    {
     pCheckArea++;
     pSrvTable = NULL;
    }
   }
   __except(EXCEPTION_EXECUTE_HANDLER)
   {
    pSrvTable = NULL;
   }
   if (pSrvTable)
    break;
}

if (pSrvTable == NULL)
{
   pSrvTable = (PSRVTABLE)((char*)KeServiceDescriptorTable-0x230);
   if (MmIsAddressValid(pSrvTable))
   {
    __try
    {
     if (memcmp(pSrvTable, KeServiceDescriptorTable, sizeof (*pSrvTable)) != 0)
      pSrvTable = NULL;
    }
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
     pSrvTable = NULL;
    }
   }
   else
   {
    pSrvTable = NULL;
   }
}

return (PSYSTEM_DESCRIPTOR_TABLE)pSrvTable;
}


PVOID GetInfoTable(ULONG ATableType)
{
ULONG mSize = 0x4000;
PVOID mPtr = NULL;
NTSTATUS St;
do
{
   mPtr = ExAllocatePool(PagedPool, mSize);
   memset(mPtr, 0, mSize);
   if (mPtr)
   {
    St = ZwQuerySystemInformation(ATableType, mPtr, mSize, NULL);
   } else return NULL;
   if (St == STATUS_INFO_LENGTH_MISMATCH)
   {
    ExFreePool(mPtr);
    mSize = mSize * 2;
   }
} while (St == STATUS_INFO_LENGTH_MISMATCH);
if (St == STATUS_SUCCESS) return mPtr;
ExFreePool(mPtr);
return NULL;
}

HANDLE GetCsrPid()
{
    HANDLE                        Process, hObject;
    HANDLE                        CsrId = (HANDLE)0;
    OBJECT_ATTRIBUTES            obj;
    CLIENT_ID                    cid;
    UCHAR                        Buff[0x100];
    POBJECT_NAME_INFORMATION      ObjName = (PVOID)&Buff;
    PSYSTEM_HANDLE_INFORMATION_EX Handles;
    ULONG                        r;

    Handles = GetInfoTable(SystemHandleInformation);

    if (!Handles) return CsrId;

    for (r = 0; r < Handles->NumberOfHandles; r++)
    {
        if (Handles->Information[r].ObjectTypeNumber == 21) //Port object
        {
            InitializeObjectAttributes(&obj, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
           
            cid.UniqueProcess = (HANDLE)Handles->Information[r].ProcessId;
            cid.UniqueThread = 0;
  
            if (NT_SUCCESS(NtOpenProcess(&Process, PROCESS_DUP_HANDLE, &obj, &cid)))
            {
                if (NT_SUCCESS(ZwDuplicateObject(Process,
      (HANDLE)Handles->Information[r].Handle,
      NtCurrentProcess(),
      &hObject,
      0, 0, DUPLICATE_SAME_ACCESS)))
                {
                    if (NT_SUCCESS(ZwQueryObject(hObject,
       ObjectNameInformation,
       ObjName,
       0x100, NULL)))
                    {
                        if (ObjName->Name.Buffer &&
                            !wcsncmp(L"\\Windows\\ApiPort", ObjName->Name.Buffer, 20))
                        {
                            CsrId = (HANDLE)Handles->Information[r].ProcessId;
                        }
                    }
    
                    ZwClose(hObject);
                }
   
                ZwClose(Process);
            }
        }
    }

    ExFreePool(Handles);

    return CsrId;
}


PCWSTR GetProcessFullName()
{
DWORD dwAddress;
if(KeGetCurrentIrql() != PASSIVE_LEVEL)
   return NULL;
dwAddress = (DWORD)PsGetCurrentProcess();
if(dwAddress == 0 || dwAddress == 0xFFFFFFFF)
   return NULL;
dwAddress += BASE_PROCESS_PEB_OFFSET;
if((dwAddress = *(DWORD*)dwAddress) == 0) return 0;
dwAddress += BASE_PEB_PROCESS_PARAMETER_OFFSET;
if((dwAddress = *(DWORD*)dwAddress) == 0) return 0;
dwAddress += BASE_PROCESS_PARAMETER_FULL_IMAGE_NAME;
if((dwAddress = *(DWORD*)dwAddress) == 0) return 0;
return (PCWSTR)dwAddress;
}


PVOID PsGetProcessSectionBaseAddress(PEPROCESS Process);
//---------------------------------------------------------------------------------------------------
ULONG NewNtUserFindWindowEx(HWND hwndParent, HWND hwndChild, PUNICODE_STRING pstrClassName OPTIONAL, PUNICODE_STRING pstrWindowName OPTIONAL, DWORD dwType)
{
KIRQL OldIrql;
ULONG result;
if(KeGetCurrentIrql() <= DISPATCH_LEVEL)
   KeRaiseIrql(DISPATCH_LEVEL,&OldIrql);
// UNICODE_STRING filtter;
// PUNICODE_STRING p=&filtter;
// RtlInitUnicodeString( &filtter, L"GAMECLIENT");
DbgPrint("Window title:\t%ws",pstrWindowName->Buffer);
DbgPrint("Window class:\t%ws",pstrClassName->Buffer);
DbgPrint( "Caller path\r\n%ws",GetProcessFullName());
DbgPrint( "---------------------------------------------------------");
result=OldNtUserFindWindowEx(hwndParent,hwndChild,pstrClassName,pstrWindowName,dwType);
return result;
}
//C:\mydrivers\ShadowSSDT_Hook\objchk\i386\ShadowSSDT.sys

I don't know why this, each hook succeed. But unload to show BSOD...

Error code INVALIDPROCESSATTACH_ ATTEMPT

I thought for a long time, no way out solve final...我的小笨脑想了很久,最终还是没办法解决...I guess KeAttachProcess behind no use KeDetachProcess,  hope past master help me.


1 comment:

  1. If i try this code for windows 7 32 bit i got an error i have changed the callnumber of apis

    ReplyDelete