环境工具:
Windows 10

010Editor

目标程序功能:

调用MessageBoxA弹出消息框。

1.构造DOS头

typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header

WORD e_magic; // Magic number

WORD e_cblp; // Bytes on last page of file

WORD e_cp; // Pages in file

WORD e_crlc; // Relocations

WORD e_cparhdr; // Size of header in paragraphs

WORD e_minalloc; // Minimum extra paragraphs needed

WORD e_maxalloc; // Maximum extra paragraphs needed

WORD e_ss; // Initial (relative) SS value

WORD e_sp; // Initial SP value

WORD e_csum; // Checksum

WORD e_ip; // Initial IP value

WORD e_cs; // Initial (relative) CS value

WORD e_lfarlc; // File address of relocation table

WORD e_ovno; // Overlay number

WORD e_res[4]; // Reserved words

WORD e_oemid; // OEM identifier (for e_oeminfo)

WORD e_oeminfo; // OEM information; e_oemid specific

WORD e_res2[10]; // Reserved words

LONG e_lfanew; // File address of new exe header

} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;

关键字段:
WORD e_magic;    MZ 4D 5A (标识符)
LONG e_lfanew;   40h 40 00 00 00(DosStub去除后,IMAGE_DOS_HEADER 的结构体大小就是Dos头大小)

4D 5A 00 00 00 00 00 00 00 00 00 00 00 00 00 00

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00

2.构造NT头

typedef struct _IMAGE_NT_HEADERS64 {

DWORD Signature;

IMAGE_FILE_HEADER FileHeader;

IMAGE_OPTIONAL_HEADER64 OptionalHeader;

} IMAGE_NT_HEADERS64, *PIMAGE_NT_HEADERS64;

typedef struct _IMAGE_NT_HEADERS {

DWORD Signature; //标示符(PE)

IMAGE_FILE_HEADER FileHeader; //文件头结构体

IMAGE_OPTIONAL_HEADER32 OptionalHeader; //可选映像头结构体

} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;

关键字段:
DWORD Signature;   50 45 00 00 (标识符)

IMAGE_FILE_HEADER FileHeader;

typedef struct _IMAGE_FILE_HEADER {

WORD Machine;    //运行平台

WORD NumberOfSections; //文件区块数量

DWORD TimeDateStamp; //文件创建日期和时间

DWORD PointerToSymbolTable; //指向符号表(主要用于调试)

DWORD NumberOfSymbols; //符号表中符号个数

WORD SizeOfOptionalHeader; //IMAGE_OPTIONAL_HEADER32结构大小

WORD Characteristics;   //文件属性

} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;

关键字段
2.1 WORD Machine;          4c 01 (0x014c x86)
2.2 WORD NumberOfSections;     02 00 (1.text 2.rdata)
2.3 WORD SizeOfOptionalHeader;    E0 00 (NT扩展头大小)
2.4 WORD Characteristics;       0F 01 (可以自定义)

IMAGE_OPTIONAL_HEADER32 OptionalHeader; // 可选映像头结构体

typedef struct _IMAGE_OPTIONAL_HEADER

