《Undocumented Windows 2000 Secrets》翻译 --- 第一章(补充:PDB格式)(2)

第一章  Windows 2000对调试技术的支持

翻译:Kendiv ( fcczj@263.net )

更新:Tuesday, May 03, 2005

 

 

声明:转载请注明出处,并保证文章的完整性,本人保留译文的所有权利。

 

 

.dbg文件的内部结构

Windows NT 4.0组件的符号化信息均保存在扩展名为.dbg的文件中。如果假设符号文件所在的根目录为:d:/winnt/symbols,则组件filename.ext的符号文件的全路径就是:d:/winnt/symbols/filename.dbg。例如,内核符号可以在文件d:/winnt/symbols/exe/ntoskrnl.dbg中找到。Windows 2000也使用.dbg文件。不过,在Windows 2000下符号化的信息被移动到了独立的.pdb文件中。因此,每个Windows 2000组件在符号文件根目录下都有一个相关的ext/filename.dbg和一个附加的ext/filename.pdb文件,除此之外,Windows NT 4.0Windows 2000.dbg文件的内容仍是相同的。

 

 

幸运的是,有关.dbg文件的内部信息的文档还是有一小部分的。Win32 SDK头文件winnt.h提供了核心的常量和类型定义,在MSDN中也有一些有关.dbg文件格式的很有帮助的文章。其中最具有启发性的是Matt Pietrek19993月的MSJMicrosoft Systems JournalMSJ,现在该命位 MSDN Magazine)的“Under the Hood”专栏中发表的文章。基本上,一个.dbg文件包含一个文件头和数据节。这两部分的大小并不固定,并且将来可能会进一步划分。文件头中包含四个主要的分段(subsections):

1.         一个IMAGE_SEPARATE_DEBUG_HEADER结构,该结构以两个标志性字符“DI”开始。(见列表1-13

 

 

2.         一个IMAGE_SECTION_HEADER类型的数组,该数组中的每个结构都位于对应组件的PE文件中。该数组的大小由IMAGE_SEPARATE_DEBUG_HEADERNumberOfSections成员指定。

 

 

3.         一组以零结尾的ANSI字符串(每个ANSI字符串占8个字节),这些字符串均是导出符号的解码格式(undecorated form)。 IMAGE_SEPARATE_DEBUG_HEADERExportedNameSize成员指出了一共有多少个字符串。如果模块没有导出任何符号,ExportedNameSize将为0,并且该分段也将不存在。

 

 

4.         一个IMAGE_DEBUG_DIRECTORY类型的数组,这些结构用来描述随后部分的格式以及它们的位置。IMAGE_SEPARATE_DEBUG_HEADERDebugDirectorySize成员给出了该数组的大小。

 

 

#define IMAGE_SEPARATE_DEBUG_SIGNATURE 0x4944 // "DI"

 

 

typedef struct _IMAGE_SEPARATE_DEBUG_HEADER

{

       WORD Signature;

       WORD Flags ;

       WORD Machine;

       WORD Characteristics;

       DWORD TimeDateStamp;

       DWORD Checksum;

       DWORD ImageBase;

       DWORD SizeOf Image;

       DWORD NurnberOf Sections ;

       DWORD ExportedNamesSize ;

       DWORD DebugDirectorySize;

       DWORD SectionAlignment;

       DWORD Reserved [2 ];

}

IMAGE_SEPARATE_DEBUG_HEADER, *PIMAGE_SEPARATE_DEBUG_HEADER;

 

 

//-----------------------------------------------------------

 

 

#define IMAGE_SIZEOF_SHORT_NAME 8

typedef struct _IMAGE_SECTION_HEADER

       BYTE Name[IMAGE_SIZEOF_SHORT_NAME] ;

       union

       (

              DWORD PhysicalAddress;

              DWORD VirtualSize;

       } Misc;

              DWORD VirtualAddress;

              DWORD SizeOf RawData;

              DWORD PointerToRawData;

              DWORD PointerToRelocations;

              DWORD PointerToLinenumbers ;

              WORD NumberOf Relocations;

              WORD NumberOf Linenumbers ;

              DWORD Characteristics;

       }

IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;

 

 

#define IMAGE_DEBUG_TYPE_UNKNOWN       0

#define IMAGE_DEBUG_TYPE_COFF          1

#define IMAGE_DEBUG_TYPE_CODEVIEW      2

#define IMAGE_DEBUG_TYPE_FPO           3

#define IMAGE_DEBUG_TYPE_MISC          4

