现在的位置: 首页 > 综合 > 正文

从ntoskrnl文件中直接查找ssdt各个参数

2013年05月04日 ⁄ 综合 ⁄ 共 7696字 ⁄ 字号 评论关闭
 bool LoadNtosFile(PWCHAR szNtosFullPath, PVOID *FileBase, ULONG *FileSize)
{
    NTSTATUS st;

    /************************************************************************/
    /* 读取文件镜像                                                        */
    /************************************************************************/
    HANDLE hFile;
    IO_STATUS_BLOCK iosb;
    UNICODE_STRING    usNtosPath;
    RtlInitUnicodeString(&usNtosPath, szNtosFullPath);
    OBJECT_ATTRIBUTES oa;
    RtlZeroMemory(&oa, sizeof(OBJECT_ATTRIBUTES)) ;
    InitializeObjectAttributes(&oa,
        &usNtosPath,
        OBJ_CASE_INSENSITIVE,
        NULL,
        NULL);
    st = ZwOpenFile(&hFile,
        FILE_READ_DATA|FILE_EXECUTE|SYNCHRONIZE,
        &oa,
        &iosb,
        FILE_SHARE_READ,
        FILE_SYNCHRONOUS_IO_NONALERT);
    if(st != STATUS_SUCCESS)
    {
        DbgPrint("ReadNtosFile: ZwOpenFile() failed, NTSTATUS = %08X/n", st);
        return false;
    }

    //设置名称为NULL
    oa.ObjectName = 0;

    FILE_STANDARD_INFORMATION fsi;
    st = ZwQueryInformationFile(hFile,
        &iosb,
        &fsi,
        sizeof(FILE_STANDARD_INFORMATION),
        FileStandardInformation);
    if(st != STATUS_SUCCESS)
    {
        DbgPrint("ReadNtosFile: ZwQueryInformationFile() failed, NTSTATUS = %08X/n", st);
        return false;
    }

    ULONG ulFileSize = fsi.AllocationSize.LowPart;
    PVOID lpFileBase = ExAllocatePoolWithTag(NonPagedPool, ulFileSize, GGDRIVER_POOL_TAG);
    if(lpFileBase == NULL)
    {
        DbgPrint("ReadNtosFile: ExAllocatePool() failed!");
        return false;
    }

    st = ZwReadFile(hFile, NULL, NULL, NULL, &iosb, lpFileBase, ulFileSize, NULL, NULL);
    if(st != STATUS_SUCCESS)
    {
        DbgPrint("ReadNtosFile: ZwReadFile() failed, NTSTATUS = %08X/n", st);
        return false;
    }

    //关闭文件句柄
    ZwClose(hFile);

    DbgPrint("ReadNtosFile: read ntoskrnl file success base=0x%p, size=%d/n",
        lpFileBase, ulFileSize);

    *FileBase = lpFileBase;
    *FileSize = ulFileSize;

    return true;
}

/************************************************************************/
/*                                                                      */
/************************************************************************/
ULONG PeFileGetImageBase(PVOID lpFileBase)
{
    //MZ头
    IMAGE_DOS_HEADER *lpDosHeader = (IMAGE_DOS_HEADER *)lpFileBase;
    //PE头
    IMAGE_NT_HEADERS *lpNtHeader  = (IMAGE_NT_HEADERS *)((PUCHAR)lpDosHeader + lpDosHeader->e_lfanew);

    return lpNtHeader->OptionalHeader.ImageBase;
}