{

//

// Standard fields.

//

+18h WORD Magic; // 标志字, ROM 映像(0107h),普通可执行文件(010Bh)

+1Ah BYTE MajorLinkerVersion; // 链接程序的主版本号

+1Bh BYTE MinorLinkerVersion; // 链接程序的次版本号

+1Ch DWORD SizeOfCode; // 所有含代码的节的总大小

+20h DWORD SizeOfInitializedData; // 所有含已初始化数据的节的总大小

+24h DWORD SizeOfUninitializedData; // 所有含未初始化数据的节的大小

+28h DWORD AddressOfEntryPoint; //-----> 程序执行入口RVA(OEP)

+2Ch DWORD BaseOfCode; // 代码的区块的起始RVA

+30h DWORD BaseOfData; // 数据的区块的起始RVA

//

// NT additional fields. 以下是属于NT结构增加的领域。

//

+34h DWORD ImageBase; // ---------->程序的首选装载地址(基地址)

+38h DWORD SectionAlignment; // 内存中的区块的对齐大小

+3Ch DWORD FileAlignment; // 文件中的区块的对齐大小

+40h WORD MajorOperatingSystemVersion; // 要求操作系统最低版本号的主版本号

+42h WORD MinorOperatingSystemVersion; // 要求操作系统最低版本号的副版本号

+44h WORD MajorImageVersion; // 可运行于操作系统的主版本号

+46h WORD MinorImageVersion; // 可运行于操作系统的次版本号

+48h WORD MajorSubsystemVersion; // 要求最低子系统版本的主版本号

+4Ah WORD MinorSubsystemVersion; // 要求最低子系统版本的次版本号

+4Ch DWORD Win32VersionValue; // 莫须有字段,不被病毒利用的话一般为0

+50h DWORD SizeOfImage; // 映像装入内存后的总尺寸

+54h DWORD SizeOfHeaders; // 所有头 + 区块表的尺寸大小

+58h DWORD CheckSum; // 映像的校检和

+5Ch WORD Subsystem; // 可执行文件期望的子系统

+5Eh WORD DllCharacteristics; // DllMain()函数何时被调用,默认为 0

+60h DWORD SizeOfStackReserve; // 初始化时的栈大小

+64h DWORD SizeOfStackCommit; // 初始化时实际提交的栈大小

+68h DWORD SizeOfHeapReserve; // 初始化时保留的堆大小

+6Ch DWORD SizeOfHeapCommit; // 初始化时实际提交的堆大小

+70h DWORD LoaderFlags; // 与调试有关,默认为 0

+74h DWORD NumberOfRvaAndSizes; // 下边数据目录的项数,这个字段自Windows NT 发布以来 // 一直是16

+78h IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];

//-----> 数据目录表

} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;

关键字段(可选映像头)

关键字段
WORD Magic;            0B 01 (文件类型:PE32文件)
DWORD AddressOfEntryPoint;     00 10 00 00(.text在文件中200h位置,转内存偏移后为1000h)
DWORD ImageBase;         00 00 04 00 (PE文件在内存的优先加载起始地址VA)
DWORD SectionAlignment;        00 10 00 00 (内存对齐)
DWORD FileAlignment;          00 02 00 00 (文件对齐)
WORD MajorOperatingSystemVersion;    06 00
WORD MajorSubsystemVersion;       06 00
DWORD SizeOfImage;           7E 20 00 00 (加载到内存中镜像大小)
DWORD SizeOfHeaders;          00 02 00 00 (Dos+NT+Section :在文件中未超过200h)
WORD Subsystem;            03 00 (使用界面的子系统:(CUI) subsystem)
WORD DllCharacteristics;          00 81 (DLL文件属性)
DWORD NumberOfRvaAndSizes;      10 00 (表示数据目录结构的数量.默认16个)
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
typedef struct _IMAGE_DATA_DIRECTORY {
DWORD VirtualAddress;

DWORD Size;

} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress

// 2000h+10h(IAT字节数) =>10 20 00 00

IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size

// 2个Dll,即两个导入表结构体(20个00结尾)=>3C 00 00 00

