#define SEC_IMAGE         0x1000000
#define PROCESSNAME_OFFSET 0x174
UNICODE_STRING DrvName;

typedef struct _USER_STACK {
 PVOID FixedStackBase;
 PVOID FixedStackLimit;
 PVOID ExpandableStackBase;
 PVOID ExpandableStackLimit;
 PVOID ExpandableStackBottom;
} USER_STACK, *PUSER_STACK;


typedef struct _SERVICE_DESCRIPTOR_TABLE
{
 PVOID  ServiceTableBase;
 PULONG SerivceCounterTableBase;
 ULONG  NumberOfService;
 ULONG  ParamTableBase;
}SERVICE_DESCRIPTOR_TABLE,*PSERVICE_DESCRIPTOR_TABLE;
extern "C" PSERVICE_DESCRIPTOR_TABLE KeServiceDescriptorTable;

 

#ifdef __cplusplus
extern "C"
{
#endif

 _declspec(dllexport) NTSTATUS
  NTAPI
  ZwCreateSection(
  OUT PHANDLE SectionHandle,
  IN ACCESS_MASK DesiredAccess,
  IN POBJECT_ATTRIBUTES ObjectAttributes,
  IN PLARGE_INTEGER SectionSize OPTIONAL,
  IN ULONG Protect,
  IN ULONG Attributes,
  IN HANDLE FileHandle) ;
 NTSTATUS PsLookupThreadByThreadId(IN HANDLE ThreadId, OUT PETHREAD *Thread);
 PCHAR PsGetProcessImageFileName(IN  PEPROCESS process);
#ifdef __cplusplus
}
#endif


//=========================================================================
//函数名:GetNativeApiAddress
//功能 :在驱动内遍历指定Dll的PE文件,
//  找出指定函数名在内存中的地址位置
//参数:
//  IN pszFunctionName   指定函数名
//  IN pszDllName   指定Dll名
//返回值:
//  0    失败
//  其它 成功
//
//=========================================================================
ULONG GetNativeApiAddress(PCHAR pszFunctionName, PUNICODE_STRING pszDllName)
{
 NTSTATUS      ntStatus ;
 HANDLE       hfile = NULL;
 HANDLE       hsection = NULL;
 OBJECT_ATTRIBUTES    oa;
 IO_STATUS_BLOCK     IoStatus;
 PVOID       BaseAddress = NULL;
 SIZE_T       size = 0;
 IMAGE_DOS_HEADER       *dos_head = NULL;
 IMAGE_OPTIONAL_HEADER  *option_head = NULL;
 IMAGE_EXPORT_DIRECTORY *export = NULL;
 ULONG       *arrayOfFunctionAddress = NULL;
 ULONG       *arrayOfFunctionName = NULL;
 USHORT       *arrayOfFunctionOrdinal = NULL;
 ULONG       ulFunctionOrdinal = 0;
 ULONG       ulBase = 0;
 STRING       FunctionNameSearch, NtFunctionName;
 PCHAR       pszAllFunctionName;
 ULONG       ulCount = 0;
 ULONG       ulFunctionAddress = 0;

 ::RtlZeroMemory(&oa, sizeof(OBJECT_ATTRIBUTES));
 InitializeObjectAttributes(&oa,
  pszDllName,
  OBJ_CASE_INSENSITIVE,
  0,
  NULL);
 ntStatus = ::ZwOpenFile(&hfile,
  FILE_EXECUTE | SYNCHRONIZE,
  &oa,
  &IoStatus,
  FILE_SHARE_READ,
  FILE_SYNCHRONOUS_IO_NONALERT);
 if(!NT_SUCCESS(ntStatus))
 {
  KdPrint(("ZwOpenFile is error\n"));
  return 0;
 }

 oa.ObjectName = 0;
 ntStatus = ZwCreateSection(&hsection,
  SECTION_ALL_ACCESS,
  &oa,
  0,
  PAGE_EXECUTE,
  SEC_IMAGE,
  hfile);

 if(!NT_SUCCESS(ntStatus))
 {
  KdPrint(("ZwCreateSection is error\n"));
  return 0;
 }

 ntStatus = ZwMapViewOfSection(hsection,
  NtCurrentProcess(),
  &BaseAddress,
  0,
  1000,
  0,
  &size,
  (SECTION_INHERIT)1,
  MEM_TOP_DOWN,
  PAGE_READWRITE);
 if(!NT_SUCCESS(ntStatus))
 {
  KdPrint(("%x\n",ntStatus));
  KdPrint(("ZwMapViewOfSection is error\n"));
  return 0;
 }
 ::ZwClose(hfile);

 dos_head = (IMAGE_DOS_HEADER *)BaseAddress;
 option_head = (IMAGE_OPTIONAL_HEADER *)((ULONG)BaseAddress + dos_head->e_lfanew + 24);
 export = (IMAGE_EXPORT_DIRECTORY *)((ULONG)BaseAddress + option_head->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);

 arrayOfFunctionAddress = (ULONG *)((ULONG)BaseAddress + export->AddressOfFunctions);
 arrayOfFunctionName = (ULONG *)((ULONG)BaseAddress + export->AddressOfNames);
 arrayOfFunctionOrdinal = (USHORT *)((ULONG)BaseAddress + export->AddressOfNameOrdinals);
 ulBase = export->ulBase;

 ::RtlInitString(&FunctionNameSearch, pszFunctionName);
 for(ulCount = 0; ulCount < export->NumberOfFunctions; ulCount++)
 {
  pszAllFunctionName = (PCHAR)((ULONG)BaseAddress + arrayOfFunctionName[ulCount]);
  ::RtlInitString(&NtFunctionName, pszAllFunctionName);
  ulFunctionOrdinal = arrayOfFunctionOrdinal[ulCount] + ulBase - 1;

  ulFunctionAddress = (ULONG)((ULONG)BaseAddress + arrayOfFunctionAddress[ulFunctionOrdinal]);
  if(::RtlCompareString(&NtFunctionName, &FunctionNameSearch, TRUE) == 0)                                                          //对名字进行比较
  {
   return ulFunctionAddress;
  }

 }

 ZwClose(hsection);
 return 0;
}


//=========================================================================
//函数名:GetSSDTAddress
//功能 : 取得指定函数在SSDT表中的地址
//参数:
//  IN pszFunName   指定函数名
//返回值:
//  0    失败
//  其它 函数在SSDT中的地址
//=========================================================================
ULONG GetSSDTAddress(PCHAR pszFunName)
{
 UNICODE_STRING usDllName;
 ULONG ulAddress = 0;
 ULONG ulNum = 0;

 RtlInitUnicodeString(&usDllName, L"\\SystemRoot\\System32\\ntdll.dll");
 ulAddress = ::GetNativeApiAddress(pszFunName, &usDllName);
 if(0 == ulAddress)
 {
  return 0;
 }
 ulNum = *(ULONG *)(ulAddress + 1);
 if (0 == ulNum)
 {
  return 0;
 }

 ulAddress = (ULONG)KeServiceDescriptorTable->ServiceTableBase;

 return ulAddress +ulNum * 4;
}