关键词不能为空

当前您在: 主页 > 英语 >

打造最小的PE文件

作者:高考题库网
来源:https://www.bjmy2z.cn/gaokao
2020-10-25 05:51
tags:hrl

华中师范大学教务网-徇私读音

2020年10月25日发(作者:倪雅伦)


打造最小的PE文件

打造最小的PE文件

打造最小的PE文件
(bkbll# 2005-9-18
9:01)一. 前言.
最近在鼓捣windows下PE文件格式, 在达到既定目
标后, 对生成最小PE文件产生了兴趣, 恰好
看到 watercloud(watercloud_at_)在近2年前
写过 一篇文章<<手工打造微型Win32
可执行文件
>>(http:),
我也依葫芦画瓢,打造
一下我认为最小的PE文件,由于是初次接触PE格式,如
有差错,敬请斧正.
本文所有程序均在win2k sp4 cn和windows xp sp1
cn上测试通过.二. PE文件格式,结构
在winnt.h中,有PE各种结构的定义,这里就不一一
列举, 仅将相关结构名列举如下:

IMAGE_DOS_HEADER,IMAGE_NT_HEADERS,IMAGE _F


ILE_HEADER,IMAGE_OPTIONAL_HEADER,

IMAGE_DATA_DIRECTORY,IMAGE_SECTION_HEAD ER
,IMAGE_IMPORT_DESCRIPTOR
因为目标是打造最小的PE文件,所以仅用到一个
IMPORT表.
PE整个文件框架大致如下:

| IMAGE_DOS_HEADER |
| Signature
|
| IMAGE_NT_HEADER | -> |
IMAGE_FILE_HEADER |
|
IMAGE_OPTIONAL_HEADER | ->

| IMAGE_DATA_DIRECTORY |

......

| IMAGE_SECTION_HEADER |


........

| 代码段 |
三. 不一样的地方
watercloud 的PE已经比较小了,但还有几个地方
我处理的不大一样:
1. WindowsXP 可以允许PE section为1个. 试验
系统是xp sp1 cn
2. 文件对齐 windows是规定是2的幂, 当然可以
比0x200小.
当然,除了上面2点以外,我还有用到一种比较巧妙的技
巧.

运行PE文件,会在屏幕上打印Hello,world信息.

四. 打造过程.
1. 过程一:
最开始我们按照PE结构和顺序一步步填充结构,
看能有多大:
我们先选取对齐值为0x20.
这里我们选
MAGE_OPTIONAL_ rectory个数为16个


(所有都用上),但
只用到IMPORT table.

这个过程没有什么技巧,因为只用到一个section,文
件对齐又小了很多,最终大小为
496字节, 其中我们的汇编代码占了47字节.
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D
0E 0F
00000000h: 4D 5A 90 00 03 00 00 00 04 00 00 00 FF FF
00 00 MZ?........??..
00000010h: B8 00 00 00 00 00 00 00 40 00 00 00 00 00 00
00 ?......@.......
00000020h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 ................
00000030h: 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00
00 ............@...
00000040h: 50 45 00 00 4C 01 01 00 00 00 00 00 00 00 00
00 PE..L...........
00000050h: 00 00 00 00 E0 00 0F 01 0B 01 06 00 00 00
00 00 ....?..........
00000060h: 00 00 00 00 00 00 00 00 B4 01 00 00 00 00 00
00 ........?......


