标 题: 使用DELPHI编写PE区段查看器
作 者: pathletboy
时 间: 2007-01-09,12:30
链 接:
http://bbs.pediy.com/showthread.php?s=&threadid=37667
所需工具:Ollydbg、Delphi7
要点:纪录结构、FileStream操作
提前说明,本人是新手,对PE结构很不了解,下文可能漏洞百出,希望观者能指出错误。
STEP1
建立PE文件头的结构和PE区段头的数据结构。
打开OD随便加载一个EXE文件,然后alt+m后找到加载程序的内存空间后(见下图)
双击PE文件头一行。
在偏移$3C处发现
0040003C 00010000 DD 00000100 ; Offset to PE signature
根据提示到偏移$100处
00400100 50 45 00 00>ASCII "PE" ; PE signature (PE)
00400104 4C01 DW 014C ; Machine = IMAGE_FILE_MACHINE_I386
00400106 0800 DW 0008 ; NumberOfSections = 8
00400108 195E422A DD 2A425E19 ; TimeDateStamp = 2A425E19
0040010C 00000000 DD 00000000 ; PointerToSymbolTable = 0
00400110 00000000 DD 00000000 ; NumberOfSymbols = 0
00400114 E000 DW 00E0 ; SizeOfOptionalHeader = E0 (224.)
00400116 8E81 DW 818E ; Characteristics =
EXECUTABLE_IMAGE|32BIT_MACHINE|LINE_NUMS_STRIPPED|LOCAL_SYMS_STRIPPED|BYTES_REVERSED_LO|BYTES_REVERSED_HI
00400118 0B01 DW 010B ; MagicNumber = PE32
0040011A 02 DB 02 ; MajorLinkerVersion = 2
0040011B 19 DB 19 ; MinorLinkerVersion = 19 (25.)
0040011C 00CC0600 DD 0006CC00 ; SizeOfCode = 6CC00 (445440.)
00400120 00180100 DD 00011800 ; SizeOfInitializedData = 11800 (71680.)
00400124 00000000 DD 00000000 ; SizeOfUninitializedData = 0
00400128 0CDB0600 DD 0006DB0C ; AddressOfEntryPoint = 6DB0C
0040012C 00100000 DD 00001000 ; BaseOfCode = 1000
00400130 00E00600 DD 0006E000 ; BaseOfData = 6E000
00400134 00004000 DD 00400000 ; ImageBase = 400000
00400138 00100000 DD 00001000 ; SectionAlignment = 1000
0040013C 00020000 DD 00000200 ; FileAlignment = 200
00400140 0400 DW 0004 ; MajorOSVersion = 4
00400142 0000 DW 0000 ; MinorOSVersion = 0
00400144 0000 DW 0000 ; MajorImageVersion = 0
00400146 0000 DW 0000 ; MinorImageVersion = 0
00400148 0400 DW 0004 ; MajorSubsystemVersion = 4
0040014A 0000 DW 0000 ; MinorSubsystemVersion = 0
0040014C 00000000 DD 00000000 ; Reserved
00400150 00400800 DD 00084000 ; SizeOfImage = 84000 (540672.)
00400154 00040000 DD 00000400 ; SizeOfHeaders = 400 (1024.)
00400158 00000000 DD 00000000 ; CheckSum = 0
0040015C 0200 DW 0002 ; Subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI
0040015E 0000 DW 0000 ; DLLCharacteristics = 0
00400160 00001000 DD 00100000 ; SizeOfStackReserve = 100000 (1048576.)
00400164 00400000 DD 00004000 ; SizeOfStackCommit = 4000 (16384.)
00400168 00001000 DD 00100000 ; SizeOfHeapReserve = 100000 (1048576.)
0040016C 00100000 DD 00001000 ; SizeOfHeapCommit = 1000 (4096.)
00400170 00000000 DD 00000000 ; LoaderFlags = 0
00400174 10000000 DD 00000010 ; NumberOfRvaAndSizes = 10 (16.)
00400178 00000000 DD 00000000 ; Export Table address = 0
0040017C 00000000 DD 00000000 ; Export Table size = 0
00400180 00100700 DD 00071000 ; Import Table address = 71000
00400184 96200000 DD 00002096 ; Import Table size = 2096 (8342.)
00400188 00E00700 DD 0007E000 ; Resource Table address = 7E000
0040018C 005E0000 DD 00005E00 ; Resource Table size = 5E00 (24064.)
00400190 00000000 DD 00000000 ; Exception Table address = 0
00400194 00000000 DD 00000000 ; Exception Table size = 0
00400198 00000000 DD 00000000 ; Certificate File pointer = 0
0040019C 00000000 DD 00000000 ; Certificate Table size = 0
004001A0 00600700 DD 00076000 ; Relocation Table address = 76000
004001A4 547E0000 DD 00007E54 ; Relocation Table size = 7E54 (32340.)
004001A8 00000000 DD 00000000 ; Debug Data address = 0
004001AC 00000000 DD 00000000 ; Debug Data size = 0
004001B0 00000000 DD 00000000 ; Architecture Data address = 0
004001B4 00000000 DD 00000000 ; Architecture Data size = 0
004001B8 00000000 DD 00000000 ; Global Ptr address = 0
004001BC 00000000 DD 00000000 ; Must be 0
004001C0 00500700 DD 00075000 ; TLS Table address = 75000
004001C4 18000000 DD 00000018 ; TLS Table size = 18 (24.)
004001C8 00000000 DD 00000000 ; Load Config Table address = 0
004001CC 00000000 DD 00000000 ; Load Config Table size = 0
004001D0 00000000 DD 00000000 ; Bound Import Table address = 0
004001D4 00000000 DD 00000000 ; Bound Import Table size = 0
004001D8 00000000 DD 00000000 ; Import Address Table address = 0
004001DC 00000000 DD 00000000 ; Import Address Table size = 0
004001E0 00000000 DD 00000000 ; Delay Import Descriptor address = 0
004001E4 00000000 DD 00000000 ; Delay Import Descriptor size = 0
004001E8 00000000 DD 00000000 ; COM+ Runtime Header address = 0
004001EC 00000000 DD 00000000 ; Import Address Table size = 0
004001F0 00000000 DD 00000000 ; Reserved
004001F4 00000000 DD 00000000 ; Reserved
根据以上内容建立一个PE文件头纪录结构
type PeHead = record
Pesingature: array[0..3] of Char;
Machine: word;
NumberOfSections: word;
TimeDataStamp: dword;
PointerToSymbolTable: dword;
NumberOfSymbols: dword;
SizeOfOptionalHeader: word;
Characteristics: word;
MagicNumber: word;
MajorLinkerVersion: byte;
MinorLinkerVersion: byte;
SizeOfCode: dword;
SizeOfInitializedData: dword;
SizeOfUninitializedData: dword;
AddressOfEntryPointer: dword;
BaseOfCode: dword;
BaseOfData: dword;
ImageBase: dword;
SectionAlignment: dword;
FileAlignment: dword;
MajorOSVersion: word;
MinorOSVersion: word;
MajorImageVersion: word;
MinorImageVersion: word;
MajorSubsystemVersion: word;
MinorSubsystemVersion: word;
Reserved_a: dword;
SizeOfImage: dword;
SizeOfheaders: dword;
CheackSum: dword;
Subsystem: word;
DLLCharacteristics: word;
SizeOfStackReserve: dword;
SizeOfstackCommit: dword;
SizeOfHeapReserve: dword;
SizeOfHeapCommit: dword;
LoaderFlags: dword;
NumberOfRvaAndSizes: dword;
ExportTableAddress: dword;
ExportTableSize: dword;
ImportTableAddress: dword;
ImportTableSize_a: dword;
ResourceTableAddress: dword;
ResourceTableSize: dword;
ExceptionTableAddress: dword;
ExceptionTableSize: dword;
CertificateFilePointer: dword;
CertificateTableSize: dword;
RelocationTableAddress: dword;
RelocationTableSize: dword;
DebugDataAddress: dword;
DebugDataSize: dword;
ArchitectureDataAddress: dword;
ArchitectureDataSize: dword;
GlobalPtrAddress: dword;
MustBe0: dword;
TLSTableAddress: dword;
TLSTableSize: dword;
LoadConfigTableAddress: dword;
LoadConfigTableSize: dword;
BoundImportTableAddress: dword;
BoundImportTableSize: dword;
ImportAddressTableAddress: dword;
ImportAddressTableSize: dword;
DelayImportDescriptorAddress: dword;
DelayImportDescriptorSize: dword;
COMRuntimeHeaderAddress: dword;
ImportAddressTableSize_b: dword;
Reserver_b: dword;
Reserver_c: dword;
end;
在OD中往下拉看到
004001F8 43 4F 44 45>ASCII "CODE" ; SECTION
00400200 7CCB0600 DD 0006CB7C ; VirtualSize = 6CB7C (445308.)
00400204 00100000 DD 00001000 ; VirtualAddress = 1000
00400208 00CC0600 DD 0006CC00 ; SizeOfRawData = 6CC00 (445440.)
0040020C 00040000 DD 00000400 ; PointerToRawData = 400
00400210 00000000 DD 00000000 ; PointerToRelocations = 0
00400214 00000000 DD 00000000 ; PointerToLineNumbers = 0
00400218 0000 DW 0000 ; NumberOfRelocations = 0
0040021A 0000 DW 0000 ; NumberOfLineNumbers = 0
0040021C 20000060 DD 60000020 ; Characteristics = CODE|EXECUTE|READ
根据以上内容建立一个PE区段头纪录结构
type SectionHead = record
SectionName: array[0..7] of Char;
VirtualSize: dword;
VirtualAddress: dword;
SizeOfRawData: dword;
PointerToRawData: dword;
PointerToRelocations: dword;
PointerToLineNumbers: dword;
NumberOfRelocations: word;
NumberOfLineNumbers: word;
Characteristics: dword;
end;
STEP2
程序编写
申明变量
FileDir: string; //目标文件路径
upeheadoffset: dword; //目标文件PE头的偏移位置
loopsection: integer; //用于循环获取PE区段头的变量
tempstrings: Tstrings; //用于显示PE区段头内容的变量
targetfile: TStream; //文件流对象,用来操作对象文件
upehead: PeHead; //PE文件头变量
usectionhead: SectionHead; //PE区段头变量
通过文件流操作,首先从文件偏移$3C处获取文件头偏移放入upeheadoffset中
然后在偏移upeheadoffset处获取文件头放入upehead中
upehead.NumberOfSections即为区段数量
循环获取区段头放入usectionhead并显示出来。
具体实现见代码。
代码下载
http://bbs.itsong.com/PBsPEEDITOR.rar
错误已修正。
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!