首先我在这里说明,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》
一般的调式信息由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》