首页
社区
课程
招聘
[求助]内核重载之KiFastCalEntry Hook
发表于: 2020-9-16 22:43 2889

[求助]内核重载之KiFastCalEntry Hook

2020-9-16 22:43
2889

#include<ntddk.h>

 

#include"PE.h"

 

#include"LDR.h"
UCHAR Buf = NULL;
UCHAR
Mem1 = NULL;
DWORD OldImageBase;
DWORD SizeOfHeaders;
DWORD SetionNumber;
DWORD SizeofImage ;
NTSTATUS NTAPI GetMoudleAddress(PUNICODE_STRING);
NTSTATUS NTAPI GetProcessAddress(DWORD , char*);
PDRIVER_OBJECT CurrentObject = NULL;

 

DWORD HookAddress = 0x8053e621;
DWORD RetAddress;
DWORD NewSeriverBase = 0;
char HooKData[5] = { 0 };

 

extern PKSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable;
//extern __declspec(dllimport) PKSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable;
PKSERVICE_TABLE_DESCRIPTOR g_NewKernelSeriveDescriptorTaber = NULL;
void Cr0Close();
void Cr0Off();
void MemFree() {
ExFreePool(Buf);
ExFreePool(Mem1);
DbgPrint("内存释放成功!\n");
}
void UnLoadHook() {
Cr0Off();
RtlCopyMemory((void*)HookAddress, HooKData, 5);
Cr0Close();
DbgPrint("钩子卸载成功!\n");
}
NTSTATUS DriverUnload(PDRIVER_OBJECT Pobject) {
DbgPrint("驱动卸载成功!\n");
MemFree();
UnLoadHook();
return STATUS_SUCCESS;
}
NTSTATUS GetFileSize(PUNICODE_STRING KernelPathName) {
DWORD Temp = 0;
PE_HEADER pE = { 0 };
HANDLE hFile=NULL;
NTSTATUS status = 0;
OBJECT_ATTRIBUTES Object;
IO_STATUS_BLOCK Io_Status;
LARGE_INTEGER fileOffset = { 0 };

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
InitializeObjectAttributes(&Object, KernelPathName, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);
 
status=ZwCreateFile(&hFile, GENERIC_READ, &Object, &Io_Status, NULL, FILE_ATTRIBUTE_NORMAL,
    FILE_SHARE_READ, FILE_OPEN, FILE_NON_DIRECTORY_FILE, NULL, 0);
 
if (!NT_SUCCESS(status)) {
    DbgPrint("ZwCreateFile 函数打开文件失败!\n");
    return 0;
}
Buf = (UCHAR*)ExAllocatePool(PagedPool, 0x1000);                                        //开辟分页内存    0x1000   会被交换到文件中
if (NULL == Buf) {
    DbgPrint("开辟一个页的分页内存失败\n");
    return -1;
}
 
status=ZwReadFile(hFile, NULL, NULL, NULL, &Io_Status, Buf, 0x1000,&fileOffset, NULL);
if (!NT_SUCCESS(status)) {
    DbgPrint("ZwReadFile读取文件内容DosHeader失败  status=%d\n", status);
    return -2;
}
pE.DosHeader = (PIMAGE_DOS_HEADER)Buf;
pE.NtHeaders.FileHeader = (PIMAGE_FILE_HEADER)((DWORD)pE.DosHeader+(DWORD)pE.DosHeader->e_lfanew + 4);                   
pE.NtHeaders.OptionalHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pE.NtHeaders.FileHeader + sizeof(IMAGE_FILE_HEADER));
pE.SectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pE.NtHeaders.OptionalHeader + pE.NtHeaders.FileHeader->SizeOfOptionalHeader);
 
 
SizeofImage  = pE.NtHeaders.OptionalHeader->SizeOfImage;                                //拉伸后的大小
OldImageBase = pE.NtHeaders.OptionalHeader->ImageBase;                                    //ntkrnlpa.exe的imagebase
SizeOfHeaders= pE.NtHeaders.OptionalHeader->SizeOfHeaders;                                //获得PE头大小
SetionNumber = pE.NtHeaders.FileHeader->NumberOfSections;                                //ntkrnlpa.exe文件节的数量  0x19
 
 
DbgPrint("%p  SizeofImage=%p ImageBase=%p\n SizeOfHeaders=%p    SetionNumber=%p\n", *((DWORD*)Buf), SizeofImage, OldImageBase, SizeOfHeaders, SetionNumber);
Mem1=(UCHAR*)(UCHAR*)ExAllocatePool(PagedPool, SizeofImage);
if (NULL == Mem1) {
    DbgPrint("ExAllocatePool函数开辟内核文件内存 sizeofimage大小内存失败!\n");
    return -3;
}

