PE格式之DOS头+PE头
清明节回来乘车到学校,没想到竟然做错了公交车。来回竟然多花了3个小时。。。。。。车子又挤。真的快无语了。
所以写下代码来泄愤。。。。
首先给大家推广下小甲鱼的网站
http://fishc.com/ 小甲鱼是个大帅锅(。。。。)
这个网站做的很齐全,里面讲汇编,PE,破解等很多好的资源。小甲鱼的视频讲解也是很详细的。自己看完书再看一遍小甲鱼的视频,最后自己再写代码巩固一下,感觉学习效果还是不错的。
好吧,接下来就不说废话了。先发一张图片,这个是比较完整的PE结构。图片有点大貌似不太好看。
然后从小甲鱼那里搞来的DOS头结构和PE头结构的数据结构如下(有中文翻译的)
IMAGE_DOS_HEADER STRUCT
{
+0h WORD e_magic // Magic DOS signature MZ(4Dh 5Ah) DOS可执行文件标记
+2h WORD e_cblp // Bytes on last page of file
+4h WORD e_cp // Pages in file
+6h WORD e_crlc // Relocations
+8h WORD e_cparhdr // Size of header in paragraphs
+0ah WORD e_minalloc // Minimun extra paragraphs needs
+0ch WORD e_maxalloc // Maximun extra paragraphs needs
+0eh WORD e_ss // intial(relative)SS value DOS代码的初始化堆栈SS
+10h WORD e_sp // intial SP value DOS代码的初始化堆栈指针SP
+12h WORD e_csum // Checksum
+14h WORD e_ip // intial IP value DOS代码的初始化指令入口[指针IP]
+16h WORD e_cs // intial(relative)CS value DOS代码的初始堆栈入口
+18h WORD e_lfarlc // File Address of relocation table
+1ah WORD e_ovno // Overlay number
+1ch WORD e_res[4] // Reserved words
+24h WORD e_oemid // OEM identifier(for e_oeminfo)
+26h WORD e_oeminfo // OEM information;e_oemid specific
+29h WORD e_res2[10] // Reserved words
+3ch DWORD e_lfanew // Offset to start of PE header 指向PE文件头
} IMAGE_DOS_HEADER ENDS
首先是IMAGE_NT_HEADERS 结构的定义:(啥?结构不会,先看看小甲鱼童鞋的《零基础入门学习C语言》关于结构方面的章节吧~)
IMAGE_NT_HEADERS STRUCT
{
+0h DWORDSignature
+4h IMAGE_FILE_HEADER FileHeader
+18h IMAGE_OPTIONAL_HEADER32OptionalHeader
} IMAGE_NT_HEADERS ENDS
Signature 字段:
在一个有效的 PE 文件里,Signature 字段被设置为00004550h, ASCII 码字符是“PE00”。标志这 PE 文件头的开始。
“PE00” 字符串是 PE 文件头的开始,DOS 头部的 e_lfanew 字段正是指向这里。
如下图所示:
IMAGE_FILE_HEADER 结构
typedef struct _IMAGE_FILE_HEADER
{
+04h WORD Machine; // 运行平台
+06h WORD NumberOfSections; // 文件的区块数目
+08h DWORD TimeDateStamp; // 文件创建日期和时间
+0Ch DWORD PointerToSymbolTable; // 指向符号表(主要用于调试)
+10h DWORD NumberOfSymbols; // 符号表中符号个数(同上)
+14h WORD SizeOfOptionalHeader; // IMAGE_OPTIONAL_HEADER32 结构大小
+16h WORD Characteristics; // 文件属性
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
该结构如下图所示:
下边,小甲鱼童鞋为大家详细解释各个成员的含义和用法:
(1)Machine:可执行文件的目标CPU类型。
Value | Meaning |
---|---|
|
x86 |
|
Intel Itanium |
|
x64 |
(2)NumberOfSection: 区块的数目。(注:区块表是紧跟在 IMAGE_NT_HEADERS 后边的)
(3)TimeDataStamp: 表明文件是何时被创建的。
这个值是自1970年1月1日以来用格林威治时间(GMT) 计算的秒数,这个值是比文件系统(FILESYSTEM)的日期时间更加精确的指示器。如何将这个值翻译请 看:http://home.fishc.com/space.php?uid=9&do=blog&id=555
提示:VC的话可以用_ctime 函数或者 gmtime 函数。
(4)PointerToSymbolTable: COFF 符号表的文件偏移位置,现在基本没用了。
(5)NumberOfSymbols: 如果有COFF 符号表,它代表其中的符号数目,COFF符号是一个大小固定的结构,如果想找到COFF 符号表的结束位置,则需要这个变量。
(6)SizeOfOptionalHeader: 紧跟着IMAGE_FILE_HEADER 后边的数据结构(IMAGE_OPTIONAL_HEADER)的大小。(对于32位PE文件,这个值通常是00E0h;对于64位PE32+文件,这个值是00F0h )。
(7)Characteristics: 文件属性,有选择的通过几个值可以运算得到。( 这些标志的有效值是定义于 winnt.h 内的 IMAGE_FILE_** 的值,具体含义见下表。普通的EXE文件这个字段的值一般是 0100h,DLL文件这个字段的值一般是 210Eh。)小甲鱼温馨提示:多种属性可以通过 “或运算” 使得同时拥有!
The characteristics of the image. This member can be one or more of the following values.
Value | Meaning |
---|---|
|
Relocation information was stripped from the file. The file must be loaded at its preferred base address. If the base address is not available, the loader reports an error. |
|
The file is executable (there are no unresolved external references). |
|
COFF line numbers were stripped from the file. |
|
COFF symbol table entries were stripped from file. |
|
Aggressively trim the working set. This value is obsolete as of Windows 2000. |
|
The application can handle addresses larger than 2 GB. |
|
The bytes of the word are reversed. This flag is obsolete. |
|
The computer supports 32-bit words. |
|
Debugging information was removed and stored separately in another file. |
|
If the image is on removable media, copy it to and run it from the swap file. |
|
If the image is on the network, copy it to and run it from the swap file. |
|
The image is a system file. |
|
The image is a DLL file. While it is an executable file, it cannot be run directly. |
|
The file should be run only on a uniprocessor computer. |
|
The bytes of the word are reversed. This flag is obsolete. |
最后是自己写的读取dos头和pe头的代码(参考了醒哥的博客www.kkmonster.com)
#include <stdio.h>
#include <windows.h>
#include <tchar.h>const TCHAR* FileName = "c:\\windows\\system32\\cmd.exe";
//文件目录
BYTE* pBase = NULL;
//基地址
BYTE* fnReadFile();
//读取文件
int fnReadPE (BYTE *pBuffer);
//读取PE文件信息
BYTE* fnReadDosHeader(BYTE* pBuffer);
//读取dos文件头信息
int fnReadNTHeader(BYTE* pBuffer);
//读取 PE文件头信息
int fnReadFileHeader(BYTE* ImageFileHeader);
//读取PE文件头中的FileHeader结构的信息
int fnReadOptionalHeader(BYTE* ImageOptionalHeader);
//读取PE文件头中的OptionalHeader结构的信息
int main()
{
BYTE* pBuffer = fnReadFile();fnReadPE (pBuffer);return 0;
}
BYTE* fnReadFile()
{
printf("映射文件...\n");
HANDLE hFile = CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
//读取文件
if (hFile == INVALID_HANDLE_VALUE)
{
printf("打开文件出错\n");
return 0;
}
DWORD dwFileSize = GetFileSize(hFile, NULL);
//获得文件大小
BYTE* pBuffer = new BYTE[dwFileSize];
//new相当于malloc
DWORD dwSizeOfRead;if(!ReadFile(hFile, pBuffer, dwFileSize, &dwSizeOfRead, NULL))
{
printf("读取文件出错\n");
pBase = NULL;
return 0;
}
pBase = pBuffer;
return pBase;
//基地址
}int fnReadPE(BYTE *pBuffer)
{
printf("读取PE信息...\n");
BYTE* pBaseNTHeader = fnReadDosHeader(pBuffer);
//调用fnReadDosHeader函数获取Dos头信息,并且获得PE文件头的基地址
if (!pBaseNTHeader)
{
return 1;
}if (!fnReadNTHeader(pBaseNTHeader))
//读取PE文件头信息
{
return 1;
}
return 0;
}BYTE* fnReadDosHeader(BYTE* pBuffer)
//读取dos文件头信息
{
printf("读取DOS文件头...\n");
PIMAGE_DOS_HEADER SrcImageDosHeader = (PIMAGE_DOS_HEADER)pBuffer;
if (SrcImageDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
{
return 0;
}
else
{
printf("IMAGE_DOS_HEADER结构\n");
printf("e_magic :%04x DOS可执行文件标记\n",SrcImageDosHeader->e_magic);
printf("e_cblp :%04x Bytes on last page of file\n",SrcImageDosHeader->e_cblp);
printf("e_cp :%04x Page in file\n", SrcImageDosHeader->e_cp);
printf("e_crlc :%04x Relocations\n", SrcImageDosHeader->e_crlc);
printf("e_cparhdr :%04x Size of header in paragraphs\n", SrcImageDosHeader->e_cparhdr);
printf("e_minalloc:%04x Minimum extra paragraphs needed\n", SrcImageDosHeader->e_minalloc);
printf("e_maxalloc:%04x Maximum extra paragraphs needed\n", SrcImageDosHeader->e_maxalloc);
printf("e_ss :%04x Initial (relative) SS value DOS代码的初始化堆栈SS\n", SrcImageDosHeader->e_ss);
printf("e_sp :%04x Initial SP value DOS代码的初始化堆栈指针SP\n", SrcImageDosHeader->e_sp);
printf("e_csum :%04x Checksum\n", SrcImageDosHeader->e_csum);
printf("e_ip :%04x Initial IP value DOS代码的初始化指针入口\n", SrcImageDosHeader->e_ip);
printf("e_cs :%04x Initial (relative) CS value DOS代码的初始堆栈入口\n", SrcImageDosHeader->e_cs);
printf("e_lfarlc :%04x File address of elocation table\n", SrcImageDosHeader->e_lfarlc);
printf("e_ovno :%04x Overlay number\n", SrcImageDosHeader->e_ovno);
printf("e_res[4] :%04x, %04x, %04x, %04x Reserved words\n", SrcImageDosHeader->e_res[0],SrcImageDosHeader->e_res[1],SrcImageDosHeader->e_res[2],SrcImageDosHeader->e_res[3]);
printf("e_oemid :%04x OEM identifier (for e_oeminfo)\n", SrcImageDosHeader->e_oemid);
printf("e_oeminfo :%04x OEM information; e_oemid specific\n", SrcImageDosHeader->e_oeminfo);
printf("e_res2[10]:%04x,%04x,%04x,%04x,%04x,%04x,%04x,%04x,%04x,%04x, Reserved words\n", SrcImageDosHeader->e_res2[0],SrcImageDosHeader->e_res2[1],SrcImageDosHeader->e_res2[2],SrcImageDosHeader->e_res2[3],SrcImageDosHeader->e_res2[4],SrcImageDosHeader->e_res2[5],SrcImageDosHeader->e_res2[6],SrcImageDosHeader->e_res2[7],SrcImageDosHeader->e_res2[8],SrcImageDosHeader->e_res2[9]);
printf("e_lfanew :%04x File address of new exe header 指向PE文件头\n", SrcImageDosHeader->e_lfanew);
}
return (BYTE*) (pBuffer + SrcImageDosHeader->e_lfanew);
}int fnReadNTHeader(BYTE* pBaseNTBuffer)
{
printf("读取PE文件头...\n");
PIMAGE_NT_HEADERS SrcImageNTHeader = (PIMAGE_NT_HEADERS)(pBaseNTBuffer);
if (SrcImageNTHeader->Signature != IMAGE_NT_SIGNATURE)
{
return 1;
}
else
{
printf("IMAGE_NT_HEADERS结构\n");
printf("Signature :%08x\n", SrcImageNTHeader->Signature);
fnReadFileHeader((BYTE*)&SrcImageNTHeader->FileHeader);
//读取FileHeader结构的信息
fnReadOptionalHeader((BYTE*) &SrcImageNTHeader->OptionalHeader);
//读取OptionalHeader结构的信息}
return 0;
}int fnReadFileHeader(BYTE* ImageFileHeader)
{
PIMAGE_FILE_HEADER SrcImageFileHeader = (PIMAGE_FILE_HEADER)ImageFileHeader;
printf("IMAGE_NT_HEADERS结构\n");
printf("Machine: %04x\n", SrcImageFileHeader->Machine);
printf("NumberOfSections: %04x\n", SrcImageFileHeader->NumberOfSections);
printf("TimeDateStamp: %08x\n", SrcImageFileHeader->TimeDateStamp);
printf("PointerToSymbolTable: %08x\n", SrcImageFileHeader->PointerToSymbolTable);
printf("NumberOfSymbols: %08x\n", SrcImageFileHeader->NumberOfSymbols);
printf("SizeOfOptionalHeader: %04x\n", SrcImageFileHeader->SizeOfOptionalHeader);
printf("Characteristics: %04x\n", SrcImageFileHeader->Characteristics);return 0;
}int fnReadOptionalHeader(BYTE* ImageOptionalHeader)
{
PIMAGE_OPTIONAL_HEADER SrcImageOptional_Header = (PIMAGE_OPTIONAL_HEADER)ImageOptionalHeader;
printf("IMAGE_OPTIONAL_HEADER结构\n");// Standard fields.
printf("Magic: %04x\n", SrcImageOptional_Header->Magic);
printf("MajorLinkerVersion: %02x\n", SrcImageOptional_Header->MajorLinkerVersion);
printf("MinorLinkerVersion: %02x\n", SrcImageOptional_Header->MinorLinkerVersion);
printf("SizeOfCode: %08x\n", SrcImageOptional_Header->SizeOfCode);
printf("SizeOfInitializedData: %08x\n", SrcImageOptional_Header->SizeOfInitializedData);
printf("SizeOfUninitializedData: %08x\n", SrcImageOptional_Header->SizeOfUninitializedData);
printf("AddressOfEntryPoint: %08x\n", SrcImageOptional_Header->AddressOfEntryPoint);
printf("BaseOfCode: %08x\n", SrcImageOptional_Header->BaseOfCode);
printf("BaseOfData: %08x\n", SrcImageOptional_Header->BaseOfData);// NT additional fields.
printf("ImageBase: %08x\n", SrcImageOptional_Header->ImageBase);
printf("SectionAlignment: %08x\n", SrcImageOptional_Header->SectionAlignment);
printf("FileAlignmen: %08x\n", SrcImageOptional_Header->FileAlignment);
printf("MajorOperatingSystemVersion:%04x\n", SrcImageOptional_Header->MajorOperatingSystemVersion);
printf("MinorOperatingSystemVersion:%04x\n", SrcImageOptional_Header->MinorOperatingSystemVersion);
printf("MajorImageVersion; %04x\n", SrcImageOptional_Header->MajorImageVersion);
printf("MinorImageVersion: %04x\n", SrcImageOptional_Header->MinorImageVersion);
printf("MajorSubsystemVersion: %04x\n", SrcImageOptional_Header->MajorSubsystemVersion);
printf("MinorSubsystemVersion: %04x\n", SrcImageOptional_Header->MinorSubsystemVersion);
printf("Win32VersionValue: %08x\n", SrcImageOptional_Header->Win32VersionValue);
printf("SizeOfImage: %08x\n", SrcImageOptional_Header->SizeOfImage);
printf("SizeOfHeaders: %08x\n", SrcImageOptional_Header->SizeOfHeaders);
printf("CheckSum: %08x\n", SrcImageOptional_Header->CheckSum);
printf("Subsystem: %04x\n", SrcImageOptional_Header->Subsystem);
printf("DllCharacteristics: %04x\n", SrcImageOptional_Header->DllCharacteristics);
printf("SizeOfStackReserve: %08x\n", SrcImageOptional_Header->SizeOfStackReserve);
printf("SizeOfStackCommit: %08x\n", SrcImageOptional_Header->SizeOfStackCommit);
printf("SizeOfHeapReserve: %08x\n", SrcImageOptional_Header->SizeOfHeapCommit);
printf("SizeOfHeapCommit: %08x\n", SrcImageOptional_Header->SizeOfHeapCommit);
printf("LoaderFlags: %08x\n", SrcImageOptional_Header->LoaderFlags);
printf("NumberOfRvaAndSizes: %08x\n", SrcImageOptional_Header->NumberOfRvaAndSizes);
//IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
return 0;
}
这只是初步,代码还有待完善。。。。
PE格式之DOS头+PE头相关推荐
- PE格式的定义头文件winnt.h
PE格式定义的主要地方位于我们的头文件winnt.h,这个头文件中几乎能找到关于PE文件的所有定义. 在很多编译器.调试器中都会带有这个头文件,如VC++6.0.codeblocks.Olly ...
- PE文件(一)PE头
PE文件结构(一)PE头 12/100 发布文章 qq_63329753 未选择任何文件 new PE文件结构 PE(Portble Executable File Format,可移植的执行体文件格 ...
- 学破解 一 PE格式之MS-DOS MZ header
from:http://www.2cto.com/Article/201203/123125.html PE的意思就是这个the Protable Executable (PE) file forma ...
- PE 格式详解与试验
PE 格式详解与试验 可执行文件结构分析 DOS头 文件头 可选头 PE RVA 地址与文件地址转换 块表 Section Header 导入表 Data Directory 基址重定位 reloc ...
- PE详解 - DOS文件头、PE文件头、节表和表详解
原文地址:http://www.blogfshare.com/pe-header-one.html PE(Portable Executeable File Format,可移植的执行体文件格式),使 ...
- PE格式: 分析IatHook并实现
Ring 3层的 IAT HOOK 和 EAT HOOK 其原理是通过替换IAT表中函数的原始地址从而实现Hook的,与普通的 InlineHook 不太一样 IAT Hook 需要充分理解PE文件的 ...
- PE格式第七讲,重定位表
PE格式第七讲,重定位表 作者:IBinary 出处:http://www.cnblogs.com/iBinary/ 版权所有,欢迎保留原文链接进行转载:) 一丶何为重定位(注意,不是重定位表格) 首 ...
- PE格式详细讲解4 - 系统篇04|解密系列
PE格式详细讲解4 - 系统篇04 让编程改变世界 Change the world by program 到此为止,小甲鱼和大家已经学了许多关于 DOS header 和 PE header 的 ...
- PE格式详细讲解1 - 系统篇01|解密系列
PE格式详细讲解1 - 系统篇01 让编程改变世界 Change the world by program 由于时间关系,这里只整理出必要的课件内容,详细请下载具体课件和详细讲解视频. [codesy ...
最新文章
- “你写的 Bug 让我来改好吗” | 每日趣闻
- python需要的数学基础训练答案_新编基础训练数学答案
- html无序标签前面的标点后移,为啥在网页里,标点符号跑到行首了呢
- python 错误--UnboundLocalError: local variable '**' referenced before assignment
- 如何生成WebPart的部署文件(wsp文件)
- navicat 添加外键1215错误
- 进程在linux系统中原理,Linux系统原理知识 进程切换的概念介绍
- OBJECTPROPERTY函数使用
- html正常php不正常,不完全的HTML头消息,可能被某些PHP服务器拒绝.
- 你知道哪几种MYSQL的连接查询
- 学生用计算机指数函数,指数函数计算器
- 入侵手游服务器修改数据库,如何入侵手游服务器数据库
- Asp.Net Core 系列教程 (一)
- 应用程序无法正常启动 0x0000005
- P3900 [湖南集训]图样图森破
- ZPanel-开源免费的虚拟主机在线管理系统
- 支付宝小程序设置服务器维护,支付宝小程序配置
- Fedora 17正式版 亮点抢先体验
- 怪物猎人ol服务器维护,腾讯宣布怪物猎人OL停运 12月31日正式关服
- python打卡以及Linux自动运行python文件
热门文章
- 机器学习系列之交叉验证、网格搜索
- 鲁迅研究(海南大学)
- CC00039.scala——|HadoopScala.V01|——|Scala.v01|特质|作为接口|使用特质|
- Centos指令mysql安装报错为“ Failing package is: mysql-community-client-5.7.38-1.el7.x86_64”
- Vue的生命周期是什么
- android scroller,深入理解Android中Scroller的滚动原理
- word编辑中空格变成灰点
- 使用ipv6-test.com测试服务器域名是否支持IPV6
- 2021云计算技能竞赛真题卷(附标准答案)
- 走进音视频的世界——剖析exo播放器架构