#ifndef _H_C_L
#define _H_C_L
#include <wdm.h>
#include <string.h>
#define WINAPI __stdcall
#define IMAGE_DIRECTORY_ENTRY_EXPORT 0
typedef unsigned long DWORD;
typedef DWORD *PDWORD;
typedef unsigned char BYTE;
typedef BYTE *PBYTE;
typedef unsigned short WORD;
typedef int BOOL;
typedef struct ServiceDescriptorEntry
{
PDWORD ServiceTable;
PDWORD CounterTableBase;
DWORD ServiceLimit;
PBYTE ArgumentTable;
} SSDT;
typedef struct _LDR_DATA_TABLE_ENTRY {
LIST_ENTRY InLoadOrderLinks;
LIST_ENTRY InMemoryOrderLinks;
LIST_ENTRY InInitializationOrderLinks;
PVOID DllBase;
PVOID EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
ULONG Flags;
WORD LoadCount;
WORD TlsIndex;
union
{
LIST_ENTRY HashLinks;
struct
{
PVOID SectionPointer;
ULONG CheckSum;
};
};
union
{
ULONG TimeDateStamp;
PVOID LoadedImports;
};
PVOID EntryPointActivationContext;
PVOID PatchInformation;
LIST_ENTRY ForwarderLinks;
LIST_ENTRY ServiceTagLinks;
LIST_ENTRY StaticLinks;
} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;
typedef struct _KEXECUTE_OPTIONS {
ULONG ExecuteDisable: 1;
ULONG ExecuteEnable: 1;
ULONG DisableThunkEmulation: 1;
ULONG Permanent: 1;
ULONG ExecuteDispatchEnable: 1;
ULONG ImageDispatchEnable: 1;
ULONG Spare: 2;
} KEXECUTE_OPTIONS, *PKEXECUTE_OPTIONS;
typedef struct _KIDTENTRY {
WORD Offset;
WORD Selector;
WORD Access;
WORD ExtendedOffset;
} KIDTENTRY, *PKIDTENTRY;
typedef struct _KGDTENTRY {
WORD LimitLow;
WORD BaseLow;
ULONG HighWord;
} KGDTENTRY, *PKGDTENTRY;
typedef struct _KPROCESS {
DISPATCHER_HEADER Header;
LIST_ENTRY ProfileListHead;
ULONG DirectoryTableBase;
ULONG Unused0;
KGDTENTRY LdtDescriptor;
KIDTENTRY Int21Descriptor;
WORD IopmOffset;
UCHAR Iopl;
UCHAR Unused;
ULONG ActiveProcessors;
ULONG KernelTime;
ULONG UserTime;
LIST_ENTRY ReadyListHead;
SINGLE_LIST_ENTRY SwapListEntry;
PVOID VdmTrapcHandler;
LIST_ENTRY ThreadListHead;
ULONG ProcessLock;
ULONG Affinity;
union
{
ULONG AutoAlignment: 1;
ULONG DisableBoost: 1;
ULONG DisableQuantum: 1;
ULONG ReservedFlags: 29;
LONG ProcessFlags;
};
CHAR BasePriority;
CHAR QuantumReset;
UCHAR State;
UCHAR ThreadSeed;
UCHAR PowerState;
UCHAR IdealNode;
UCHAR Visited;
union
{
KEXECUTE_OPTIONS Flags;
UCHAR ExecuteOptions;
};
ULONG StackCount;
LIST_ENTRY ProcessListEntry;
UINT64 CycleTime;
} KPROCESS, *PKPROCESS;
typedef struct _KAPC_STATE {
LIST_ENTRY ApcListHead[2];
PKPROCESS Process;
UCHAR KernelApcInProgress;
UCHAR KernelApcPending;
UCHAR UserApcPending;
} KAPC_STATE, *PKAPC_STATE;
typedef struct _RTL_USER_PROCESS_PARAMETERS {
BYTE Reserved1[16];
PVOID Reserved2[10];
UNICODE_STRING ImagePathName;
UNICODE_STRING CommandLine;
} RTL_USER_PROCESS_PARAMETERS,*PRTL_USER_PROCESS_PARAMETERS;
typedef struct _PEB_LDR_DATA {
ULONG Length;
BOOLEAN Initialized;
PVOID SsHandle;
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
} PEB_LDR_DATA, *PPEB_LDR_DATA;
typedef struct _PEB {
BYTE Reserved1[2];
BYTE BeingDebugged;
BYTE Reserved2[1];
PVOID Reserved3[2];
PPEB_LDR_DATA Ldr;
PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
BYTE Reserved4[104];
PVOID Reserved5[52];
PVOID PostProcessInitRoutine;
BYTE Reserved6[128];
PVOID Reserved7[1];
ULONG SessionId;
} PEB, *PPEB;
typedef enum _SYSTEM_INFORMATION_CLASS {
SystemInformationClassMin = 0,
SystemBasicInformation = 0,
SystemProcessorInformation = 1,
SystemPerformanceInformation = 2,
SystemTimeOfDayInformation = 3,
SystemPathInformation = 4,
SystemNotImplemented1 = 4,
SystemProcessInformation = 5,
SystemProcessesAndThreadsInformation = 5,
SystemCallCountInfoInformation = 6,
SystemCallCounts = 6,
SystemDeviceInformation = 7,
SystemConfigurationInformation = 7,
SystemProcessorPerformanceInformation = 8,
SystemProcessorTimes = 8,
SystemFlagsInformation = 9,
SystemGlobalFlag = 9,
SystemCallTimeInformation = 10,
SystemNotImplemented2 = 10,
SystemModuleInformation = 11,
SystemLocksInformation = 12,
SystemLockInformation = 12,
SystemStackTraceInformation = 13,
SystemNotImplemented3 = 13,
SystemPagedPoolInformation = 14,
SystemNotImplemented4 = 14,
SystemNonPagedPoolInformation = 15,
SystemNotImplemented5 = 15,
SystemHandleInformation = 16,
SystemObjectInformation = 17,
SystemPageFileInformation = 18,
SystemPagefileInformation = 18,
SystemVdmInstemulInformation = 19,
SystemInstructionEmulationCounts = 19,
SystemVdmBopInformation = 20,
SystemInvalidInfoClass1 = 20,
SystemFileCacheInformation = 21,
SystemCacheInformation = 21,
SystemPoolTagInformation = 22,
SystemInterruptInformation = 23,
SystemProcessorStatistics = 23,
SystemDpcBehaviourInformation = 24,
SystemDpcInformation = 24,
SystemFullMemoryInformation = 25,
SystemNotImplemented6 = 25,
SystemLoadImage = 26,
SystemUnloadImage = 27,
SystemTimeAdjustmentInformation = 28,
SystemTimeAdjustment = 28,
SystemSummaryMemoryInformation = 29,
SystemNotImplemented7 = 29,
SystemNextEventIdInformation = 30,
SystemNotImplemented8 = 30,
SystemEventIdsInformation = 31,
SystemNotImplemented9 = 31,
SystemCrashDumpInformation = 32,
SystemExceptionInformation = 33,
SystemCrashDumpStateInformation = 34,
SystemKernelDebuggerInformation = 35,
SystemContextSwitchInformation = 36,
SystemRegistryQuotaInformation = 37,
SystemLoadAndCallImage = 38,
SystemPrioritySeparation = 39,
SystemPlugPlayBusInformation = 40,
SystemNotImplemented10 = 40,
SystemDockInformation = 41,
SystemNotImplemented11 = 41,
SystemInvalidInfoClass2 = 42,
SystemProcessorSpeedInformation = 43,
SystemInvalidInfoClass3 = 43,
SystemCurrentTimeZoneInformation = 44,
SystemTimeZoneInformation = 44,
SystemLookasideInformation = 45,
SystemSetTimeSlipEvent = 46,
SystemCreateSession = 47,
SystemDeleteSession = 48,
SystemInvalidInfoClass4 = 49,
SystemRangeStartInformation = 50,
SystemVerifierInformation = 51,
SystemAddVerifier = 52,
SystemSessionProcessesInformation = 53,
SystemInformationClassMax
} SYSTEM_INFORMATION_CLASS;
typedef struct _VM_COUNTERS {
DWORD PeakVirtualSize;
DWORD VirtualSize;
DWORD PageFaultCount;
DWORD PeakWorkingSetSize;
DWORD WorkingSetSize;
DWORD QuotaPeakPagedPoolUsage;
DWORD QuotaPagedPoolUsage;
DWORD QuotaPeakNonPagedPoolUsage;
DWORD QuotaNonPagedPoolUsage;
DWORD PagefileUsage;
DWORD PeakPagefileUsage;
} VM_COUNTERS;
typedef struct _IO_COUNTERS {
ULONGLONG ReadOperationCount;
ULONGLONG WriteOperationCount;
ULONGLONG OtherOperationCount;
ULONGLONG ReadTransferCount;
ULONGLONG WriteTransferCount;
ULONGLONG OtherTransferCount;
} IO_COUNTERS,
*PIO_COUNTERS;
typedef struct _SYSTEM_THREAD_INFORMATION {
LARGE_INTEGER KernelTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER CreateTime;
ULONG WaitTime;
PVOID StartAddress;
CLIENT_ID ClientId;
LONG Priority;
LONG BasePriority;
ULONG ContextSwitchCount;
LONG State;
LONG WaitReason;
} SYSTEM_THREAD_INFORMATION, * PSYSTEM_THREAD_INFORMATION;
typedef struct _IMAGE_DATA_DIRECTORY {
ULONG VirtualAddress;
ULONG Size;
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
typedef struct _SYSTEM_PROCESS_INFORMATION {
ULONG NextEntryDelta;
ULONG ThreadCount;
ULONG Reserved1[6];
LARGE_INTEGER CreateTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER KernelTime;
UNICODE_STRING ProcessName;
LONG BasePriority;
ULONG ProcessId;
ULONG InheritedFromProcessId;
ULONG HandleCount;
ULONG Reserved2[2];
VM_COUNTERS VmCounters;
IO_COUNTERS IoCounters;
SYSTEM_THREAD_INFORMATION Threads[1];
} SYSTEM_PROCESS_INFORMATION, * PSYSTEM_PROCESS_INFORMATION;
typedef struct _IMAGE_EXPORT_DIRECTORY {
ULONG Characteristics;
ULONG TimeDateStamp;
short MajorVersion;
short MinorVersion;
ULONG Name;
ULONG Base;
ULONG NumberOfFunctions;
ULONG NumberOfNames;
ULONG AddressOfFunctions; ULONG AddressOfNames; ULONG AddressOfNameOrdinals; } IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;
typedef struct _IMAGE_DOS_HEADER {
short e_magic;
short e_cblp;
short e_cp;
short e_crlc;
short e_cparhdr;
short e_minalloc;
short e_maxalloc;
short e_ss;
short e_sp;
short e_csum;
short e_ip;
short e_cs;
short e_lfarlc;
short e_ovno;
short e_res[4];
short e_oemid;
short e_oeminfo;
short e_res2[10];
LONG e_lfanew;
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
typedef struct _IMAGE_FILE_HEADER {
short Machine;
short NumberOfSections;
ULONG TimeDateStamp;
ULONG PointerToSymbolTable;
ULONG NumberOfSymbols;
short SizeOfOptionalHeader;
short Characteristics;
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
typedef struct _IMAGE_OPTIONAL_HEADER {
short Magic;
UCHAR MajorLinkerVersion;
UCHAR MinorLinkerVersion;
ULONG SizeOfCode;
ULONG SizeOfInitializedData;
ULONG SizeOfUninitializedData;
ULONG AddressOfEntryPoint;
ULONG BaseOfCode;
ULONG BaseOfData;
ULONG ImageBase;
ULONG SectionAlignment;
ULONG FileAlignment;
short MajorOperatingSystemVersion;
short MinorOperatingSystemVersion;
short MajorImageVersion;
short MinorImageVersion;
short MajorSubsystemVersion;
short MinorSubsystemVersion;
ULONG Win32VersionValue;
ULONG SizeOfImage;
ULONG SizeOfHeaders;
ULONG CheckSum;
short Subsystem;
short DllCharacteristics;
ULONG SizeOfStackReserve;
ULONG SizeOfStackCommit;
ULONG SizeOfHeapReserve;
ULONG SizeOfHeapCommit;
ULONG LoaderFlags;
ULONG NumberOfRvaAndSizes;
IMAGE_DATA_DIRECTORY DataDirectory[16];
} IMAGE_OPTIONAL_HEADER, *PIMAGE_OPTIONAL_HEADER;
typedef struct _IMAGE_NT_HEADERS {
ULONG Signature;
IMAGE_FILE_HEADER FileHeader;
IMAGE_OPTIONAL_HEADER OptionalHeader;
} IMAGE_NT_HEADERS, *PIMAGE_NT_HEADERS;
__declspec(dllimport) SSDT KeServiceDescriptorTable;
#define HOOK_SSDT(funct2Hook,functHooked,storeOriFunct) \
*storeOriFunct = (ULONG)InterlockedExchange((LONG volatile*)&KeServiceDescriptorTable.ServiceTable[*(PULONG)((PUCHAR)funct2Hook+1)] , (LONG)functHooked); \
#define UNHOOK_SSDT(funct2UnHook , functOriginal) \
InterlockedExchange((LONG volatile*)&KeServiceDescriptorTable.ServiceTable[*(PULONG)((PUCHAR)funct2UnHook+1)] , (LONG)functOriginal);
VOID
KeStackAttachProcess (
__in PKPROCESS Process,
__out PKAPC_STATE ApcState
);
VOID
KeUnstackDetachProcess(
__in PKAPC_STATE ApcState
);
NTSTATUS
WINAPI
ZwQuerySystemInformation(
__in SYSTEM_INFORMATION_CLASS SystemInformationClass,
__inout PVOID SystemInformation,
__in ULONG SystemInformationLength,
__out_opt PULONG ReturnLength
);
NTSTATUS
PsLookupProcessByProcessId(
__in HANDLE ProcessId,
__out PEPROCESS *Process
);
int name2Pid(char* name);
PEPROCESS name2Eprocess(char* name);
PVOID parseEatNtdll(char* function);
PVOID findDllImageBase(char* process , char* dll);
BOOL hookSSDT(PULONG funct2Hook , PULONG functHooked , PULONG storeOriginalFunct);
BOOL unHookSSDT(PULONG funct2UnHook , PULONG functOriginal);
BOOL unHookSSDT(PULONG funct2UnHook , PULONG functOriginal)
{
__asm
{
push eax
mov eax, CR0
and eax, 0FFFEFFFFh mov CR0, eax
pop eax
}
UNHOOK_SSDT(funct2UnHook , functOriginal);
__asm
{
push eax
mov eax, CR0
or eax, NOT 00010000h mov CR0, eax
pop eax
}
return TRUE;
}
BOOL hookSSDT(PULONG funct2Hook , PULONG functHooked , PULONG storeOriginalFunct)
{
__asm
{
push eax
mov eax, CR0
and eax, 0FFFEFFFFh mov CR0, eax
pop eax
}
HOOK_SSDT(funct2Hook , functHooked , storeOriginalFunct);
__asm
{
push eax
mov eax, CR0
or eax, NOT 00010000h mov CR0, eax
pop eax
}
return TRUE;
}
PVOID findDllImageBase(char* process , char* dll)
{
PEPROCESS pEprocess;
PPEB pPeb;
PPEB_LDR_DATA pPebLdr;
PLDR_DATA_TABLE_ENTRY pCurrentLdrDataEntry , pStartLdrDataEntry;
LIST_ENTRY listEntry;
PLIST_ENTRY pListEntry;
BOOLEAN isFound = FALSE;
KAPC_STATE kApcState;
ANSI_STRING nameProcessA;
UNICODE_STRING nameProcessW;
PVOID imgBase;
RtlInitAnsiString(&nameProcessA , dll);
RtlAnsiStringToUnicodeString(&nameProcessW , &nameProcessA , TRUE);
pEprocess = name2Eprocess(process);
if(pEprocess == NULL)
return NULL;
KeStackAttachProcess((PKPROCESS)pEprocess , &kApcState);
pPeb = (PPEB)*(PULONG)((PUCHAR)pEprocess + 0x1b0); pPebLdr = pPeb->Ldr;
listEntry = pPebLdr->InLoadOrderModuleList;
pListEntry = listEntry.Flink;
pCurrentLdrDataEntry = (pStartLdrDataEntry = (PLDR_DATA_TABLE_ENTRY)pListEntry);
while(pStartLdrDataEntry != (PLDR_DATA_TABLE_ENTRY)pListEntry->Flink)
{
if(wcscmp(pCurrentLdrDataEntry->BaseDllName.Buffer , nameProcessW.Buffer) == 0)
{
isFound = TRUE;
break;
}
pCurrentLdrDataEntry = (PLDR_DATA_TABLE_ENTRY)pListEntry->Flink;
pListEntry = pListEntry->Flink;
}
RtlFreeUnicodeString(&nameProcessW);
imgBase = pCurrentLdrDataEntry->DllBase;
KeUnstackDetachProcess(&kApcState);
if(!isFound)
return NULL;
return imgBase;
}
PVOID parseEatNtdll(char* function)
{
PEPROCESS pCurrentEprocess;
KAPC_STATE kApcState;
PPEB pPeb;
PPEB_LDR_DATA pPebLdr;
PLDR_DATA_TABLE_ENTRY pCurrentLdrDataEntry , pStartLdrDataEntry;
LIST_ENTRY listEntry;
PLIST_ENTRY pListEntry;
BOOLEAN isFound = FALSE;
PIMAGE_DOS_HEADER pImgDosHeader;
PIMAGE_NT_HEADERS pImgNtHeaders;
PIMAGE_EXPORT_DIRECTORY pImgExportDirectory;
int nbFunctions , i;
PULONG rvaFunctionTable , rvaNameFunctionTable , pFunction;
pCurrentEprocess = name2Eprocess("csrss.exe");
if(pCurrentEprocess == NULL)
return NULL;
KeStackAttachProcess((PKPROCESS)pCurrentEprocess , &kApcState);
pPeb = (PPEB)*(PULONG)((PUCHAR)pCurrentEprocess + 0x1b0); pPebLdr = pPeb->Ldr;
listEntry = pPebLdr->InLoadOrderModuleList;
pListEntry = listEntry.Flink;
pCurrentLdrDataEntry = (pStartLdrDataEntry = (PLDR_DATA_TABLE_ENTRY)pListEntry);
while(pStartLdrDataEntry != (PLDR_DATA_TABLE_ENTRY)pListEntry->Flink)
{
if(wcscmp(pCurrentLdrDataEntry->BaseDllName.Buffer , L"ntdll.dll") == 0)
{
isFound = TRUE;
break;
}
pCurrentLdrDataEntry = (PLDR_DATA_TABLE_ENTRY)pListEntry->Flink;
pListEntry = pListEntry->Flink;
}
if(!isFound)
{
KeUnstackDetachProcess(&kApcState);
return NULL;
}
isFound = FALSE;
pImgDosHeader = (PIMAGE_DOS_HEADER)pCurrentLdrDataEntry->DllBase;
pImgNtHeaders = (PIMAGE_NT_HEADERS)((PUCHAR)pImgDosHeader + pImgDosHeader->e_lfanew);
pImgExportDirectory = (PIMAGE_EXPORT_DIRECTORY)((PUCHAR)pImgDosHeader + pImgNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
nbFunctions = pImgExportDirectory->NumberOfFunctions;
rvaFunctionTable = (PULONG)((PUCHAR)pImgDosHeader + pImgExportDirectory->AddressOfFunctions);
rvaNameFunctionTable = (PULONG)((PUCHAR)pImgDosHeader + pImgExportDirectory->AddressOfNames);
for(i = 0 ; i < nbFunctions ; i++)
{
if(strcmp(((PUCHAR)pImgDosHeader + rvaNameFunctionTable[i]) , function) == 0)
{
isFound = TRUE;
break;
}
}
if(!isFound)
{
KeUnstackDetachProcess(&kApcState);
return NULL;
}
pFunction = (PULONG)((PUCHAR)pImgDosHeader + rvaFunctionTable[i]);
KeUnstackDetachProcess(&kApcState);
return pFunction;
}
int name2Pid(char* name)
{
NTSTATUS state;
PSYSTEM_PROCESS_INFORMATION pProcessInfo;
ULONG size;
UNICODE_STRING uProcName;
ANSI_STRING aProcName;
RtlInitAnsiString(&aProcName , name);
RtlAnsiStringToUnicodeString(&uProcName , &aProcName , TRUE);
state = ZwQuerySystemInformation(SystemProcessInformation , NULL , 0 , &size);
pProcessInfo = (PSYSTEM_PROCESS_INFORMATION)ExAllocatePoolWithTag(NonPagedPool , size , 't4pz');
if(pProcessInfo == NULL)
return 0;
state = ZwQuerySystemInformation(SystemProcessInformation , pProcessInfo , size , &size);
if(!NT_SUCCESS(state))
return 0;
while(pProcessInfo->NextEntryDelta != 0)
{
if(pProcessInfo->ProcessName.Buffer != NULL)
{
if(wcscmp(uProcName.Buffer , pProcessInfo->ProcessName.Buffer) == 0)
{
RtlFreeUnicodeString(&uProcName);
return pProcessInfo->ProcessId;
}
}
pProcessInfo = (PSYSTEM_PROCESS_INFORMATION)((PUCHAR)pProcessInfo + pProcessInfo->NextEntryDelta);
}
if(wcscmp(uProcName.Buffer , pProcessInfo->ProcessName.Buffer) == 0)
{
RtlFreeUnicodeString(&uProcName);
return pProcessInfo->ProcessId;
}
return 0;
}
PEPROCESS name2Eprocess(char* name)
{
PEPROCESS pEprocess = NULL;
NTSTATUS state;
int pid;
pid = name2Pid(name);
if(pid == 0)
return NULL;
state = PsLookupProcessByProcessId((HANDLE)pid , &pEprocess);
if(!NT_SUCCESS(state))
return NULL;
return pEprocess;
}
#endif