#if 1
DbgPrint("Buf=%p Mem1=%p SizeOfHeaders=%p\n", Buf, Mem1,SizeOfHeaders);
memset(Mem1,0, SizeofImage);
memcpy(Mem1, Buf, SizeOfHeaders); //CPY 复制PE头
for (Temp = 0; Temp < SetionNumber; Temp++) {
fileOffset.QuadPart = pE.SectionHeader->PointerToRawData; //这个参数决定了ReadFile读取文件内容从哪里开始 该节的FOA
//DbgPrint("Temp=%p %p %p\n", Temp + 1, pE.SectionHeader->VirtualAddress,pE.SectionHeader->PointerToRawData);
//DbgPrint("%p %p\n", (VOID)((DWORD)Mem1 + pE.SectionHeader->VirtualAddress), pE.SectionHeader->Misc.VirtualSize);
status = ZwReadFile(hFile, NULL, NULL, NULL, &Io_Status, (VOID
)((DWORD)Mem1+ pE.SectionHeader->VirtualAddress), pE.SectionHeader->Misc.VirtualSize, &fileOffset, NULL);
if (!NT_SUCCESS(status)) {
DbgPrint("拉伸FileBuf到ImagaeBuf失败 status=%d\n", status);
return -2;
}
pE.SectionHeader++;
}

 

#endif

1
2
3
DbgPrint("拉伸成功!\n");
ZwClose(hFile);
return 1;

}
NTSTATUS RestoreReLcationTaber() { //修改内核文件重定位
DWORD i;
WORD Data;
DWORD
Item;
PE_HEADER pE = { 0 };
PIMAGE_BASE_RELOCATION Reloction;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
pE.DosHeader = (PIMAGE_DOS_HEADER)Mem1;
pE.NtHeaders.FileHeader = (PIMAGE_FILE_HEADER)((DWORD)pE.DosHeader + (DWORD)pE.DosHeader->e_lfanew + 4);    //e_lfarlc写错找到2个小时bug
pE.NtHeaders.OptionalHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pE.NtHeaders.FileHeader + sizeof(IMAGE_FILE_HEADER));
pE.SectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pE.NtHeaders.OptionalHeader + pE.NtHeaders.FileHeader->SizeOfOptionalHeader);
 
DbgPrint("%p ",pE.NtHeaders.OptionalHeader->Magic);
DbgPrint("OPtion=%p\n", pE.NtHeaders.FileHeader->SizeOfOptionalHeader);
DbgPrint("%p  %p   \n%p   %p\n", pE.DosHeader, pE.NtHeaders.FileHeader, pE.NtHeaders.OptionalHeader, pE.SectionHeader);
if (pE.NtHeaders.OptionalHeader->DataDirectory[5].VirtualAddress) {
    DbgPrint("存在重定位表  %p  Size=%p!\n", pE.NtHeaders.OptionalHeader->DataDirectory[5].VirtualAddress, pE.NtHeaders.OptionalHeader->DataDirectory[5].Size);
    Reloction = (PIMAGE_BASE_RELOCATION)((DWORD)Mem1+(DWORD)pE.NtHeaders.OptionalHeader->DataDirectory[5].VirtualAddress);    //指向重定位表
}else {
    DbgPrint("不存在重定位表 加载内核重载失败\n");
    return 0;
}
pE.NtHeaders.OptionalHeader->ImageBase = (DWORD)Mem1;                                                                        //修改IMAGEBASE