( #define IMAGE_DIRECTORY_ENTRY_IMPORT 1 // Import Directory )

50 45 00 00 4C 01 02 00 00 00 00 00 00 00 00 00

00 00 00 00 E0 00 0F 01 0B 01 00 00 00 00 00 00

00 00 00 00 00 00 00 00 00 10 00 00 00 00 00 00

00 00 00 00 00 00 40 00 00 10 00 00 00 02 00 00

06 00 00 00 00 00 00 00 06 00 00 00 00 00 00 00

7E 20 00 00 00 02 00 00 00 00 00 00 03 00 00 81

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

00 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00

10 20 00 00 3C 00 00 00 00 00 00 00 00 00 00 00

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

00 00 00 00 00 00 00 00

3.构造区段头

typedef struct _IMAGE_SECTION_HEADER {

BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; // 节表名称,如“.text”

union {

DWORD PhysicalAddress; // 物理地址

DWORD VirtualSize; // 真实长度,这两个值是一个联合结构,可以使用其中的任何一个,一般是取后一个

} Misc;

DWORD VirtualAddress; // 节区的 RVA 地址

DWORD SizeOfRawData; // 在文件中对齐后的尺寸

DWORD PointerToRawData; // 在文件中的偏移量

DWORD PointerToRelocations; // 在OBJ文件中使用,重定位的偏移

DWORD PointerToLinenumbers; // 行号表的偏移(供调试使用地)

WORD NumberOfRelocations; // 在OBJ文件中使用,重定位项数目

WORD NumberOfLinenumbers; // 行号表中行号的数目

DWORD Characteristics; // 节属性如可读,可写,可执行等

} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;

关键字段
1.text
BYTE Name[IMAGE_SIZEOF_SHORT_NAME];   2E 74 65 78 74 00 00 00(区段名称)
DWORD VirtualSize;                22 00 00 00 (有效的OpCode数目)
DWORD VirtualAddress;              00 10 00 00 (区段rva:200h映射到内存中为1000h)
DWORD SizeOfRawData;              00 02 00 00 (在文件中的对齐后大小)
DWORD PointerToRawData;            00 02 00 00 (在文件中相对与0的偏移)
DWORD Characteristics;              E0 00 00 E0 (区段属性可以自定义)
2.rdata
BYTE Name[IMAGE_SIZEOF_SHORT_NAME];    2E 72 64 61 74 61 00 00(区段名称)

DWORD VirtualSize;                7E 00 00 00 (有效的字节数目)

DWORD VirtualAddress;               00 20 00 00 (区段rva:400h映射到内存中为2000h)

DWORD SizeOfRawData;              00 02 00 00 (在文件中的对齐后大小)

DWORD PointerToRawData;             00 04 00 00 (在文件中相对与0的偏移)

DWORD Characteristics;              E0 00 00 E0 (区段属性可以自定义)

2E 74 65 78 74 00 00 00 22 00 00 00 00 10 00 00

00 02 00 00 00 02 00 00 00 00 00 00 00 00 00 00

00 00 00 00 E0 00 00 E0 2E 72 64 61 74 61 00 00

7E 00 00 00 00 20 00 00 00 02 00 00 00 04 00 00

00 00 00 00 00 00 00 00 00 00 00 00 E0 00 00 E0

4.构造区段身体

.text段

VS程序IAT调用为:FF 15 XXXXXXXX(IAT地址)(有2个dll)

IAT1:FOA:400h ==> RVA: 2000h ==>VA:400000h + 2000h==>402000h

IAT2:FOA:408h ==> RVA: 2008h ==>VA:400000h + 2008h==>402008h

伪代下:

push 0x0;

push 0x0;

push 0x0;

push 0x0;

call MessageBoxA; // MessageBoxA()

push 0x0;

call ExitProcess; // ExitProcess()

push 0x0; 6A 00

push 0x0; 6A 00

push 0x0; 6A 00

push 0x0; 6A 00

call MessageBoxA; FF 15 00 20 40 00

push 0x0; 6A 00

call ExitProcess;   FF 15 08 20 40 00

.rdata段

typedef struct _IMAGE_IMPORT_DESCRIPTOR {

union {

DWORD Characteristics; // 0 for terminating null import descriptor

DWORD OriginalFirstThunk; // RVA to original unbound IAT (PIMAGE_THUNK_DATA) INT的地址

} DUMMYUNIONNAME;

DWORD TimeDateStamp; // 0 if not bound,

// -1 if bound, and real date\time stamp

// in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND)

// O.W. date/time stamp of DLL bound to (Old BIND)

DWORD ForwarderChain; // -1 if no forwarders

DWORD Name; //库名称字符串地址

DWORD FirstThunk; // RVA to IAT (if bound this IAT has actual addresses) IAT的地址

} IMAGE_IMPORT_DESCRIPTOR;

typedef IMAGE_IMPORT_DESCRIPTOR UNALIGNED *PIMAGE_IMPORT_DESCRIPTOR;

typedef struct _IMAGE_THUNK_DATA32 {

union {

DWORD ForwarderString; // PBYTE

DWORD Function; // PDWORD

DWORD Ordinal;

DWORD AddressOfData; // PIMAGE_IMPORT_BY_NAME

} u1;

} IMAGE_THUNK_DATA32;

typedef IMAGE_THUNK_DATA32 * PIMAGE_THUNK_DATA32;

//

// Import Format

//

typedef struct _IMAGE_IMPORT_BY_NAME {

WORD Hint; //ordinal

CHAR Name[1]; //function name string

} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;

5C 20 00 00 00 00 00 00 75 20 00 00 00 00 00 00

4C 20 00 00 00 00 00 00 00 00 00 00 6A 20 00 00

00 20 00 00 54 20 00 00 00 00 00 00 00 00 00 00

83 20 00 00 08 20 00 00 00 00 00 00 00 00 00 00

00 00 00 00 00 00 00 00 00 00 00 00 5C 20 00 00

00 00 00 00 75 20 00 00 00 00 00 00 00 00 4D 65

73 73 61 67 65 42 6F 78 41 00 55 53 45 52 33 32

2E 64 6C 6C 00 00 00 45 78 69 74 50 72 6F 63 65

73 73 00 4B 45 52 4E 45 4C 33 32 2E 64 6C 6C 00

IAT:

typedef struct _IMAGE_THUNK_DATA32 {

union {

DWORD ForwarderString; // PBYTE

DWORD Function; // PDWORD

DWORD Ordinal;

DWORD AddressOfData; // PIMAGE_IMPORT_BY_NAME

} u1;

} IMAGE_THUNK_DATA32;

typedef IMAGE_THUNK_DATA32 * PIMAGE_THUNK_DATA32;

关键字段
DWORD AddressOfData1;      MessageBoxA ==>5C 20 00 00 00 00 00 00 (以0结尾)
DWORD AddressOfData2;      ExitProcess ==>75 20 00 00 00 00 00 00 (以0结尾)

Import Table:

typedef struct _IMAGE_IMPORT_DESCRIPTOR {

union {

DWORD Characteristics; // 0 for terminating null import descriptor

DWORD OriginalFirstThunk; //指向INT =>4C 20 00 00

} DUMMYUNIONNAME;

DWORD ForwarderChain; // -1 if no forwarders =>00 00 00 00

DWORD Name; //指向库文件名(USER32.DLL) => 6A 20 00 00

DWORD TimeDateStamp; // 0 if not bound =>00 00 00 00

DWORD FirstThunk; // RVA to IAT => 00 20 00 00

} IMAGE_IMPORT_DESCRIPTOR;

typedef IMAGE_IMPORT_DESCRIPTOR UNALIGNED *PIMAGE_IMPORT_DESCRIPTOR;

关键字段

DWORD AddressOfData1;      MessageBoxA ==>5C 20 00 00 00 00 00 00 (以0结尾)

DWORD AddressOfData2;      ExitProcess ==>75 20 00 00 00 00 00 00 (以0结尾)

INT:

typedef struct _IMAGE_THUNK_DATA32 {

union {

DWORD ForwarderString;   // PBYTE

DWORD Function; // PDWORD

DWORD Ordinal;

DWORD AddressOfData;  // PIMAGE_IMPORT_BY_NAME

} u1;

} IMAGE_THUNK_DATA32;

typedef IMAGE_THUNK_DATA32 * PIMAGE_THUNK_DATA32;

关键字段

DWORD AddressOfData1;      MessageBoxA ==>5C 20 00 00 00 00 00 00 (以0结尾)

DWORD AddressOfData2;      ExitProcess ==>75 20 00 00 00 00 00 00 (以0结尾)

HintName:

typedef struct _IMAGE_IMPORT_BY_NAME {

WORD Hint; //名称导入 =>00 00

CHAR Name[1];

} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;

关键字段
1.MessageBoxA
1.1 WORD Hint;         API名称在DLL中的编号==>00 00 (名称导入)
1.2 CHAR Name[1];        MessageBoxA名称 ==>4D 65 73 73 61 67 65 42 6F 78 41
                USER32.dll ==>00 55 53 45 52 33 32 2E 64 6C 6C 00
2.ExitProcess
WORD Hint;           API名称在DLL中的编号==>00 00 (名称导入)
CHAR Name[1];          ExitProcess名称 ==>45 78 69 74 50 72 6F 63 65 73 73
                KERNEL32.dll ==>00 4B 45 52 4E 45 4C 33 32 2E 64 6C 6C 00

手写简单PE的更多相关文章

  1. 不使用Tomcat,手写简单的web服务

    背景: 公司使用的YDB提供了http的查询数据库服务,直接通过url传入sql语句查询数据-_-||.ydb的使用参照:https://www.cnblogs.com/hd-zg/p/7115112 ...

  2. 手写简单call,apply,bind

    分析一下call的使用方法:call是显示绑定this指向,然后第一个参数是你所指向的this对象,后面跟着多个参数,以逗号隔开 function sum(num1,num2){ return num ...

  3. 编写自定义PE结构的程序(如何手写一个PE,高级编译器都是编译好的PE头部,例如MASM,TASM等,NASM,FASM是低级编译器.可以自定义结构)

    正在学PE结构...感谢个位大哥的文章和资料...这里先说声谢谢 一般高级编译器都是编译好的PE头部,例如MASM,TASM等一直都说NASM,FASM是低级编译器.可以自定义结构但是苦于无人发布相关 ...

  4. 手写简单的jq雪花飘落

    闲来无事,准备写个雪花飘落的效果,没有写太牛逼的特效,极大的简化了代码量,这样容易读取代码,用起来也很简单,对于那些小白简直是福利啊,简单易读易学.先直接上代码吧,然后再一一讲解,直接复制粘贴就可以拿 ...

  5. 利用Java手写简单的httpserver

    前言: 在看完尚学堂JAVA300中讲解如何实现一个最简单的httpserver部分的视频之后, 一.前置知识 1.HTTP协议 当前互联网网页访问主要采用了B/S的模式,既一个浏览器,一个服务器,浏 ...

  6. 通过反射来手写简单的ORM SQlserver

    不说废话,直接上干货,如发现问题,欢迎大家指出,谢谢! //------------------------------------MySQlServerORM [简单 CURD] using Sys ...

  7. 手写简单的promise

    function Promise(fn) { var that = this; this.status = "pedding"; this.value = undefined; / ...

  8. node搭环境(四)--webpack启服务运行VUE模块文件(手写简单脚手架)

    webpack启服务步骤: 1.新建空文件夹webpack-vue.在空文件夹右键点击- GIt Bath here--输入cnpm init--按程序走完会生成package.json文件 2.打开 ...

  9. 手写简单的php生成Html网页

    这个是基本功,以前用到laravel及thinkphp时,这一步,都被设置好了吧. 这里只依靠纯的php环境,而没有任何框架, 而框架,只是将这一切规范化,加快代码效率及减小沟通成本,维护升级也方便, ...

随机推荐

  1. sphinx-2.1.9的安装使用

    1.下载/编译安装 cd /usr/local/src wget http://sphinxsearch.com/files/sphinx-2.1.9-release.tar.gz tar -xf s ...

  2. C#下用于同时使用OpenCvSharp和Emgu.CV两个库的相互转换库

    很久以前做的一个图像处理项目,在.NET平台上使用OpenCV,但因为同时使用了C#支持的两个比较有名的库,由于封装方式不同,难免要转换两个库之间的Mat对象. 同时还封装了一些WPF下,System ...

  3. configure,make,make install作用和关系的一些理解

    一. 整体关系 为求直观,画了一张大致关系图: 我个人的理解是这样的,将编译安装比作做菜的话, △ configure的作用,以厨师的构想以参数的形式作为输入,生成并输出菜谱,菜谱包含两个部分---- ...

  4. random-----随机数

    1 import random 2 3 print(random.random())#(0,1)----float 大于0且小于1之间的小数 4 5 print(random.randint(1,3) ...

  5. js一行代码解决各种IE兼容问题

    在网站开发中不免因为各种兼容问题苦恼,针对兼容问题,其实 IE给出了解决方案 Google也给出了解决方案 百度也应用了这种方案去解决IE的兼容问题 百度源代码如下 <!Doctype html ...

  6. Windows邮件客户端

    换回WIndows 因为要保存邮件 所以需要邮件客户端 Foxmail 腾讯自家 同样需要独立密码 之前的foxmail是全拼 新注册了一个@qq 发现新注册的@qq绑定到的是新的QQ号 算了 去用1 ...

  7. win10 开发mfc 64位 ocx控件

    问题1.模块“XXX.ocx”加载失败 解决办法:项目--〉属性--〉常规-〉配置类型-〉  动态库(.dll) 修改为 静态库(.lib) 问题2.1>x64\Release\stdafx.o ...

  8. Zabbix监控平台3.2.4(一)搭建部署与概述

    一,Zabbix架构 zabbix 是一个基于 WEB 界面的提供分布式系统监视以及网络监视功能的企业级的开源解决方案.zabbix 能监视各种网络参数,保证服务器系统的安全运营:并提供灵活的通知机制 ...

  9. 使用MagickNet编辑图片

            ImageMagick是一个免费的创建.编辑.合成图片的软件.它可以读取.转换.写入多种格式的图片.图片切割.颜色替换.各种效果的应用,图片的旋转.组合,文本,直线,多边形,椭圆,曲线 ...

  10. 第九篇 Flask 中的蓝图(BluePrint)

    第九篇 Flask 中的蓝图(BluePrint)   蓝图,听起来就是一个很宏伟的东西 在Flask中的蓝图 blueprint 也是非常宏伟的 它的作用就是将 功能 与 主服务 分开怎么理解呢? ...