/************************************************************************/
/* 在文件中查找ssdt的相关指针和变量

ReadNtosFile: read ntoskrnl file success base=0x81CE8000, size=2015232

81e9416f a1b0cd4200      mov    eax,dword ptr ds:[0042CDB0h]        //NumberOfService
81e94174 6a10            push    10h
81e94176 59              pop    ecx

81e941cc c705e046480040c94200 mov dword ptr ds:[4846E0h],42C940h    //ServiceTableBase
81e941d6 8935e4464800    mov    dword ptr ds:[4846E4h],esi
81e941dc c705ec464800b4cd4200 mov dword ptr ds:[4846ECh],42CDB4h    //ParamTableBase
81e941e6 8bc1            mov    eax,ecx
81e941e8 89b0e8464800    mov    dword ptr [eax+4846E8h],esi
81e941ee 03c1            add    eax,ecx
81e941f0 83f840          cmp    eax,40h
81e941f3 72f3            jb      81e941e8
81e941f5 bee0464800      mov    esi,4846E0h    //KeServiceDescriptorTable
81e941fa bfa0464800      mov    edi,4846A0h    //KeServiceDescriptorTableShadow
81e941ff f3a5            rep movs dword ptr es:[edi],dword ptr [esi]
81e94201 5f              pop    edi
81e94202 5e              pop    esi
81e94203 c3              ret*/
/************************************************************************/
bool PeFileNtosGetSsdtParam(PVOID lpFileBase,
                            ULONG *ulNumberOfServiceVA,
                            ULONG *ulParamTableVA,
                            ULONG *ulServiceTableVA,
                            ULONG *ulKeServiceDescriptorTableShadowVA
                            )
{
    PVOID lpSSDTAddr = NULL;        //sdt地址
    char *szSSDTName = "KeServiceDescriptorTable";

    *ulNumberOfServiceVA = 0;
    *ulParamTableVA = 0;
    *ulServiceTableVA = 0;
    *ulKeServiceDescriptorTableShadowVA = 0;

    //MZ头
    IMAGE_DOS_HEADER *lpDosHeader = (IMAGE_DOS_HEADER *)lpFileBase;
    //PE头
    IMAGE_NT_HEADERS *lpNtHeader  = (IMAGE_NT_HEADERS *)((PUCHAR)lpDosHeader + lpDosHeader->e_lfanew);

    /************************************************************************/
    /* 先查找导出地址                                                      */
    /************************************************************************/
    // 第0个目录是输出表
    IMAGE_EXPORT_DIRECTORY *lpExport = (IMAGE_EXPORT_DIRECTORY *)PeRav2RawPtr(lpFileBase,
        lpNtHeader->OptionalHeader.DataDirectory[0].VirtualAddress);
    ULONG *lpAddressOfFunctions = (ULONG *)PeRav2RawPtr(lpFileBase, lpExport->AddressOfFunctions);
    ULONG *lpAddressOfNames = (ULONG *)PeRav2RawPtr(lpFileBase, lpExport->AddressOfNames);
    USHORT *lpAddressOfNameOrdinals = (USHORT *)PeRav2RawPtr(lpFileBase, lpExport->AddressOfNameOrdinals);
    for(ULONG i=0; i<lpExport->NumberOfNames; i++)
    {
        if(!_stricmp(szSSDTName, (char *)PeRav2RawPtr(lpFileBase, lpAddressOfNames[i])))
        {
            lpSSDTAddr = (PVOID)(lpNtHeader->OptionalHeader.ImageBase +
                lpAddressOfFunctions[lpAddressOfNameOrdinals[i]]);
            break;
        }
    }

    //未找到ssdt导出地址则返回
    if(lpSSDTAddr == NULL)
    {
        DbgPrint("PeFileNtosGetSsdtParam: %s not found!/n", szSSDTName);
        return false;
    }

    /************************************************************************/
    /* 在重定位中查找引用地址,并根据特征码判断是否符合要求                */
    /************************************************************************/
    // 第5个目录是重定位
    IMAGE_BASE_RELOCATION *lpBaseReloc = (IMAGE_BASE_RELOCATION *)PeRav2RawPtr(lpFileBase,
        lpNtHeader->OptionalHeader.DataDirectory[5].VirtualAddress);
    while(lpBaseReloc->VirtualAddress != 0 || lpBaseReloc->SizeOfBlock != 0)
    {
        //word组成的偏移量数组
        PUSHORT lpOffset = (PUSHORT)((PUCHAR)lpBaseReloc + sizeof(IMAGE_BASE_RELOCATION));
        //本page中要处理的总项数
        ULONG ulRelocSize = (lpBaseReloc->SizeOfBlock - 8)/sizeof(USHORT);

        for(ULONG i=0; i<ulRelocSize; i++)
        {
            //不处理末尾项和非 IMAGE_REL_BASED_HIGHLOW 类型的重定位项
            if(lpOffset[i] == 0 || (lpOffset[i] & 0xF000) != 0x3000)
                continue;

            //计算VA地址和引用地址
            ULONG ulRelocVA = lpBaseReloc->VirtualAddress + (USHORT)(lpOffset[i] & 0x0FFF);
            PVOID lpRelocRef = PeRav2RawPtr(lpFileBase, ulRelocVA);

            if(lpSSDTAddr != (PVOID)*(PULONG)lpRelocRef)
                continue;

            //8608e1dc c705ec464800b4cd4200 mov dword ptr ds:[4846ECh],42CDB4h
            if(*(PUSHORT)((PUCHAR)lpRelocRef - 2) != 0x05C7)
                continue;

            DbgPrint("PeFileNtosGetSsdtParam: SerivceTableBase reference addresss = %p/n", (PUCHAR)lpRelocRef - 2);

            //ulServiceTableVA
            ULONG ulServiceTableAddr = *(PULONG)((PUCHAR)lpRelocRef + 4);
            *ulServiceTableVA = ulServiceTableAddr - lpNtHeader->OptionalHeader.ImageBase;
            DbgPrint("PeFileNtosGetSsdtParam: ServiceTableVA = %08X/n", *ulServiceTableVA);

            //ulParamTableVA
            for(PUCHAR j=(PUCHAR)lpRelocRef; j-(PUCHAR)lpRelocRef < 0x20; j++)
            {
                if( *(PUSHORT)j == 0x05C7 && *(PULONG)(j+2) == *(PULONG)lpRelocRef + 0x0C )
                {
                    *ulParamTableVA = *(PULONG)(j+6) - lpNtHeader->OptionalHeader.ImageBase;
                    break;
                }
            }
            if(*ulParamTableVA == 0)
            {
                DbgPrint("PeFileNtosGetSsdtParam: ParamTableBase reference addresss not found!/n");
                return false;
            }

            DbgPrint("PeFileNtosGetSsdtParam: ParamTableVA = %08X/n", *ulParamTableVA);

            //ulNumberOfServiceVA
            *ulNumberOfServiceVA = *ulParamTableVA - 4;
            DbgPrint("PeFileNtosGetSsdtParam: NumberOfServiceVA = %08X/n", *ulNumberOfServiceVA);

            //ulKeServiceDescriptorTableShadowVA
            for(PUCHAR k=(PUCHAR)lpRelocRef; k-(PUCHAR)lpRelocRef < 0x80; k++)
            {
                if( *k == 0xBE && *(k+5) == 0xBF )
                {
                    *ulKeServiceDescriptorTableShadowVA = *(PULONG)(k+6) - lpNtHeader->OptionalHeader.ImageBase;
                    break;
                }
            }
            if(*ulKeServiceDescriptorTableShadowVA == 0)
            {
                DbgPrint("PeFileNtosGetSsdtParam: KeServiceDescriptorTableShadow reference addresss not found!/n");
                return false;
            }

            DbgPrint("PeFileNtosGetSsdtParam: ulKeServiceDescriptorTableShadowVA = %08X/n", *ulKeServiceDescriptorTableShadowVA);

            return true;
        }

        lpBaseReloc = (IMAGE_BASE_RELOCATION *)((PUCHAR)lpBaseReloc + lpBaseReloc->SizeOfBlock);
    }

    DbgPrint("PeFileNtosGetSsdtParam: SerivceTableBase reference addresss not found!/n");
    return false;
}

抱歉!评论已关闭.