#if 1
//DbgPrint("Reloction->VirtualAddr=%p SizeofBloc=%p\n", Reloction->VirtualAddress, Reloction->SizeOfBlock);
while (Reloction->VirtualAddress||Reloction->SizeOfBlock) {
Data = (WORD)((DWORD)Reloction + 8);
//DbgPrint("Reloction->VirtualAddr=%p SizeofBloc=%p\n", Reloction->VirtualAddress, Reloction->SizeOfBlock);
for (i = 0; i < (Reloction->SizeOfBlock - 8) / 2; i++) {
if ((Data[i] & 0xF000) == 0x3000) {
Item = (DWORD
)((DWORD)Mem1 + Reloction->VirtualAddress + (Data[i] & 0x0FFF)); //修复重定位表
//DbgPrint("%p Size=%p\n ", Reloction->VirtualAddress, Reloction->SizeOfBlock);
Item = Item + (DWORD)Mem1 - (DWORD)OldImageBase; //修改重定位

1
2
3
4
        }
    }
    Reloction = (PIMAGE_BASE_RELOCATION)((DWORD)Reloction + Reloction->SizeOfBlock);
}

#endif
DbgPrint("修复重定位成功\n");
return 1;
}
NTSTATUS NTAPI GetProcessAddress(DWORD Base, char FuntionName) {
DWORD i = 0;
DWORD FuntionNumber = 0;
DWORD
FuntionAddress;
DWORD FuntionName1;
WORD
IndexTaber;
char PeName ;
char
FuntionName2 = NULL;
PE_HEADER pE = { 0 };
char Mz[3] = { 0 };

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
PIMAGE_EXPORT_DIRECTORY ExPort_Taber = NULL;
pE.DosHeader = (PIMAGE_DOS_HEADER)Base;
pE.NtHeaders.FileHeader = (PIMAGE_FILE_HEADER)((DWORD)pE.DosHeader + (DWORD)pE.DosHeader->e_lfanew + 4);    //e_lfarlc写错找到2个小时bug
pE.NtHeaders.OptionalHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pE.NtHeaders.FileHeader + sizeof(IMAGE_FILE_HEADER));
 
if (pE.NtHeaders.OptionalHeader->DataDirectory[0].VirtualAddress) {
    //DbgPrint("导出表 RVA=%p  Size=%p\n", pE.NtHeaders.OptionalHeader->DataDirectory[0].VirtualAddress, pE.NtHeaders.OptionalHeader->DataDirectory[0].Size);
    ExPort_Taber = (PIMAGE_EXPORT_DIRECTORY)((DWORD)Base+ pE.NtHeaders.OptionalHeader->DataDirectory[0].VirtualAddress);
}
else {
    DbgPrint("没有找到导出表!\n");
    return 0;
}
 
PeName = (char*)(Base + ExPort_Taber->Name);
//DbgPrint("PENAME=%s\n", PeName);
//DbgPrint("导出表OK  %p  %p  %p!\n", Base,PeName, ExPort_Taber->Name);
//DbgPrint("到处函数的起始序号%d  导出函数的个数=%d   按照函数名导出的函数个数=%d\n", ExPort_Taber->Base, ExPort_Taber->NumberOfFunctions, ExPort_Taber->NumberOfNames);
 
FuntionNumber = ExPort_Taber->NumberOfNames;                                                                //按照函数名导处函数的个数
FuntionAddress = (DWORD*)(Base + ExPort_Taber->AddressOfFunctions);                                            //指向函数地址表
FuntionName1 = (DWORD*)(Base + ExPort_Taber->AddressOfNames);                                                //指向函数名称表
IndexTaber = (WORD*)(Base + ExPort_Taber->AddressOfNameOrdinals);                                            //指向函数序号表
 
