清明节回来乘车到学校,没想到竟然做错了公交车。来回竟然多花了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
IMAGE_FILE_MACHINE_I3860x014c  
x86
IMAGE_FILE_MACHINE_IA640x0200
Intel Itanium
IMAGE_FILE_MACHINE_AMD640x8664
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
IMAGE_FILE_RELOCS_STRIPPED   0x0001

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.

IMAGE_FILE_EXECUTABLE_IMAGE0x0002

The file is executable (there are no unresolved

external references).

IMAGE_FILE_LINE_NUMS_STRIPPED0x0004

COFF line numbers were stripped from the

file.

IMAGE_FILE_LOCAL_SYMS_STRIPPED0x0008

COFF symbol table entries were stripped from

file.

IMAGE_FILE_AGGRESIVE_WS_TRIM0x0010

Aggressively trim the working set. This value is

obsolete as of Windows 2000.

IMAGE_FILE_LARGE_ADDRESS_AWARE0x0020

The application can handle addresses larger

than 2 GB.

IMAGE_FILE_BYTES_REVERSED_LO0x0080

The bytes of the word are reversed. This flag

is obsolete.

IMAGE_FILE_32BIT_MACHINE0x0100
The computer supports 32-bit words.
IMAGE_FILE_DEBUG_STRIPPED0x0200

Debugging information was removed and stored

separately in another file.

IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP0x0400

If the image is on removable media, copy it to

and run it from the swap file.

IMAGE_FILE_NET_RUN_FROM_SWAP0x0800

If the image is on the network, copy it to and

run it from the swap file.

IMAGE_FILE_SYSTEM0x1000
The image is a system file.
IMAGE_FILE_DLL0x2000

The image is a DLL file. While it is an executable

file, it cannot be run directly.

IMAGE_FILE_UP_SYSTEM_ONLY0x4000

The file should be run only on a uniprocessor

computer.

IMAGE_FILE_BYTES_REVERSED_HI0x8000

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头相关推荐

  1. PE格式的定义头文件winnt.h

      PE格式定义的主要地方位于我们的头文件winnt.h,这个头文件中几乎能找到关于PE文件的所有定义.   在很多编译器.调试器中都会带有这个头文件,如VC++6.0.codeblocks.Olly ...

  2. PE文件(一)PE头

    PE文件结构(一)PE头 12/100 发布文章 qq_63329753 未选择任何文件 new PE文件结构 PE(Portble Executable File Format,可移植的执行体文件格 ...

  3. 学破解 一 PE格式之MS-DOS MZ header

    from:http://www.2cto.com/Article/201203/123125.html PE的意思就是这个the Protable Executable (PE) file forma ...

  4. PE 格式详解与试验

    PE 格式详解与试验 可执行文件结构分析 DOS头 文件头 可选头 PE RVA 地址与文件地址转换 块表 Section Header 导入表 Data Directory 基址重定位 reloc ...

  5. PE详解 - DOS文件头、PE文件头、节表和表详解

    原文地址:http://www.blogfshare.com/pe-header-one.html PE(Portable Executeable File Format,可移植的执行体文件格式),使 ...

  6. PE格式: 分析IatHook并实现

    Ring 3层的 IAT HOOK 和 EAT HOOK 其原理是通过替换IAT表中函数的原始地址从而实现Hook的,与普通的 InlineHook 不太一样 IAT Hook 需要充分理解PE文件的 ...

  7. PE格式第七讲,重定位表

    PE格式第七讲,重定位表 作者:IBinary 出处:http://www.cnblogs.com/iBinary/ 版权所有,欢迎保留原文链接进行转载:) 一丶何为重定位(注意,不是重定位表格) 首 ...

  8. PE格式详细讲解4 - 系统篇04|解密系列

    PE格式详细讲解4 - 系统篇04 让编程改变世界 Change the world by program   到此为止,小甲鱼和大家已经学了许多关于 DOS header 和 PE header 的 ...

  9. PE格式详细讲解1 - 系统篇01|解密系列

    PE格式详细讲解1 - 系统篇01 让编程改变世界 Change the world by program 由于时间关系,这里只整理出必要的课件内容,详细请下载具体课件和详细讲解视频. [codesy ...

最新文章

  1. “你写的 Bug 让我来改好吗” | 每日趣闻
  2. python需要的数学基础训练答案_新编基础训练数学答案
  3. html无序标签前面的标点后移,为啥在网页里,标点符号跑到行首了呢
  4. python 错误--UnboundLocalError: local variable '**' referenced before assignment
  5. 如何生成WebPart的部署文件(wsp文件)
  6. navicat 添加外键1215错误
  7. 进程在linux系统中原理,Linux系统原理知识 进程切换的概念介绍
  8. OBJECTPROPERTY函数使用
  9. html正常php不正常,不完全的HTML头消息,可能被某些PHP服务器拒绝.
  10. 你知道哪几种MYSQL的连接查询
  11. 学生用计算机指数函数,指数函数计算器
  12. 入侵手游服务器修改数据库,如何入侵手游服务器数据库
  13. Asp.Net Core 系列教程 (一)
  14. 应用程序无法正常启动 0x0000005
  15. P3900 [湖南集训]图样图森破
  16. ZPanel-开源免费的虚拟主机在线管理系统
  17. 支付宝小程序设置服务器维护,支付宝小程序配置
  18. Fedora 17正式版 亮点抢先体验
  19. 怪物猎人ol服务器维护,腾讯宣布怪物猎人OL停运 12月31日正式关服
  20. python打卡以及Linux自动运行python文件

热门文章

  1. 机器学习系列之交叉验证、网格搜索
  2. 鲁迅研究(海南大学)
  3. CC00039.scala——|HadoopScala.V01|——|Scala.v01|特质|作为接口|使用特质|
  4. Centos指令mysql安装报错为“ Failing package is: mysql-community-client-5.7.38-1.el7.x86_64”
  5. Vue的生命周期是什么
  6. android scroller,深入理解Android中Scroller的滚动原理
  7. word编辑中空格变成灰点
  8. 使用ipv6-test.com测试服务器域名是否支持IPV6
  9. 2021云计算技能竞赛真题卷(附标准答案)
  10. 走进音视频的世界——剖析exo播放器架构