Windows xp 重载内核(使用Irp进行文件操作)
一、前言
最近在阅读A盾代码A盾电脑防护(原名 3600safe)anti-rootkit开放源代码,有兴趣的可以去看雪论坛下载,本文代码摘自其中的重载内核。
二、实现步骤
1.ZwQuerySystemInformation大法获得系统模块信息 NtosKrnl.exe 这里第一模块名称是根据单核、多核、开启PAE、未开启PAE变化的
2.自己Reload一个内核模块,打开、获得文件大小、读入内存,这里都用到Irp的操作
irpSp->Parameters.MountVolume.Vpb->RealDevice卷设备
VPB是Volume parameter block一个数据结构,把实际存储媒介设备对象和文件系统上的卷设备对象联系起来。
利用Irp请求对文件进行操作是防止Hook一些文件读取、查询的函数,除非是Hook了IoCallDriver函数,不过也会对这个函数进行监测,具体可以看<寒江独钓><文件系统开发教程>(楚狂人 谭文)
3.将读入的内存按照内存中的位置放置。VirtualAglin = 0x1000对齐
4.根据DriverSection枚举内核模块,修复Reload的导入信息
5.修复重定位表信息
6.根据重定位表中的偏移比较获得 , 在Reload中的SSDT地址的偏移
7.将Reload的SSDT函数地址写入我们的全局变量 SSDT中
8.MmGetSystemRoutine获得Reload中函数的地址
三、代码实现
1.获得模块信息
通过ZwQuerySystemInformation函数传入宏SystemModuleInformation,返回内核模块信息。
/*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,
,
&ulSize
);
if (status!=STATUS_INFO_LENGTH_MISMATCH)
{
return NULL;
}
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 NULL;
}
*SystemKernelModulePath=ExAllocatePool(NonPagedPool,*);
if (*SystemKernelModulePath==NULL)
{
*SystemKernelModuleBase=;
*SystemKernelModuleSize=;
return NULL;
} lpszKernelName = pModuleList->smi[].ModuleNameOffset+pModuleList->smi[].ImageName; //第一模块名称
RtlInitAnsiString(&AnsiKernelModule,lpszKernelName);
RtlAnsiStringToUnicodeString(&UnicodeKernelModule,&AnsiKernelModule,TRUE); RtlZeroMemory(*SystemKernelModulePath,*);
wcscat(*SystemKernelModulePath,L"\\SystemRoot\\system32\\"); memcpy(
*SystemKernelModulePath+wcslen(L"\\SystemRoot\\system32\\"), //第一模块路径
UnicodeKernelModule.Buffer,
UnicodeKernelModule.Length
); *SystemKernelModuleBase=(DWORD)pModuleList->smi[].Base; //获得第一模块地址
*SystemKernelModuleSize=(DWORD)pModuleList->smi[].Size; //获得第一模块大小
ExFreePool(pModuleList);
RtlFreeUnicodeString(&UnicodeKernelModule); }__except(EXCEPTION_EXECUTE_HANDLER){ }
return TRUE;
}
2.Reload Pe
/*
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,,,0x20); //自己创建文件对象, 并返回文件句柄,irp
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;
}
3.按VirtualAglin对齐
/*
修复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=;Index<NumberOfSections;Index++)
{
ImageSectionHeader[Index].SizeOfRawData=AlignSize(ImageSectionHeader[Index].SizeOfRawData,FileAlignment);
ImageSectionHeader[Index].Misc.VirtualSize=AlignSize(ImageSectionHeader[Index].Misc.VirtualSize,SectionAlignment);
}
if (ImageSectionHeader[NumberOfSections-].VirtualAddress+ImageSectionHeader[NumberOfSections-].SizeOfRawData>SizeOfImage)
{//no in
ImageSectionHeader[NumberOfSections-].SizeOfRawData = SizeOfImage-ImageSectionHeader[NumberOfSections-].VirtualAddress;
}
RtlCopyMemory(ImageBase,FileBuffer,SizeOfHeaders); for (Index=;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 - ) / nAlign * nAlign);
}
4.修复导入表,这里利用DriverObject->DriverSection遍历内核模块,找出导入表相等的模块,根据序号或者名称修复导入表
//修复导入表
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[];
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")==||
_stricmp(ModuleName,"ntoskrnl.exe")==||
_stricmp(ModuleName,"ntkrnlmp.exe")==||
_stricmp(ModuleName,"ntkrpamp.exe")==)
{//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==)
{
return FALSE;
}
FirstThunk->u1.Function=FunctionAddress;
}
//函数名导入
else
{
//
ImortByName=(PIMAGE_IMPORT_BY_NAME)(ImageBase+ImageThunkData->u1.AddressOfData);
FunctionAddress=(DWORD)MiFindExportedRoutine(ModuleBase,TRUE,ImortByName->Name,);
if (FunctionAddress==)
{
return FALSE;
}
FirstThunk->u1.Function=FunctionAddress;
}
FirstThunk++;
ImageThunkData++;
}
ImageImportDescriptor++;
}
return TRUE;
}
5.修复重定位表
/*
重定位表 修复
*/
BOOLEAN
FixBaseRelocTable (
PVOID NewImageBase,
DWORD ExistImageBase
)
{
LONGLONG Diff;
ULONG TotalCountBytes = ;
ULONG_PTR VA;
ULONGLONG OriginalImageBase;
ULONG SizeOfBlock;
PUCHAR FixupVA;
USHORT Offset;
PUSHORT NextOffset = NULL;
PIMAGE_NT_HEADERS NtHeaders;
PIMAGE_BASE_RELOCATION NextBlock; NtHeaders = RtlImageNtHeader( NewImageBase );
if (NtHeaders == NULL)
{
return FALSE;
} switch (NtHeaders->OptionalHeader.Magic) { case IMAGE_NT_OPTIONAL_HDR32_MAGIC: OriginalImageBase =
((PIMAGE_NT_HEADERS32)NtHeaders)->OptionalHeader.ImageBase;
break; case IMAGE_NT_OPTIONAL_HDR64_MAGIC: OriginalImageBase =
((PIMAGE_NT_HEADERS64)NtHeaders)->OptionalHeader.ImageBase;
break; default:
return FALSE;
} //
// Locate the relocation section.
// NextBlock = (PIMAGE_BASE_RELOCATION)RtlImageDirectoryEntryToData(
NewImageBase, TRUE, IMAGE_DIRECTORY_ENTRY_BASERELOC, &TotalCountBytes); //
// It is possible for a file to have no relocations, but the relocations
// must not have been stripped.
// if (!NextBlock || !TotalCountBytes)
{ if (NtHeaders->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
{
DbgPrint("Image can't be relocated, no fixup information.\n");
return FALSE; }
else
{
return TRUE;
} } //
// If the image has a relocation table, then apply the specified fixup
// information to the image.
//
Diff = (ULONG_PTR)ExistImageBase - OriginalImageBase;
while (TotalCountBytes)
{
SizeOfBlock = NextBlock->SizeOfBlock;
TotalCountBytes -= SizeOfBlock;
SizeOfBlock -= sizeof(IMAGE_BASE_RELOCATION);
SizeOfBlock /= sizeof(USHORT);
NextOffset = (PUSHORT)((PCHAR)NextBlock + sizeof(IMAGE_BASE_RELOCATION)); VA = (ULONG_PTR)NewImageBase + NextBlock->VirtualAddress; if ( !(NextBlock = LdrProcessRelocationBlockLongLong( VA,
SizeOfBlock,
NextOffset,
Diff)) )
{ DbgPrint("%s: Unknown base relocation type\n");
return FALSE; }
} return TRUE;
} /*修复重定位表*/
PIMAGE_BASE_RELOCATION
LdrProcessRelocationBlockLongLong(
IN ULONG_PTR VA,
IN ULONG SizeOfBlock,
IN PUSHORT NextOffset,
IN LONGLONG Diff
)
{
PUCHAR FixupVA;
USHORT Offset;
LONG Temp;
ULONG Temp32;
ULONGLONG Value64;
LONGLONG Temp64; while (SizeOfBlock--) { Offset = *NextOffset & (USHORT)0xfff;
FixupVA = (PUCHAR)(VA + Offset); //
// Apply the fixups.
// switch ((*NextOffset) >> ) { case IMAGE_REL_BASED_HIGHLOW :
//
// HighLow - (32-bits) relocate the high and low half
// of an address.
//
*(LONG UNALIGNED *)FixupVA += (ULONG) Diff;
break; case IMAGE_REL_BASED_HIGH :
//
// High - (16-bits) relocate the high half of an address.
//
Temp = *(PUSHORT)FixupVA << ;
Temp += (ULONG) Diff;
*(PUSHORT)FixupVA = (USHORT)(Temp >> );
break; case IMAGE_REL_BASED_HIGHADJ :
//
// Adjust high - (16-bits) relocate the high half of an
// address and adjust for sign extension of low half.
// //
// If the address has already been relocated then don't
// process it again now or information will be lost.
//
if (Offset & LDRP_RELOCATION_FINAL) {
++NextOffset;
--SizeOfBlock;
break;
} Temp = *(PUSHORT)FixupVA << ;
++NextOffset;
--SizeOfBlock;
Temp += (LONG)(*(PSHORT)NextOffset);
Temp += (ULONG) Diff;
Temp += 0x8000;
*(PUSHORT)FixupVA = (USHORT)(Temp >> ); break; case IMAGE_REL_BASED_LOW :
//
// Low - (16-bit) relocate the low half of an address.
//
Temp = *(PSHORT)FixupVA;
Temp += (ULONG) Diff;
*(PUSHORT)FixupVA = (USHORT)Temp;
break; case IMAGE_REL_BASED_IA64_IMM64: //
// Align it to bundle address before fixing up the
// 64-bit immediate value of the movl instruction.
// FixupVA = (PUCHAR)((ULONG_PTR)FixupVA & ~());
Value64 = (ULONGLONG); //
// Extract the lower 32 bits of IMM64 from bundle
// EXT_IMM64(Value64,
(PULONG)FixupVA + EMARCH_ENC_I17_IMM7B_INST_WORD_X,
EMARCH_ENC_I17_IMM7B_SIZE_X,
EMARCH_ENC_I17_IMM7B_INST_WORD_POS_X,
EMARCH_ENC_I17_IMM7B_VAL_POS_X);
EXT_IMM64(Value64,
(PULONG)FixupVA + EMARCH_ENC_I17_IMM9D_INST_WORD_X,
EMARCH_ENC_I17_IMM9D_SIZE_X,
EMARCH_ENC_I17_IMM9D_INST_WORD_POS_X,
EMARCH_ENC_I17_IMM9D_VAL_POS_X);
EXT_IMM64(Value64,
(PULONG)FixupVA + EMARCH_ENC_I17_IMM5C_INST_WORD_X,
EMARCH_ENC_I17_IMM5C_SIZE_X,
EMARCH_ENC_I17_IMM5C_INST_WORD_POS_X,
EMARCH_ENC_I17_IMM5C_VAL_POS_X);
EXT_IMM64(Value64,
(PULONG)FixupVA + EMARCH_ENC_I17_IC_INST_WORD_X,
EMARCH_ENC_I17_IC_SIZE_X,
EMARCH_ENC_I17_IC_INST_WORD_POS_X,
EMARCH_ENC_I17_IC_VAL_POS_X);
EXT_IMM64(Value64,
(PULONG)FixupVA + EMARCH_ENC_I17_IMM41a_INST_WORD_X,
EMARCH_ENC_I17_IMM41a_SIZE_X,
EMARCH_ENC_I17_IMM41a_INST_WORD_POS_X,
EMARCH_ENC_I17_IMM41a_VAL_POS_X); EXT_IMM64(Value64,
((PULONG)FixupVA + EMARCH_ENC_I17_IMM41b_INST_WORD_X),
EMARCH_ENC_I17_IMM41b_SIZE_X,
EMARCH_ENC_I17_IMM41b_INST_WORD_POS_X,
EMARCH_ENC_I17_IMM41b_VAL_POS_X);
EXT_IMM64(Value64,
((PULONG)FixupVA + EMARCH_ENC_I17_IMM41c_INST_WORD_X),
EMARCH_ENC_I17_IMM41c_SIZE_X,
EMARCH_ENC_I17_IMM41c_INST_WORD_POS_X,
EMARCH_ENC_I17_IMM41c_VAL_POS_X);
EXT_IMM64(Value64,
((PULONG)FixupVA + EMARCH_ENC_I17_SIGN_INST_WORD_X),
EMARCH_ENC_I17_SIGN_SIZE_X,
EMARCH_ENC_I17_SIGN_INST_WORD_POS_X,
EMARCH_ENC_I17_SIGN_VAL_POS_X);
//
// Update 64-bit address
// Value64+=Diff; //
// Insert IMM64 into bundle
// INS_IMM64(Value64,
((PULONG)FixupVA + EMARCH_ENC_I17_IMM7B_INST_WORD_X),
EMARCH_ENC_I17_IMM7B_SIZE_X,
EMARCH_ENC_I17_IMM7B_INST_WORD_POS_X,
EMARCH_ENC_I17_IMM7B_VAL_POS_X);
INS_IMM64(Value64,
((PULONG)FixupVA + EMARCH_ENC_I17_IMM9D_INST_WORD_X),
EMARCH_ENC_I17_IMM9D_SIZE_X,
EMARCH_ENC_I17_IMM9D_INST_WORD_POS_X,
EMARCH_ENC_I17_IMM9D_VAL_POS_X);
INS_IMM64(Value64,
((PULONG)FixupVA + EMARCH_ENC_I17_IMM5C_INST_WORD_X),
EMARCH_ENC_I17_IMM5C_SIZE_X,
EMARCH_ENC_I17_IMM5C_INST_WORD_POS_X,
EMARCH_ENC_I17_IMM5C_VAL_POS_X);
INS_IMM64(Value64,
((PULONG)FixupVA + EMARCH_ENC_I17_IC_INST_WORD_X),
EMARCH_ENC_I17_IC_SIZE_X,
EMARCH_ENC_I17_IC_INST_WORD_POS_X,
EMARCH_ENC_I17_IC_VAL_POS_X);
INS_IMM64(Value64,
((PULONG)FixupVA + EMARCH_ENC_I17_IMM41a_INST_WORD_X),
EMARCH_ENC_I17_IMM41a_SIZE_X,
EMARCH_ENC_I17_IMM41a_INST_WORD_POS_X,
EMARCH_ENC_I17_IMM41a_VAL_POS_X);
INS_IMM64(Value64,
((PULONG)FixupVA + EMARCH_ENC_I17_IMM41b_INST_WORD_X),
EMARCH_ENC_I17_IMM41b_SIZE_X,
EMARCH_ENC_I17_IMM41b_INST_WORD_POS_X,
EMARCH_ENC_I17_IMM41b_VAL_POS_X);
INS_IMM64(Value64,
((PULONG)FixupVA + EMARCH_ENC_I17_IMM41c_INST_WORD_X),
EMARCH_ENC_I17_IMM41c_SIZE_X,
EMARCH_ENC_I17_IMM41c_INST_WORD_POS_X,
EMARCH_ENC_I17_IMM41c_VAL_POS_X);
INS_IMM64(Value64,
((PULONG)FixupVA + EMARCH_ENC_I17_SIGN_INST_WORD_X),
EMARCH_ENC_I17_SIGN_SIZE_X,
EMARCH_ENC_I17_SIGN_INST_WORD_POS_X,
EMARCH_ENC_I17_SIGN_VAL_POS_X);
break; case IMAGE_REL_BASED_DIR64: *(ULONGLONG UNALIGNED *)FixupVA += Diff; break; case IMAGE_REL_BASED_MIPS_JMPADDR :
//
// JumpAddress - (32-bits) relocate a MIPS jump address.
//
Temp = (*(PULONG)FixupVA & 0x3ffffff) << ;
Temp += (ULONG) Diff;
*(PULONG)FixupVA = (*(PULONG)FixupVA & ~0x3ffffff) |
((Temp >> ) & 0x3ffffff); break; case IMAGE_REL_BASED_ABSOLUTE :
//
// Absolute - no fixup required.
//
break; case IMAGE_REL_BASED_SECTION :
//
// Section Relative reloc. Ignore for now.
//
break; case IMAGE_REL_BASED_REL32 :
//
// Relative intrasection. Ignore for now.
//
break; default :
//
// Illegal - illegal relocation type.
// return (PIMAGE_BASE_RELOCATION)NULL;
}
++NextOffset;
}
return (PIMAGE_BASE_RELOCATION)NextOffset;
}
6.获得ssdt在Reload中的偏移
//通过KeServiceDescriptorTable的RVA与重定位表项解析的地址RVA比较,一致则取出其中的SSDT表地址
BOOLEAN GetOriginalKiServiceTable(BYTE *NewImageBase,DWORD ExistImageBase,DWORD *NewKiServiceTable)
{
PIMAGE_DOS_HEADER ImageDosHeader;
PIMAGE_NT_HEADERS ImageNtHeaders;
DWORD KeServiceDescriptorTableRva;
PIMAGE_BASE_RELOCATION ImageBaseReloc=NULL;
DWORD RelocSize;
int ItemCount,Index;
int Type;
PDWORD RelocAddress;
DWORD RvaData;
DWORD count=;
WORD *TypeOffset; ImageDosHeader=(PIMAGE_DOS_HEADER)NewImageBase;
if (ImageDosHeader->e_magic!=IMAGE_DOS_SIGNATURE)
{
return FALSE;
}
ImageNtHeaders=(PIMAGE_NT_HEADERS)(NewImageBase+ImageDosHeader->e_lfanew);
if (ImageNtHeaders->Signature!=IMAGE_NT_SIGNATURE)
{
return FALSE;
}
KeServiceDescriptorTableRva=(DWORD)MiFindExportedRoutine(NewImageBase,TRUE,"KeServiceDescriptorTable",);
if (KeServiceDescriptorTableRva==)
{
return FALSE;
} KeServiceDescriptorTableRva=KeServiceDescriptorTableRva-(DWORD)NewImageBase;
ImageBaseReloc=RtlImageDirectoryEntryToData(NewImageBase,TRUE,IMAGE_DIRECTORY_ENTRY_BASERELOC,&RelocSize);
if (ImageBaseReloc==NULL)
{
return FALSE;
} while (ImageBaseReloc->SizeOfBlock)
{
count++;
ItemCount=(ImageBaseReloc->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION))/;
TypeOffset=(WORD*)((DWORD)ImageBaseReloc+sizeof(IMAGE_BASE_RELOCATION));
for (Index=;Index<ItemCount;Index++)
{
Type=TypeOffset[Index]>>; //高4位是类型 低12位位页内偏移 4k
if (Type==)
{
//Base + Virtual 定位到页 + 低12位 = RelocAddress 需要修复的地址
RelocAddress=(PDWORD)((DWORD)(TypeOffset[Index]&0x0fff)+ImageBaseReloc->VirtualAddress+(DWORD)NewImageBase);
RvaData=*RelocAddress-ExistImageBase; if (RvaData==KeServiceDescriptorTableRva) //重定位表中的rva 是 KeServiceDescriptorTable 表项的
{
if(*(USHORT*)((DWORD)RelocAddress-)==0x05c7)
{
/*
1: kd> dd 0x89651c12 RelocAddress - 2
89651c12 79c005c7 bd9c83f8 1: kd> dd KeServiceDescriptorTable
83f879c0 83e9bd9c 00000000 00000191 83e9c3e4
83f879d0 00000000 00000000 00000000 00000000 1: kd> dd 0x89651c14 RelocAddress
89651c14 83f879c0 83e9bd9c 79c41589 c8a383f8
89651c24 c783f879 f879cc05 e9c3e483 d8158983
*/
//RelocAddress 里面存放着 KeServiceDesriptorTable地址
//RelocAddress + 4 存放着 KeServiceDesriptorTable第一成员也就是SSDT基址
*NewKiServiceTable=*(DWORD*)((DWORD)RelocAddress+)-ExistImageBase+(DWORD)NewImageBase;
return TRUE;
}
} } }
ImageBaseReloc=(PIMAGE_BASE_RELOCATION)((DWORD)ImageBaseReloc+ImageBaseReloc->SizeOfBlock);
} return FALSE;
}
7.修复SSDT
VOID FixOriginalKiServiceTable(PDWORD OriginalKiServiceTable,DWORD ModuleBase,DWORD ExistImageBase)
{
DWORD FuctionCount;
DWORD Index;
FuctionCount=KeServiceDescriptorTable->TableSize; //函数个数 KdPrint(("ssdt funcion count:%X---KiServiceTable:%X\n",FuctionCount,KeServiceDescriptorTable->ServiceTable));
for (Index=;Index<FuctionCount;Index++)
{
OriginalKiServiceTable[Index]=OriginalKiServiceTable[Index]-ExistImageBase+ModuleBase; //修复SSDT函数地址
}
}
8.提供获取函数地址的函数
/*
输入FuncName 、 原来Ntos地址 、自己重载 Ntos地址
//第一次都是通过 系统的原来偏移 + NewBase 获得函数地址
//然后通过自己的RMmGetSystemRoutineAddress获得 偏移+NewBase 获得函数地址
还不能找到则遍历导出表
*/
ULONG ReLoadNtosCALL(WCHAR *lpwzFuncTion,ULONG ulOldNtosBase,ULONG ulReloadNtosBase)
{
UNICODE_STRING UnicodeFunctionName;
ULONG ulOldFunctionAddress;
ULONG ulReloadFunctionAddress;
int index=;
PIMAGE_DOS_HEADER pDosHeader;
PIMAGE_NT_HEADERS NtDllHeader; IMAGE_OPTIONAL_HEADER opthdr;
DWORD* arrayOfFunctionAddresses;
DWORD* arrayOfFunctionNames;
WORD* arrayOfFunctionOrdinals;
DWORD functionOrdinal;
DWORD Base, x, functionAddress,position;
char* functionName;
IMAGE_EXPORT_DIRECTORY *pExportTable;
ULONG ulNtDllModuleBase; UNICODE_STRING UnicodeFunction;
UNICODE_STRING UnicodeExportTableFunction;
ANSI_STRING ExportTableFunction;
//第一次都是通过 系统的原来偏移 + NewBase 获得函数地址
//然后通过自己的RMmGetSystemRoutineAddress获得 偏移+NewBase 获得函数地址
__try
{
if (RRtlInitUnicodeString &&
RRtlCompareUnicodeString &&
RMmGetSystemRoutineAddress &&
RMmIsAddressValid)
{
RRtlInitUnicodeString(&UnicodeFunctionName,lpwzFuncTion);
ulOldFunctionAddress = (DWORD)RMmGetSystemRoutineAddress(&UnicodeFunctionName);
ulReloadFunctionAddress = ulOldFunctionAddress - ulOldNtosBase + ulReloadNtosBase; //获得重载的FuncAddr
if (RMmIsAddressValid(ulReloadFunctionAddress)) //如果无效就从 导出表 获取? 应该不会无效
{
return ulReloadFunctionAddress;
}
//从导出表里获取
ulNtDllModuleBase = ulReloadNtosBase;
pDosHeader = (PIMAGE_DOS_HEADER)ulReloadNtosBase;
if (pDosHeader->e_magic!=IMAGE_DOS_SIGNATURE)
{
KdPrint(("failed to find NtHeader\r\n"));
return NULL;
}
NtDllHeader=(PIMAGE_NT_HEADERS)(ULONG)((ULONG)pDosHeader+pDosHeader->e_lfanew);
if (NtDllHeader->Signature!=IMAGE_NT_SIGNATURE)
{
KdPrint(("failed to find NtHeader\r\n"));
return NULL;
}
opthdr = NtDllHeader->OptionalHeader;
pExportTable =(IMAGE_EXPORT_DIRECTORY*)((BYTE*)ulNtDllModuleBase + opthdr.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT]. VirtualAddress); //得到导出表
arrayOfFunctionAddresses = (DWORD*)( (BYTE*)ulNtDllModuleBase + pExportTable->AddressOfFunctions); //地址表
arrayOfFunctionNames = (DWORD*)((BYTE*)ulNtDllModuleBase + pExportTable->AddressOfNames); //函数名表
arrayOfFunctionOrdinals = (WORD*)((BYTE*)ulNtDllModuleBase + pExportTable->AddressOfNameOrdinals); Base = pExportTable->Base; for(x = ; x < pExportTable->NumberOfFunctions; x++) //在整个导出表里扫描
{
functionName = (char*)( (BYTE*)ulNtDllModuleBase + arrayOfFunctionNames[x]);
functionOrdinal = arrayOfFunctionOrdinals[x] + Base - ;
functionAddress = (DWORD)((BYTE*)ulNtDllModuleBase + arrayOfFunctionAddresses[functionOrdinal]);
RtlInitAnsiString(&ExportTableFunction,functionName);
RtlAnsiStringToUnicodeString(&UnicodeExportTableFunction,&ExportTableFunction,TRUE); RRtlInitUnicodeString(&UnicodeFunction,lpwzFuncTion);
if (RRtlCompareUnicodeString(&UnicodeExportTableFunction,&UnicodeFunction,TRUE) == )
{
RtlFreeUnicodeString(&UnicodeExportTableFunction);
return functionAddress;
}
RtlFreeUnicodeString(&UnicodeExportTableFunction);
}
return NULL;
}
RtlInitUnicodeString(&UnicodeFunctionName,lpwzFuncTion);
ulOldFunctionAddress = (DWORD)MmGetSystemRoutineAddress(&UnicodeFunctionName);
ulReloadFunctionAddress = ulOldFunctionAddress - ulOldNtosBase + ulReloadNtosBase; //KdPrint(("%ws:%08x:%08x",lpwzFuncTion,ulOldFunctionAddress,ulReloadFunctionAddress)); if (MmIsAddressValid(ulReloadFunctionAddress))
{
return ulReloadFunctionAddress;
}
// }__except(EXCEPTION_EXECUTE_HANDLER){
KdPrint(("EXCEPTION_EXECUTE_HANDLER"));
}
return NULL;
}
四、代码下载
https://github.com/LycorisGuard/Windows-Rootkits/tree/master/ReloadKernel-XP
Windows xp 重载内核(使用Irp进行文件操作)的更多相关文章
- 使用IRP进行文件操作
使用IRP进行文件操作 首先声明这个是菜鸟—我的学习日记,不是什么高深文章,高手们慎看. 一定要先感谢为技术的进步而付出辛勤汗水的人,感谢他们对技术的共享. 一个通用IRP访问文件的十六进制编辑器(开 ...
- Windows phone 8 学习笔记(2) 数据文件操作
原文:Windows phone 8 学习笔记(2) 数据文件操作 Windows phone 8 应用用于数据文件存储访问的位置仅仅限于安装文件夹.本地文件夹(独立存储空间).媒体库和SD卡四个地方 ...
- Windows phone 8 学习笔记(2) 数据文件操作(转)
Windows phone 8 应用用于数据文件存储访问的位置仅仅限于安装文件夹.本地文件夹(独立存储空间).媒体库和SD卡四个地方.本节主要讲解它们的用法以及相关限制性.另外包括本地数据库的使用方式 ...
- 《天书夜读:从汇编语言到windows内核编程》八 文件操作与注册表操作
1)Windows运用程序的文件与注册表操作进入R0层之后,都有对应的内核函数实现.在windows内核中,无论打开的是文件.注册表或者设备,都需要使用InitializeObjectAttribut ...
- windows xp 环境下 Oracle8i 双击安装文件无反应的解决办法
今天调试一份比较老的程序,数据库用的是Oracle8i,在本地xp系统上搞了半天,双击安装文件就是没反应! 在网上整理了一下解决办法: 1.将ORACLE软件拷贝到硬盘. (比如我拷贝到:F:\Ora ...
- Linux系统调用和ANSI C文件操作的区别
一.在Linux下对文件操作有两种方式:Linux系统调用和ANSI C文件操作. 1.Linux系统调用调用常用于I/O文件操作,系统调用常用的函数有open.close.read.write.ls ...
- windows XP系统内核文件分析(全)
Windows XP个别 System32 文件 System32 文件夹下个别要移除的文件 我们就要删除另外600 个 system32 文件...我们要一次把它们全都解决掉. 以下是我所删除的 S ...
- 在windows下解压缩Linux内核源代码出现重复文件原因
在windows下解压缩Linux内核源代码出现重复文件原因 2009年06月30日 13:35 来源:ChinaUnix博客 作者:embededgood 编辑:周荣茂 原因一.因为在Lin ...
- [转]如何使用VS 2013發布一個可以在Windows XP中獨立運行的可執行文件
https://read01.com/Mg337.html (台/湾的论坛,需要f/q) 1. 閱讀此文章的同學先看看我的另外一篇文章: 現在,我們深入探討一下: <如何使用VS 2013發布一 ...
随机推荐
- erl0007 - erlang 远程节点连接的两种方式
启动连接:erl -setcookie abc -name xxx@192.168.x.x -remsh xxx@192.168.x.y 退出:ctrl + g,q 参考:http://www.cnb ...
- 使用crs_setperm修改RAC资源的所有者及权限
Oracle RAC 集群中,对于各种资源的管理,也存在所有者与权限的问题.crs_getperm与crs_setperm则是这样的一对命令,主要用于查看与修改集群中resource的owner,gr ...
- Oracle数据库备份手册
1 故障类型 l 实例故障 由ORACLE内部异常.操作系统故障或其它相关软件引起,导致ORACLE实例中的进程或内存区出现故障或数据库无法正常关闭,这种故障称为实例故障.实例故障没 ...
- 删除binlog的方法
不知道你有没有为mysql的binlog占用大量磁盘感到无奈,my.cnf里binlog的size可以设置多大做分割,但没有看到删除的配置,在mysql里show了一下variables, mysql ...
- centos下安装python
下载网址:http://ftp.gnu.org/gnu/gdb/ 1.编译python必须安装开发工具 # yum groupinstall "Development tools" ...
- Private Bytes,Working Set,Virtual Size的区别
http://aigo.iteye.com/blog/1930209 http://stackoverflow.com/questions/1984186/what-is-private-bytes- ...
- ylb:SQL 常用函数
ylbtech-SQL Server: SQL Server-SQL 常用函数 1,数学函数 2,日期和时间函数 3,字符串函数 4,转换函数 1,ylb:SQL 常用函数返回顶部 1,数学函数 2, ...
- JAVA CAS原理、unsafe、AQS
concurrent包的实现 由于java的CAS同时具有 volatile 读和volatile写的内存语义,因此Java线程之间的通信现在有了下面四种方式: A线程写volatile变量,随后B线 ...
- nginx 的模块及处理流程
nginx的内部结构是由核心部分和一系列的功能模块所组成.这样划分是为了使得每个模块的功能相对简单,便于开发,同时也便于对系统进行功能扩展.这样的模块化设计类似于面向对象中的接口类,它增强了 ...
- CAT XQX --- 省市三级级联实现说明
最终效果: 满足要求, 上代码 : 1. 需要调用这个控件 的地方:添加引用,因为里面写着逻辑呢..... <script type="text/javascript" ...