00000070h: 00 00 00 00 00 00 40 00 10 00 00 00 10 00 00
00 ......@.........
00000080h: 04 00 00 00 00 00 00 00 04 00 00 00 00 00 00
00 ................
00000090h: 00 10 00 00 00 00 00 00 00 00 00 00 03 00 00
00 ................
000000a0h: 00 00 10 00 00 10 00 00 00 00 10 00 00 10 00
00 ................
000000b0h: 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00
00 ................
000000c0h: 60 01 00 00 28 00 00 00 00 00 00 00 00 00 00
00 `...(...........
000000d0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 ................
000000e0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 ................
000000f0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 ................
00000100h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 ................
00000110h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 ................


00000120h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 ................
00000130h: 00 00 00 00 00 00 00 00 2E 74 65 78 74 00 00
00 .........text...
00000140h: 00 08 00 00 60 01 00 00 00 08 00 00 60 01 00
00 ....`.......`...
00000150h: 00 00 00 00 00 00 00 00 00 00 00 00 20 00 00
E0 ............ ..?
00000160h: 88 01 00 00 00 00 00 00 00 00 00 00 98 01 00
00 ?..........?..
00000170h: 90 01 00 00 00 00 00 00 00 00 00 00 00 00 00
00 ?..............
00000180h: 00 00 00 00 00 00 00 00 A8 01 00 00 00 00 00
00 ........?......
00000190h: A8 01 00 00 00 00 00 00 6B 65 72 6E 65 6C
33 32 ?......kernel32
000001a0h: 2E 64 6C 6C 00 00 00 00 00 00 57 72 69 74
65 46 .dll......WriteF
000001b0h: 69 6C 65 00 8B 43 10 8B 40 1C 33 D2 52 68
72 6C ile.婥.婡.3襌hrl
000001c0h: 64 0A 68 6F 2C 77 6F 68 68 65 6C 6C 8B CC
52 54 ,wohhell嬏RT


000001d0h: 6A 0C 51 50 68 90 01 00 00 58 03 43 08 FF
10 83 ?..X.C.?.?
000001e0h: C4 10 C3 00 00 00 00 00 00 00 00 00 00 00
00 00 ??............

2. 过程二:
压缩一下 IMAGE_OPTIONAL_HEADER 的
DataDirectory,因为只用到import表,所以
IMAGE_OPTIONAL_HEADER 的
NumberOfRvaAndSizes 可以为 2 , 这样就减少了0x70字
节,
最终大小为384字节, 47字节为我们的汇编代码,因为这
个没什么技巧,和前面差不多,所
以不贴出文件内容了.

3. 过程三:
对比一下,我们发现 IMAGE_DOS_HEADER 的
0x40大小结构,除了 e_magic 和 e_lfanew
两个结构外,其他对我们的mini-pe 似乎没什么影响,那
么这个结构没用的部分可不可以
利用起来呢? 答案是肯定的, 我决定将
IMAGE_NT_HEADERS 和 IMAGE_DOS_HEADER 重叠


起来, 但是因为 e_lfanew 是标记
IMAGE_NT_HEADERS 偏移的唯一值, 所以这个值不能被
覆盖, 同时因为两个头部重叠了,所以 e_lfanew 所在
的文件偏移位置在 IMAGE_NT_HEADERS
结构中应该是个可以被忽略的结构.
我们来分析一下 IMAGE_NT_HEADERS 的头0x40大
小的结构:
typedef struct _IMAGE_NT_HEADERS
{
DWORD Signature; +0
IMAGE_FILE_HEADER FileHeader;
IMAGE_OPTIONAL_HEADER OptionalHeader;
} IMAGE_NT_HEADERS,
*PIMAGE_NT_HEADERS;typedef struct
_IMAGE_FILE_HEADER
{
WORD Machine; +4
WORD NumberOfSections; +6
DWORD TimeDateStamp; +8
DWORD PointerToSymbolTable; +12
DWORD NumberOfSymbols; +16
WORD SizeOfOptionalHeader; +20


WORD Characteristics; +22
} IMAGE_FILE_HEADER,
*PIMAGE_FILE_HEADER;typedef struct
_IMAGE_OPTIONAL_HEADER
{
WORD Magic; +24
BYTE MajorLinkerVersion; +26
BYTE MinorLinkerVersion; +27
DWORD SizeOfCode; +28
DWORD SizeOfInitializedData; +32
DWORD SizeOfUninitializedData; +36
DWORD AddressOfEntryPoint; +40
DWORD BaseOfCode; +44
DWORD BaseOfData; +48
DWORD ImageBase; +52
DWORD SectionAlignment; +56
DWORD FileAlignment; +60
WORD MajorOperatingSystemVersion; +64
..........
}
e_lfanew 是在 IMAGE_DOS_HEADER 的0x3c =
60 处, 我们从56除往回找可以被覆盖


又没什么用处的结构, 好像最近一个就只有
BaseOfData 了. 也就是说 e_lfanew =
60 - 48 = 12 = 0xc.

重叠后的 IMAGE_DOS_HEADER 和
IMAGE_FILE_HEADER 结构图如下:
WORD e_magic; +0
WORD e_cblp; +2
WORD e_cp; +4
WORD e_crlc; +6
WORD e_cparhdr; +8
WORD e_minalloc; +10
WORD e_maxalloc; WORD e_ss; +12
IMAGE_NT_ure +0
WORD e_sp; +16
IMAGE_FILE_e +4
WORD e_csum; +18
IMAGE_FILE_OfSections+6
WORD e_ip; WORD e_cs; +20
IMAGE_FILE_teStamp +8
WORD e_lfarlc; WORD e_ovno; +24
IMAGE_FILE_rToSymbolTable


WORD e_res[4]; +28
IMAGE_FILE_HEADER. NumberOfSymbols
+32
IMAGE_FILE_OptionalHeader
+34
IMAGE_FILE_teristics
WORD e_oemid; +36
IMAGE_OPTIONAL_
WORD e_oeminfo; +38
IMAGE_OPTIONAL_inkerVersion
+39
IMAGE_OPTIONAL_inkerVersion
WORD e_res2[10]; +40
IMAGE_OPTIONAL_Code
+44
IMAGE_OPTIONAL_InitializedData
+48
IMAGE_OPTIONAL_UninitializedData
+52
IMAGE_OPTIONAL_sOfEntryPoint
+56
IMAGE_OPTIONAL_Code;


LONG e_lfanew; +60
IMAGE_OPTIONAL_Data;+48
+64
IMAGE_OPTIONAL_ase 这样光重叠
这部分就可以省下一点空间,最终 大小为336字节,其中47字
节为我们的汇编代码.
文件内容:
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D
0E 0F
00000000h: 4D 5A 90 00 03 00 00 00 04 00 00 00 50 45
00 00 MZ?........PE..
00000010h: 4C 01 01 00 00 00 00 00 00 00 00 00 00 00 00
00 L...............
00000020h: 70 00 0F 01 0B 01 06 00 00 00 00 00 00 00 00
00 p...............
00000030h: 00 00 00 00 14 01 00 00 00 00 00 00 0C 00 00
00 ................
00000040h: 00 00 40 00 10 00 00 00 10 00 00 00 04 00 00
00 ..@.............
00000050h: 00 00 00 00 04 00 00 00 00 00 00 00 00 10 00
00 ................
00000060h: 00 00 00 00 00 00 00 00 03 00 00 00 00 00 10


00 ................
00000070h: 00 10 00 00 00 00 10 00 00 10 00 00 00 00 00
00 ................
00000080h: 02 00 00 00 00 00 00 00 00 00 00 00 C0 00 00
00 ............?..
00000090h: 28 00 00 00 2E 74 65 78 74 00 00 00 00 08 00
00 (....text.......
000000a0h: C0 00 00 00 00 08 00 00 C0 00 00 00 00 00
00 00 ?......?......
000000b0h: 00 00 00 00 00 00 00 00 20 00 00 E0 00 00 00
00 ........ ..?...
000000c0h: E8 00 00 00 00 00 00 00 00 00 00 00 F8 00 00
00 ?..........?..
000000d0h: F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 ?..............
000000e0h: 00 00 00 00 00 00 00 00 08 01 00 00 00 00 00
00 ................
000000f0h: 08 01 00 00 00 00 00 00 6B 65 72 6E 65 6C 33
32 ........kernel32
00000100h: 2E 64 6C 6C 00 00 00 00 00 00 57 72 69 74
65 46 .dll......WriteF
00000110h: 69 6C 65 00 8B 43 10 8B 40 1C 33 D2 52 68


72 6C ile.婥.婡.3襌hrl
00000120h: 64 0A 68 6F 2C 77 6F 68 68 65 6C 6C 8B CC
52 54 ,wohhell嬏RT
00000130h: 6A 0C 51 50 68 F0 00 00 00 58 03 43 08 FF
10 83 ?..X.C.?.?
00000140h: C4 10 C3 00 00 00 00 00 00 00 00 00 00 00
00 00 ??............

4. 过程四.
现在已经小很多了,我们在前这几个结构
IMAGE_DOS_HEADER,IMAGE_NT_HEADERS
和IMAGE_SECTION_HEADER 上,可以重叠的不多了,
那么剩下就只有IMPORT表的描述了.

在前面我们用的import表的描述是这样的结构:
import descriptor(PEDataDir->Size) bytes
OriginalFirstThunk + 0x0000 8 bytes
FirstThunk(IAT) + 0x0000 8 bytes
12+4 = 16 bytes
0x00 +iatfunction1(
这样就占了 PEDataDir->Size + 8 + 8 + 16 + 12
字节,好像比较大哦,那我们就对它动手吧.


我们看看能不能把它整合到已有的结构里面去.
先调整唯一的section的内容:
IMAGE_SECTION_lAddress = 0x00;
IMAGE_SECTION_rToRawData =
0x00;
这样,整个文件结构以及偏移地址就都可以使用了.
import descriptor 所需要的最小大小是
sizeof(IMAGE_IMPORT_DESCRIPTOR) *2,
其中要求最后4字节内容为0
我们对比搜寻结构,发现
IMAGE_OPTIONAL_HEADER 结构从DllCharacteristics
开始满足我们的要求,
import descriptor 指向这里:
WORD DllCharacteristics;
DWORD SizeOfStackReserve;
DWORD SizeOfStackCommit;
DWORD SizeOfHeapReserve;
DWORD SizeOfHeapCommit;
DWORD LoaderFlags;
DWORD NumberOfRvaAndSizes;
IMAGE_DATA_DIRECTORY DataDirectory[0];
因为刚好第一个DataDirectory内容都是0,满足我们的


要求.
剩下的就需要找一个8字节大小的空间,要求第一个4
字节改变不会影响程序运行(这里用来保存第
一个IAT的地址),第二个4字节内容为0. 这里用来存放
IMAGE_IMPORT_DESCRIPTOR 的 OriginalFirstThunk
和 FirstThunk ,根据需求来看,这两个地址显然可以相
等.
很幸运的是 IMAGE_IMPORT_DESCRIPTOR 自己的
结构就满足这样的要求:
typedef struct _IMAGE_IMPORT_DESCRIPTOR
{
union
{
DWORD Characteristics;
DWORD OriginalFirstThunk;
};
DWORD TimeDateStamp;
DWORD ForwarderChain;
DWORD Name;
DWORD FirstThunk;
} IMAGE_IMPORT_DESCRIPTOR;
当ForwarderC hain为0的时候,TimeDateStamp偏移


就可以用来存放我们需要的IA T地址.
OK,现在还剩下两个地方没有解决:dll名字以及导入函
数的名字.
和上面一样,我们还是到已有的结构里面去找可以填充
的空间:
Dll名字存放要求很简单,后面有一个'0'结尾,然后填充
内容不影响程序运行.
IMAGE_SECTION_HEADER好像可以满足我们的要
求:

DWORD PointerToRelocations;
DWORD PointerToLinenumbers;
WORD NumberOfRelocations;
WORD NumberOfLinenumbers;
DWORD Characteristics;
一共有12字节存放我们的dll名字,同时Chara cteristics
还有后1为可以供存放,所以一
共有13字节,保存刚刚好.
IMAGE_FILE_HEADER 结构也有12字节空间:
DWORD TimeDateStamp; +8 可以随
便填
DWORD PointerToSymbolTable; +12


DWORD NumberOfSymbols; +16

我们就在这里容纳我们的函数名就可以了.

这样整个 IMAGE_IMPORT_DESCRIPTOR 结构和
import表其他内容就被我们拆散整合到
已有的结构里面去了.
接着我们再优化一下shellcode, 使用的printf
来输出信息.

这样,经过精心裁减后,整个PE文件大小为224字节,其
中汇编代码占了28字节.
最终结果:
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D
0E 0F
00000000h: 4D 5A 90 00 03 00 00 00 04 00 00 00 50 45
00 00 MZ?........PE..
00000010h: 4C 01 01 00 00 00 70 72 69 6E 74 66 00 00
00 00 L.....printf....
00000020h: 70 00 0F 01 0B 01 06 00 00 00 00 00 00 00 00
00 p...............
00000030h: 00 00 00 00 C0 00 00 00 00 00 00 00 0C 00


00 00 ....?..........
00000040h: 00 00 40 00 10 00 00 00 10 00 00 00 04 00 00
00 ..@.............
00000050h: 00 00 00 00 04 00 00 00 00 00 00 00 00 10 00
00 ................
00000060h: 00 00 00 00 00 00 00 00 03 00 6E 00 00 00 14
00 ..........n.....
00000070h: 00 00 00 00 00 00 AC 00 00 00 6E 00 00 00
00 00 ......?..n.....
00000080h: 02 00 00 00 00 00 00 00 00 00 00 00 6A 00 00
00 ............j...
00000090h: 14 00 00 00 2E 74 65 78 74 00 00 00 00 08 00
00 .....text.......
000000a0h: 00 00 00 00 00 08 00 00 00 00 00 00 6D 73 76
63 ............msvc
000000b0h: 72 74 2E 64 6C 6C 00 00 20 00 10 E0 00 00
00 00 .. ..?...
000000c0h: 50 68 72 6C 64 0A 68 6F 2C 77 6F 68 68 65
6C 6C ,wohhell
000000d0h: 54 B0 6E 03 43 08 FF 10 83 C4 14 C3 00 00
00 00 T皀.C.?.兡.?... 注意,这个PE文件是不能直接被
windbg(6.3.0017.0)调试器直接启动的,要想调试


代码可以在汇编代码前加上int 3(0xcc)来调试.
5.过程五:

最后,来考虑一下我们文件的对齐
IMAGE_OPTIONAL_nAlignment和
IMAGE_OPTIONAL_ignment, 既然要
求是2的幂,那么我们完全可以
用2的0次方即1来做我们的alignment.
最终生成的EXE又瘦身了,大小仅为216字节,其中包括
28字节的汇编代码

00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D
0E 0F
00000000h: 4D 5A 90 00 03 00 00 00 04 00 00 00 50 45
00 00 MZ?........PE..
00000010h: 4C 01 01 00 00 00 70 72 69 6E 74 66 00 00
00 00 L.....printf....
00000020h: 70 00 0F 01 0B 01 06 00 00 00 00 00 00 00 00
00 p...............
00000030h: 00 00 00 00 BC 00 00 00 00 00 00 00 0C 00
00 00 ....?..........
00000040h: 00 00 40 00 01 00 00 00 01 00 00 00 04 00 00


00 ..@.............
00000050h: 00 00 00 00 04 00 00 00 00 00 00 00 00 10 00
00 ................
00000060h: 00 00 00 00 00 00 00 00 03 00 6E 00 00 00 14
00 ..........n.....
00000070h: 00 00 00 00 00 00 AC 00 00 00 6E 00 00 00
00 00 ......?..n.....
00000080h: 02 00 00 00 00 00 00 00 00 00 00 00 6A 00 00
00 ............j...
00000090h: 14 00 00 00 2E 74 65 78 74 00 00 00 00 08 00
00 .....text.......
000000a0h: 00 00 00 00 00 08 00 00 00 00 00 00 6D 73 76
63 ............msvc
000000b0h: 72 74 2E 64 6C 6C 00 00 20 00 10 E0 50 68
72 6C .. ..郟hrl
000000c0h: 64 0A 68 6F 2C 77 6F 68 68 65 6C 6C 54 B0
6E 03 ,wohhellT皀.
000000d0h: 43 08 FF 10 83 C4 14
C3 C.?.兡.?五. 后记.
理论上来说,后面的汇编代码部分可以用任意自己的代
码来填充,只要获得了
的Ge tProcAddress函数的地址,那书写自己控制的代码


并不是问题,而代码长度 部分可以由
IMAGE_SECTION_HEADER的SizeOfRawData来控
制. 我没有试过,不过相信用188字节的PE头结构
写出的PE文件一定很cool. PE头还可以减小吗?你想,
你能.
最后祝大家中秋快乐!
六.参考.
.
.h
loud<<手工打造微型Win32可执行文件
>>http:
posted on 2007-05-14 00:46 叶子 阅读(1307) 评论(0)
编辑 收藏 引用 所属分类: 技术研究

吁气的拼音-春辉


鞭怎么读-gripper


电用英语怎么说-宇航员英语


夏之色-洗碗英文


社会主义改造道路和历史经验-星期三的英语单词


小学三年级数学应用题大全-ture什么意思


非比寻常-hris


俄语我爱你-爸爸去哪儿灵异事件



本文更新与2020-10-25 05:51,由作者提供,不代表本网站立场,转载请注明出处:https://www.bjmy2z.cn/gaokao/424751.html

打造最小的PE文件的相关文章

  • 爱心与尊严的高中作文题库

    1.关于爱心和尊严的作文八百字 我们不必怀疑富翁的捐助,毕竟普施爱心,善莫大焉,它是一 种美;我们也不必指责苛求受捐者的冷漠的拒绝,因为人总是有尊 严的,这也是一种美。

    小学作文
  • 爱心与尊严高中作文题库

    1.关于爱心和尊严的作文八百字 我们不必怀疑富翁的捐助,毕竟普施爱心,善莫大焉,它是一 种美;我们也不必指责苛求受捐者的冷漠的拒绝,因为人总是有尊 严的,这也是一种美。

    小学作文
  • 爱心与尊重的作文题库

    1.作文关爱与尊重议论文 如果说没有爱就没有教育的话,那么离开了尊重同样也谈不上教育。 因为每一位孩子都渴望得到他人的尊重,尤其是教师的尊重。可是在现实生活中,不时会有

    小学作文
  • 爱心责任100字作文题库

    1.有关爱心,坚持,责任的作文题库各三个 一则150字左右 (要事例) “胜不骄,败不馁”这句话我常听外婆说起。 这句名言的意思是说胜利了抄不骄傲,失败了不气馁。我真正体会到它

    小学作文
  • 爱心责任心的作文题库

    1.有关爱心,坚持,责任的作文题库各三个 一则150字左右 (要事例) “胜不骄,败不馁”这句话我常听外婆说起。 这句名言的意思是说胜利了抄不骄傲,失败了不气馁。我真正体会到它

    小学作文
  • 爱心责任作文题库

    1.有关爱心,坚持,责任的作文题库各三个 一则150字左右 (要事例) “胜不骄,败不馁”这句话我常听外婆说起。 这句名言的意思是说胜利了抄不骄傲,失败了不气馁。我真正体会到它

    小学作文