for (i = 0; i < FuntionNumber; i++) {                                                                        //函数名表项对应的序号表只是函数地址表的索引
    FuntionName2 = (char*)(Base + *FuntionName1);
    if (0 == strcmp(FuntionName2, FuntionName)) {
        return FuntionAddress[IndexTaber[i]] + Base;
    }
    //DbgPrint("%d  %s\n", i + 1, FuntionName2);
    FuntionName1++;
}
return 0;

}
NTSTATUS NTAPI GetMoudleAddress(PUNICODE_STRING DLLName) {
PLDR_DATA_TABLE_ENTRY Moude= (PLDR_DATA_TABLE_ENTRY )CurrentObject->DriverSection;
PLIST_ENTRY Flag = &(Moude->InLoadOrderLinks);

1
2
3
4
5
6
7
8
9
10
11
12
while (Moude->InLoadOrderLinks.Flink) {
    if (0==RtlCompareUnicodeString(DLLName,&Moude->BaseDllName, TRUE)) {
        //DbgPrint("DLLNAME %wZ  DLLBase=%p\n", &Moude->BaseDllName, Moude->DllBase);
        return (DWORD)Moude->DllBase;
    }
    //DbgPrint("DLLNAME %wZ\n", &Moude->BaseDllName);
    Moude = (PLDR_DATA_TABLE_ENTRY)Moude->InLoadOrderLinks.Flink;
    if (&(Moude->InLoadOrderLinks) == Flag) {
        break;
    }
}
return 0;

}
NTSTATUS RestoreIATTaber() {
DWORD i = 0;
DWORD ImageBase = 0;
NTSTATUS status = 0;
char DllName ;
char
FuintionName1;
char FuintionName2;
DWORD
INT = NULL;
DWORD* IAT = NULL;
PE_HEADER pE = { 0 };
ANSI_STRING Transition;
ANSI_STRING Transition1;
UNICODE_STRING Unicode_String;
UNICODE_STRING Unicode_DLLName;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
PIMAGE_BASE_RELOCATION    Reloction;
PIMAGE_IMPORT_DESCRIPTOR    ImPort_Taber = NULL;
 
pE.DosHeader = (PIMAGE_DOS_HEADER)Mem1;
pE.NtHeaders.FileHeader = (PIMAGE_FILE_HEADER)((DWORD)pE.DosHeader + (DWORD)pE.DosHeader->e_lfanew + 4);    //e_lfarlc写错找到2个小时bug
pE.NtHeaders.OptionalHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pE.NtHeaders.FileHeader + sizeof(IMAGE_FILE_HEADER));
//pE.SectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pE.NtHeaders.OptionalHeader + pE.NtHeaders.FileHeader->SizeOfOptionalHeader);
if (pE.NtHeaders.OptionalHeader->DataDirectory[1].VirtualAddress) {
    //DbgPrint("存在导入表!  RVA=%p  Size=%p\n", pE.NtHeaders.OptionalHeader->DataDirectory[1].VirtualAddress, pE.NtHeaders.OptionalHeader->DataDirectory[1].Size);
    ImPort_Taber = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)Mem1 + pE.NtHeaders.OptionalHeader->DataDirectory[1].VirtualAddress);
}
else {
    DbgPrint("获得导入表失败!\n");
    return 0;
}
/*经过验证得到了经验到PE文件没有加载到内存中的时候,INT和IAT项指向的都是函数名的RVA结构  OK*/
while (ImPort_Taber->OriginalFirstThunk&&ImPort_Taber->FirstThunk) {
    DWORD n = 0;
    DllName = (char*)((DWORD)Mem1 + ImPort_Taber->Name);
    INT = (DWORD*)((DWORD)Mem1 + ImPort_Taber->OriginalFirstThunk);                                                                    //(INT函数名称表)
    IAT = (DWORD*)((DWORD)Mem1 + ImPort_Taber->FirstThunk);                                                                            //(IAT函数地址表)   
 
    RtlInitAnsiString(&Transition1, DllName);                                                                                        //将DLL名从ASCLL字符串转换位ANSI字符串
    status=RtlAnsiStringToUnicodeString(&Unicode_DLLName, &Transition1, sizeof(DllName) * 2);                                        //将DLL从ANSI转换为UNICODE字符串
    if (status) {
        DbgPrint("RtlAnsiStringToUnicodeString开辟空间失败!\n");
    }
    ImageBase = GetMoudleAddress(&Unicode_DLLName);
    if (ImageBase == 0) {
        DbgPrint("获取模块Base失败  修复IAT表失败!\n");
        return -1;
 
    }
    DbgPrint("%s   Base\n", DllName, ImageBase);
    while ((*IAT)) {
 
        if (((*INT)&0x80000000) != 0x80000000) {                                                                                                    //INT项存储胡DWORD数据的最高位不为0时候执行这个
            FuintionName1 = (char*)((DWORD)Mem1 + *INT + 2);
            FuintionName2 = (char*)((DWORD)Mem1 + *IAT + 2);           
            //RtlInitAnsiString(&Transition, FuintionName1);                                                                            //把ASCLL字符转换位ANSI_STRING
            //status = RtlAnsiStringToUnicodeString(&Unicode_String, &Transition, sizeof(FuintionName1) * 2);                            //把ANSI_STRING字符串转换为UNICODE_STRING字符串
            //DbgPrint("%wZ     %d  %Z\n", &Unicode_String, status,&Transition);
            //DbgPrint("i=%d  DLLName=%s,FuntionName=%s,FuntionName2=%s  *INT=%p *IAT=%p",i+1, DllName, FuintionName1, FuintionName2, *INT,*IAT);
            //RtlFreeUnicodeString(&Unicode_String);
            *IAT=GetProcessAddress(ImageBase, FuintionName1);
            if (0 == *IAT) {
                DbgPrint("FuintionName1=%s 获取导入函数地址函数!\n", FuintionName1);
                return -2;
            }
            DbgPrint("%d  DllName=%s Address=%p   FuntionName=%s\n",n+1, DllName,*IAT ,FuintionName1);
            //DbgPrint("%d  DllName=%s  %s  \n",n+1, DllName,FuintionName1);
        }
        else {
            //FuintionName1=
            //FuintionName2=
            DbgPrint("*INT=%p  *IAT=%p\n",*INT, *IAT);
        }
        IAT++;
        INT++;
        n++;
    }
    RtlFreeUnicodeString(&Unicode_DLLName);
    ImPort_Taber++;
 
}
DbgPrint("导入表 ok!\n");
 