#define IMAGE_DEBUG_TYPE_EXCEPTION     5

#define IMAGE_DEBUG_TYPE_FIXUP         6

#define IMAGE_DEBUG_TYPE_OMAP_TO_SRC   7

#define IMAGE_DEBUG_TYPE_OMAP_FROM_SRC 8

#define IMAGE_DEBUG_TYPE_BORLAND       9

#define IMAGE_DEBUG_TYPE_RESERVED10    10

#define IMAGE_DEBUG_TYPE_CLSID         11

 

 

//-----------------------------------------------------------

 

 

typedef struct _IMAGE_DEBUG_DIRECTORY

{

       DWORD Characteristics;

       DWORD TimeDateStamp;

       WORD MajorVersion;

       WORD MinorVersion;

       DWORD Type;

       DWORD SizeOfData;

       DWORD AddressOfRawData;

       DWORD PointerToRawData;

}

IMAGE_DEBUG_DIRECTORY , * PIMAGE_DEBUG_DIRECTORY ;

列表1-13.  .dbg文件的文件头结构

 

 

由于文件头中的表头分段的大小不能确定,因此它们在.dbg文件中的绝对位置必须通过它们前面的分段的大小来计算出来。一个.dbg文件分析器通常采用如下算法:

l         IMAGE_SEPARATE_DEBUG_HEADER结构总是位于文件的开始位置。

 

 

l         第一个IMAGE_SECTION_HEADER结构紧随IMAGE_SEPARATE_DEBUG_HEADER结构之后,因此总是可以在文件偏移量为0x30的位置找到该结构。

 

 

l         IMAGE_SECTION_HEADER结构的大小与该结构的个数相乘然后加上第一个IMAGE_SECTION_HEADER结构在文件中的偏移量就可得到第一个导出符号的偏移量。即第一个导出字符串的位置是:0x30+(NumberOfSections*0x28)

 

 

l         通过将ExportedNameSize与导出符号分段的偏移量相加即可得到第一个IMAGE_DEBUG_DIRECTORY结构的位置。

 

 

l         通过IMAGE_DEBUG_DIRECTORY项可确定.dbg文件中剩余数据项的偏移量。PointerToRawSizeOfData成员分别指出了相关数据块的偏移量和大小。

 

 

列表1-13给出了IMAGE_DEBUG_TYPE_*结构的定义。这些结构反映了.dbg文件中所包含的多种数据格式。不过,Windows NT 4.0的符号文件通常仅包含这些结构中的四个:IMAGE_DEBUG_TYPE_COFFIMAGE_DEBUG_TYPE_CODEVIEWIMAGE_DEBUG_TYPE_FPOIMAGE_DEBUG_TYPE_MISCWindows 2000.dbg文件通常会增加IMAGE_DEBUG_TYPE_OMAP_TO_SRCIMAGE_DEBUG_TYPE_OMAP_FROM_SRC以及一个未文档化的类型ID0x1000的结构。如果你仅对解析或浏览符号感兴趣,那么你只需要了解目录项结构:IMAGE_DEBUG_TYPE_CODEVIEWIMAGE_DEBUG_TYPE_OMAP_TO_SRCIMAGE_DEBUG_TYPE_OMAP_FROM_SRC

 

 

本书的CD中包含一个示例DLL----w2k_img.dll,该DLL用于解析.dbg.pdb文件并导出了多个用于开发内核调试工具的重要函数。可在本书的/src/w2k_img目录下找到该DLL的源代码。w2k_img.dll的一个重要属性是:它所有Win32平台上都可以运行。这不只包括Windows 2000Windows NT 4.0还包括Windows 9x。像所有Win32世界中的好市民一样,这个DLL的每个函数为支持ANSIUnicode字符串均提供了独立的接口。默认情况下,客户端使用ANSI版的函数。如果应用程序的源文件中包含了#define UICODE,那么将选择Unicode版的函数。运行于Win32平台上的程序最好选择ANSI版的函数。针对Windows NT/2000开发的程序则可选择Unicode版的函数以获取更好的性能。

 

 

在本书CD中还包含一个名为“SBS Windows 2000 CodeView Decompiler”的示例程序,可在CD/src/w2k_cv目录下找到该程序的Visual C/C++项目文件。该程序是一个简单的用于分析.dbg.pdb文件,并在Windows控制台中显示它们的内容。在阅读本节时,你可以使用该程序来查看我们正在讨论的这些数据结构。w2k_cv.exe大量使用了w2k_img.dll中的API函数。

 

 

