本想跟在那个贴后面的,也许,我想没人会理了。就新开了一个贴!如果有什么不当的地方,就别在意了。。。。。。。。
正好我也在研究PE结构,我把我的看发贴出来,顺便请把你的问题再解释的清楚点。
我专门找了点专业点的:
typedef struct _IMAGE_FILE_HEADER {
WORD Machine;
WORD NumberOfSections;
DWORD TimeDateStamp;
DWORD PointerToSymbolTable;
DWORD NumberOfSymbols;
WORD SizeOfOptionalHeader;
WORD Characteristics;
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
这个结构就是MS的定义,它的意思是文件头,MS在NT头是分了三部分的。
下面是属性头,根据MS的结构来看我们知道的不很清楚了,我想kmyc朋友是NumberOfRvaAndSizes
对这个的怀疑??我记得,从我研究PE结构开始它的值好象一直为0x10字节。如果这个可再大点,我就不知道了,再小点我想是不可能的了。看我后面的解释!
typedef struct _IMAGE_OPTIONAL_HEADER {
//
// Standard fields.
//
WORD Magic;
BYTE MajorLinkerVersion;
BYTE MinorLinkerVersion;
DWORD SizeOfCode;
DWORD SizeOfInitializedData;
DWORD SizeOfUninitializedData;
DWORD AddressOfEntryPoint;
DWORD BaseOfCode;
DWORD BaseOfData;
//
// NT additional fields.
//
DWORD ImageBase;
DWORD SectionAlignment;
DWORD FileAlignment;
WORD MajorOperatingSystemVersion;
WORD MinorOperatingSystemVersion;
WORD MajorImageVersion;
WORD MinorImageVersion;
WORD MajorSubsystemVersion;
WORD MinorSubsystemVersion;
DWORD Win32VersionValue;
DWORD SizeOfImage;
DWORD SizeOfHeaders;
DWORD CheckSum;
WORD Subsystem;
WORD DllCharacteristics;
DWORD SizeOfStackReserve;
DWORD SizeOfStackCommit;
DWORD SizeOfHeapReserve;
DWORD SizeOfHeapCommit;
DWORD LoaderFlags;
DWORD NumberOfRvaAndSizes;
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
根据MS的结构定义很难看出来PE头和文件的联系:
//-----------------------------------------------------------------------------------------
//下面是我自己写的PE头结构,我就不明白了,我这个结构是F8字节,后面紧跟的就是区段列表了.
//实际我以前的读PE头很简单,三次ReadFile就能搞定了,我知道的PE结构内部里,这些项目都是基本具备的
//如果真要说那个一项没有也可以,我就郁闷了,也许我学的还不好要继续修行了.
//也许楼主说的不明白我也看了好几遍没能觉得楼主说的是什么???
//我们可以肯定的是,NT头大小是F8字节,如果有朋友想知道为什么?那就可以算,DWORD是4字节,WORD是2字节,BYTE是1个字节
//而我也可以肯定的说,从_38NumberOfRvaAndSizes这个之后确实是0x80字节.至少,我的程序都是这样的,感觉MS的结构不清楚,
//所以,自己写了个.但是我这样写也没出什么错误.
struct _DLLHEADINFO_PESIG{
DWORD _01PESignature; // (PE)50450000
WORD _02Machine ; //= IMAGE_FILE_MACHINE_I386
WORD _03NumberOfSections; // = 5
DWORD _04TimeDateStamp ; // = 46AD3FF8
DWORD _05PointerToSymbolTable; // = 0
DWORD _06NumberOfSymbols ; //= 0
WORD _07SizeOfOptionalHeader; // = E0 (224.)
WORD _08Characteristics ; //=
DLL|EXECUTABLE_IMAGE|32BIT_MACHINE|LINE_NUMS_STRIPPED|LOCAL_SYMS_STRIPPED
WORD _09MagicNumber ; //= PE32
BYTE _10MajorLinkerVersion; //= 6
BYTE _11MinorLinkerVersion; // = 0
DWORD _12SizeOfCode ; // = D000 (53248.)
DWORD _13SizeOfInitializedData ; //= D000 (53248.)
DWORD _14SizeOfUninitializedData; // = 0
DWORD _15AddressOfEntryPoint ; //= 54C1
DWORD _16BaseOfCode ; //= 1000
DWORD _17BaseOfData ; //= E000
DWORD _18ImageBase ; //= 10000000
DWORD _19SectionAlignment; // = 1000
DWORD _20FileAlignment ; //= 1000
WORD _21MajorOSVersion ; //= 4
WORD _22MinorOSVersion ; //= 0
WORD _23MajorImageVersion; // = 0
WORD _24MinorImageVersion; // = 0
WORD _25MajorSubsystemVersion; // = 4
WORD _26MinorSubsystemVersion; // = 0
DWORD _27Reserved ;
DWORD _28SizeOfImage ; //= 1B000 (110592.)
DWORD _29SizeOfHeaders ; //= 1000 (4096.)
DWORD _30CheckSum ; // = 0
WORD _31Subsystem ; //= IMAGE_SUBSYSTEM_WINDOWS_GUI
WORD _32DLLCharacteristics; // = 0
DWORD _33SizeOfStackReserve; //= 100000 (1048576.)
DWORD _34SizeOfStackCommit ; //= 1000 (4096.)
DWORD _35SizeOfHeapReserve ; //= 100000 (1048576.)
DWORD _36SizeOfHeapCommit ; //= 1000 (4096.)
DWORD _37LoaderFlags ; //= 0
DWORD _38NumberOfRvaAndSizes; // = 10 (16.)
DWORD _39ExportTableAddress ; //= F800
DWORD _40ExportTableSize ; //= 67 (103.)
DWORD _41ImportTableAddress ; //= EC38
DWORD _42ImportTableSize ; //= 8C (140.)
DWORD _43ResourceTableAddress; // = 16000
DWORD _44ResourceTableSize ; // = 21E8 (8680.)
DWORD _45ExceptionTableAddress; // = 0
DWORD _46ExceptionTableSize ; //= 0
DWORD _47CertificateFilePointer; // = 0
DWORD _48CertificateTableSize ; // = 0
DWORD _49RelocationTableAddress; // = 19000
DWORD _50RelocationTableSize ; //= B54 (2900.)
DWORD _51DebugDataAddress ; //= 0
DWORD _52DebugDataSize ; //= 0
DWORD _53ArchitectureDataAddress; // = 0
DWORD _54ArchitectureDataSize ; //= 0
DWORD _55GlobalPtrAddress ; //= 0
DWORD _56Mustbe ; //0
DWORD _57TLSTableAddress ; // = 0
DWORD _58TLSTableSize ; //= 0
DWORD _59LoadConfigTableAddress ; //= 0
DWORD _60LoadConfigTableSize ; //= 0
DWORD _61BoundImportTableAddress; // = 0
DWORD _62BoundImportTableSize ; // = 0
DWORD _63ImportAddressTableAddress ; //= E000
DWORD _64ImportAddressTableSize ; //= 230 (560.)
DWORD _65DelayImportDescriptorAddress ; //= 0
DWORD _66DelayImportDescriptorSize ; // = 0
DWORD _67COMRuntimeHeaderAddress ; // = 0
DWORD _68ImportAddressTableSize ; //= 0
DWORD _69Reserved ;
DWORD _70Reserved ;
};
//---------------------------下面是我自己的读PE头的代码------------------
//DOS结构:
BYTE dsbuf[0x1000]={0}; //初始化一个字节数组存放PE头
m_pnFiles.ReadFiles(0x00,dsbuf,sizeof(_DLLHEADINFO_DOSSIG)); //读DOS头部分
memset(&_hiDosSig,0,sizeof(_DLLHEADINFO_DOSSIG)); //原结构清空
memcpy(&_hiDosSig,dsbuf,sizeof(_DLLHEADINFO_DOSSIG)); //将内容初始化结构
for(int m=0,n=0;m<n_dsSig;m++,n=n+0x02)
{
_addrHeadInfo._01AddrDOSSIG[m]=n;
_addrHeadInfo._01sAddrDOSSIG[m].Format("0x%08X",n);
}
//PE 偏移量:
memset(dsbuf,0,0x1000); //数组清空
memset(&_hiOffsetSig,0,sizeof(_DLLHEADINFO_OFFSETSIG));
m_pnFiles.ReadFiles(sizeof(_DLLHEADINFO_DOSSIG),dsbuf,sizeof(_DLLHEADINFO_OFFSETSIG)); //从DOS头大小的地方开始读
memcpy(&_hiOffsetSig,dsbuf,sizeof(_DLLHEADINFO_OFFSETSIG)); //初始化结构
for(int m=0,n=sizeof(_DLLHEADINFO_DOSSIG);m<n_OffsetSig;m++,n=n+0x04)
{
_addrHeadInfo._02AddrOFFSETSIG[m]=n;
_addrHeadInfo._02sAddrOFFSESIG[m].Format("0x%08X",n);
}
//PE 结构:
memset(dsbuf,0,0x1000); //数组清空
memset(&_hiPESig,0,sizeof(_DLLHEADINFO_PESIG)); //结构清空
m_pnFiles.ReadFiles(_hiOffsetSig._8OffsetSignature,dsbuf,sizeof(_DLLHEADINFO_PESIG)); //从偏移量指定的地方读NT头
memcpy(&_hiPESig,dsbuf,sizeof(_DLLHEADINFO_PESIG));
//上面这里读的就是我前面贴出来的哪个结构.
//区段信息:
DWORD seek=_hiOffsetSig._8OffsetSignature+sizeof(_DLLHEADINFO_PESIG); //计算区段位置=偏移量+NT结构头长度(我自己的结构,MS那个不行!),
for(int i=0;i<_hiPESig._03NumberOfSections;i++)
{
memset(dsbuf,0,0x1000);
memset(&_hiSection[i],0,sizeof(_DLLHEADINFO_SECTIONS));
m_pnFiles.ReadFiles(seek,dsbuf,sizeof(_DLLHEADINFO_SECTIONS));
memcpy(&_hiSection[i],dsbuf,sizeof(_DLLHEADINFO_SECTIONS));
seek=seek+sizeof(_DLLHEADINFO_SECTIONS); //当前位置加区段头长度,为下个区段头位置;
}
//看到上面的代码我真的觉得PE头是个死格式,但是,Kmyc朋友说的78和80是什么问题,能不能解释的清楚点!
//实在是搞不懂,到底你说的那有问题!!!!!!!!!!!!!
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)