通行证│用户名: 密码: 验证码: 验证码,看不清楚?请点击刷新验证码 电信网通铁通移动   在线
文章搜索:
热门搜索:红客 黑鹰 红客技术 安全动画 红客培训
首页 文章 软件 动画 资源 励志 论坛 邮箱 会员 军事 科技 博客 爱心红客 最近更新 800g资源
 业内新闻 漏洞公告 病毒公告 电脑知识 网络知识 菜鸟入门 攻防教程 黑客攻防 安全编程 工具使用 综合安全 个人安全 安全相关 Q Q安全 原创精华 红客人物 站内事件
您现在的位置: 爱国者安全网 >> 文章类 >> 红客教程 >> 网络攻防 >> 文章正文
《加密解密 技术内幕》2.1 关于PE可执行文件的修改
责任编辑:酷酷の鱼   更新日期:2008-3-14
 

来源:安全中国

在windows 9x、NT、2000下,所有的可执行文件都是基于Microsoft设计的一种新的文件格式Portable Executable File Format(可移植的执行体),即PE格式。有一些时候,我们需要对这些可执行文件进行修改,下面文字试图详细的描述PE文件的格式及对PE格式文件的修改。 
1、PE文件框架构成 
DOS MZ header 
DOS stub 
PE header 
Section table 
Section 1 
Section 2 
Section ... 
Section n 

上 表是PE文件结构的总体层次分布。所有 PE文件(甚至32位的 DLLs) 必须以一个简单的 DOS MZ header 开始,在偏移0处有DOS下可执行文件的“MZ标志”,有了它,一旦程序在DOS下执行,DOS就能识别出这是有效的执行体,然后运行紧随 MZ header 之后的 DOS stub。DOS stub实际上是个有效的EXE,在不支持 PE文件格式的操作系统中,它将简单显示一个错误提示,类似于字符串 " This program cannot run in DOS mode " 或者程序员可根据自己的意图实现完整的 DOS代码。通常DOS stub由汇编器/编译器自动生成,对我们的用处不是很大,它简单调用中断21h服务9来显示字符串"This program cannot run in DOS mode"。 
紧接着 DOS stub 的是 PE header。 PE header 是PE相关结构 IMAGE_NT_HEADERS 的简称,其中包含了许多PE装载器用到的重要域。可执行文件在支持PE文件结构的操作系统中执行时,PE装载器将从 DOS MZ header的偏移3CH处找到 PE header 的起始偏移量。因而跳过了 DOS stub 直接定位到真正的文件头 PE header。 

PE文件的真正内容划分成块,称之为sections(节)。每节是一块拥有共同属性的数据,比如“.text”节等,那么,每一节的内容都是什么呢?实际上PE格式的文件把具有相同属性的内容放入同一个节中,而不必关心类似“.text”、“.data”的命名,其命名只是为了便于识别,所有,我们如果对PE格式的文件进行修改,理论上讲可以写入任何一个节内,并调整此节的属性就可以了。 

PE header 接下来的数组结构 section table(节表)。 每个结构包含对应节的属性、文件偏移量、虚拟偏移量等。如果PE文件里有5个节,那么此结构数组内就有5个成员。 