return 1;

}
NTSTATUS CharacteristicScan(DWORD ImageBase) {
DWORD SizeofImage;
DWORD i = 0;
DWORD j = 0;
DWORD Number = 0;
PE_HEADER pE = { 0 };
char Data = NULL;
char
Dest = NULL;
pE.DosHeader = (PIMAGE_DOS_HEADER)ImageBase;
pE.NtHeaders.FileHeader = (PIMAGE_FILE_HEADER)((DWORD)pE.DosHeader + (DWORD)pE.DosHeader->e_lfanew + 4); //e_lfarlc写错找到2个小时bug
pE.NtHeaders.OptionalHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pE.NtHeaders.FileHeader + sizeof(IMAGE_FILE_HEADER));

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Data = (char*)KeServiceDescriptorTable;
SizeofImage = pE.NtHeaders.OptionalHeader->SizeOfImage;                                                                    //ShaDow所在模块大小
Dest = (char*)ImageBase;
DbgPrint("SizeofImage=%p\n", SizeofImage);
for (i = ImageBase; i < ImageBase +SizeofImage; i++) {                                                                    //应该是扫描到
    if (Dest[i] == Data[j]) {
        Number++;
        j++;
    }
    else {
        if (j >= 15) {
            DbgPrint("%p\n", Dest + i-j);
        }
        j = 0;
        Number = 0;
    }
}
return 0;

}
NTSTATUS GetKernelMoudleAddr() {
DWORD ImageBase = 0;
__asm {
push eax
mov eax, fs:[0x34]
add eax, 0x18
mov eax, [eax]
mov eax, [eax]
mov eax, [eax + 0x18] //指向内核模块基地址
mov ImageBase, eax
pop eax
}
return (ImageBase == 0) ? 0 : ImageBase;
}
NTSTATUS RepairSSDT(DWORD OlbkernelAddress) {
DWORD u_offset;
DWORD i;
DbgPrint("%p %p %p", KeServiceDescriptorTable, Mem1, OlbkernelAddress);
g_NewKernelSeriveDescriptorTaber = (PKSERVICE_TABLE_DESCRIPTOR)((DWORD)(KeServiceDescriptorTable) + ((DWORD)Mem1 - OlbkernelAddress)); //老系统服务表地址-老内核Base+新内核Base=RVA+内核base

1
2
3
4
5
6
7
8
u_offset = ((DWORD)KeServiceDescriptorTable->ntoskrnel.ServiceTableBase - OlbkernelAddress);                                                //得到旧内核SSDT函数表到ImageBase的offset
g_NewKernelSeriveDescriptorTaber->ntoskrnel.ServiceTableBase = (PVOID)(u_offset + (DWORD)Mem1);
g_NewKernelSeriveDescriptorTaber->ntoskrnel.NumberOfServices = KeServiceDescriptorTable->ntoskrnel.NumberOfServices;
g_NewKernelSeriveDescriptorTaber->ntoskrnel.ParamTableBase = (PVOID)((DWORD)Mem1+ ((DWORD)KeServiceDescriptorTable->ntoskrnel.ParamTableBase - OlbkernelAddress));
DbgPrint("新内核的系统服务表地址%p   %p  %p   %p %p\n", g_NewKernelSeriveDescriptorTaber, g_NewKernelSeriveDescriptorTaber->ntoskrnel.ServiceTableBase,
    g_NewKernelSeriveDescriptorTaber->ntoskrnel.ServiceCouterTable, g_NewKernelSeriveDescriptorTaber->ntoskrnel.NumberOfServices, g_NewKernelSeriveDescriptorTaber->ntoskrnel.ParamTableBase);
 
NewSeriverBase = (DWORD)g_NewKernelSeriveDescriptorTaber->ntoskrnel.ServiceTableBase;

#if 0 /修复重定位的时候这个都修复了/
for (i = 0; i < g_NewKernelSeriveDescriptorTaber->ntoskrnel.NumberOfServices; i++) {
g_NewKernelSeriveDescriptorTaber->ntoskrnel.NumberOfServices[i] += u_offset; //修复SSDT
}

 

#endif

1
2
3
//DbgPrint("%p  %p  %p", g_NewKernelSeriveDescriptorTaber->ntoskrnel.ServiceTableBase, g_NewKernelSeriveDescriptorTaber->ntoskrnel.ServiceCouterTable,
//    g_NewKernelSeriveDescriptorTaber->ntoskrnel.NumberOfServices, g_NewKernelSeriveDescriptorTaber->ntoskrnel.ParamTableBase);
return 0;

}
DWORD DisPaly(DWORD Base,DWORD FuntionAddress,DWORD Index) {
DWORD Data = NULL;
DWORD
New = NULL;
char ProcessName = NULL;
char
CurrentProcessName = 0;
PEPROCESS Current;
if (Base == (DWORD)KeServiceDescriptorTable->ntoskrnel.ServiceTableBase) {
Current = PsGetCurrentProcess();
CurrentProcessName = (char*)((DWORD)Current + 0x174);
if (Index == 0x25) {

1
2
3
4
5
6
7
8
9
10
11
12
13
        DbgPrint("NtCreateFile!  =%p   %s  %s\n", FuntionAddress, CurrentProcessName,ProcessName);
    }
    else if (Index == 0x74) {
        char* Size = (char*)(((DWORD)KeServiceDescriptorTable->ntoskrnel.ParamTableBase) + Index);
        DbgPrint("NtOpenFile! =%p  %s   %s\n", FuntionAddress, CurrentProcessName, ProcessName);
    }
    DbgPrint("111111111   eax=%p   %p       %p", Index, FuntionAddress, Base);
    return *((DWORD*)((DWORD)g_NewKernelSeriveDescriptorTaber->ntoskrnel.ServiceTableBase + Index * 4));
}
else {
    DbgPrint("eax=%p   %p       %p", Index, FuntionAddress, Base);
    return FuntionAddress;
}

}/
push EAX, ECX,EDX,EBX, ESP(初始值0x7c00),EBP,ESI,EDI
popad EDI ESI EBP ESP EBX EDX ECX EAX
/
declspec(naked) void MyKiFastCallEntry() { //我自己的KiFastCallEntry asm {
pushad
pushfd
__asm {
int 3
}
push eax //eaxSSDT索引
push ebx //ebx指向即将别调用函数的地址
push edi //执行到了这里edi指向函数表地址
//push edx
call DisPaly
test eax,eax
je L
mov [esp+0x14],eax

 

L:
popfd
popad

1
2
3
4
    sub     esp, ecx   
    shr     ecx, 2
    jmp        RetAddress
}

}
void Cr0Close() {
__asm {
mov eax,cr0
and eax, 0xFFFEFFFF
mov cr0,eax
sti //STI允许中断发生
}
}

 