列表1-14给出了w2k_img.h中定义的一个最基本的数据结构---IMG_DBG,该结构是由.dbg文件头中的前两个分段串联而成,也就是说,该结构由一个大小固定的基本表头和一组PE节的表头构成。给定PE节表头的数目就可通过IMG_DBG__()宏计算出该结构的实际大小。这一大小还确定了导出符号节(exported-names subsections)在文件中的偏移量。

 

 

W2k_img.dll中有几个函数需要一个指向已初始化的IMG_DBG结构的指针。imgDbgLoad()函数可分配一个IMG_DBG结构,并对该结构进行适当的初始化(该函数会用指定的.dbg文件的内容填充该结构)。imgDbgLoad()会对数据进行严格的完整性检查以确定指定的.dbg文件是有效和完整的。imgDbgLoad()函数返回的IMG_DBG结构可传递给多个分析函数,通过这些分析函数我们可得到一些经常使用的线性地址。例如,imgDbgExports()函数可计算出导出符号节(该节紧随IMAGE_SECTION_HEADER数组之后)的线性地址。该函数还可通过扫描整个导出符号节来统计有效符号名的个数,并可通过pdcount参数来返回统计的结果(可选)。

 

 

typedef struct _IMG_DBG

{

       IMAGE_SEPARATE_DEBUG_HEADER  Header;

       IMAGE_SECTION_HEADER         aSections[];

}

IMG_DBG, *PIMG_DBG, **PPIMG_DBG;

 

 

#define IMG_DBG_ sizeof(IMG_DBG)

#define IMG_DBG__(_n) (IMG_DBG_+((_n)*IMAGE_SECTION_HEADER_))

 

 

#define IMG_DBG_DATA(_p,_d) /

        ((PVOID)((PBYTE)(_p) + (_d)->PointerToRawData))

列表1-14.  IMG_DBG结构以及相关的宏定义

 

 

 

 

PVOID WINAPI imgDbgLoadA (PBYTE  pbPath,

                          PDWORD pdSize)

    {

    DWORD dOffset = (pdSize != NULL ? *pdSize : 0);

    DWORD dSize   = dOffset;

    PBYTE pbData  = imgFileLoadA (pbPath, &dSize);

 

 

    if ((pbData != NULL) &&

        (!imgDbgVerify ((PIMG_DBG) (pbData + dOffset), dSize)))

        {

        pbData = imgMemoryDestroy (pbData);

        }

    if (pdSize != NULL) *pdSize = dSize;

    return pbData;

    }

 

 

// -----------------------------------------------------------------

 

 

PVOID WINAPI imgDbgLoadW (PWORD  pwPath,

                          PDWORD pdSize)

    {

    DWORD dOffset = (pdSize != NULL ? *pdSize : 0);

    DWORD dSize   = dOffset;

    PBYTE pbData  = imgFileLoadW (pwPath, &dSize);

 

 

    if ((pbData != NULL) &&

        (!imgDbgVerify ((PIMG_DBG) (pbData + dOffset), dSize)))

        {

        pbData = imgMemoryDestroy (pbData);

        }

    if (pdSize != NULL) *pdSize = dSize;

    return pbData;

    }

 

 

// -----------------------------------------------------------------

 

 

PBYTE WINAPI imgDbgExports (PIMG_DBG pid,

                            PDWORD   pdCount)

    {

    DWORD i, j;

    DWORD dCount    = 0;

    PBYTE pbExports = NULL;

 

 

    if (pid != NULL)

        {

        pbExports = (PBYTE) pid->aSections

                    + (pid->Header.NumberOfSections

                       * IMAGE_SECTION_HEADER_);

 

 

        for (i = 0; i < pid->Header.ExportedNamesSize; i = j)

            {

            if (!pbExports [j = i]) break;

 

 

            while ((j < pid->Header.ExportedNamesSize) &&

                   pbExports [j++]);

 

 

            if ((j > i) && (!pbExports [j-1])) dCount++;

            }

        }

    if (pdCount != NULL) *pdCount = dCount;

    return pbExports;

    }

列表1-15.  imgDbgLoad()imgDbgExports()函数

 

 

列表1-16定义了两个可根据ID(这里的ID形如:IMAGE_DEBGU_TYPE_*)来定位相应的调试目录项(debug directory entry)的API函数。imgDbgDirectories()返回IMAGE_DEBUG_DIRECTORY数组的基地址,imgDbgDirectory()返回指向给定ID所对应的第一个目录项的指针,如果不存在这样的目录项,则返回NULL

 

 

