#include
<ntddk.h>
#include
<ntimage.h>
#ifndef
SEC_IMAGE
#define
SEC_IMAGE 0x1000000 // winnt
#endif
extern
PUSHORT
NtBuildNumber;
PVOID
pfn_XxxDispatchAPC = NULL;
PVOID
pfn_LoadLibraryA = NULL;
PVOID
pszText_Kernel32 = NULL;
ULONG
Offset_szText = 0;
ULONG
Offset_LoadLibraryA = 0;
ULONG
Offset_BaseDispatchAPC = 0;
ULONG
Offset_RtlDispatchAPC = 0;
UNICODE_STRING
gModuleName[] =
{
RTL_CONSTANT_STRING(L
"\\systemroot\\system32\\ntdll.dll"
),
RTL_CONSTANT_STRING(L
"\\systemroot\\system32\\kernel32.dll"
),
RTL_CONSTANT_STRING(L
"\\WINDOWS\\system32\\kernel32.dll"
),
RTL_CONSTANT_STRING(L
"\\systemroot\\system\\text.dll"
),
RTL_CONSTANT_STRING(L
"\\Device\\HarddiskVolume1\\WINDOWS\\system32\\notepad.exe"
)
};
PIMAGE_NT_HEADERS
NTAPI
RtlImageNtHeader(
PVOID
Base
);
NTSYSAPI
PVOID
NTAPI
RtlImageDirectoryEntryToData(
PVOID
BaseOfImage,
BOOLEAN
MappedAsImage,
USHORT
DirectoryEntry,
PULONG
Size
);
NTSTATUS
(NTAPI* pfn_NtQueueApcThread)(
__in
HANDLE
ThreadHandle,
__in
PVOID
ApcRoutine,
__in_opt
PVOID
ApcArgument1,
__in_opt
PVOID
ApcArgument2,
__in_opt
PVOID
ApcArgument3
);
PVOID
NTAPI
TlLoadSysPEtoMem(
IN
PUNICODE_STRING FilePath
)
{
OBJECT_ATTRIBUTES
ObjectAttributes = {0};
IO_STATUS_BLOCK
IoStatusBlock = {0};
HANDLE
FileHandle = NULL;
HANDLE
SectionHandle = NULL;
PVOID
ViewBase = NULL;
PVOID
MemBase = NULL;
SIZE_T
ViewSize = 0;
NTSTATUS
Status = STATUS_INVALID_PARAMETER;
InitializeObjectAttributes(
&ObjectAttributes,
FilePath,
OBJ_KERNEL_HANDLE|OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
Status
= ZwOpenFile ( &FileHandle,
FILE_GENERIC_READ,
&ObjectAttributes,
&IoStatusBlock,
FILE_SHARE_READ|FILE_SHARE_WRITE,
FILE_NON_DIRECTORY_FILE
);
if
( NT_SUCCESS( Status ) )
{
InitializeObjectAttributes(
&ObjectAttributes,
NULL,
OBJ_KERNEL_HANDLE,
NULL,
NULL
);
Status
= ZwCreateSection( &SectionHandle,
SECTION_MAP_READ,
&ObjectAttributes,
(PLARGE_INTEGER)NULL,
PAGE_READONLY,
SEC_IMAGE,
FileHandle);
if
( NT_SUCCESS( Status ) )
{
Status
= ZwMapViewOfSection(SectionHandle,
ZwCurrentProcess(),
&ViewBase,
0L,
PAGE_SIZE,
NULL,
&ViewSize,
ViewUnmap,
MEM_TOP_DOWN,
PAGE_READWRITE);
if
(
NT_SUCCESS( Status ) )
{
MemBase
= ExAllocatePoolWithTag( NonPagedPool, ViewSize,
'
dmC'
);
if
(
MemBase )
{
RtlMoveMemory(
MemBase, ViewBase, ViewSize );
}
ZwUnmapViewOfSection(
ZwCurrentProcess(), ViewBase );
}
ZwClose(
SectionHandle );
}
ZwClose(
FileHandle );
}
return
MemBase;
}
PVOID
NTAPI
TlMapKnownDlltoMem(
IN
PUNICODE_STRING FilePath
)
{
OBJECT_ATTRIBUTES
ObjectAttributes = {0};
HANDLE
SectionHandle = NULL;
PVOID
ViewBase = NULL;
PVOID
MemBase = NULL;
SIZE_T
ViewSize = 0;
NTSTATUS
Status = STATUS_INVALID_PARAMETER;
InitializeObjectAttributes(
&ObjectAttributes,
FilePath,
OBJ_KERNEL_HANDLE|OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
Status
= ZwOpenSection( &SectionHandle,
SECTION_MAP_READ,
&ObjectAttributes
);
if
( NT_SUCCESS( Status ) )
{
Status
= ZwMapViewOfSection(SectionHandle,
ZwCurrentProcess(),
&ViewBase,
0L,
PAGE_SIZE,
NULL,
&ViewSize,
ViewUnmap,
MEM_TOP_DOWN,
PAGE_READWRITE
);
if
(
NT_SUCCESS( Status ) )
{
MemBase
= ExAllocatePoolWithTag( NonPagedPool, ViewSize,
'
dmC'
);
if
(
MemBase )
{
RtlMoveMemory(
MemBase, ViewBase, ViewSize );
}
ZwUnmapViewOfSection(
ZwCurrentProcess(), ViewBase );
}
ZwClose(
SectionHandle );
}
return
MemBase;
}
PVOID
NTAPI
TlGetProcAddress(
IN
PVOID
ImageBase,
IN
PUCHAR
ApiName
)
{
PIMAGE_EXPORT_DIRECTORY
ExpDir = NULL;
PULONG
AddressOfNames = NULL;
PULONG
AddressOfFunctions = NULL;
PUSHORT
AddressOfNameOrdinals = NULL;
PVOID
FuncAddress = NULL;
ULONG
ExpDirSize = 0;
ULONG
NumberOfNames = 0;
LONG
Idx = 0;
LONG
ret = 0;
LONG
low = 0;
LONG
mid = 0;
LONG
high = 0;
PCHAR
pName = NULL;
if
(
!ImageBase )
return
NULL;
ExpDir
= (PIMAGE_EXPORT_DIRECTORY)RtlImageDirectoryEntryToData(ImageBase,TRUE,IMAGE_DIRECTORY_ENTRY_EXPORT,&ExpDirSize );
if
( ExpDir )
{
AddressOfNames
= (
PULONG
)(
(
ULONG
)ImageBase
+ ExpDir->AddressOfNames );
AddressOfFunctions
= (
PULONG
)(
(
ULONG
)ImageBase
+ ExpDir->AddressOfFunctions );
AddressOfNameOrdinals
= (
PUSHORT
)(
(
ULONG
)ImageBase
+ ExpDir->AddressOfNameOrdinals );
NumberOfNames
= ExpDir->NumberOfNames;
if
(
(
ULONG
)ApiName
& 0xFFFF0000 )
{
high
= NumberOfNames-1;
while
(low
<= high)
{
mid
= (high+low)>>1;
pName
= (
PCHAR
)ImageBase+AddressOfNames[mid]
;
Idx
= 0;
while
(
pName[Idx] && pName[Idx] == ApiName[Idx] )
{
++Idx;
}
ret
= pName[Idx] - ApiName[Idx];
if
( ret==0 )
{
(
PUCHAR
)FuncAddress=(
PUCHAR
)ImageBase
+ AddressOfFunctions[ AddressOfNameOrdinals[ mid ] ];
break
;
}
else
if
(
ret > 0 )
{
high=mid-1;
}
else
{
low=mid+1;
}
}
}
else
{
(
PUCHAR
)FuncAddress=(
PUCHAR
)ImageBase
+ AddressOfFunctions[ (
ULONG
)ApiName
& 0x0FFFF ];
}
}
return
FuncAddress;
}
ULONG
NTAPI
GetOffsetForXxxDispatchApc(
IN
PVOID
pfn_QueueUserApc,
IN
PVOID
ImageBase
)
{
ULONG
Offset = 0;
PUCHAR
pMem = (
PUCHAR
)pfn_QueueUserApc;
PUCHAR
pLim = (
PUCHAR
)pfn_QueueUserApc
+ 0x100;
while
(
pMem < pLim && *(
PULONG
)pMem
!= 0x90000CC2 ) pMem++;
if
(
*(
PULONG
)pMem
== 0x90000CC2 )
{
pLim
= (
PUCHAR
)pfn_QueueUserApc;
while
(
(--pMem) > pLim )
{
if
(
*(
PUSHORT
)pMem
== 0x75FF && *(
PUSHORT
)(pMem+3)
== 0x15FF && *(pMem-5) == 0x68 )
{
Offset
= *(
PULONG
)(pMem-4)
- (
ULONG
)ImageBase;
break
;
}
}
}
return
Offset;
}
ULONG
NTAPI
GetOffsetForSpecialText(
IN
PVOID
ImageBase,
IN
PCSTR
szText
)
{
ULONG
Offset = 0;
PUCHAR
pMem = (
PUCHAR
)ImageBase;
PUCHAR
pLim = (
PUCHAR
)ImageBase
+ 0x400;
while
(
pMem < pLim )
{
if
(
_stricmp( szText, pMem) == 0 )
{
Offset
= (
ULONG
)(pMem-(
PUCHAR
)ImageBase);
break
;
}
pMem++;
}
return
Offset;
}
PVOID
NTAPI
TlBuildNtFunc(
IN
ULONG
ServiceId
)
{
PVOID
NtFunc = NULL;
PVOID
pfn_KiSystemService;
PVOID
pfn_ZwQueryKey;
UNICODE_STRING
RoutineName;
RtlInitUnicodeString(
&RoutineName, L
"ZwQueryKey"
);
pfn_ZwQueryKey
= MmGetSystemRoutineAddress( &RoutineName );
if
(
pfn_ZwQueryKey )
{
NtFunc
= ExAllocatePoolWithTag( NonPagedPool, 32,
'
dmC'
);
if
(
NtFunc )
{
(
PUCHAR
)pfn_KiSystemService
= (
PUCHAR
)pfn_ZwQueryKey
+ 12 + 5 + *(
PULONG
)((
PUCHAR
)pfn_ZwQueryKey
+ 12 + 1);
RtlFillMemory(
NtFunc, 32, 0xCC );
RtlMoveMemory(
NtFunc, pfn_ZwQueryKey, 20 );
*(
PULONG
)((
PUCHAR
)NtFunc
+ 12 + 1 ) = (
ULONG
)((
PUCHAR
)pfn_KiSystemService
- ((
PUCHAR
)NtFunc
+ 12 + 5));
*(
PULONG
)((
PUCHAR
)NtFunc
+ 1 ) = ServiceId;
}
}
return
NtFunc;
}
BOOLEAN
NTAPI
TlCheckFileExist(
IN
PUNICODE_STRING FileName
)
{
OBJECT_ATTRIBUTES
ObjectAttributes = {0};
IO_STATUS_BLOCK
IoStatusBlock = {0};
HANDLE
FileHandle = NULL;
NTSTATUS
Status = STATUS_INVALID_PARAMETER;
InitializeObjectAttributes(
&ObjectAttributes,
FileName,
OBJ_KERNEL_HANDLE|OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
Status
= ZwOpenFile ( &FileHandle,
FILE_GENERIC_READ,
&ObjectAttributes,
&IoStatusBlock,
FILE_SHARE_READ|FILE_SHARE_WRITE,
FILE_NON_DIRECTORY_FILE
);
if
( NT_SUCCESS( Status ) )
{
ZwClose(
FileHandle );
}
return
NT_SUCCESS( Status );
}
VOID
LoadImageNotifyRoutine(
IN
PUNICODE_STRING FullImageName,
IN
HANDLE
ProcessId,
IN
PIMAGE_INFO ImageInfo
)
{
if
(
!pfn_XxxDispatchAPC || !pfn_LoadLibraryA || !pszText_Kernel32 )
{
if
(
!pfn_LoadLibraryA || !pszText_Kernel32 )
{
if
(
RtlCompareUnicodeString( FullImageName, &gModuleName[2], TRUE ) == 0 )
{
(
PUCHAR
)pfn_LoadLibraryA
= (
PUCHAR
)ImageInfo->ImageBase
+ Offset_LoadLibraryA;
(
PUCHAR
)pszText_Kernel32
= (
PUCHAR
)ImageInfo->ImageBase
+ Offset_szText;
if
(
Offset_BaseDispatchAPC )
{
(
PUCHAR
)pfn_XxxDispatchAPC=
(
PUCHAR
)ImageInfo->ImageBase
+ Offset_BaseDispatchAPC;
}
}
}
if
(
Offset_RtlDispatchAPC && !pfn_XxxDispatchAPC )
{
if
(
RtlCompareUnicodeString( FullImageName, &gModuleName[0], TRUE ) == 0 )
{
(
PUCHAR
)pfn_XxxDispatchAPC=
(
PUCHAR
)ImageInfo->ImageBase
+ Offset_RtlDispatchAPC;
}
}
}
else
if
(
pfn_NtQueueApcThread )
{
if
(
RtlCompareUnicodeString( FullImageName, &gModuleName[4], TRUE ) == 0 )
{
pfn_NtQueueApcThread(
ZwCurrentThread(),
pfn_XxxDispatchAPC,
pfn_LoadLibraryA,
pszText_Kernel32,
NULL
);
}
}
}
VOID
DriverUnload(IN PDRIVER_OBJECT DriverObject)
{
PsRemoveLoadImageNotifyRoutine(
LoadImageNotifyRoutine );
ExFreePool(
pfn_NtQueueApcThread );
}
NTSTATUS
DriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath)
{
NTSTATUS
Status = 0;
ULONG
ServiceId = -1;
PVOID
ImageBase_Ntdll ;
PVOID
ImageBase_Kernel;
PVOID
pfn;
ImageBase_Ntdll
= TlLoadSysPEtoMem( &gModuleName[0] );
if
(
ImageBase_Ntdll )
{
pfn
= TlGetProcAddress( ImageBase_Ntdll,
"NtQueueApcThread"
);
if
(
pfn )
{
ServiceId
= *(
PULONG
)((
PUCHAR
)pfn
+ 1 );
}
if
(
*NtBuildNumber == 7601 )
{
pfn
= TlGetProcAddress( ImageBase_Ntdll, (
PUCHAR
)7
);
if
(
pfn )
{
Offset_RtlDispatchAPC
= (
ULONG
)pfn
- (
ULONG
)ImageBase_Ntdll;
}
}
ExFreePool(
ImageBase_Ntdll );
}
ImageBase_Kernel
= TlLoadSysPEtoMem( &gModuleName[1] );
if
(
ImageBase_Kernel )
{
PIMAGE_NT_HEADERS
NtHdrs = RtlImageNtHeader( ImageBase_Kernel );
if
(
*NtBuildNumber == 2600 )
{
pfn
= TlGetProcAddress( ImageBase_Kernel,
"QueueUserAPC"
);
if
(
pfn )
{
Offset_BaseDispatchAPC
= GetOffsetForXxxDispatchApc( pfn, (
PVOID
)NtHdrs->OptionalHeader.ImageBase);
}
}
pfn
= TlGetProcAddress( ImageBase_Kernel,
"LoadLibraryA"
);
if
(
pfn )
{
Offset_LoadLibraryA
= (
ULONG
)pfn
- (
ULONG
)ImageBase_Kernel;
}
Offset_szText
= GetOffsetForSpecialText( (
PUCHAR
)ImageBase_Kernel,
"text"
);
ExFreePool(
ImageBase_Kernel );
}
Status
= STATUS_NOT_SUPPORTED;
if
(
Offset_LoadLibraryA && Offset_szText && (Offset_BaseDispatchAPC || Offset_RtlDispatchAPC) && ServiceId != -1 )
{
Status
= STATUS_NO_SUCH_FILE;
if
(
TlCheckFileExist( &gModuleName[3] ) )
{
pfn_NtQueueApcThread
= TlBuildNtFunc( ServiceId );
}
}
if
(
pfn_NtQueueApcThread )
{
Status
= PsSetLoadImageNotifyRoutine( LoadImageNotifyRoutine );;
}
if
(
!NT_SUCCESS(Status) && pfn_NtQueueApcThread )
{
ExFreePool(
pfn_NtQueueApcThread );
}
DriverObject->DriverUnload
= DriverUnload;
return
Status;
}