《WindowsPE权威指南》戚利第2章三个小工具的编写Word格式.docx
- 文档编号:622826
- 上传时间:2023-04-29
- 格式:DOCX
- 页数:46
- 大小:143.20KB
《WindowsPE权威指南》戚利第2章三个小工具的编写Word格式.docx
《《WindowsPE权威指南》戚利第2章三个小工具的编写Word格式.docx》由会员分享,可在线阅读,更多相关《《WindowsPE权威指南》戚利第2章三个小工具的编写Word格式.docx(46页珍藏版)》请在冰点文库上搜索。
7#defineIDM_OPEN2001
8#defineIDM_EXIT2002
9
10#defineIDM_14000
11#defineIDM_24001
12#defineIDM_34002
13#defineIDM_44003
14
15
16ICO_MAINICON"
main.ico"
17
18DLG_MAINDIALOG50,50,544,399
19STYLEDS_MODALFRAME|WS_POPUP|WS_VISIBLE|WS_CAPTION|WS_SYSMENU
20CAPTION"
PE文件基本信息byqixiaorui"
21MENUIDM_MAIN
22FONT9,"
宋体"
23BEGIN
24CONTROL"
"
IDC_INFO,"
RichEdit20A"
196|ES_WANTRETURN|WS_CHILD|WS_READONLY
25|WS_VISIBLE|WS_BORDER|WS_VSCROLL|WS_TABSTOP,0,0,540,396
26END
27
28IDM_MAINmenudiscardable
29BEGIN
30POPUP"
文件(&
F)"
31BEGIN
32menuitem"
打开文件(&
O)..."
IDM_OPEN
33menuitemseparator
34menuitem"
退出(&
x)"
IDM_EXIT
35END
36
37POPUP"
查看"
38BEGIN
39menuitem"
源文件"
IDM_1
40menuitem"
窗口透明度"
IDM_2
41menuitemseparator
42menuitem"
大小"
IDM_3
43menuitem"
宽度"
IDM_4
44END
45
46END
行1~13定义了各元素常量,行16指定了显示在窗口标题栏的图标为main.ico。
需要注意的是,必须保证图标文件与资源文件在同一个目录中,如果指定的图标文件在其他目录,则需要使用绝对路径。
语法如下:
ICO_MAINICON"
C:
\source\icon\main.ico"
行18~26定义了对话框DIALOG,该对话框最终显示效果如图2-1所示。
窗口定义中包含了窗口的显示样式、标题栏文字、窗口中包含的菜单IDM_MAIN及窗口字体格式,在窗口工作区域中只包含了一个富文本框控件IDC_INFO(在行24、行25定义)。
行28~46定义了菜单IDM_MAIN。
它包含了两个弹出式下拉菜单,分别是“文件”菜单和“查看”菜单,每个弹出式菜单中又各包含了多个菜单选项。
2.生成资源目标文件pe.res
资源文件是文本文件,由定义资源的一些脚本语句组成。
资源文件可以使用文本编辑软件(如记事本)查看和修改。
资源目标文件是对这些脚本的一种再组织,根据脚本描述将脚本涉及到的所有资源编译到一起,形成二进制字节码,资源目标文件无法通过文本编辑软件查看。
编译资源文件,生成资源目标文件(扩展名为res)。
在命令提示符下输入以下命令(非斜体部分):
D:
\masm32\source\chapter2>
rc–rpe.rc
如果执行编译没有错误发生(如资源脚本中定义的相关文件不存在就会产生错误提示),则命令执行后会在当前目录下生成资源目标文件pe.res。
该资源目标文件最终要被链接程序嵌入到PE文件中,形成PE资源表所描述的数据的一部分。
2.1.3通用程序框架的实现
资源目标文件生成以后,接下来的工作就是实现通用程序框架。
主要分为三个阶段:
❑编码源程序pe.asm
❑编译生成目标文件pe.obj
❑链接生成可执行文件pe.exe
下面我们分别介绍各阶段的详细内容。
1.编码源程序pe.asm
首先,打开记事本,输入代码清单2-2所示内容(去掉前面的行号)。
代码清单2-2:
通用程序框架的源程序(chapter2\pe.asm)
1.386
2.modelflat,stdcall
3optioncasemap:
none
4
5includewindows.inc
6includeuser32.inc
7includelibuser32.lib
8includekernel32.inc
9includelibkernel32.lib
10includecomdlg32.inc
11includelibcomdlg32.lib
12
13
14ICO_MAINequ1000
15DLG_MAINequ1000
16IDC_INFOequ1001
17IDM_MAINequ2000
18IDM_OPENequ2001
19IDM_EXITequ2002
20IDM_1equ4000
21IDM_2equ4001
22IDM_3equ4002
23
24.data
25hInstancedd?
;
进程实例句柄
26hRichEditdd?
富文本动态链接库句柄
27hWinMaindd?
窗口句柄
28hWinEditdd?
文本控件句柄
29szFileNamedbMAX_PATHdup(?
)
30
31.const
32szDllEditdb'
RichEd20.dll'
0
33szClassEditdb'
RichEdit20A'
34szFontdb'
宋体'
35
37.code
38
39;
----------------
40;
初始化窗口程序
41;
42_initproc
43local@stCf:
CHARFORMAT
44
45invokeGetDlgItem,hWinMain,IDC_INFO
46movhWinEdit,eax
47
48;
为窗口设置图标
49invokeLoadIcon,hInstance,ICO_MAIN
50invokeSendMessage,hWinMain,WM_SETICON,ICON_BIG,eax
51
52;
设置编辑控件
53invokeSendMessage,hWinEdit,EM_SETTEXTMODE,TM_PLAINTEXT,0
54invokeRtlZeroMemory,addr@stCf,sizeof@stCf
55mov@stCf.cbSize,sizeof@stCf
56mov@stCf.yHeight,9*20
57mov@stCf.dwMask,CFM_FACEorCFM_SIZEorCFM_BOLD
58invokelstrcpy,addr@stCf.szFaceName,addrszFont
59invokeSendMessage,hWinEdit,EM_SETCHARFORMAT,0,addr@stCf
60invokeSendMessage,hWinEdit,EM_EXLIMITTEXT,0,-1
61ret
62_initendp
63
64
65;
-------------------
66;
窗口回调函数
67;
68_ProcDlgMainprocusesebxediesihWnd,wMsg,wParam,lParam
69moveax,wMsg
70.ifeax==WM_CLOSE
71invokeEndDialog,hWnd,NULL
72.elseifeax==WM_INITDIALOG;
初始化
73pushhWnd
74pophWinMain
75call_init
76.elseifeax==WM_COMMAND;
菜单
77moveax,wParam
78.ifeax==IDM_EXIT;
退出
79invokeEndDialog,hWnd,NULL
80.elseifeax==IDM_OPEN;
打开文件
81.elseifeax==IDM_1;
其他菜单项
82.elseifeax==IDM_2
83.elseifeax==IDM_3
84.endif
85.else
86moveax,FALSE
87ret
88.endif
89moveax,TRUE
90ret
91_ProcDlgMainendp
92
93start:
94invokeLoadLibrary,offsetszDllEdit
95movhRichEdit,eax
96invokeGetModuleHandle,NULL
97movhInstance,eax
98invokeDialogBoxParam,hInstance,\
99DLG_MAIN,NULL,offset_ProcDlgMain,NULL
100invokeFreeLibrary,hRichEdit
101invokeExitProcess,NULL
102endstart
代码清单2-2第98行通过调用DialogBoxParam函数创建了一个弹出式窗口作为整个程序的主窗口,并将内部函数_ProcDlgMain的地址当成该函数的参数之一传入该函数。
函数_ProcDlgMain是弹出窗口的回调函数,如果我们要对发生在窗口中的消息进行捕获,则需要在此函数中设置对不同消息响应的代码,由于编写的只是一个基本程序框架,所以回调函数只对菜单中的“退出”选项做了响应,如下所示:
代码编写完成以后保存为pe.asm文件,然后进行编译生成目标文件。
2.编译生成目标文件pe.obj
在编写一些大程序时,通常会根据功能将源代码分别写到不同的文件里,有时为了项目分工合作,在一个项目中也会出现使用不同语言编写的源代码。
这些源代码文件都需要在各自独立的环境中被编译生成各自的目标文件,目标文件是符合通用对象文件格式(COFF)的文件,该格式的定制主要是为了方便混合编程。
生成目标文件的过程是处理源代码中可能会出现错误(如引入外部符号错误、源代码语法错误等)的过程,生成的目标文件最终会被链接程序拼接到最终的可执行文件中,当然,除了编译源代码生成的目标文件外,可执行文件还包含资源目标文件、外部引入的符号等信息。
在命令提示符下输入以下命令,编译源文件pe.asm:
ml–c–coffpe.asm
如果没有错误,则会在当前目录下生成目标文件pe.obj。
接下来链接所有的目标文件(包括资源目标文件和源代码目标文件)生成最终的可执行文件:
3.链接生成可执行文件pe.exe
在命令提示符下输入以下命令:
link–subsystem:
windowspe.objpe.res
上述命令指定最终生成的EXE文件的运行平台为Windows,链接程序将根据pe.obj中的描述构造PE文件,并将相关资源内容附加到PE文件里,最终生成可执行的pe.exe。
在命令提示符下输入pe,然后回车,即可看到最终的运行效果,效果见图2-1。
至此,一个基本的基于汇编语言的窗口程序就编写完成了。
接下来的工作就是在此基础上进行扩展,开发三个基于WindowsPE的小工具,首先来看字节码查看器PEDump的编写。
2.2PEDump的实现
PEDump是字节码查看器,利用它可以查看和阅读指定的PE文件的十六进制字节码,帮助我们更好地分析PE结构。
2.2.1编写PEDump程序的流程
PEDump的编写重点在于显示功能,首先来看一看最终可能的输出效果如图2-2所示:
列一:
地址列二:
字节码内容列三:
ASCII字符
000001400E1FBA0E00B409CD-21B8014CCD215468........!
..L.!
Th
0000015069732070726F6772-616D2063616E6E6Fisprogramcanno
00000160742062652072756E-20696E20444F5320tberuninDOS
000001706D6F64652E0D0D0A-240000mode....$..
图2-2PEDump的输出效果
如图所示,最终输出包含三列内容。
❑第一列是地址,地址的值是第(n*16+1)个字节在文件中的位置。
❑第二列是由空格分隔符分隔的16个字节的16进制显示。
❑第三列是这16个字节对应的ASCII码值,如果ASCII码中无对应值,或者这些值是一些功能键,则以“.”代替。
有的查看器(如FlexHex)还增加了Unicode字符一列,用以显示字节码中包含的Unicode字符。
编程时要考虑到最后一行可能会少于16个字节,这时候第二列和第三列不足的地方就可以使用空格补足。
程序编写的流程如图2-3所示。
图2-3:
编写PEDump程序的流程
如图所示,第1步是打开PE文件。
需要说明的是,打开的PE文件会被映射为内存文件,因为内存文件中的内容是线性存放的,存取方便,速度也快,并且操作起来比在文件中使用指针定位要更容易些。
第2步,使用API函数GetFileSize得到打开的PE文件的大小。
第3步至第5步,将上步获取的值与16相除,商作为循环计数,余数则是字节码查看器最后一行的字节个数。
在程序中构造一个循环,用来显示PE文件除最后一行外其他行的字节内容。
为了更好地理解该开发过程,我们需要理解两个概念:
内存映射文件与PE内存映像。
内存映射文件是指将硬盘上的文件不做修改地装载到内存中。
这样,文件中字节与字节之间就是顺序的了。
在硬盘上,文件被分割成若干簇,这些簇不一定会按照文件内容顺序排列在一起,当我们访问磁盘上的文件时,需要计算机首先将不同位置的内容读取到内存。
有了内存映射文件,访问就会变得更轻松和快捷,由于读取磁盘的操作集中到了一起进行,读写效率会提高很多。
被一次性读取到内存的文件字节按线性排序,访问相对简单,速度也提升了不少。
所以我们在许多大型的编辑软件设计中经常会见到使用内存映射文件存取磁盘文件的示例。
PE内存映像是指将PE文件按照一定的规则装载到内存中,装入后的整个文件头内容不会发生变化,但PE文件的某一部分如节的内容会按照字段中的对齐方式在内存中对齐,从而使得内存中的PE映像和装载前的PE文件出现不同。
那么,为什么PE内存映像不能和一般的内存映射文件一样呢?
答案很简单:
PE文件是由操作系统装载进内存,其目的是为了运行。
为了配合操作系统的运行,方便调度,提高运行效率,PE映像必须按照一定的格式对齐,所以内存中的PE映像和原来硬盘上的文件是不同的,当然与内存映射文件也就不一样了。
2.2.2PEDump编码
简单了解了程序开发的流程,接下来进入编码阶段。
此处将会用到2.1节中的源程序文件pe.asm。
PEDump.asm在pe.asm的基础上增加了对菜单项IDM_OPEN的响应代码,如下所示:
.elseifeax==IDM_OPEN;
打开文件
invoke_openFile
函数_openFile的代码详见代码清单2-3。
代码清单2-3:
PEDump主要代码实现(chapter2\pedump.asm的_openFile函数)
1;
--------------------
2;
打开PE文件并处理
3;
4_openFileproc
5local@stOF:
OPENFILENAME
6local@hFile,@hMapFile
7local@bufTemp1;
十六进制字节码
8local@bufTemp2;
第一列
9local@dwCount;
计数,逢16则重新计
10local@dwCount1;
地址顺号
11local@dwBlanks;
最后一行空格数
13invokeRtlZeroMemory,addr@stOF,sizeof@stOF
14mov@stOF.lStructSize,sizeof@stOF
15pushhWinMain
16pop@stOF.hwndOwner
17mov@stOF.lpstrFilter,offsetszExtPe
18mov@stOF.lpstrFile,offsetszFileName
19mov@stOF.nMaxFile,MAX_PATH
20mov@stOF.Flags,OFN_PATHMUSTEXISTorOFN_FILEMUSTEXIST
21invokeGetOpenFileName,addr@stOF;
让用户选择打开的文件
22.if!
eax
23jmp@F
24.endif
25invokeCreateFile,addrszFileName,GENERIC_READ,\
26FILE_SHARE_READorFILE_SHARE_WRITE,NULL,\
27OPEN_EXISTING,FILE_ATTRIBUTE_ARCHIVE,NULL
28.ifeax!
=INVALID_HANDLE_VALUE
29mov@hFile,eax
30invokeGetFileSize,eax,NULL;
获取文件大小
31movtotalSize,eax
32
33.ifeax
34invokeCreateFileMapping,@hFile,\;
内存映射文件
35NULL,PAGE_READONLY,0,0,NULL
36.ifeax
37mov@hMapFile,eax
38invokeMapViewOfFile,eax,\
39FILE_MAP_READ,0,0,0
40.ifeax
41movlpMemory,eax;
获得文件在内存的映象起始位置
42assumefs:
nothing
43pushebp
44pushoffset_ErrFormat
45pushoffset_Handler
46pushfs:
[0]
47movfs:
[0],esp
48
49;
开始处理文件
50……
177……
178;
处理文件结束
179
180jmp_ErrorExit
181
182_ErrFormat:
183invokeMessageBox,hWinMain,offsetszErrFormat,NULL,MB_OK
184_ErrorExit:
185popfs:
186addesp,0ch
187invokeUnmapViewOfFile,lpMemory
188.endif
189invokeCloseHandle,@hMapFile
190.endif
191invokeCloseHandle,@hFile
192.endif
193.endif
194@@:
195ret
196_openFileendp
子程序_openFile首先调用GetOpenFileName,显示一个文件选择对话框,让用户选择要打开的PE文件,然后获取指定文件的大小,并用这个值使用函数CreateFileMapping在内存中建立该文件的映像,全局变量lpMemory指向了内存映像的起始地址。
有了这个地址,再对文件进行各种操作就简单多了。
行50~177是对内存映像文件的处理过程,这个过程如果太复杂,可以继续使用子程序,如果不很复杂,则可以直接在此编写处理代码,十六进制字节码查看器的主要代码如下:
51;
缓冲区初始化
52invokeRtlZeroMemory,addr@bufTemp1,10
53invokeRtlZeroMemory,addr@bufTemp2,20
54invokeRtlZeroMemory,addrlpServicesBuffer,100
55invokeRtlZeroMemory,addrbufDisplay,50
56
57mov@dwCount,1
58mo
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- WindowsPE权威指南 WindowsPE 权威 指南 戚利第 三个 小工 编写