[驱动开发] windows内核重载(xp3) 完整代码

1 了解PE结构

2 懂HOOK KiFastCallEntry

3 理解SSDT表 (需要修复SSDT表)


其实操作不算太复杂, 需要有一定的基础


完整测试的实例代码


001#include <ntddk.h>
002#include "ntimage.h"
003#define  __Max(a,b) a>b?a:b
004 
005#pragma pack(1)
006typedef struct ServiceDescriptorEntry {
007    unsigned int *ServiceTableBase;
008    unsigned int *ServiceCounterTableBase; //仅适用于checked build版本
009    unsigned int NumberOfServices;
010    unsigned char *ParamTableBase;
011} ServiceDescriptorTableEntry_t, *PServiceDescriptorTableEntry_t;
012#pragma pack()
013 
014__declspec(dllimport) ServiceDescriptorTableEntry_t KeServiceDescriptorTable;
015 
016typedef struct _LDR_DATA_TABLE_ENTRY{
017    LIST_ENTRY         InLoadOrderLinks;
018    LIST_ENTRY         InMemoryOrderLinks;
019    LIST_ENTRY         InInitializationOrderLinks;
020    PVOID              DllBase;
021    PVOID              EntryPoint;
022    ULONG              SizeOfImage;
023    UNICODE_STRING     FullDllName;
024    UNICODE_STRING     BaseDllName;
025    ULONG              Flags;
026    USHORT             LoadCount;
027    USHORT             TlsIndex;
028    union
029    {
030        LIST_ENTRY     HashLinks;
031        struct
032        {
033            PVOID      SectionPointer;
034            ULONG      CheckSum;
035        };
036    };
037    union
038    {
039        ULONG           TimeDateStamp;
040        PVOID           LoadedImports;
041    };
042    PVOID               EntryPointActivationContext;
043    PVOID               PatchInformation;
044} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;
045 
046 
047 
048typedef NTSTATUS
049(*NTCREATEFILE) (
050__out PHANDLE FileHandle,
051__in ACCESS_MASK DesiredAccess,
052__in POBJECT_ATTRIBUTES ObjectAttributes,
053__out PIO_STATUS_BLOCK IoStatusBlock,
054__in_opt PLARGE_INTEGER AllocationSize,
055__in ULONG FileAttributes,
056__in ULONG ShareAccess,
057__in ULONG CreateDisposition,
058__in ULONG CreateOptions,
059__in_bcount_opt(EaLength) PVOID EaBuffer,
060__in ULONG EaLength
061);
062 
063 
064//全局变量的定义
065PVOID   g_lpVirtualPointer = 0;
066ULONG   g_ntcreatefile;
067ULONG   g_fastcall_hookpointer;
068ULONG   g_goto_origfunc;
069ULONG   g_NewKernelInc;
070 
071ServiceDescriptorTableEntry_t   *g_pNewSeviceTable;
072 
073void PageProtectOn()
074{
075    __asm{//恢复内存保护 
076        mov  eax, cr0
077            or   eax, 10000h
078            mov  cr0, eax
079            sti
080    }
081}
082 
083void PageProtectOff()
084{
085    __asm{//去掉内存保护
086        cli
087            mov  eax, cr0
088            and  eax, not 10000h
089            mov  cr0, eax
090    }
091}
092 
093ULONG SearchHookPointer(ULONG StartAddress)
094{
095    ULONG   u_index;
096 
097    UCHAR   *p = (UCHAR*)StartAddress;
098 
099    for (u_index = 0; u_index < 200; u_index++)
100    {
101        if (*p == 0x2B &&
102            *(p + 1) == 0xE1 &&
103            *(p + 2) == 0xC1 &&
104            *(p + 3) == 0xE9 &&
105            *(p + 4) == 0x02)
106        {
107            return (ULONG)p;
108        }
109 
110        p--;
111    }
112 
113    return 0;
114}
115 
116 
117ULONG FilterKiFastCallEntry(ULONG ServiceTableBase, ULONG FuncIndex, ULONG OrigFuncAddress)
118{
119    if (ServiceTableBase == (ULONG)KeServiceDescriptorTable.ServiceTableBase)
120    {
121        if (strstr((char*)PsGetCurrentProcess() + 0x174, "Ollydbg") != 0)
122        {
123            //用新的NtCreateFile来处理
124            return g_pNewSeviceTable->ServiceTableBase[FuncIndex];
125 
126            //针对inlineHook
127            //return (OrigFuncAddress+g_NewKernelInc);
128        }
129    }
130 
131    return OrigFuncAddress;
132}
133 
134__declspec(naked)
135void NewKiFastCallEntry()
136{
137    __asm{
138        pushad
139            pushfd
140 
141            push    edx
142            push    eax
143            push    edi
144            call    FilterKiFastCallEntry
145 
146            mov [esp + 0x18], eax
147 
148            popfd
149            popad
150 
151            sub     esp, ecx
152            shr     ecx, 2
153            jmp     g_goto_origfunc
154    }
155}
156 
157void UnHookKiFastCallEntry()
158{
159    UCHAR   str_origfuncode[5] = { 0x2B, 0xE1, 0xC1, 0xE9, 0x02 };
160 
161    if (g_fastcall_hookpointer == 0)
162    {
163        return;
164    }
165 
166    PageProtectOff();
167    RtlCopyMemory((PVOID)g_fastcall_hookpointer, str_origfuncode, 5);
168    PageProtectOn();
169}
170 
171void HookKiFastCallEntry(ULONG HookPointer)
172{
173    ULONG   u_temp;
174    UCHAR   str_jmp_code[5];
175 
176    str_jmp_code[0] = 0xE9;
177 
178    u_temp = (ULONG)NewKiFastCallEntry - HookPointer - 5;
179    *(ULONG*)&str_jmp_code[1] = u_temp;
180 
181    PageProtectOff();
182 
183    RtlCopyMemory((PVOID)HookPointer, str_jmp_code, 5);
184 
185    PageProtectOn();
186 
187}
188 
189NTSTATUS NewNtCreateFile(
190    __out PHANDLE FileHandle,
191    __in ACCESS_MASK DesiredAccess,
192    __in POBJECT_ATTRIBUTES ObjectAttributes,
193    __out PIO_STATUS_BLOCK IoStatusBlock,
194    __in_opt PLARGE_INTEGER AllocationSize,
195    __in ULONG FileAttributes,
196    __in ULONG ShareAccess,
197    __in ULONG CreateDisposition,
198    __in ULONG CreateOptions,
199    __in_bcount_opt(EaLength) PVOID EaBuffer,
200    __in ULONG EaLength
201    )
202{
203    ULONG   u_call_retaddr;
204 
205    __asm{
206        pushad
207            mov     eax, [ebp + 0x4]
208            mov     u_call_retaddr, eax
209            popad
210    }
211 
212    g_fastcall_hookpointer = SearchHookPointer(u_call_retaddr);
213    if (g_fastcall_hookpointer == 0)
214    {
215        KdPrint(("search failed."));
216    }
217    else{
218        KdPrint(("search success."));
219    }
220 
221    g_goto_origfunc = g_fastcall_hookpointer + 5;
222    HookKiFastCallEntry(g_fastcall_hookpointer);
223 
224    PageProtectOff();
225    KeServiceDescriptorTable.ServiceTableBase[37] = (unsigned int)g_ntcreatefile;
226    PageProtectOn();
227 
228    return ((NTCREATEFILE)g_ntcreatefile)(
229        FileHandle, \
230        DesiredAccess, \
231        ObjectAttributes, \
232        IoStatusBlock, \
233        AllocationSize, \
234        FileAttributes, \
235        ShareAccess, \
236        CreateDisposition, \
237        CreateOptions, \
238        EaBuffer, \
239        EaLength);
240}
241 
242 
243void SearchKiFastCallEntry()
244{
245    HANDLE              hFile;
246    NTSTATUS            Status;
247    OBJECT_ATTRIBUTES   ObjAttr;
248    UNICODE_STRING      usFileName;
249    IO_STATUS_BLOCK     IoStatusBlock;
250 
251    RtlInitUnicodeString(&usFileName, L"\\??\\C:\\Windows\\System32\\ntkrnlpa.exe");
252    InitializeObjectAttributes(\
253        &ObjAttr, \
254        &usFileName, \
255        OBJ_CASE_INSENSITIVE, \
256        NULL, \
257        NULL);
258 
259    g_ntcreatefile = KeServiceDescriptorTable.ServiceTableBase[37];
260    PageProtectOff();
261    KeServiceDescriptorTable.ServiceTableBase[37] = (unsigned int)NewNtCreateFile;
262    PageProtectOn();
263 
264    Status = ZwCreateFile(\
265        &hFile, \
266        FILE_ALL_ACCESS, \
267        &ObjAttr, \
268        &IoStatusBlock, \
269        NULL, \
270        FILE_ATTRIBUTE_NORMAL, \
271        FILE_SHARE_READ, \
272        FILE_OPEN, \
273        FILE_NON_DIRECTORY_FILE, \
274        NULL, \
275        0);
276    if (NT_SUCCESS(Status))
277    {
278        ZwClose(hFile);
279    }
280}
281 
282 
283VOID SetNewSSDT(\
284    PVOID pNewImage, \
285    PVOID pOrigImage, \
286    ServiceDescriptorTableEntry_t **pNewSeviceTable)
287{
288    ULONG                           uIndex;
289    ULONG                           uNewKernelInc, uOffset;
290    ServiceDescriptorTableEntry_t   *pNewSSDT;
291 
292 
293    uNewKernelInc = (ULONG)pNewImage - (ULONG)pOrigImage;
294    pNewSSDT = (ServiceDescriptorTableEntry_t *)((ULONG)&KeServiceDescriptorTable + uNewKernelInc);
295 
296    if (!MmIsAddressValid(pNewSSDT))
297    {
298        KdPrint(("pNewSSDT"));
299        return;
300    }
301 
302    pNewSSDT->NumberOfServices = KeServiceDescriptorTable.NumberOfServices;
303 
304    uOffset = (ULONG)KeServiceDescriptorTable.ServiceTableBase - (ULONG)pOrigImage;
305    pNewSSDT->ServiceTableBase = (unsigned int*)((ULONG)pNewImage + uOffset);
306    if (!MmIsAddressValid(pNewSSDT->ServiceTableBase))
307    {
308        KdPrint(("pNewSSDT->ServiceTableBase:%X", pNewSSDT->ServiceTableBase));
309        return;
310    }
311 
312    for (uIndex = 0; uIndex < pNewSSDT->NumberOfServices; uIndex++)
313    {
314        pNewSSDT->ServiceTableBase[uIndex] += uNewKernelInc;
315    }
316 
317    uOffset = (ULONG)KeServiceDescriptorTable.ParamTableBase - (ULONG)pOrigImage;
318    pNewSSDT->ParamTableBase = (unsigned char*)((ULONG)pNewImage + uOffset);
319    if (!MmIsAddressValid(pNewSSDT->ParamTableBase))
320    {
321        KdPrint(("pNewSSDT->ParamTableBase"));
322        return;
323    }
324    RtlCopyMemory(pNewSSDT->ParamTableBase, KeServiceDescriptorTable.ParamTableBase, pNewSSDT->NumberOfServices*sizeof(char));
325 
326    *pNewSeviceTable = pNewSSDT;
327    KdPrint(("set new ssdt success."));
328}
329 
330 
331void RelocModule(PVOID pNewImage, PVOID pOrigImage)
332{
333    ULONG                   uIndex;
334    ULONG                   uRelocTableSize;
335    USHORT                  TypeValue;
336    USHORT                  *pwOffsetArrayAddress;
337    ULONG                   uTypeOffsetArraySize;
338    ULONG                   uRelocOffset;
339    ULONG                   uRelocAddress;
340 
341    PIMAGE_DOS_HEADER       pImageDosHeader;
342    PIMAGE_NT_HEADERS       pImageNtHeader;
343    IMAGE_DATA_DIRECTORY    ImageDataDirectory;
344    IMAGE_BASE_RELOCATION   *pImageBaseRelocation;
345 
346    pImageDosHeader = (PIMAGE_DOS_HEADER)pNewImage;
347    pImageNtHeader = (PIMAGE_NT_HEADERS)((ULONG)pNewImage + pImageDosHeader->e_lfanew);
348 
349    uRelocOffset = (ULONG)pOrigImage - pImageNtHeader->OptionalHeader.ImageBase;
350    //DbgPrint("pOrigImage -- %x,  uRelocOffset -- %x", pOrigImage, uRelocOffset);
351 
352    ImageDataDirectory = pImageNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
353 
354    pImageBaseRelocation = (PIMAGE_BASE_RELOCATION)(ImageDataDirectory.VirtualAddress + (ULONG)pNewImage);
355    uRelocTableSize = ImageDataDirectory.Size;
356 
357    while (uRelocTableSize)
358    {
359        uTypeOffsetArraySize = (pImageBaseRelocation->SizeOfBlock - sizeof(ULONG)* 2) / sizeof(USHORT);
360 
361        pwOffsetArrayAddress = pImageBaseRelocation->TypeOffset;
362        for (uIndex = 0; uIndex < uTypeOffsetArraySize; uIndex++)
363        {
364            TypeValue = pwOffsetArrayAddress[uIndex];
365            if (TypeValue >> 12 == IMAGE_REL_BASED_HIGHLOW)
366            {
367                uRelocAddress = (TypeValue & 0xfff) + pImageBaseRelocation->VirtualAddress + (ULONG)pNewImage;
368                if (!MmIsAddressValid((PVOID)uRelocAddress))
369                {
370                    continue;
371                }
372 
373                *(ULONG*)uRelocAddress += uRelocOffset;
374            }
375        }
376 
377        uRelocTableSize -= pImageBaseRelocation->SizeOfBlock;
378        pImageBaseRelocation = (IMAGE_BASE_RELOCATION *)(\
379            (ULONG)pImageBaseRelocation + pImageBaseRelocation->SizeOfBlock);
380    }
381}
382 
383 
384NTSTATUS ReadFileToMemory(wchar_t *strFileName, PVOID *lpVirtualAddress, PVOID pOrigImage)
385{
386    NTSTATUS Status;
387    LARGE_INTEGER FileOffset;
388    HANDLE hFile;
389    OBJECT_ATTRIBUTES ObjAttr;
390    IO_STATUS_BLOCK IoStatusBlock;
391    UNICODE_STRING usFileName;
392    IMAGE_DOS_HEADER ImageDosHeader;
393    IMAGE_NT_HEADERS ImageNtHeader;
394    IMAGE_SECTION_HEADER *pImageSectionHeader;
395 
396    PVOID lpVirtualPointer;
397    ULONG SecVirtualAddress, SizeOfSection;
398    ULONG PointerToRawData;
399 
400    ULONG uIndex = 0;
401 
402    if (!MmIsAddressValid(strFileName))
403    {
404        return STATUS_UNSUCCESSFUL;
405    }
406    RtlInitUnicodeString(&usFileName, strFileName);
407 
408    InitializeObjectAttributes(&ObjAttr, &usFileName, OBJ_CASE_INSENSITIVE, NULL, NULL);
409 
410    Status = ZwCreateFile(&hFile, FILE_ALL_ACCESS, &ObjAttr, &IoStatusBlock,
411        NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN, FILE_NON_DIRECTORY_FILE,
412        NULL, 0);
413 
414    if (!NT_SUCCESS(Status))
415    {
416        DbgPrint("ZwCreateFile Error --- %#X", Status);
417        return Status;
418    }
419    FileOffset.QuadPart = 0;
420    Status = ZwReadFile(hFile, NULL, NULL, NULL,
421        &IoStatusBlock, &ImageDosHeader, sizeof(IMAGE_DOS_HEADER), &FileOffset, NULL);
422 
423    if (!NT_SUCCESS(Status))
424    {
425        DbgPrint("ZwReadFile  ImageDosHeader  Error --- %#X", Status);
426        ZwClose(hFile);
427        return Status;
428    }
429 
430    FileOffset.QuadPart = ImageDosHeader.e_lfanew;
431 
432    Status = ZwReadFile(hFile, NULL, NULL, NULL, &IoStatusBlock,
433        &ImageNtHeader, sizeof(IMAGE_NT_HEADERS), &FileOffset, NULL);
434 
435    if (!NT_SUCCESS(Status))
436    {
437        DbgPrint("ZwReadFile  ImageNtHeader  Error --- %#X", Status);
438        ZwClose(hFile);
439        return Status;
440    }
441 
442    pImageSectionHeader = ExAllocatePool(NonPagedPool, sizeof(IMAGE_SECTION_HEADER)*ImageNtHeader.FileHeader.NumberOfSections);
443    if (pImageSectionHeader == NULL)
444    {
445        DbgPrint("ExAllocatePool  pImageSectionHeader Error --- ");
446        return STATUS_UNSUCCESSFUL;
447    }
448 
449    FileOffset.QuadPart = ImageDosHeader.e_lfanew + sizeof(IMAGE_NT_HEADERS);
450    Status = ZwReadFile(hFile, NULL, NULL, NULL, &IoStatusBlock, pImageSectionHeader,
451        sizeof(IMAGE_SECTION_HEADER)*ImageNtHeader.FileHeader.NumberOfSections, &FileOffset, NULL);
452     
453    if (!NT_SUCCESS(Status))
454    {
455        DbgPrint("ZwReadFile  ImageSectionHeader  Error --- %#X", Status);
456        ExFreePool(pImageSectionHeader);
457        ZwClose(hFile);
458        return Status;
459    }
460 
461    lpVirtualPointer = ExAllocatePool(NonPagedPool, ImageNtHeader.OptionalHeader.SizeOfImage);
462    if (lpVirtualPointer == NULL)
463    {
464        DbgPrint("ExAllocatePool    Error ");
465        ExFreePool(pImageSectionHeader);
466        ZwClose(hFile);
467        return STATUS_UNSUCCESSFUL;
468    }
469 
470    memset(lpVirtualPointer, 0, ImageNtHeader.OptionalHeader.SizeOfImage);
471    RtlCopyMemory(lpVirtualPointer, &ImageDosHeader, sizeof(IMAGE_DOS_HEADER));
472    RtlCopyMemory((PVOID)((ULONG)lpVirtualPointer+ImageDosHeader.e_lfanew),
473        &ImageNtHeader,
474        sizeof(IMAGE_NT_HEADERS));
475    RtlCopyMemory((PVOID)((ULONG)lpVirtualPointer + ImageDosHeader.e_lfanew + sizeof(IMAGE_NT_HEADERS)),
476        pImageSectionHeader, sizeof(IMAGE_SECTION_HEADER)*ImageNtHeader.FileHeader.NumberOfSections);
477 
478    for (uIndex = 0; uIndex < ImageNtHeader.FileHeader.NumberOfSections; uIndex++)
479    {
480        SecVirtualAddress = pImageSectionHeader[uIndex].VirtualAddress;
481        SizeOfSection = __Max(pImageSectionHeader[uIndex].SizeOfRawData,
482            pImageSectionHeader[uIndex].Misc.VirtualSize);
483 
484        PointerToRawData = pImageSectionHeader[uIndex].PointerToRawData;
485        FileOffset.QuadPart = PointerToRawData;
486 
487        Status = ZwReadFile(hFile, NULL, NULL, NULL, &IoStatusBlock, (PVOID)((ULONG)lpVirtualPointer + SecVirtualAddress),
488            SizeOfSection, &FileOffset, NULL);                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
489 
490        if (!NT_SUCCESS(Status))
491        {
492            DbgPrint("ZwReadFile  ImageSectionHeader  Error --- %#X", Status);
493            ExFreePool(pImageSectionHeader);
494            ExFreePool(lpVirtualPointer);
495            ZwClose(hFile);
496            return Status;
497        }
498 
499    }
500 
501    //基址重定位
502    RelocModule(lpVirtualPointer, pOrigImage);
503    SetNewSSDT(lpVirtualPointer, pOrigImage, &g_pNewSeviceTable);
504    //DbgPrint("RelocModule ok!");
505 
506    //释放内存
507    ExFreePool(pImageSectionHeader);
508    *lpVirtualAddress = lpVirtualPointer;
509    DbgPrint("文件内存复制成功");
510 
511    ZwClose(hFile);
512     
513    return STATUS_SUCCESS;
514}
515 
516 
517 
518PLDR_DATA_TABLE_ENTRY SearchDriver(PDRIVER_OBJECT pDriverObject, wchar_t *strDriverName)
519{
520     
521    ULONG Base = 0;//模块基地址
522    LDR_DATA_TABLE_ENTRY* SectionBase = 0;
523    LIST_ENTRY* Entry = 0;
524    LIST_ENTRY InLoadOrderLinks = { 0 };
525    UNICODE_STRING          usModuleName;
526 
527    RtlInitUnicodeString(&usModuleName, strDriverName);
528    Entry = ((LIST_ENTRY*)pDriverObject->DriverSection)->Flink;
529 
530 
531    do{
532        SectionBase = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);//得到这个Entry所属的Section的地址,此方法经过验证可行
533        if (SectionBase->EntryPoint &&
534            SectionBase->BaseDllName.Buffer &&
535            SectionBase->FullDllName.Buffer &&
536            SectionBase->LoadCount
537            )
538        {
539            //KdPrint(("%wZ", &SectionBase->BaseDllName));
540            //DbgPrint("模块名称:%wZ,地址:%x\n",  &(SectionBase->FullDllName), SectionBase->DllBase);
541            if (0 == RtlCompareUnicodeString(&SectionBase->BaseDllName, &usModuleName, FALSE))
542            {
543                KdPrint(("----%wZ-----", &SectionBase->BaseDllName));
544                return SectionBase;
545            }
546            //DbgPrint("方法一遍历模块名称:%wZ,地址:%x\n",  &(SectionBase->FullDllName), SectionBase->DllBase);
547        }
548        Entry = Entry->Flink;
549    } while (Entry != ((LIST_ENTRY*)pDriverObject->DriverSection)->Flink);//直到遍历回来
550 
551    return 0;
552}  
553 
554 
555 
556VOID DriverUnload(IN PDRIVER_OBJECT pDriverObject)
557{
558    DbgPrint("DriverUnload");
559 
560    if (g_lpVirtualPointer)
561    {
562        ExFreePool(g_lpVirtualPointer);
563        UnHookKiFastCallEntry();
564    }
565}
566 
567 
568 
569NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING RegistryPath)
570{
571    //C:\WINDOWS\system32\ntkrnlpa.exe
572    //ReadFileToMemory(L"\\??\\C:\\WINDOWS\\system32\\ntkrnlpa.exe", &g_lpVitutalPointer, (PVOID)0x804D8000);
573    //Method1(pDriverObject);
574    PLDR_DATA_TABLE_ENTRY pLdrDataTableEntry;
575    pLdrDataTableEntry = SearchDriver(pDriverObject, L"ntoskrnl.exe");
576    //g_lpVitutalPointer
577    if (pLdrDataTableEntry)
578    {
579        ReadFileToMemory(L"\\??\\C:\\Windows\\System32\\ntkrnlpa.exe", &g_lpVirtualPointer, pLdrDataTableEntry->DllBase);
580        KdPrint(("g_lpVirtualPointer:%X", g_lpVirtualPointer));
581        g_NewKernelInc = (ULONG)g_lpVirtualPointer - (ULONG)pLdrDataTableEntry->DllBase;
582        SearchKiFastCallEntry();
583    }
584 
585 
586    pDriverObject->DriverUnload = DriverUnload;
587    DbgPrint("DriverEntry");
588     
589    return STATUS_SUCCESS;
590}

原文链接: [驱动开发] windows内核重载(xp3) 完整代码 版权所有,转载时请注明出处,违者必究。
注明出处格式:流沙团 ( http://www.gyarmy.com/?post=498 )

发表评论

0则评论给“[驱动开发] windows内核重载(xp3) 完整代码”