PIMAGE_DEBUG_DIRECTORY WINAPI imgDbgDirectories (PIMG_DBG pid,

                                                 PDWORD   pdCount)

    {

    DWORD                  dCount = 0;

    PIMAGE_DEBUG_DIRECTORY pidd   = NULL;

 

 

    if (pid != NULL)

        {

        pidd   = (PIMAGE_DEBUG_DIRECTORY)

                 ((PBYTE) pid

                  + IMG_DBG__ (pid->Header.NumberOfSections)

                  + pid->Header.ExportedNamesSize);

 

 

        dCount = pid->Header.DebugDirectorySize

                 / IMAGE_DEBUG_DIRECTORY_;

        }

    if (pdCount != NULL) *pdCount = dCount;

    return pidd;

    }

 

 

// -----------------------------------------------------------------

 

 

PIMAGE_DEBUG_DIRECTORY WINAPI imgDbgDirectory (PIMG_DBG pid,

                                               DWORD    dType)

    {

    DWORD                  dCount, i;

    PIMAGE_DEBUG_DIRECTORY pidd = NULL;

 

 

    if ((pidd = imgDbgDirectories (pid, &dCount)) != NULL)

        {

        for (i = 0; i < dCount; i++, pidd++)

            {

            if (pidd->Type == dType) break;

            }

        if (i == dCount) pidd = NULL;

        }

    return pidd;

    }

列表1-16.  imgDbgDirectories()imgDbgDirectory() API函数

 

 

imgDbgDirectories()函数可用来查找.dbg文件中的CodeView数据。列表1-17中的imgDbgCv()函数完成了这一任务。imgDbgCv()函数使用IMAGE_DEBUG_TYPE_CODEVIEW调用imgDbgDirectories(),并使用IMG_DBG_DATA()宏将IMAGE_DEBUG_DIRECTORY项提供的偏移量转化为绝对线性地址。该宏只是简单的将IMG_DBG结构的基地址与给定的偏移量相加然后再将结果转型(typecast)为PVOID类型的指针。如果pdSize参数不为NULL,则imgDbgCv()CodeView子节的大小保存到该参数中。接下来我们将讨论CodeView数据的内部结构。

 

 

针对其他数据子节(data subsection)的函数非常类似。列表1-18给出了imgDbgOmapToSrc()imgDbgOmapFromSrc()函数以及它们使用的OMAP_TO_SRCOMAP_FROM_SRC结构。稍后,我们将使用这些结构来计算位于CodeView子节中的符号的线性地址。因为OMAP数据结构是一个长度固定的数组,所以这两个API函数并不返回子节的大小,而是计算数组中的项数。该项数将被保存到*pdcount参数中(如果该参数不为NULL的话)。

 

 

PCV_DATA WINAPI imgDbgCv (PIMG_DBG pid,

                          PDWORD   pdSize)

    {

    PIMAGE_DEBUG_DIRECTORY pidd;

    DWORD                  dSize = 0;

    PCV_DATA               pcd   = NULL;

 

 

    if ((pidd = imgDbgDirectory (pid, IMAGE_DEBUG_TYPE_CODEVIEW))

        != NULL)

        {

        pcd   = IMG_DBG_DATA (pid, pidd);

        dSize = pidd->SizeOfData;

        }

    if (pdSize != NULL) *pdSize = dSize;

    return pcd;

    }

列表1-17.  imgDbgCv()函数

 

 

typedef struct _OMAP_TO_SRC

    {

    DWORD dTarget;

    DWORD dSource;

    }

    OMAP_TO_SRC, *POMAP_TO_SRC, **PPOMAP_TO_SRC;

 

 

#define OMAP_TO_SRC_ sizeof (OMAP_TO_SRC)

 

 

// -----------------------------------------------------------------

 

 

typedef struct _OMAP_FROM_SRC

    {

    DWORD dSource;

    DWORD dTarget;

    }

    OMAP_FROM_SRC, *POMAP_FROM_SRC, **PPOMAP_FROM_SRC;

 

 

#define OMAP_FROM_SRC_ sizeof (OMAP_FROM_SRC)

 

 

 

 

// -----------------------------------------------------------------

 

 