/WP位是Supervisor的写保护位(CPL < 3是Supervisor) Supervisor监管者模式就是内核模式
当WP = 1时,Supervisor不能写R / W没有置位的页。 WP=1 内核下不能写 R/W=0的物理页
WP = 0时,Supervisor可以写任何页。 WP=0是 可以写任何页
/
void Cr0Off() {
__asm {
cli //静止中断发送
mov eax, cr0
or eax, 0x10000
mov cr0, eax
}
}

 

NTSTATUS HookkiFastCallEntry() {
unsigned char Jmp_Code[5] = {0};
Jmp_Code[0] = 0xE9;
/JMP后面跟的32位数=目标地址-当前指令地址-5/
((DWORD)&Jmp_Code[1]) = (DWORD)MyKiFastCallEntry - HookAddress - 5;
RetAddress = HookAddress + 5;
Cr0Off();
RtlCopyMemory(HooKData, (void)HookAddress, 5);
RtlCopyMemory((void
)HookAddress,(void*)Jmp_Code, 5);
Cr0Close();

1
2
3
DbgPrint("Hook  Yes!\n");
 
return 0;

}

 

NTSTATUS DirverEntry(PDRIVER_OBJECT Pobject, PUNICODE_STRING RegPath) {
DWORD OlbkernelAddress;
NTSTATUS status;
UNICODE_STRING KernelPathName;
char Name[10] = "taolaoda";
CurrentObject = Pobject;
RtlInitUnicodeString(&KernelPathName, L"\??\C:\WINDOWS\system32\ntkrnlpa.exe"); //ntkrnlpa.exe
DbgPrint("驱动加载成功!\n");
if (1==GetFileSize(&KernelPathName)) {
if (1 != RestoreReLcationTaber()) {
DbgPrint("修复重定位表失败");
goto exit;
}
}
switch (RestoreIATTaber()) {
case -2:
DbgPrint("修复IAT获得函数地址失败\n");
break;
case -1:
DbgPrint("修复IAT获得模块Base失败!\n");
break;
case 0:
DbgPrint("获得导入表RVA失败!\n");
break;
case 1:
DbgPrint("修复IAT表成功!\n");
break;
}
exit:
//GetProcessAddress(0x804D8000, Name);

1
2
3
4
5
6
7
8
9
10
11
DbgPrint(" KeServiceDescriptorTable=%p  %p  %p  %p %p\n",  KeServiceDescriptorTable, KeServiceDescriptorTable->ntoskrnel.ServiceTableBase,
    KeServiceDescriptorTable->ntoskrnel.ServiceCouterTable, KeServiceDescriptorTable->ntoskrnel.NumberOfServices, KeServiceDescriptorTable->ntoskrnel.ParamTableBase);
//CharacteristicScan(0x804D8000);
//DbgPrint("KeServiceDescriptorTableShadow=%p\n", KeServiceDescriptorTableShadow);
OlbkernelAddress = GetKernelMoudleAddr();                                                                                                    //旧内核模块的地址
DbgPrint("内核模块地址为=%p\n", OlbkernelAddress);
 
RepairSSDT(OlbkernelAddress);
HookkiFastCallEntry();
Pobject->DriverUnload = DriverUnload;
return  STATUS_SUCCESS;

}

 

通过重载一份内核后,通过Hook KiFastCallEntry 中的那两行代码,可以实现Ring3调用SSDT中的函数都走我们hook的MyKiFastCallEntry函数,我们又在MyKiFastCallEntry函数中打印出来,结构却发现大部分的结构eax都是溢出的大于11C小于0x1000 都溢出了甚至很多时候打印出的SSDT函数表的Base值都是错误的,得到的函数地址也是错误的,但是我们不在MyKiFastCallEntry 中改变Ebx的值运行却不会出现问题,因为按照打印的结构来看应该必出现问题的,实在找不到原因,求有经验的大佬指点,按照KiFastCallEntry函数逆向的结构 执行SSDT中的函数 eax如果溢出了不会执行我们hook的地方


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//