以上就是PE文件格式的物理分布,下面将总结一下装载一PE文件的主要步骤: 
1、 PE文件被执行,PE装载器检查 DOS MZ header 里的 PE header 偏移量。如果找到,则跳转到 PE header。 
2、PE装载器检查 PE header 的有效性。如果有效,就跳转到PE header的尾部。 
3、紧跟 PE header 的是节表。PE装载器读取其中的节信息,并采用文件映射方法将这些节映射到内存,同时付上节表里指定的节属性。 
4、PE文件映射入内存后,PE装载器将处理PE文件中类似 import table(引入表)逻辑部分。 
上述步骤是一些前辈分析的结果简述。 
2、PE文件头概述 
我们可以在winnt.h这个文件中找到关于PE文件头的定义: 
typedef struct _IMAGE_NT_HEADERS { 
DWORD Signature; 
//PE文件头标志 :“PE\0\0”。在开始DOS header的偏移3CH处所指向的地址开始 
IMAGE_FILE_HEADER FileHeader; //PE文件物理分布的信息 
IMAGE_OPTIONAL_HEADER32 OptionalHeader; //PE文件逻辑分布的信息 
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32; 

typedef struct _IMAGE_FILE_HEADER { 
WORD Machine; //该文件运行所需要的CPU,对于Intel平台是14Ch 
WORD NumberOfSections; //文件的节数目 
DWORD TimeDateStamp; //文件创建日期和时间 
DWORD PointerToSymbolTable; //用于调试 
DWORD NumberOfSymbols; //符号表中符号个数 
WORD SizeOfOptionalHeader; //OptionalHeader 结构大小 
WORD Characteristics; //文件信息标记,区分文件是exe还是dll 
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER; 

typedef struct _IMAGE_OPTIONAL_HEADER { 
WORD Magic; //标志字(总是010bh) 
BYTE MajorLinkerVersion; //连接器版本号 
BYTE MinorLinkerVersion; // 
DWORD SizeOfCode; //代码段大小 
DWORD SizeOfInitializedData; //已初始化数据块大小 
DWORD SizeOfUninitializedData; //未初始化数据块大小 
DWORD AddressOfEntryPoint; //PE装载器准备运行的PE文件的第一个指令的RVA,若要改变整个执行的流程,可以将该值指定到新的RVA,这样新RVA处的指令首先被执行。(许多文章都有介绍RVA,请去了解) 
DWORD BaseOfCode; //代码段起始RVA 
DWORD BaseOfData; //数据段起始RVA 
DWORD ImageBase; //PE文件的装载地址 
DWORD SectionAlignment; //块对齐 
DWORD FileAlignment; //文件块对齐 
WORD MajorOperatingSystemVersion;//所需操作系统版本号 
WORD MinorOperatingSystemVersion;// 
WORD MajorImageVersion; //用户自定义版本号 
WORD MinorImageVersion; // 
WORD MajorSubsystemVersion; //win32子系统版本。若PE文件是专门为Win32设计的 
WORD MinorSubsystemVersion; //该子系统版本必定是4.0否则对话框不会有3维立体感 
DWORD Win32VersionValue; //保留 
DWORD SizeOfImage; //内存中整个PE映像体的尺寸 
DWORD SizeOfHeaders; //所有头+节表的大小 
DWORD CheckSum; //校验和 
WORD Subsystem; //NT用来识别PE文件属于哪个子系统 
WORD DllCharacteristics; // 
DWORD SizeOfStackReserve; // 
DWORD SizeOfStackCommit; // 
DWORD SizeOfHeapReserve; // 
DWORD SizeOfHeapCommit; // 
DWORD LoaderFlags; // 
DWORD NumberOfRvaAndSizes; // 
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; 
//IMAGE_DATA_DIRECTORY 结构数组。每个结构给出一个重要数据结构的RVA,比如引入地址表等 
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32; 

typedef struct _IMAGE_DATA_DIRECTORY { 
DWORD VirtualAddress; //表的RVA地址 
DWORD Size; //大小 
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY; 

PE文件头后是节表,在winnt.h下如下定义 
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; //重定位的偏移 
DWORD PointerToLinenumbers; //行号表的偏移 
WORD NumberOfRelocations; //重定位项数目 
WORD NumberOfLinenumbers; //行号表的数目 
DWORD Characteristics; //节属性 
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER; 

以上结构就是在winnt.h中关于PE文件头的定义,如何我们用C/C++来进行PE可执行文件操作,就要用到上面的所有结构,它详细的描述了PE文件头的结构。 

3、修改PE可执行文件 
现在让我们把一段代码写入任何一个PE格式的可执行文件,代码如下: 
-- test.asm -- 
.386p 
.model flat, stdcall 
option casemap:none 

include \masm32\include\windows.inc 
include \masm32\include\user32.inc 
includelib \masm32\lib\user32.lib 

.code 

start: 
INVOKE MessageBoxA,0,0,0,MB_ICONINFORMATION or MB_OK 
ret 
end start 

以上代码只显示一个MessageBox框,编译后得到二进制代码如下: 
unsigned char writeline[18]={ 
0x6a,0x40,0x6a,0x0,0x6a,0x0,0x6a,0x0,0xe8,0x01,0x0,0x0,0x0,0xe9,0x0,0x0,0x0,0x0 
}; 

好,现在让我们看看该把这些代码写到那。现在用Tdump.exe显示一个PE格式得可执行文件信息,可以发现如下描述: 
Object table: 
# Name VirtSize RVA PhysSize Phys off Flags 
-- -------- -------- -------- -------- -------- -------- 
01 .text 0000CCC0 00001000 0000CE00 00000600 60000020 [CER] 
02 .data 00004628 0000E000 00002C00 0000D400 C0000040 [IRW] 
03 .rsrc 000003C8 00013000 00000400 00010000 40000040 [IR] 

Key to section flags: 
C - contains code 
E - executable 
I - contains initialized data 
R - readable 
W - writeable 

上面描述此文件中存在3个段及每个段得信息,实际上我们的代码可以写入任何一个段,这里我选择“.text”段。

[1] [2] [3] 下一页

  • 上一篇文章:
  • 下一篇文章:
  • 最近更新
    固顶文章 Delphi编程培训班开课了
    普通文章 万元赏金 寻找动易SiteWeaver CMS/eShop 产品安全漏洞
    普通文章 瑞星公司03月15日发布 每日计算机病毒及木马播报
    推荐文章 [推荐]Windows用户摆脱黑客攻击的方法
    普通文章 加密与你零距离 个人隐私不泄露!
    普通文章 解开高强度文件夹加密大师里面的"秘密"
    普通文章 运用Windows命令 识别木马蛛丝马迹
    普通文章 拔营起寨 插入式木马的清除方法!
    普通文章 电脑菜鸟必懂 常见木马连接的原理
    普通文章 计算机在中毒后的五大紧急处理措施
    热门文章
    普通文章安全你我他:IPS与IDS技术路向何方?
    普通文章企业用户防御网络威胁十要素
    普通文章使用360安全卫士 教你五分钟搞定装机
    普通文章针对性防御手段 十招教你应对邮件欺诈
    普通文章设置Web邮箱黑客警报器 防止财务损失
    普通文章Discuz! 6 后台拿Shell的方法
    普通文章如何使电脑无法更改系统用户名
    推荐文章推荐:XSS攻击Cookie欺骗中隐藏JavaScript执行
    普通文章瑞星公司03月05日发布 每日计算机病毒及木马播报
    普通文章微软证实Hotmail登录故障未解决 遭用户抗议
    精彩专题