MS 调试信息分析(一)

首先我在这里说明,MS 调试信息的支持其实MS 已经提供了DBGhelp和imagehel 这两个库,当我们如果想更深入的了解调试信息就必须来了解调试文件。我在这里只讨论DBG文件和PDB文件,由于其中的很多信息,MS并没有公开,我也只属于探索阶段,所以错误再所难免。

  一般的调式信息由MS提供的一般由两个文件,DBG文件和PDB文件,在NT4。0中没有PDB文件,PDB文件中的信息被保存在DBG文件中。

下面我们就仔细的看看DGB 文件的内容
IMAGE_SEPARATE_DEBUG_HEADER     该结构以两个标志性字符“DI”开始
IMAGE_SECTION_HEADER    数组,该数组中的每个结构都位于对应组件的PE 文件中。该数组的大小由IMAGE_SEPARATE_DEBUG_HEADER 的NumberOfSections 成员指定。
EXPORT 字符串的解码    一组以零结尾的ANSI 字符串(每个ANSI 字符串占8 个字节),这些字符串均是导出符号的解码格式(undecorated form)。IMAGE_SEPARATE_DEBUG_HEADER的ExportedNameSize 成员指出了一共有多少个字符串。如果模块没有导出任何符号,ExportedNameSize 将为0,并且该分段也将不存在
IMAGE_DEBUG_DIRECTORY     数组,这些结构用来描述随后部分的格式以及它们的位置。IMAGE_SEPARATE_DEBUG_HEADER 的DebugDirectorySize成员给出了该数组的大小。
dbg文件结构分布如下图:













IMAGE_SEPARATE_DEBUG_HEADER 结构说明:该结构总是在文件的开始处.在WINNT.H中的定义如下,
typedef struct _IMAGE_SEPARATE_DEBUG_HEADER {
WORD        Signature;                        
WORD        Flags;
    WORD        Machine;
    WORD        Characteristics;
    DWORD       TimeDateStamp;
    DWORD       CheckSum;
    DWORD       ImageBase;
    DWORD       SizeOfImage;
    DWORD       NumberOfSections;
    DWORD       ExportedNamesSize;
    DWORD       DebugDirectorySize;
    DWORD       SectionAlignment;
    DWORD       Reserved[2];
} IMAGE_SEPARATE_DEBUG_HEADER, *PIMAGE_SEPARATE_DEBUG_HEADER;

Signature :标志 总为 0x4944 ’DI’

Flags: 不知道,(至少我是不知道什么意思)

Machine:机器类型,在WINNT.H中的定义以下几中类型,从字面意思我们就可以知道该文件的类型.一般我们的机器的类型为IMAGE_FILE_MACHINE_I386.
变量值    意思
IMAGE_FILE_MACHINE_UNKNOWN    不知道机器类型
IMAGE_FILE_MACHINE_I386    Intel 386.
IMAGE_FILE_MACHINE_R3000    MIPS little-endian
IMAGE_FILE_MACHINE_R4000    
IMAGE_FILE_MACHINE_R10000    MIPS little-endian
IMAGE_FILE_MACHINE_WCEMIPSV2    WCE v2
IMAGE_FILE_MACHINE_ALPHA    / Alpha_AXP
IMAGE_FILE_MACHINE_POWERPC    IBM PowerPC Little-Endian
IMAGE_FILE_MACHINE_SH3    SH3 little-endian
IMAGE_FILE_MACHINE_SH3E    SH3E little-endian
IMAGE_FILE_MACHINE_SH4    SH4 little-endian
IMAGE_FILE_MACHINE_ARM    ARM Little-Endian
IMAGE_FILE_MACHINE_THUMB    
IMAGE_FILE_MACHINE_IA64    Intel 64
IMAGE_FILE_MACHINE_MIPS16    MIPS
IMAGE_FILE_MACHINE_MIPS16    
IMAGE_FILE_MACHINE_MIPSFPU    MIPS
IMAGE_FILE_MACHINE_MIPSFPU16    MIPS
IMAGE_FILE_MACHINE_ALPHA64    ALPHA64
IMAGE_FILE_MACHINE_AXP64    