POMAP_TO_SRC WINAPI imgDbgOmapToSrc (PIMG_DBG pid,

                                     PDWORD   pdCount)

    {

    PIMAGE_DEBUG_DIRECTORY pidd;

    DWORD                  dCount = 0;

    POMAP_TO_SRC           pots   = NULL;

 

 

    if ((pidd = imgDbgDirectory (pid,

                                 IMAGE_DEBUG_TYPE_OMAP_TO_SRC))

        != NULL)

        {

        pots   = IMG_DBG_DATA (pid, pidd);

        dCount = pidd->SizeOfData / OMAP_TO_SRC_;

        }

    if (pdCount != NULL) *pdCount = dCount;

    return pots;

    }

 

 

// -----------------------------------------------------------------

 

 

POMAP_FROM_SRC WINAPI imgDbgOmapFromSrc (PIMG_DBG pid,

                                         PDWORD   pdCount)

    {

    PIMAGE_DEBUG_DIRECTORY pidd;

    DWORD                  dCount = 0;

    POMAP_FROM_SRC         pofs   = NULL;

 

 

    if ((pidd = imgDbgDirectory (pid,

                                 IMAGE_DEBUG_TYPE_OMAP_FROM_SRC))

        != NULL)

        {

        pofs   = IMG_DBG_DATA (pid, pidd);

        dCount = pidd->SizeOfData / OMAP_FROM_SRC_;

        }

    if (pdCount != NULL) *pdCount = dCount;

    return pofs;

    }

