阅读:5968回复:14
[原创](AVP)卡巴驱动程序载入分析随记
(AVP)卡巴驱动程序载入分析随记 by Sucsor/RCT
忘记是什么原因了,去年曾经跟踪过AVP的驱动程序,发现kl1.sys的驱动程序中多出了几个设备对象, 但是代码中又没有找到创建设备对象相应的代码.后来发现在是在别的驱动里创建的,但是在KD时, 又没有发现其模块,很纳闷,后来发现Kl1.sys中果然是将几个*.sys载入了几个驱动,并执行了这些驱动的代码. 最近突发奇想,想要做个驱动的壳,而AVP有那么点儿意思,让一个驱动程序做Loader,然后在这个Loader里 处理其他代码,我想应该可以按这个思路做个小壳......... 声明,只是爱好和学习,没有其他目的.本文初发布于http://www.debugman.com,后来看到XIkug的文件来到这里, 所以也来热闹一下,希望本文能起抛砖引玉的作用. 致谢:fly,xikug,winroot,throb,lemon... 以下流程都是在kl1.sys 中执行的,其文件版本是:6.0.15.229,文章写的比较仓促,再加上实在不太会写文章,失误之处请指正 1,HOOK SSDT NtOpenFile,将自己的NtOpenFile替换系统的,在做完自己的处理后再传递给系统 .text:000112E9 83 C4 0C add esp, 0Ch ; 下面是HookZwOpenFile .text:000112EC 0F 20 C3 mov ebx, cr0 .text:000112EF 53 push ebx .text:000112F0 81 E3 FF FF FE FF and ebx, 0FFFEFFFFh ;取消页保护 16bit of Cr0 .text:000112F6 0F 22 C3 mov cr0, ebx .text:000112F9 B8 34 1A 01 00 mov eax, offset ZwOpenFile(x,x,x,x,x,x) .text:000112FE 33 C9 xor ecx, ecx .text:00011300 8B 40 02 mov eax, [eax+2] .text:00011303 8B 00 mov eax, [eax] .text:00011305 80 38 B8 cmp byte ptr [eax], 0B8h ;目前2000-2003的首字节都是B8 .text:00011308 75 04 jnz short loc_1130E .text:00011308 ;得到服务号 .text:0001130A 0F B6 48 01 movzx ecx, byte ptr [eax+1] .text:0001130A .text:0001130E .text:0001130E loc_1130E: ; CODE XREF: DriverEntry(x,x)+FBj .text:0001130E A1 C8 02 01 00 mov eax, ds:__imp__KeServiceDescriptorTable .text:00011313 C1 E1 02 shl ecx, 2 .text:00011316 8B 10 mov edx, [eax] .text:00011318 8B 14 0A mov edx, [edx+ecx] ;计算SSDT项 .text:0001131B 89 15 0C 1C 01 00 mov long (*r_ZwOpenFile)(void * *,ulong,_OBJECT_ATTRIBUTES *,_IO_STATUS_BLOCK *,ulong,ulong), edx .text:00011321 8B 00 mov eax, [eax];修改SSDT项 .text:00011323 C7 04 08 28 10 01+ mov dword ptr [eax+ecx], offset hZwOpenFile(void * *,ulong,_OBJECT_ATTRIBUTES *,_IO_STATUS_BLOCK *,ulong,ulong) .text:0001132A 5B pop ebx .text:0001132B 0F 22 C3 mov cr0, ebx ;还原Cr0 .text:0001132E 33 C0 xor eax, eax 2,AVP的NtOpenFile被调用时,都会判断IsHook变量是否为TRUE和文件路径是否是包含"\\SystemRoot\\System32\\DRIVERS\\", 根据我的理解,这个判断是为了确认OS是否已经支持访问这个路径了。 3,如果包括有"\\SystemRoot\\System32\\DRIVERS\\"路径并IsHook为FALSE,则执行载入自己驱动的操作,在执行成功后设置 IsHook为TRUE. 4,AVP的载入驱动的函数是从MyLoad开始的,MyLoad做了两件事,1是从 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\kl1\Parameters中取出各个需要启动的驱动的路径, 以备后面打开文件;2,调用Load函数处理文件的载入操作 5,Load函数首先初始了Module对像(参见附录的对象关系),构造函数的第一个参数是要载入驱动的名字,在这个构造 函数返回的对象中包含了载入的驱动的入口地址(具体见对象关系);然后,Load调用Module::Begin开始执行被载入 驱动的代码. 6,Module::Module函数的工作流程: 6.1 从文件名的全路径中得到*.sys名字,与"\\SystemRoot\\System32\\DRIVERS\\%s"接合, 6,2 打开文件,查询文件大小,分配内存,将整个文件读到内存,调用函数分别是: ZwCreateFile,ZwQueryInformationFile,ExAllocatePoolWithTag和ZwReadFile 6.3 初始了Module2对象,该对象偏移8处保存了被读入文件的缓冲区地址, 并将对象保存到Module对象成员中,调用Module::Init函数(),该函数分配了一个结构, 该结构中最重的是一个成员保存了被载入驱动的入口函数地址. 6.4 调用Module2::Mark2,该函数对驱动文件进行了Mapping,处理了重定位表,处理了IAT ,然后将驱动的入口函数地址保存到结构里 以下是从Module2::Mark2截取的代码: 这段代码新开缓冲区,准备进行Mapping .text:00011683 55 push ebp .text:00011684 8B EC mov ebp, esp .text:00011686 83 EC 20 sub esp, 20h .text:00011689 8B 45 08 mov eax, [ebp+Offset2c] .text:0001168C 53 push ebx .text:0001168D 8B D9 mov ebx, ecx ==>Ecx是Module2对象,+8处保存了文件缓冲区地址 .text:0001168F 56 push esi .text:00011690 83 20 00 and dword ptr [eax], 0 .text:00011693 57 push edi .text:00011694 8B 43 08 mov eax, [ebx+8] ;取文件缓冲区地址 .text:00011697 68 47 65 4E 2D push '-NeG' ; Tag .text:0001169C 89 45 F4 mov [ebp+OffsetOfBaseAddress], eax .text:0001169F 8B 48 3C mov ecx, [eax+3Ch] ; IMAGE_NT_HEADERS的偏移 .text:000116A2 FF 74 08 50 push dword ptr [eax+ecx+50h] ; NumberOfBytes ==>SizeOfImage .text:000116A6 8D 34 08 lea esi, [eax+ecx] .text:000116A9 89 75 FC mov [ebp+pImageNtHeader], esi .text:000116AC 6A 00 push 0 ; PoolType .text:000116AE FF 15 04 03 01 00 call ds:ExAllocatePoolWithTag(x,x,x) ; 又分配是一个缓冲区用于以Image的方式Mapping文件 .text:000116B4 89 43 0C mov [ebx+0Ch], eax ;将缓冲区保存的0xc 处 .text:000116B7 8B 4E 54 mov ecx, [esi+_IMAGE_NT_HEADERS.OptionalHeader.SizeOfHeaders] ; SizeOfHeaders .text:000116BA 8B 73 08 mov esi, [ebx+8] .text:000116BD 8B F8 mov edi, eax .text:000116BF 8B C1 mov eax, ecx .text:000116C1 C1 E9 02 shr ecx, 2 .text:000116C4 F3 A5 rep movsd ; 将Headers传到新分析的缓冲区里 .text:000116C6 8B C8 mov ecx, eax .text:000116C8 8B 45 F4 mov eax, [ebp+OffsetOfBaseAddress] .text:000116CB 83 E1 03 and ecx, 3 .text:000116CE F3 A4 rep movsb ; 将边界剩下的传送 .text:000116D0 33 C9 xor ecx, ecx 以下代码处理Section的影射,特别之处主要是对于SectionAlignment的处理(注:这里变量多个含义,名字起的不一定准确) 这段将每个段进行了影射,除了Reloc段 .text:000116D0 33 C9 xor ecx, ecx .text:000116D2 66 81 38 4D 5A cmp word ptr [eax], 'ZM' .text:000116D7 89 4D F0 mov [ebp+NextSectionOffset], ecx .text:000116DA 0F 85 97 00 00 00 jnz loc_11777 .text:000116DA .text:000116E0 39 48 3C cmp [eax+IMAGE_DOS_HEADER.e_lfanew], ecx .text:000116E3 0F 84 8E 00 00 00 jz loc_11777 .text:000116E3 .text:000116E9 8B 55 FC mov edx, [ebp+pImageNtHeader] .text:000116EC 89 4D F4 mov [ebp+OffsetOfBaseAddress], ecx .text:000116EF 66 39 4A 06 cmp [edx+_IMAGE_NT_HEADERS.FileHeader.NumberOfSections], cx .text:000116F3 0F 86 81 00 00 00 jbe loc_1177A ; Image Buffer .text:000116F3 .text:000116F9 8D B2 08 01 00 00 lea esi, [edx+108h] .text:000116FF 89 75 F8 mov [ebp+pSizeOfRawData], esi .text:000116FF .text:00011702 .text:00011702 loc_11702: ; CODE XREF: Module2::Mark2(void * *)+F2j .text:00011702 F6 46 14 60 test byte ptr [esi+14h], 60h ; Characteristics ==> READ | Execute .text:00011706 74 2D jz short loc_11735 .text:00011706 .text:00011708 8B 46 F8 mov eax, [esi-8] ; VirtualSize .text:0001170B 8B 0E mov ecx, [esi] ; SizeOfRawData .text:0001170D 3B C1 cmp eax, ecx .text:0001170F 77 02 ja short loc_11713 .text:0001170F .text:00011711 8B C8 mov ecx, eax ; 取大 .text:00011711 .text:00011713 .text:00011713 loc_11713: ; CODE XREF: Module2::Mark2(void * *)+8Cj .text:00011713 8B 45 F8 mov eax, [ebp+pSizeOfRawData] .text:00011716 8B 76 04 mov esi, [esi+4] ; PointerToRawData .text:00011719 03 73 08 add esi, [ebx+8] ; 指向原代码的Raw位置 .text:0001171C 8B 78 FC mov edi, [eax-4] ; VirtualAddress .text:0001171F 8B C1 mov eax, ecx .text:00011721 03 7B 0C add edi, [ebx+0Ch] ; 求目标[虚拟]地址 .text:00011724 C1 E9 02 shr ecx, 2 .text:00011727 F3 A5 rep movsd ; Copy Code .text:00011729 8B C8 mov ecx, eax ; .text:0001172B 83 E1 03 and ecx, 3 .text:0001172E F3 A4 rep movsb .text:00011730 8B 75 F8 mov esi, [ebp+pSizeOfRawData] .text:00011733 EB 19 jmp short loc_1174E ; 处理SectionAlignment .text:00011733 .text:00011735 ; --------------------------------------------------------------------------- .text:00011735 .text:00011735 loc_11735: ; CODE XREF: Module2::Mark2(void * *)+83j .text:00011735 8B 4E F8 mov ecx, [esi-8] .text:00011738 8B 7E FC mov edi, [esi-4] ; VirtualAddress .text:0001173B 03 7B 08 add edi, [ebx+8] ; 计算目标的虚拟地址 .text:0001173E 8B D1 mov edx, ecx .text:00011740 33 C0 xor eax, eax .text:00011742 C1 E9 02 shr ecx, 2 .text:00011745 F3 AB rep stosd .text:00011747 8B CA mov ecx, edx .text:00011749 83 E1 03 and ecx, 3 .text:0001174C F3 AA rep stosb .text:0001174C .text:0001174E .text:0001174E loc_1174E: ; CODE XREF: Module2::Mark2(void * *)+B0j .text:0001174E 8B 7D FC mov edi, [ebp+pImageNtHeader] ; 处理SectionAlignment .text:00011751 8B 46 F8 mov eax, [esi-8] .text:00011754 33 D2 xor edx, edx .text:00011756 83 C6 28 add esi, 28h ; esi==> SizeOfRawData .text:00011759 8B 4F 38 mov ecx, [edi+38h] ; SectionAlignment .text:0001175C 89 75 F8 mov [ebp+pSizeOfRawData], esi .text:0001175F 8D 44 08 FF lea eax, [eax+ecx-1] ; 对齐到SectionAlignemnt .text:00011763 F7 F1 div ecx .text:00011765 0F AF C1 imul eax, ecx .text:00011768 01 45 F0 add [ebp+NextSectionOffset], eax .text:0001176B FF 45 F4 inc [ebp+OffsetOfBaseAddress] .text:0001176E 0F B7 47 06 movzx eax, word ptr [edi+6] ; NumerOfSections .text:00011772 39 45 F4 cmp [ebp+OffsetOfBaseAddress], eax ; .text:00011775 72 8B jb short loc_11702 ; Characteristics ==> READ | Execute 以下代码处理重定位表,貌似跟流出来的Win2k的代码中处理重定位表的代码相似 .text:00011777 8B 55 FC mov edx, [ebp+pImageNtHeader] ; int .text:00011777 .text:0001177A .text:0001177A loc_1177A: ; CODE XREF: Module2::Mark2(void * *)+70j .text:0001177A 8B 4B 0C mov ecx, [ebx+0Ch] ; Image Buffer .text:0001177D 8B 82 A0 00 00 00 mov eax, [edx+0A0h] ; ==>IMAGE_DIRECTORY_ENTRY_BASERELOC 重定位表的VirtualAddress .text:00011783 8B B2 A4 00 00 00 mov esi, [edx+0A4h] ; 重定位表的大小 .text:00011789 8B F9 mov edi, ecx .text:0001178B 2B 7A 34 sub edi, [edx+_IMAGE_NT_HEADERS.OptionalHeader.ImageBase] ; ImageBase .text:0001178E 03 C1 add eax, ecx .text:00011790 85 F6 test esi, esi .text:00011792 89 75 F4 mov [ebp+OffsetOfBaseAddress], esi .text:00011795 74 52 jz short loc_117E9 ; .text:00011795 .text:00011797 .text:00011797 b_processReloc: ; CODE XREF: Module2::Mark2(void * *)+164j .text:00011797 8B 48 04 mov ecx, [eax+IMAGE_BASE_RELOCATION.SizeOfBlock] .text:0001179A 8D 70 08 lea esi, [eax+8] .text:0001179D 29 4D F4 sub [ebp+OffsetOfBaseAddress], ecx .text:000117A0 8B 00 mov eax, [eax] .text:000117A2 03 43 0C add eax, [ebx+0Ch] .text:000117A5 83 C1 F8 add ecx, -8 .text:000117A8 D1 E9 shr ecx, 1 .text:000117AA 89 75 F8 mov [ebp+pSizeOfRawData], esi .text:000117AD 8B F1 mov esi, ecx .text:000117AF 49 dec ecx .text:000117B0 85 F6 test esi, esi .text:000117B2 74 2C jz short loc_117E0 .text:000117B2 .text:000117B4 41 inc ecx .text:000117B5 89 4D F0 mov [ebp+NextSectionOffset], ecx .text:000117B5 .text:000117B8 .text:000117B8 loc_117B8: ; CODE XREF: Module2::Mark2(void * *)+15Bj .text:000117B8 8B 4D F8 mov ecx, [ebp+pSizeOfRawData] .text:000117BB 0F B7 09 movzx ecx, word ptr [ecx] .text:000117BE 8B F1 mov esi, ecx ; 处理重定位表 见附录 .text:000117C0 66 81 E1 00 F0 and cx, 0F000h ; .text:000117C5 81 E6 FF 0F 00 00 and esi, 0FFFh .text:000117CB 03 F0 add esi, eax .text:000117CD 81 F9 00 30 00 00 cmp ecx, 3000h .text:000117D3 75 02 jnz short loc_117D7 .text:000117D3 .text:000117D5 01 3E add [esi], edi .text:000117D5 .text:000117D7 .text:000117D7 loc_117D7: ; CODE XREF: Module2::Mark2(void * *)+150j .text:000117D7 83 45 F8 02 add [ebp+pSizeOfRawData], 2 .text:000117DB FF 4D F0 dec [ebp+NextSectionOffset] .text:000117DE 75 D8 jnz short loc_117B8 .text:000117DE .text:000117E0 .text:000117E0 loc_117E0: ; CODE XREF: Module2::Mark2(void * *)+12Fj .text:000117E0 83 7D F4 00 cmp [ebp+OffsetOfBaseAddress], 0 .text:000117E4 8B 45 F8 mov eax, [ebp+pSizeOfRawData] .text:000117E7 75 AE jnz short b_processReloc 以下是处理导入表的代码,相信这个大家都比较了解了 .text:000117E9 8B 82 80 00 00 00 mov eax, [edx+80h] ; 导入表的VirtualAddress .text:000117EF 85 C0 test eax, eax .text:000117F1 0F 84 B1 00 00 00 jz loc_118A8 .text:000117F1 .text:000117F7 8B 7B 0C mov edi, [ebx+0Ch] .text:000117FA 03 F8 add edi, eax ; edi指向 IMAGE_IMPORT_DESCRIPTOR .text:000117FA .text:000117FC .text:000117FC loc_117FC: ; CODE XREF: Module2::Mark2(void * *)+220j .text:000117FC 8B 4F 0C mov ecx, [edi+IMAGE_IMPORT_DESCRIPTOR.Name] .text:000117FF 85 C9 test ecx, ecx .text:00011801 0F 84 A1 00 00 00 jz loc_118A8 .text:00011801 .text:00011807 8B 43 0C mov eax, [ebx+0Ch] .text:0001180A 03 C8 add ecx, eax .text:0001180C 89 4D F4 mov [ebp+OffsetOfBaseAddress], ecx .text:0001180F 8B 4F 10 mov ecx, [edi+IMAGE_IMPORT_DESCRIPTOR.FirstThunk] .text:00011812 8D 34 01 lea esi, [ecx+eax] .text:00011815 8B 0F mov ecx, [edi] .text:00011817 85 C9 test ecx, ecx .text:00011819 74 07 jz short loc_11822 .text:00011819 .text:0001181B 03 C8 add ecx, eax .text:0001181D 89 4D F8 mov [ebp+pSizeOfRawData], ecx .text:00011820 EB 03 jmp short loc_11825 计算驱动入口地址 .text:000118A8 8B 42 28 mov eax, [edx+_IMAGE_NT_HEADERS.OptionalHeader.AddressOfEntryPoint] .text:000118AB 8B 4D 08 mov ecx, [ebp+Offset2c] .text:000118AE 03 43 0C add eax, [ebx+0Ch] .text:000118B1 5F pop edi .text:000118B2 5E pop esi .text:000118B3 5B pop ebx .text:000118B4 89 01 mov [ecx], eax 7,在得到Entry后,Module::Module就结束了,返回到Load函数,Load函数调用Module::Begin执行被载入的驱动代码 .text:000109D4 8B F1 mov esi, ecx ==>指向Module对象, .text:000109D6 8B 46 10 mov eax, [esi+10h] .text:000109D9 85 C0 test eax, eax .text:000109DB 74 5E jz short loc_10A3B .text:000109DB .text:000109DD 8B 0D 00 1C 01 00 mov ecx, _NT_CONTEXT * myctx ;见附录结构 .text:000109E3 53 push ebx .text:000109E4 83 C1 04 add ecx, 4 .text:000109E7 51 push ecx .text:000109E8 50 push eax .text:000109E9 FF 50 2C call dword ptr [eax+2Ch] ; 调用入口 [ecx+10h]=xxBuffer 其偏移 0x2c处是驱动的入口地址 附录: Module::Module [ecx]=vptable [ecx+8]=FileBuffer Same As 0x1c [ecx+10h]=xxBuffer 其偏移 0x2c处是驱动的入口地址 [ecx+0x14]=="un" [ecx+18h]==FileName [ecx+1Ch]==FileBuffer [ecx+0x20]=Module2 Module2:Module2 ecx+8==FileBuffer ecx+c==用户Mapping驱动文件的Buffer _NT_CONTEXT [myctx+0]=DriverObject [myctx+4]=RegistryPath \ [myctx+8]=RegistryPath->Buffer / // // Based relocation format. // typedef struct _IMAGE_BASE_RELOCATION { DWORD VirtualAddress; DWORD SizeOfBlock; // WORD TypeOffset[1]; 解释见下面注释 } IMAGE_BASE_RELOCATION; typedef IMAGE_BASE_RELOCATION UNALIGNED * PIMAGE_BASE_RELOCATION; 4 bits Type Stored in the high 4 bits of the WORD, a value that indicates the type of base relocation to be applied. For more information, see section 6.6.2, “Base Relocation Types.” 12 bits Offset Stored in the remaining 12 bits of the WORD, an offset from the starting address that was specified in the Page RVA field for the block. This offset specifies where the base relocation is to be applied. 下面是从Win2k源码里找到的,处理重定位表的 PIMAGE_BASE_RELOCATION NTAPI LdrProcessRelocationBlock(IN ULONG_PTR Address, IN ULONG Count, IN PUSHORT TypeOffset, IN LONG_PTR Delta) { SHORT Offset; USHORT Type; USHORT i; PUSHORT ShortPtr; PULONG LongPtr; for (i = 0; i < Count; i++) { Offset = *TypeOffset & 0xFFF; Type = *TypeOffset >> 12; switch (Type) { case IMAGE_REL_BASED_ABSOLUTE: break; case IMAGE_REL_BASED_HIGH: ShortPtr = (PUSHORT)((ULONG_PTR)Address + Offset); *ShortPtr += HIWORD(Delta); break; case IMAGE_REL_BASED_LOW: ShortPtr = (PUSHORT)((ULONG_PTR)Address + Offset); *ShortPtr += LOWORD(Delta); break; case IMAGE_REL_BASED_HIGHLOW: LongPtr = (PULONG)((ULONG_PTR)Address + Offset); *LongPtr += Delta; break; case IMAGE_REL_BASED_HIGHADJ: case IMAGE_REL_BASED_MIPS_JMPADDR: default: DPRINT1("Unknown/unsupported fixup type %hu.\n", Type); return NULL; } TypeOffset++; } return (PIMAGE_BASE_RELOCATION)TypeOffset; } /********************************************************************** * NAME LOCAL * LdrPerformRelocations * * DESCRIPTION * Relocate a DLL's memory image. * * ARGUMENTS * * RETURN VALUE * * REVISIONS * * NOTE * */ static NTSTATUS LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders, PVOID ImageBase) { PIMAGE_DATA_DIRECTORY RelocationDDir; PIMAGE_BASE_RELOCATION RelocationDir, RelocationEnd; ULONG Count, ProtectSize, OldProtect, OldProtect2; PVOID Page, ProtectPage, ProtectPage2; PUSHORT TypeOffset; ULONG_PTR Delta; NTSTATUS Status; if (NTHeaders->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED) { return STATUS_UNSUCCESSFUL; } RelocationDDir = &NTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]; if (RelocationDDir->VirtualAddress == 0 || RelocationDDir->Size == 0) { return STATUS_SUCCESS; } ProtectSize = PAGE_SIZE; Delta = (ULONG_PTR)ImageBase - NTHeaders->OptionalHeader.ImageBase; RelocationDir = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)ImageBase + RelocationDDir->VirtualAddress); RelocationEnd = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)ImageBase + RelocationDDir->VirtualAddress + RelocationDDir->Size); while (RelocationDir < RelocationEnd && RelocationDir->SizeOfBlock > 0) { Count = (RelocationDir->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(USHORT); Page = (PVOID)((ULONG_PTR)ImageBase + (ULONG_PTR)RelocationDir->VirtualAddress); TypeOffset = (PUSHORT)(RelocationDir + 1); /* Unprotect the page(s) we're about to relocate. */ ProtectPage = Page; Status = NtProtectVirtualMemory(NtCurrentProcess(), &ProtectPage, &ProtectSize, PAGE_READWRITE, &OldProtect); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to unprotect relocation target.\n"); return Status; } if (RelocationDir->VirtualAddress + PAGE_SIZE < NTHeaders->OptionalHeader.SizeOfImage) { ProtectPage2 = (PVOID)((ULONG_PTR)ProtectPage + PAGE_SIZE); Status = NtProtectVirtualMemory(NtCurrentProcess(), &ProtectPage2, &ProtectSize, PAGE_READWRITE, &OldProtect2); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to unprotect relocation target (2).\n"); NtProtectVirtualMemory(NtCurrentProcess(), &ProtectPage, &ProtectSize, OldProtect, &OldProtect); return Status; } } else { ProtectPage2 = NULL; } RelocationDir = LdrProcessRelocationBlock((ULONG_PTR)Page, Count, TypeOffset, Delta); if (RelocationDir == NULL) return STATUS_UNSUCCESSFUL; /* Restore old page protection. */ NtProtectVirtualMemory(NtCurrentProcess(), &ProtectPage, &ProtectSize, OldProtect, &OldProtect); if (ProtectPage2 != NULL) { NtProtectVirtualMemory(NtCurrentProcess(), &ProtectPage2, &ProtectSize, OldProtect2, &OldProtect2); } } return STATUS_SUCCESS; } |
|
最新喜欢:zhczf |
沙发#
发布于:2007-02-02 10:11
原来卡吧是这样加载驱动的。。。学习了。。。
|
|
|
板凳#
发布于:2007-02-02 10:14
我被托了,赫赫
|
|
地板#
发布于:2007-02-03 10:58
呵呵。支持呀~
|
|
地下室#
发布于:2007-02-03 13:03
呵呵,支持...
感谢fly ,xikug,winroot,doskey |
|
5楼#
发布于:2007-02-13 15:34
感谢CCTV.???V
|
|
|
6楼#
发布于:2007-03-27 19:28
good
|
|
|
7楼#
发布于:2007-03-28 20:28
Thanks.
|
|
8楼#
发布于:2007-04-12 22:29
Very GOod!!
|
|
9楼#
发布于:2007-12-30 10:57
|
|
10楼#
发布于:2008-01-03 11:10
我估计很多人已经对卡巴了解很深了
|
|
11楼#
发布于:2008-03-08 12:38
回头写篇破文,小弟系菜鸟,大家多多帮助啊
|
|
12楼#
发布于:2008-08-26 19:49
thanks
|
|
13楼#
发布于:2008-12-19 12:03
|
|
14楼#
发布于:2009-05-05 16:33
回 楼主
谢谢啦,我遇到问题。 卡巴和自己过滤驱动蓝屏,原来卡巴这样加载,但是有没有好方式处理他所造成蓝屏呢? |
|