#include <ntddk.h>
#include <string.h>

#define WINAPI __stdcall

typedef unsigned long DWORD;
typedef DWORD *PDWORD;
typedef unsigned short WORD;
typedef WORD *PWORD;
typedef unsigned char BYTE;
typedef BYTE *PBYTE;

typedef struct _HANDLE_TABLE
{
    ULONG TableCode;
    PVOID QuotaProcess;
    PVOID UniqueProcessId;
    ULONG HandleTableLock[4];
    LIST_ENTRY HandleTableList;
    ULONG HandleContentionEvent;
    PVOID DebugInfo;
    LONG ExtraInfoPages;
    ULONG FirstFreeHandle;
    ULONG LastFreeHandle;
    ULONG NextHandleNeedingPool;
    LONG HandleCount;
    union {
	ULONG Flags;
	ULONG StrictFIFO:1;
    };
} HANDLE_TABLE, *PHANDLE_TABLE;

typedef struct _HANDLE_TABLE_ENTRY
{
    union
    {
        PVOID Object;
        ULONG ObAttributes;
        PULONG AuditMask;
        ULONG Value;
    };
    union
    {
        ULONG GrantedAccess;
        struct
        {
            WORD GrantedAccessIndex;
            WORD CreatorBackTraceIndex;
        };
        LONG NextFreeTableEntry;
    };
} HANDLE_TABLE_ENTRY, *PHANDLE_TABLE_ENTRY;

typedef struct _OBJECT_TYPE_INITIALIZER {
    USHORT Length;
    BOOLEAN UseDefaultObject;
    BOOLEAN Reserved;
    ULONG InvalidAttributes;
    UCHAR GenericMapping[0x10];
    ULONG ValidAccessMask;
    BOOLEAN SecurityRequired;
    BOOLEAN MaintainHandleCount;
    BOOLEAN MaintainTypeList;
    USHORT PoolType;
    ULONG DefaultPagedPoolCharge;
    ULONG DefaultNonPagedPoolCharge;
    PVOID DumpProcedure;
    PVOID OpenProcedure;
    PVOID CloseProcedure;
    PVOID DeleteProcedure;
    PVOID ParseProcedure;
    PVOID SecurityProcedure;
    PVOID QueryNameProcedure;
    PVOID OkayToCloseProcedure;
} OBJECT_TYPE_INITIALIZER, *POBJECT_TYPE_INITIALIZER;

typedef struct _OBJECT_HEADER
{
    LONG PointerCount;
    union
    {
        LONG HandleCount;
        PVOID NextToFree;
    };
    POBJECT_TYPE Type;
    UCHAR NameInfoOffset;
    UCHAR HandleInfoOffset;
    UCHAR QuotaInfoOffset;
    UCHAR Flags;
    union
    {
        PVOID ObjectCreateInfo;
        PVOID QuotaBlockCharged;
    };
    PVOID SecurityDescriptor;
    QUAD Body;
} OBJECT_HEADER, *POBJECT_HEADER;

typedef struct _OBJECT_HEADER_NAME_INFO
{
    PVOID Directory;
    UNICODE_STRING Name;
    ULONG QueryReferences;
    ULONG Reserved2;
    ULONG DbgReferenceCount;
} OBJECT_HEADER_NAME_INFO, *POBJECT_HEADER_NAME_INFO;

VOID OnUnload(IN PDRIVER_OBJECT pDriverObject);
NTSTATUS OnStubDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
DWORD FindProcessEPROC(int Pid);
VOID listHandle(DWORD tableHandle, PDWORD Handle);

NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING RegistryPath) {
    NTSTATUS    	Status = 0;
    DWORD		SysEproc, PEB, tableHandle, Handle = 0;
    PHANDLE_TABLE 	ObjectTable;
    ULONG 		i;
	
    pDriverObject->DriverUnload = OnUnload;

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

    SysEproc = FindProcessEPROC(4);
    ObjectTable = (PHANDLE_TABLE)*((PDWORD)(SysEproc+0xc4));

    DbgPrint("Object table adresse: 0x%x (%d handle)\n\n", ObjectTable, ObjectTable->HandleCount);
    tableHandle = ObjectTable->TableCode;

    if((ObjectTable->TableCode & 1) < 1) {
	listHandle(tableHandle, &Handle);
    } else {
	tableHandle |= 0x80000000;
	tableHandle &= 0xfffffff8;
	while(*(PDWORD)tableHandle != 0) {
		listHandle(*(PDWORD)tableHandle, &Handle);
		((PDWORD)tableHandle)++;
	}
    }
	
    return Status;
}

VOID OnUnload(IN PDRIVER_OBJECT pDriverObject) {
    DbgPrint("Unload...");
}

NTSTATUS OnStubDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
    Irp->IoStatus.Status = STATUS_SUCCESS;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return STATUS_SUCCESS;
}

DWORD FindProcessEPROC (int Pid) 
{ 
    DWORD 	eproc       = 0x00000000;  
    int   	current_PID = 0; 
    int   	start_PID   = 0;  
    int   	i	    = 0; 
    PLIST_ENTRY plist_active_procs; 
 
    if (Pid == 0) 
	return Pid; 
 
    eproc = (DWORD)PsGetCurrentProcess(); 
    start_PID = *((DWORD*)(eproc+0x84)); 
    current_PID = start_PID; 
 
    while(1) 
    { 
	if(Pid == current_PID) 
		return eproc; 
	else if((i >= 1) && (start_PID == current_PID)) 
		return 0x00000000; 
	else { 
		plist_active_procs = (LIST_ENTRY *) (eproc+0x88); 
		eproc = (DWORD) plist_active_procs->Flink; 
		eproc = eproc - 0x88; 
		current_PID = *((int *)(eproc+0x84)); 
		i++; 
	} 
    } 
}

VOID listHandle(DWORD tableHandle, PDWORD Handle) {
    PHANDLE_TABLE_ENTRY 	entryHandle;
    POBJECT_HEADER 		entryHeadObj, typeHeadObj;
    POBJECT_TYPE 		entryType;
    POBJECT_HEADER_NAME_INFO 	nameType, nameObj;
    ANSI_STRING 		AnsiString;
    ULONG 			i;
	
    for(i=0; i<512; i++) {
	entryHandle = (PHANDLE_TABLE_ENTRY)((DWORD)tableHandle+i*8); 
	if(*(PDWORD)entryHandle != 0) {

	        entryHeadObj = (POBJECT_HEADER)(((DWORD)entryHandle->Object | 0x80000000) & 0xfffffff8);
		typeHeadObj = (POBJECT_HEADER)((((DWORD)entryHeadObj->Type | 0x80000000) & 0xfffffff8)-0x18);
		nameType = (POBJECT_HEADER_NAME_INFO)((DWORD)typeHeadObj-(DWORD)typeHeadObj->NameInfoOffset);

		DbgPrint("%04x: Object: %x GrantedAccess: %x Entry: %x\n", *Handle, (DWORD)entryHeadObj+0x18, entryHandle->GrantedAccess, entryHandle);
		DbgPrint("\tType: %S ObjectHeader: %x\n", nameType->Name.Buffer, (DWORD)entryHeadObj);
		DbgPrint("\tHandleCount: %ld  PointerCount: %ld\n", entryHeadObj->HandleCount, entryHeadObj->PointerCount);
		if(entryHeadObj->NameInfoOffset != 0) {
			nameObj = (POBJECT_HEADER_NAME_INFO)((DWORD)entryHeadObj-(DWORD)entryHeadObj->NameInfoOffset);
			DbgPrint("\tName: %S\n", nameObj->Name.Buffer);
		}
		DbgPrint("\n"); 
	}
	*Handle += 4;
    }
}