Characteristics:该文件的特征点,它的变量可以为以下值的结合
变量    意思
IMAGE_FILE_RELOCS_STRIPPED    Relocation information is stripped from the file.
IMAGE_FILE_EXECUTABLE_IMAGE    The file is executable (there are no unresolved external references).
IMAGE_FILE_LINE_NUMS_STRIPPED    Line numbers are stripped from the file.
IMAGE_FILE_LOCAL_SYMS_STRIPPED    Local symbols are stripped from file.
IMAGE_FILE_AGGRESIVE_WS_TRIM    Aggressively trim the working set.
IMAGE_FILE_LARGE_ADDRESS_AWARE    The application can handle addresses larger than 2 GB.
IMAGE_FILE_BYTES_REVERSED_LO    Bytes of the word are reversed.
IMAGE_FILE_32BIT_MACHINE    Computer supports 32-bit words.
IMAGE_FILE_DEBUG_STRIPPED    Debugging information is stored separately in a .dbg file.
IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP    If the image is on removable media, copy and run from the swap file
IMAGE_FILE_NET_RUN_FROM_SWAP    If the image is on the network, copy and run from the swap file.
IMAGE_FILE_SYSTEM    System file.
IMAGE_FILE_DLL    DLL file.
IMAGE_FILE_UP_SYSTEM_ONLY    File should be run only on a uniprocessor computer.
IMAGE_FILE_BYTES_REVERSED_HI    Bytes of word are reversed.

TimeDateStamp 该文件的创建时间,从1970年1月1日0点开始算起的时间

CheckSum: 检验码,和PE文件的CheckSum一样才能可以认为DBG文件是该PE文件的调试信息..

ImageBase: PE文件的基地址,,这只是一个默认的基地址,往往在PE文件被装载之后地址会变.

SizeOfImag: 暂时不知道什么代表的是谁的大小

NumberOfSections:文件接下来的结构数组的个数IMAGE_SECTION_HEADER.

ExportedNamesSize: 导出符号的长度,以字节为单位.

DebugDirectorySize: 所有IMAGE_DEBUG_DIRECTORY 数组的长度,以字节为单位

SectionAlignment:   各个段的对齐方式.
接下来我们看一看在调试中经常用的ntoskrnl.dbg文件书输出的IMAGE_SEPARATE_DEBUG_HEADER,由于可能本人使用DBG文件和各位读者的不一定相同,所以有些数据可能也有点不一样,
Signature            =     0x4944;        //“DI”                
Flags            =     0x0000;
    Machine            =     0x014c;        // IMAGE_FILE_MACHINE_I386
   Characteristics        =     0x030e;        //
   TimeDateStamp    =     0x4047db83;    // 2004.3.6 1:44:35
   CheckSum            =     0x001ac013;
   ImageBase            =     0x00400000;//
IMAGE_FILE_DEBUG_STRIPPED| IMAGE_FILE_32BIT_MACHINE|
IMAGE_FILE_LOCAL_SYMS_STRIPPED|
IMAGE_FILE_LINE_NUMS_STRIPPED|
IMAGE_FILE_RELOCS_STRIPPED
  SizeOfImage        =     0x001a59c0;
    NumberOfSections    =     0x00000015;
    ExportedNamesSize=     0x00006390;
    DebugDirectorySize=     0x000000a8;
    SectionAlignment    =     0x00000040;
  从上面的数据中我们可以知道该DBG文件的一些基本的信息,在这些参数中,我们最关心的是NumberOfSections和ExportedNamesSize,因为,这两个参数将决定了我们以后的数据的分布情况,而创建时间TimeDateStamp和校验码CheckSum则可以验证当前可PE文件是否和我们的调试文件相匹配.