列表1-18.  imgDbgOmapToSrc()imgDbgOmapFromSrc()函数

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
This book documents what goes on under the covers in Windows NT. Three experts share what they've dug up on NT through years of hands-on research and programming experience. The authors dissect the Win32 interface, deconstruct the underlying APIs, and decipher the Memory Management architecture to help you understand operations, fix flaws, and enhance performance. Table of Contents Chapter 1: Windows NT: An Inside Look EVALUATING WINDOWS NT DELVING INTO THE WINDOWS NT ARCHITECTURE SUMMARY Chapter 2: Writing Windows NT Device Drivers PREREQUISITES TO WRITING NT DEVICE DRIVERS DRIVER BUILD PROCEDURE STRUCTURE OF A DEVICE DRIVER SUMMARY Chapter 3: Win32 Implementations: A Comparative Look WIN32 API IMPLEMENTATION ON WINDOWS 95 WIN32 API IMPLEMENTATION ON WINDOWS NT WIN32 IMPLEMENTATION DIFFERENCES SUMMARY Chapter 4: Memory Management MEMORY MODELS IN MICROSOFT OPERATING SYSTEMS WINDOWS NT MEMORY MANAGEMENT OVERVIEW BELOW THE OPERATING SYSTEM THE INSIDE LOOK VIRTUAL MEMORY MANAGEMENT VIRTUAL ADDRESS DESCRIPTORS IMPACT ON HOOKING SWITCHING CONTEXT DIFFERENCES BETWEEN WINDOWS NT AND WINDOWS 95/98 SUMMARY Chapter 5: Reverse Engineering Techniques HOW TO PREPARE FOR REVERSE ENGINEERING HOW TO REVERSE ENGINEER UNDERSTANDING CODE GENERATION PATTERNS HOW WINDOWS NT PROVIDES DEBUGGING INFORMATION HOW TO DECIPHER THE PARAMETERS PASSED TO AN UNDOCUMENTED FUNCTION TYPICAL ASSEMBLY LANGUAGE PATTERNS AND THEIR MEANINGS THE PRACTICAL APPLICATION OF REVERSE ENGINEERING SUMMARY Chapter 6: Hooking Windows NT System Services SYSTEM SERVICES: THE LONG VIEW NEED FOR HOOKING SYSTEM SERVICES TYPES OF HOOKS IMPLEMENTATIONS OF HOOKS WINDOWS NT SYSTEM SERVICES HOOKING NT SYSTEM SERVICES SUMMARY Chapter 7: Adding New System Services to the Windows NT Kernal DETAILED IMPLEMENTATION OF A SYSTEM SERVICE IN WINDOWS NT ADDING NEW SYSTEM SERVICES EXAMPLE OF ADDING A NEW SYSTEM SERVICE SUMMARY Chapter 8: Local Procedure Call THE ORIGIN OF THE SUBSYSTEMS LOCAL PROCEDURE CALL PORT-RELATED FUNCTIONS LPC SAMPLE PROGRAMS QUICK LPC SUMMARY Chapter 9: Hooking Software Interrupts WHAT ARE INTERRUPTS? HOW OPERATING SYSTEMS USE SOFTWARE INTERRUPTS WHY SOFTWARE INTERRUPTS NEED TO BE HOOKED HOW TO HOOK SOFTWARE INTERRUPTS SUMMARY Chapter 10: Adding New Software Interrupts WHAT HAPPENS WHEN A 32-BIT APPLICATION EXECUTES AN INT NN INSTRUCTION? ADDING NEW SOFTWARE INTERRUPTS TO THE WINDOWS NT KERNEL USING CALLGATES TO EXECUTE PRIVILEGED CODE HOW TO USE THE CALLGATE TECHNIQUE PAGING ISSUES SUMMARY Chapter 11: Portable Executable File Format OVERVIEW OF A PE FILE STRUCTURE OF A PE FILE RELATIVE VIRTUAL ADDRESS DETAILS OF THE PE FORMAT INDICES IN THE DATA DIRECTORY LOADING PROCEDURE SUMMARY
Table of Contents Chapter 1: Windows NT: An Inside Look EVALUATING WINDOWS NT DELVING INTO THE WINDOWS NT ARCHITECTURE SUMMARY Chapter 2: Writing Windows NT Device Drivers PREREQUISITES TO WRITING NT DEVICE DRIVERS DRIVER BUILD PROCEDURE STRUCTURE OF A DEVICE DRIVER SUMMARY Chapter 3: Win32 Implementations: A Comparative Look WIN32 API IMPLEMENTATION ON WINDOWS 95 WIN32 API IMPLEMENTATION ON WINDOWS NT WIN32 IMPLEMENTATION DIFFERENCES SUMMARY Chapter 4: Memory Management MEMORY MODELS IN MICROSOFT OPERATING SYSTEMS WINDOWS NT MEMORY MANAGEMENT OVERVIEW BELOW THE OPERATING SYSTEM THE INSIDE LOOK VIRTUAL MEMORY MANAGEMENT VIRTUAL ADDRESS DESCRIPTORS IMPACT ON HOOKING SWITCHING CONTEXT DIFFERENCES BETWEEN WINDOWS NT AND WINDOWS 95/98 SUMMARY Chapter 5: Reverse Engineering Techniques HOW TO PREPARE FOR REVERSE ENGINEERING HOW TO REVERSE ENGINEER UNDERSTANDING CODE GENERATION PATTERNS HOW WINDOWS NT PROVIDES DEBUGGING INFORMATION HOW TO DECIPHER THE PARAMETERS PASSED TO AN UNDOCUMENTED FUNCTION TYPICAL ASSEMBLY LANGUAGE PATTERNS AND THEIR MEANINGS THE PRACTICAL APPLICATION OF REVERSE ENGINEERING SUMMARY Chapter 6: Hooking Windows NT System Services SYSTEM SERVICES: THE LONG VIEW NEED FOR HOOKING SYSTEM SERVICES TYPES OF HOOKS IMPLEMENTATIONS OF HOOKS WINDOWS NT SYSTEM SERVICES HOOKING NT SYSTEM SERVICES SUMMARY Chapter 7: Adding New System Services to the Windows NT Kernal DETAILED IMPLEMENTATION OF A SYSTEM SERVICE IN WINDOWS NT ADDING NEW SYSTEM SERVICES EXAMPLE OF ADDING A NEW SYSTEM SERVICE SUMMARY Chapter 8: Local Procedure Call THE ORIGIN OF THE SUBSYSTEMS LOCAL PROCEDURE CALL PORT-RELATED FUNCTIONS LPC SAMPLE PROGRAMS QUICK LPC SUMMARY Chapter 9: Hooking Software Interrupts WHAT ARE INTERRUPTS? HOW OPERATING SYSTEMS USE SOFTWARE INTERRUPTS WHY SOFTWARE INTERRUPTS NEED TO BE HOOKED HOW TO HOOK SOFTWARE INTERRUPTS SUMMARY Chapter 10: Adding New Software Interrupts WHAT HAPPENS WHEN A 32-BIT APPLICATION EXECUTES AN INT NN INSTRUCTION? ADDING NEW SOFTWARE INTERRUPTS TO THE WINDOWS NT KERNEL USING CALLGATES TO EXECUTE PRIVILEGED CODE HOW TO USE THE CALLGATE TECHNIQUE PAGING ISSUES SUMMARY Chapter 11: Portable Executable File Format OVERVIEW OF A PE FILE STRUCTURE OF A PE FILE RELATIVE VIRTUAL ADDRESS DETAILS OF THE PE FORMAT INDICES IN THE DATA DIRECTORY LOADING PROCEDURE SUMMARY

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值