IMAGE_SECTION_HEADER 数据
从上面的文件中我们可以看出,在DBG文件中, IMAGE_SEPARATE_DEBUG_HEADER后的数据就是IMAGE_SECTION_HEADER数据了,当IMAGE_SECTION_HEADER数据是一个数据组,它的大小主要由IMAGE_SEPARATE_DEBUG_HEADER的NumberOfSections来决定,该结构在WINNT.H中的定义如下:
typedef struct _IMAGE_SECTION_HEADER {
    BYTE    Name[IMAGE_SIZEOF_SHORT_NAME];
    union {
            DWORD   PhysicalAddress;
            DWORD   VirtualSize;
    } Misc;
    DWORD   VirtualAddress;
    DWORD   SizeOfRawData;
    DWORD   PointerToRawData;
    DWORD   PointerToRelocations;
    DWORD   PointerToLinenumbers;
    WORD    NumberOfRelocations;
    WORD    NumberOfLinenumbers;
    DWORD   Characteristics;
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;

Name :该段的名称,长度为8
PhysicalAddress:文件地址
VirtualSize:装载在内存中以后的大小
VirtualAddress :该段第一个字节的地址
SizeOfRawData: 保存在磁盘上数据的大小
PointerToRawData:该段对应COFF文件的开始位置
PointerToRelocations:从新定位的地址的指针
PointerToLinenumbers:开始后的行数
NumberOfRelocations :从新定位的个数
NumberOfLinenumbers: 数量
Characteristics: 文件的特性
变量    意思
IMAGE_SCN_TYPE_REG    
IMAGE_SCN_TYPE_DSECT    
IMAGE_SCN_TYPE_NOLOAD    
IMAGE_SCN_TYPE_GROUP    
IMAGE_SCN_TYPE_NO_PAD    
IMAGE_SCN_TYPE_COPY    
IMAGE_SCN_CNT_CODE    Section contains executable code.
IMAGE_SCN_CNT_INITIALIZED_DATA    Section contains initialized data
IMAGE_SCN_CNT_UNINITIALIZED_DATA    Section contains uninitialized data
IMAGE_SCN_LNK_OTHER    
IMAGE_SCN_LNK_INFO    
IMAGE_SCN_TYPE_OVER    
IMAGE_SCN_LNK_COMDAT    Section contains COMDAT data
IMAGE_SCN_MEM_FARDATA    
IMAGE_SCN_MEM_PURGEABLE    
IMAGE_SCN_MEM_16BIT    
IMAGE_SCN_MEM_LOCKED    
IMAGE_SCN_MEM_PRELOAD    
IMAGE_SCN_ALIGN_1BYTES    Align data on a 1-byte boundary
    
我们来分析一下ntoskrnl.dgb文件中个段信息,从上面的IMAGE_SEPARATE_DEBUG_HEADER的信息分析中我们已经知道该DBG文件一共包含21(0x15)个段信息,在这里我只列举4个段的信息,有兴趣的朋友可以将21个段信息都列举出来分析一下看看
SECTION   0
Name  :.text
PhysicalAddress : 0x 0006ad1b
VirtualSize : 0x 0006ad1b
VirtualAddress : 0x 00000540
SizeOfRawData : 0x 0006ad40
PointerToRawData : 0x 00000540
PointerToRelocations : 0x 00000000
PointerToLinenumbers : 0x 00000000
NumberOfRelocations : 0x 00000000
NumberOfLinenumbers : 0x 00000000
Characteristics : 0x 68000020


SECTION   1
Name  :POOLCODE5

PhysicalAddress : 0x 00000b35
VirtualSize : 0x 00000b35
VirtualAddress : 0x 0006b280
SizeOfRawData : 0x 00000b40
PointerToRawData : 0x 0006b280
PointerToRelocations : 0x 00000000
PointerToLinenumbers : 0x 00000000
NumberOfRelocations : 0x 00000000
NumberOfLinenumbers : 0x 00000000
Characteristics : 0x 68000020


SECTION   2
Name  :POOLMI
PhysicalAddress : 0x 00001289
VirtualSize : 0x 00001289
VirtualAddress : 0x 0006bdc0
SizeOfRawData : 0x 000012c0
PointerToRawData : 0x 0006bdc0
PointerToRelocations : 0x 00000000
PointerToLinenumbers : 0x 00000000
NumberOfRelocations : 0x 00000000
NumberOfLinenumbers : 0x 00000000
Characteristics : 0x 68000020


SECTION   3
Name  :MISYSPTE?
PhysicalAddress : 0x 000006ec
VirtualSize : 0x 000006ec
VirtualAddress : 0x 0006d080
SizeOfRawData : 0x 00000700
PointerToRawData : 0x 0006d080
PointerToRelocations : 0x 00000000
PointerToLinenumbers : 0x 00000000
NumberOfRelocations : 0x 00000000
NumberOfLinenumbers : 0x 00000000
Characteristics : 0x 68000020

EXPORT 符号名称
它的起始地址为获取文件数据的地址+ IMAGE_SEPARATE_DEBUG_HEADER大小+
IMAGE_SECTION_HEADER大小*个数,它的大小为IMAGE_SEPARATE_DEBUG_HEADER 中的ExportedNamesSize;在这里将列出所有导出的符号。Ntoskrnl.dbg一共导出1230 个符号,如下所示
CcCanIWrite CcCopyRead CcCopyWrite CcDeferWrite CcFastCopyRead CcFastCopyWrite CcFastMdlReadWait CcFastReadNotPossible CcFastReadWait CcFlushCache CcGetDirtyPages 。。。。。。。towupper vsprintf  wcscat  wcschr wcscmp wcscpy wcscspn  wcslen wcsncat wcsncmp wcsncpy wcsrchr wcsspn wcsstr wcstombs wctomb


IMAGE_DEBUG_DIRECTORY 数组
DBG文件的最后一部分为IMAGE_DEBUG_DIRECTORY 数组,这里保存着调试信息目录,它的地址为EXPORT 符号名称的地址+EXPORT 符号名称的大小,在WINNT.H中定义为
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;

Characteristics: 保留
TimeDateStamp:调试信息创建的时间和日期
MajorVersion: 调试信息的主版本号
MinorVersion: 调试信息的次版本号
Type: 调试信息的类型为以下变量中的一种
变量     信息
IMAGE_DEBUG_TYPE_UNKNOWN    Unknown value, ignored by all tools
IMAGE_DEBUG_TYPE_COFF    COFF debugging information (line numbers, symbol table, and string table). This type of debugging information is also pointed to by fields in the file headers.
IMAGE_DEBUG_TYPE_CODEVIEW    CodeView debugging information. The format of the data block is described by the CodeView 4.0 specification.
IMAGE_DEBUG_TYPE_FPO    Frame pointer omission (FPO) information. This information tells the debugger how to interpret nonstandard stack frames, which use the EBP register for a purpose other than as a frame pointer.
IMAGE_DEBUG_TYPE_MISC    Miscellaneous information.
IMAGE_DEBUG_TYPE_EXCEPTION    Exception information
IMAGE_DEBUG_TYPE_FIXUP    Fixup information.
IMAGE_DEBUG_TYPE_BORLAND    Borland debugging information.
IMAGE_DEBUG_TYPE_OMAP_TO_SRC    
IMAGE_DEBUG_TYPE_OMAP_FROM_SRC    
IMAGE_DEBUG_TYPE_RESERVED10    
SizeOfData:当前调试信息的长度。
AddressOfRawData:当文件被LOAD时的地址,
PointerToRawData:调试信息的文件指针。

在这里并非所有的信息DGB文件都包含,WINNT4。0 仅仅包含其中的4个IMAGE_DEBUG_TYPE_COFF 、IMAGE_DEBUG_TYPE_CODEVIEW IMAGE_DEBUG_TYPE_FPO 和IMAGE_DEBUG_TYPE_MISC 而Windows 2000 的.dbg 文件通常会增加IMAGE_DEBUG_TYPE_OMAP_TO_SRC 、IMAGE_DEBUG_TYPE_OMAP_FROM_SRC以及一个未文档化的类型ID为0x1000 的结构。
如果你仅对解析或浏览符号感兴趣, 那么你只需要了解目录项结构:IMAGE_DEBUG_TYPE_CODEVIEW 、IMAGE_DEBUG_TYPE_OMAP_TO_SRC 和
IMAGE_DEBUG_TYPE_OMAP_FROM_SRC
IMAGE_DEBUG_DIRECTORY 数组个主要是由IMAGE_SEPARATE_DEBUG_HEADER中的DebugDirectorySize信息确定的。IMAGE_DEBUG_DIRECTORY的个数=DebugDirectorySize/sizeof(IMAGE_DEBUG_DIRECTORY),由于IMAGE_DEBUG_DIRECTORY数据比较重要,我在这里将详细对它们进行介绍。还是让我们来看看ntoskrnl.dgb 中的Directory吧
先求DGB文件中IMAGE_DEBUG_DIRECTORY的地址
IMAGE_DEBUG_DIRECTORY* pDir=(IMAGE_DEBUG_DIRECTORY*)(pExport+pSeDebugHeader->ExportedNamesSize);
再求个数    
DWORD DireSize=(pdebu->DebugDirectorySize)/(sizeof(IMAGE_DEBUG_DIRECTORY));
DireSize为6和我们前面说的一样,它所指向的数据文件的地址为文件的基地址+ PointerToRawData,它的大小为SizeOfData;
下面我们再来看看具体每个结构

第一个IMAGE_DEBUG_DIRECTORY的信息为
TimeDateStamp        0x403d35e2;//2004.2.25.23.55.14
MajorVersion         0x0000;
MinorVersion         0x0000;
   Type                 0x00000002;// IMAGE_DEBUG_TYPE_CODEVIEW
   SizeOfData               0x0000001d;
   AddressOfRawData     0x00000000;
  PointerToRawData       0x000067d0;
可以看出它的数据类型为IMAGE_DEBUG_TYPE_CODEVIEW,这我们将在后面进行详细的讨论,在这里略过。

在看第二个IMAGE_DEBUG_DIRECTORY
TimeDateStamp        0x403d35e2;//2004.2.25.23.55.14
MajorVersion         0x0000;
MinorVersion         0x0000;
Type                 0x00000003;// IMAGE_DEBUG_TYPE_FPO
SizeOfData               0x00011f10;
AddressOfRawData     0x00000000;
PointerToRawData       0x000067f0;
该类型为IMAGE_DEBUG_TYPE_FPO ,数据结构为FPO_DATA数组,她的起始地址为文件的装载地址+ PointerToRawData,它的大小为SizeOfData。
在WINNT。H 中FPO_DATA结构的定义如下
typedef struct _FPO_DATA {
    DWORD       ulOffStart;             // offset 1st byte of function code
    DWORD       cbProcSize;             // # bytes in function
    DWORD       cdwLocals;              // # bytes in locals/4
    WORD        cdwParams;              // # bytes in params/4
    WORD        cbProlog : 8;           // # bytes in prolog
    WORD        cbRegs   : 3;           // # regs saved
    WORD        fHasSEH  : 1;           // TRUE if SEH in func
    WORD        fUseBP   : 1;           // TRUE if EBP has been allocated
    WORD        reserved : 1;           // reserved for future use
    WORD        cbFrame  : 2;           // frame type
} FPO_DATA, *PFPO_DATA;
#define SIZEOF_RFPO_DATA 16

ulOffStart :该函数和基地址的偏移。

CbProcSize:该函数的大小

CdwLocals: 本地变量,单位为DWORD

CdwParams:参数数量,单位为DWORD

CbProlog:预处理的字节数

CbRegs: 注册数量
FHasSEH:如果为TRUE 则有异常处理函数
fUseBP   :如果为TRUE 则注册EPB
cbFrame  :框架类型
类型    意思
FRAME_FPO    FPO frame
FRAME_TRAP    Trap frame
FRAME_TSS    TSS frame
FRAME_NONFPO    Non-FPO frame


在看第三个IMAGE_DEBUG_DIRECTORY
TimeDateStamp        0x403d35e2;//2004.2.25.23.55.14
MajorVersion         0x0000;
MinorVersion         0x0000;
Type                 0x00000004;// IMAGE_DEBUG_TYPE_MISC
SizeOfData            0x00000110;
AddressOfRawData     0x00000000;
PointerToRawData      0x00018700;
该结构从字面意思应该理解为各类信息,它的长度为272个字节让我们看看具体的信息吧,该信息的结构为
typedef struct _IMAGE_DEBUG_MISC {
    DWORD       DataType;               // type of misc data, see defines
    DWORD       Length;                 // total length of record, rounded to four
                                        // byte multiple.
    BOOLEAN     Unicode;                // TRUE if data is unicode string
    BYTE        Reserved[ 3 ];
    BYTE        Data[ 1 ];              // Actual data
} IMAGE_DEBUG_MISC, *PIMAGE_DEBUG_MISC;

DataType: 信息的类型,现在只定义了一种即
#define IMAGE_DEBUG_MISC_EXENAME    1
Length: 总的数据长度
Unicode: 是否为UNICODE
Data  : 数据信息.
我们来看看ntoskrnl.dBG中的数据情况DataType为IMAGE_DEBUG_MISC_EXENAME,Length 为0x110,Unicode为false,Data数据为一些字符串组合为obj/i386/ntoskrnl.exe,从上面可以看出MISC信息应该是编译生成文件的路径。
在看第四个IMAGE_DEBUG_DIRECTORY
TimeDateStamp        0x000000004
MajorVersion         0x0001
MinorVersion         0x0000
Type                 0x00000007;// IMAGE_DEBUG_TYPE_OMAP_TO_SRC
SizeOfData            0x000d4d08;
AddressOfRawData     0x00000000;
PointerToRawData      0x00018810;
从数据上可以看得出来,和前面的目录有些不同,她没有创建时间,而且它的主版本号为1,数据也特别多。看看OMAP结构的定义,
typedef struct _OMAP {
    ULONG  rva;
    ULONG  rvaTo;
} OMAP, *POMAP;
rva: 本地虚拟地址
rvaTo: 原程序中的地址


在看第五个IMAGE_DEBUG_DIRECTORY
它的类型为IMAGE_DEBUG_TYPE_OMAP_FROM_SRC,结构和IMAGE_DEBUG_TYPE_OMAP_TO_SRC一样。

看第六个IMAGE_DEBUG_DIRECTORY 不知道是什么意思,微软也没有公开


在下一节中,我将介绍CODEVIEW节的信息。
参考 《Undocumented Windows 2000 Secrets》
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值