Bootstrap

《Windows PE》第一章 PE学习环境搭建

基础篇

第一章 PE学习环境搭建

在正式学习PE之前,先给大家介绍一下学习WindowsPE所需的开发环境和相关工具软件的使用方法。

本章学习知识概要:

      源码编译工具

      静态分析工具

      动态分析工具

    1. 源码编译工具

本书提供的示例代码有两种,一种是32位汇编语言代码,另一种是32位C语言代码。因此,需要使用汇编语言和C语言两种不同的编译工具。接下来我们将介绍汇编和C语言两种编译环境的搭建。有兴趣的读者可以将两种代码互译。

本节必须掌握的知识点:

    汇编语言开发环境

    C语言开发环境

1.1.1 汇编语言开发环境

MASM32介绍

MASM32是Steve Hutchessond在微软的不同产品基础上集成开发出来的汇编开发工具包,适合Win32编程环境的汇编语言,主要用于基于Windows平台的32位汇编语言开发, 是现在最流行的Win32汇编开发包。与VC++和VB等高级语言相比,Win32汇编具有得天独厚的优势,这些优势主要体现在:

(1)摒弃了对系统细节的封装,更接近于系统的底层,从而使得编码更加灵活,能完成许多髙级语言无法做到的事情(如代码重定位和特殊寄存器赋值等)。

(2)生成的可执行PE文件体积小,执行速度快。

(3)可用于软件的核心程序段设计,以提高软件的性能。

(4)能够直接接触系统的底层,所以使用它要远比使用VC++和VB等高级语言更适合开发与系统安全相关的程序。比如,与计算机硬件密切相关的驱动程序的开发、计算机病毒的分析与防治、软件加密与解密、软件调试、Windows PE研究等。

MASM32是一个免费的软件包,该软件包中包含了汇编器ml.exe、资源编译器rc.exe、32位的链接器link.exe和一个简单的集成开发环境(Intergrated Development Environment, IDE) QEditor.exe。

软件包中的ml.exe来自Microsoft的MASM软件包,rc.exe和link.exe则来自Microsoft的 Visual Studio。

MASM32软件包还包括了详尽的头文件、导入库文件、例子文件、帮助文档和一些工具程序,如lib.exe和dumpbin.exe等。可以从网站http://www.masm32.com/上获得MASM32 SDK的最新版本(masm32v11r),并可以在论坛里与来自世界各地的汇编爱好者交流技术和思想。

       ■MASM32安装

步骤1:运行安装程序install.exe,安装汇编环境。

首先选择安装路径,此处我们选择的路径为 D:\(软件),然后单击“Install”按钮,如图1-1和图1-2所示。此后,中间过程所有的按钮均选择默认的设置,即可完成软件安装。安装结束后,会显示IDE汇编集成环境QEditor的界面,如图1-3所示。我们也可以选择自己熟悉的文本编辑工具,建议使用Notepad++,如图1-4所示。

图1-1 MASM32安装                                                                

图1-2 安装路径

图1-3 Qeditor                                                                           

图1-4 Notepad++

步骤2:建立自己的工作区

建议选择将软件安装到非系统盘(例如D盘)。为了能存放自己编写的汇编代码。可以在D:\masm32中新建立一个文件夹source存放代码。也可以在其他目录新建一个文件夹,如图1-5所示。接下来设置汇编程序所依赖的环境,以及要调用的API函数库都在该文件夹内。

图1-5 设置工作区

步骤3设置系统环境变量

“我的电脑”上点鼠标右键,选择“属性”,选择“高级”选项 卡,单击“环境变量”按钮,在用户的环境变量中增加以下三个环境变量,如图1-6所示:

1.include=d:\masm32\include        //头文件目录

2.lib=d:\masm32\lib               //lib库

3.path=d:\masm32\bin            //编译工具软件

如果系统中已经存在相同名字的环境变量(如path变

量),则在该变量的值的最后加上一个分号,然后加

上上面列出的值即可。

例如,假设未设置前系统存在路径变量path,且值为:

C:\Users\16400\AppData\Local\Microsoft\WindowsApps

修改以后的值为:                                     

d:\masm32\bin; C:\Users\16400\AppData\Local 

\Microsoft\WindowsApps

特别提示:要用英文输入,且不要忘记前面的分号。               

也可以建立系统环境变量的批处理文件:假设文件名为var.bat

@echo off

set include = d:\masm32\include

set lib = d:\masm32\lib

set path = d:\masm32\bin;%path%

echo on

图1-6 环境变量设置

文件中设置了3个环境变量:

1.indude变量指定头文件的搜索目录。定义了这个环境变量后,ml.exe和rc.exe在处理asm和rc文件中遇到include语句时,会自动在环境变量定义的目录中查找include 语句指定的文件,这样include语句中就不必写头文件的全路径名,如下所示:

include c : \masm32 \ include\windows . inc     //不设置. include 环境变量时的写法

include windows . inc                        //设置include环境变量后可以这样写

这样处理的好处是以后移动了 MASM32的安装位置后不必修改每个源文件中的include语句。

如果使用Visual C++的集成环境来建立rc文件的话,为了使rc.exe能找到头件,还要把VC++安装目录下的include和MFC\include 目录包含进来,多个路径之间用“;”隔开:

set include=x:\masm32\include;VC目录\include;VC目录\MFC\include。

2.lib环境变量指定导入库文件的搜索目录。ml.exe根据这个变量寻找include lib语句指定的导入库文件,Link.exe也根据这个变量寻找库文件的位置。

3.path环境变量可以使我们不必在键入命令时带长长的路径。

代码编辑工具软件2使用Nodepad++,如图1-7所示。可以根据个人偏好选择自己满意的编辑工具。

实验一:使用NotePad++编写32位汇编源程序HelloWord.asm。

图1-7 Notepad++

        

源代码

;FileName:HelloWorld.asm

;例1:第一个32位汇编源程序

;by:bcdaren

;2021.01.06

;=======================================

.386 ;支持386及以上CPU

.model flat,stdcall  ;flat内存模式,stdcall调用约定

option casemap:none   ;区分大小写

;Windows系统头文件和导入库

include windows.inc

include user32.inc

includelib user32.lib

include kernel32.inc

includelib kernel32.lib

;数据段简化定义

.data

szCaption      byte "hello",0

szText            byte "Hello,welcome to PE!",0

;代码段简化定义

.code

start:

       ;显示窗口信息

       invoke MessageBox,NULL,offset szText,offset szCaption,MB_OK

       invoke ExitProcess,NULL;退出程序,返回操作系统

end start;程序入口地址

参见本书源代码ch01。

命令行编译方式

步骤1:进入工作区

通过转换磁盘命令和CD命令进入存放源文件HelloWorld.asm的目录中,命令如下:

C:\Users\16400>d:

D:\>cd D:\code\winpe\ch01

D:\code\winpe\ch01>

步骤2:编译源文件

在当前工作区中输入命令:

“ml -c -coff HelloWorld.asm”或者“ml /c /coff HelloWorld.asm”,然后回车。

D:\code\masm32\Chapter28\HelloWorld>ml -c -coff HelloWorld.asm

Microsoft (R) Macro Assembler Version 6.14.8444

Copyright (C) Microsoft Corp 1981-1997.  All rights reserved.

 Assembling: HelloWorld.asm

***********

ASCII build

***********

参数-c表示独立编译,不进行链接;

参数-coff表示编译后生成标准的COFF目标文件(Windows PE文件)——必须使用,否则无法识别外部标识符或函数名。 编译以后会在源文件所在目录生成一个与源文件同名的obj目标文件。

ml.exe是汇编语言的编译程序,它负责将汇编源程序编译成目标文件。该程序可接受的 各参数的解释和描述如下所示:

/AT允许支持微型内存模式                             /nologo不输出编译LOGO信息

/Bl<linker>使用其他的链接器                         /Sa打开所有可用信息列表

/c只编译不链接                                              /SG在列表中增加指令执行时间信息

/Cp保留所有用户定义标识符的大小写           /Sf在列表中增加第一次编译后的信息

/Cu将所有标识符转换为大写                         /Sl<width>设置行宽

/Cx保留公共和外部符号的大小写                   /Sn生成列表文件时关闭符号表

/coff编译成符合公共目标文件格式的目标文件/Sp<length>设置列表文件每页

/D<name> [=text]定义给定名字的文本宏        /Ss<string>为列表文件设置子标题

/EP生成一个预处理后的列表文件                   /St<string>为列表文件设置标题

/F <hex>设置栈大小                                   Sx允许在列表中列出条件为假的代码清单

/Fe<file>指定可执行文件名                             /Ta<file>编译不以.asm结尾的源文件

/FI [file]生成汇编代码列表文件                        /w同参数/WX

/Fm[file]生成一个链接映像文件                       /WX将警告视为错误

/Fo<file>指定目标文件名                      /W<number>设置警告级别

/FPi为浮点运算生成模拟代码                         /X忽略INCLUDE环境变量

/Fr [file]生成.sbr源浏览文件                            /Zd增加行号调试信息

/FR[file]生成扩展形式的.sbr源浏览文件         /Zf使所有符号变成公共符号

/G<c|d|z>指定使用不同语言格式的函数调用约定和命名约定   /Zi增加符号调试信息

/H<number>外部名字有效长度                    /Zm设置为与MASM .10兼容的模式

/l<name>指定包含文件路径                           /Zp [n]设置结构对齐

/link <linker options and libraries> 包含链接   /Zs 只进行参数检查

步骤3:链接目标文件与动态链接库

链接是为了将源文件中调用到的动态链接库中的函数的相关信息附加到可执行文件中。 链接命令是:

link -subsystem:windows HelloWorld.obj  ;或用’/’代替‘-’

命令行输入链接命令:

D:\code\masm32\Chapter28\HelloWorld>link -subsystem:windows HelloWorld.obj

Microsoft (R) Incremental Linker Version 5.12.8078

Copyright (C) Microsoft Corp 1992-1998. All rights reserved.

参数-subsystem表示允许该代码运行的子系统(必须要的),这个例子需要加载windows 动态链接DLL。如果没有错误,执行以上命令后会在源文件所在目录下生成最终的可执行文件HelloWorld.exe。

链接器

●链接程序的参数解释如下:

Microsoft (R) Incremental Linker Version 6.00.8168 Copyright (C) Microsoft Corp 1992-1998. All rights reserved.

usage:LINK [options] [files] [@commandfile]

options:

/ALIGN:#节区对齐尺寸

/BASE:{address | @filename, key}设置映像地址

/COMMENT:comment 在头部插入一个注释字符串

/DEBUG 创建调试信息

/DEBUGTYPE :{CV| COFF} 创建特定格式(CV/COFF)的调试信息

/DEF: filename      指定链接库导出函数声明文件

/DEFAULTLIB :library 指定处理外部引用时使用的特定库

/DLL生成目标为DLL文件

/DRIVER [: {UPONLY|WDM}]创建Windows NT 核心启动程序

/ENTRY:symbol 设定目标PE入口点

/EXETYPE:DYNAMIC生成动态加载的虚拟设备驱动程序

/EXPORT:symbol导出一个函数

/FIXED [:NO]创建的目标PE只加载到首选基地址处

/FORCE [: {MULTIPLE | UNRESOLVED}]针对那些UNRESOLVED或MULTIPLE定义的符号实施强制链接

/GPSIZE:#在MIPS和Alpha平台上指定公有变量的尺寸

/HEAP:reserve [, commit]设定保留或提交的堆的大小

/IMPLIB:filename涵盖默认的引入链接库名

/INCLUDE:symbol 指定包含INC文件

/INCREMENTAL: {YES | NO} 是否控制增量连接

/LARGEADDRESSAWARE [ :N0]通知编译器应用程序是否支持大于2GB的地址

/LIBPATH:dir LIB文件所在路径,允许用户重写该环境变量

/MACHINE:{ALPHA| ARM | 1X86 | MIPS | MIPS16 | MIPSR41XX | PPC | SH3 | SH4 }指定目标平台

/MAP [: filename]创建一个MAP文件

/MAPINFO:{ EXPORTS | FIXUPS | LINES }在MAP文件中包含指定的信息(如导出信息、行等)

/MERGE:from=to 合并节

/NODEFAULTLIB [:library] 在处理引入符号时忽略所有的默认库。

/NOENTRY 创建纯资源DLL文件

/NOLOGO 无LOGO

/OPT: {ICF[, iterations] | NOICF | NOREF | NOWIN98 |REF|WIN98}控制 LINK优化

/ORDER:@f ilename按预定顺序将COMDATs放置到映像文件中

/OUT:filename指定输出文件名

/PDB:{filename |NONE}创建 PDB 文件

/PDBTYPE:{CON [SOLIDATE] | SEPT [YPES] }指定在哪里存储PDB调试类型信息。

/PROFILE 创建一个MAP文件。

/RELEASE在文件头部设置校验和。

/SECTION:name, [E] [R] [W] [S] [D] [K] [L] [P] [X]设置指定节区的属性。

/STACK:reserve [, commit]设置保留或提交堆栈的大小。

/STUB:filename指定DOS STUB块从文件中获取。

/SUBSYSTEM: {NATIVE | WINDOWS | CONSOLE | WINDOWSCE | POSIX} [,#[.##]]指定子系统。

/SWAPRUN: {CD | NET}告诉操作系统在运行映像前先将链接器的输出复制到交换文件中。

/VERBOSE [:LIB]输出链接过程的信息。

/VERSION:# [.#]指定主次版本号。

/VXD创建一个虚拟设备驱动器。

/WARN [:warninglevel]链接时打开警告级别。

/WINDOWSCE : {CONVERT | EMULATION}创建基于Windows CE 的目标映像文件。

/WS:AGGRESSIVE 修剪程内存。

 注意

此处列举的参数并非link.exe程序支持的所有参数,例如,此处没有出现的-DelayLoad参数,在后面的章节中会用到。

此外,编译器和链接器的参数只需要记住常用的几个参数就可以了。

make工具

●make工具介绍

make工具可以看成是一个智能的批处理工具,通过调用makefile文件中用户指定的命令来进行编译和链接 。但是,批处理会执行全部命令将全部源文件编译,包括那些不必重新编译的源文件,make工具则可根据目标文件上一次编译的时间和所依赖的源文件的更新时间自动判断 应当编译哪些源文件,对没有更新过的文件不会处理,这样就可以大大提高程序调试的效率。

举例

举例说明,写一个test.exe文件,生成最后的可执行文件有4个步骤:

(1)汇编源文件test1.asm,其中用到头文件common.inc,它们经ml.exe编译成test.obj。

(2)汇编源文件test2.asm,用到头文件common.inc和test.inc,它们经ml.exe编译成test2.obj。

(3)资源脚本文件test.rc,经rc.exe编译成test.res。

(4)最后用Link将test1.obj,test2.obj和 test.res 链接成 test.exe。

可以看出,当程序调试的时候,如果修改了 test1.asm,也就是说test1.obj的文件时间比test1.asm 要早,就需要重新执行步骤(1)和(4)。如果修改了 test2.asm或test.inc,那么需要重新执行步骤(2)和(4)。如果修改的是test.rc,则步骤(3)和(4)必须重新执行。如果修改的是common.inc,因为test1.asm和test2.asm都和它有关,所以步骤(1)、(2)和(4)都要重新执行。如果同时修改了common.inc和test.rc,那么必须重复全部步骤。

在这个例子中,文件的依赖关系就是:

• test.exe 依赖于 test1.obj,test2.obj 和 test.res;

• test.res 依赖于 test.rc;

• test1.obj 依赖于 test1.asm 和 common.inc;

• test2.obj 依赖于 test2.asm、common.inc 和 test.inc。

make可以根据文件的时间正确判断文件的新旧并执行相应的步骤。但make又是如何 知道文件之间的依赖关系呢?这需要用户用一个描述文件来指定。前面提到的makefile就是这个描述文件,执行make工具的时候,它会默认用makefile做描述文件名来进行相应的工作,书写描述文件有规定的语法,虽然语法不是很简单,但写好以后就省事多了。

Microsoft的make工具文件名为nmake.exe,它并不是MASM软件包的一部分,需要在Visual C++的Bin目录下找到nmake.exe,并复制到MASM32开发环境bin目录下才可以使用。Borland公司的make工具文件名是make.exe,它已经包括在TASM 5.0工具包中。两者默认的描述文件名都是makefile,描述文件的语法也大同小异,只是使用时命令行参数有些不同。

make 的使用法

在命令行键入nmake /?可以显示帮助信息。

nmake的语法如下

nmake [选项][/f描述文件名][/x输出信息文件名][宏定义][目标]

说明如下:

/f参数:如果描述文件名不使用默认的makefile,可以用/f参数指定。

/x参数:如果想把屏幕输出的信息存到一个文件中,可以用/x参数指定(用DOS 下的管道操作符nmake >文件名的方法无效)。

宏定义:可以用新的定义覆盖描述文件中的宏定义。

目标:指定建立描述文件中描述的某个文件。

nmake常用的选项

如表1-1所示:

选项

   

/A

不检测文件时间,强制更新所有文件

/B

文件时间相等时也要更新文件

/D

make时显示文件新旧信息

/N

显示make时要执行的命令,但并不真正执行

/P

一个比较有用的选择,make时显示详细信息

表1-1 nmake常用选项

由于nmake的应用是基于文件时间的,当计算机的时钟不准确或文件拷贝到另一台计 算机后文件时间有些偏差,那么文件的更新可能会不正确,这时最好用/A选项强制把所有 文件更新一遍。在平时使用的时候,以makefile当做建立的描述文件名,那么仅键入不加参数的nmake命令就可以完成所有工作了。

编写make文件

# makefile文件

# 宏定义

NAME = HelloWorld

EXE = $(NAME).exe                           #输出文件

OBJS = $(NAME).obj                          #目标文件

ML_FLAG = /c /coff                           #编译选项

LINK_FLAG = /subsystem:windows    #链接选项

# 定义依赖关系和执行命令

$(EXE):$(OBJS)

       link $(LINK_FLAG) $(OBJS)

# 定义汇编编译和资源编译默认规则,$<表示使用默认原文件名

.asm.obj:

       ml $(ML_FLAG) $<

.rc.res:

       rc $<

# 清除临时文件

clean:

       del *.obj

       del*.res

描述文件的语法

注释

以#号开头一直到行尾的字符,当nmake 工具处理到这些字符的时候,它会完全忽略#号及其后面的全部字符。makefile的换行符是’\’。

宏定义

在引用宏时只需在变量前加$符号, 但是要注意的是,如果变量名的长度超过一个字符,在引用时就必须加圆括号(),下面 都是有效的宏引用:

$(LINK_FLAG)

$(EXE)

$A

$ (A)

$最后两个引用是完全一致的。

●显式规则

makefile中包含有一些规则,这些规则定义了文件之间的依赖关系和产生命令,一个规则的格式是这样的:

目标文件:依赖文件;命令(方法1)

目标文件:依赖文件 (方法2 )

命令——命令前有一个tab符

在规则定义和命令行中,不能包含注释。

●隐含规则

隐含规则可以为某一类的文件指出建立的命令,它具体定义了如何将带一个特定扩展 名的文件转换成具有另一种扩展名的文件,定义的格式是:

.源扩展名.目标扩展名:命令(方法1)

.源扩展名.目标扩展名: (方法2)

       ●命令

隐含规则的语法和显式规则相似,也是用“:”隔开,在“;”下面书写命令,也可以不用而将命令写在第2行,同理,这时命令之前要加一个Tab字符。

隐含规则不能有依赖文件,所以下面没有内容,例子中的第17、18行定义了从 asm文件建立obj文件的隐含规则,第19和20行定义了从rc文件建立res文件的隐含规则,隐含规则中无法指定确定的输入文件名,因为输入文件名是泛指的有相同扩展名的一整类文件,这时候就要用到几个特殊的内定宏来指定文件名,这些宏是$@,$*, $?和$<, 它们的含义如下:

• $@——全路径的目标文件。

• $*——除去扩展名的全路径的目标文件。

• $?——所有源文件名。

• $<——源文件名(只能用在隐含规则中)。

●使用make工具编译链接

实验二:使用make工具编译链接HelloWorld.asm源程序。

命令行输入命令:

       D:\code\winpe\ch01>nmake /a

Microsoft (R) Program Maintenance Utility Version 14.13.26132.1

Copyright (C) Microsoft Corporation.  All rights reserved.

        ml /c /coff HelloWorld.asm

Microsoft (R) Macro Assembler Version 6.14.8444

Copyright (C) Microsoft Corp 1981-1997.  All rights reserved.

      Assembling: HelloWorld.asm

***********

ASCII build

***********

        link /subsystem:windows HelloWorld.obj

Microsoft (R) Incremental Linker Version 5.12.8078

Copyright (C) Microsoft Corp 1992-1998. All rights reserved.

●运行

       图1-8 运行

创建资源

       资源编译器的使用

资源编译器用来把资源脚本文件(*.rc)编译成资源文件(*.res),MASM32 SDK软件包中使用的Visual C++附带的rc.exe程序,TASM软件包中使用的是BRC32.exe或 BRCC32.exe,两者的用法都比较简单,它们有相同的命令行语法:

RC或BRC32 [选项]资源脚本文件名

资源脚本文件中一个典型的对话框定义如下: 

DLG_MAIN    DIALOG 0,0,176,     66

STYLE     DS_MODALFRAME I WS_POPUP I WS_VISIBLE I WS_CAPTION I WS_SYSMENU CAPTION "对话框模板"

FONT     9,"宋体"

{    

DEFPUSHBUTTON "退出 ",IDOK, 120, 46, 50, 14    

CONTROL" ",-1, "Static",SS_ETCHEDHORZ I WS_CHILD I WS_VISIBLE,7,38 , 164, 2

}

DLG_MAIN:资源ID;

DIALOG:资源类型;

0,0,176,     66:对话框大小;

STYLE:对话框风格,模态对话框,弹出式,可见的,有标题,有系统菜单;

CAPTION       :对话框标题"对话框模板"

FONT:对话框字体,9号"宋体"字

接下来的大括号内包含两个控件:

一个是DEFPUSHBUTTON "退出 "按钮控件,控件ID和大小。

另一个控件是"Static"静态文本控件,标题为空,ID为-1,使用 EDGE_ETCHED 边缘样式绘制,可见的子窗口控件,大小为“7,38 , 164, 2”。

1.1.2 C语言开发环境

VS开发工具

编程达人系列教材以Windows平台为基础,因而C语言的开发环境选用Visual Studio(简称VS)作为开发工具。Visual Studio是微软开发的一个功能非常强大的IDE,可用于构建Windows、Mac、Linux、iOS和Android跨平台应用程序。Visual Studio是一个集成开发环境工具包,包括源代码编辑、编译、链接、调试,此外还集成了图形设计工具、代码完成工具、代码管理功工具等。附带可即时使用的多种不同语言、框架和运行时的支持(例如,.NET、Python、C++、Node.js 和 TypeScript),甚至附带更多可用的扩展。

●Visual Studio下载安装

1.微软官方网站下载

https://docs.microsoft.com/zh-cn/visualstudio/?view=vs-2019

Visual Studio 2022、2019、2017或其他版本

图1-9 Visual Studio下载

提示

       可以选community个人免费版;或者Professional试用版(需要注册微软账户)

2.下载后运行,并点击继续

图1-10 安装步骤一

图1-11 安装步骤二

图1-12 安装步骤三

3.安装组件

在提取文件之后显示的安装界面如图1-13所示,需要勾选添加“使用C++桌面开发”和“通用Windows平台开发”两个组件。以后使用过程中,可以根据实际需要,在“工具”菜单下选择“获取工具和功能(T)…”或者“扩展和更新(U)”,添加需要的功能组件或工具。

图1-13 安装组件

新建项目

    ●步骤一:VS安装完之后,开始新建一个项目。打开 “文件”菜单,依次点击“新建”-> “项目”,如图1-14所示。

图1-14 新建项目

步骤二:接下来弹出的界面如图1-15所示。界面下方填写项目名称,位置(可以通过右侧“浏览”控件选择合适的保存路径)。最后一项就是填写解决方案名称。同一个解决方案下可以创建多个项目。界面左侧选择“Visual C++”,“Windows桌面”,界面中间位置选择“Windows桌面向导”,最后点击确定。

步骤三:点击确定之后,显示图1-16界面,选择“控制台应用程序(.exe)”,勾选“空项目”,然后点击“确定”。

图1-15 新建C\C++Windows桌面项目

图1-16 新建控制台程序

   

步骤四:创建完项目之后,最后一步新建源代码文件。如图1-17所示,在项目Project1中,选中左侧源文件,点击鼠标右键,选择“添加”->“新建项”新建一个新的源文件。如果是打开一个已存在的源文件,选择“添加”-> “现有项”就可以了。

图1-17 新建源文件

Visual C++编辑资源 Visual C++本身是一个很大的软件包,里面集成了资源编辑功能,它也是所见即所得的编辑工具,并且支持最新的资源特征。如最新的对话框风格和一些新的控件等,同时它是双字节版本,不必担心乱码问题。Visual C++也支持编辑脚本文件*.rc和资源文件*.res。

图1-18 VS添加资源

可以在两者之间互相转换。单从功能方面考虑,用Visual C++来编辑资源是一个很好的选择。

如果要添加资源,在VS解决方案资源管理器一栏,鼠标选中资源文件,并点击鼠标右键,选择“添加”>“资源”,如图1-18所示。

VS提供了一些预定义的资源类型,如快捷键、位图、鼠标、对话框、图标等。可以选择右侧按钮“导入”,导入已有的资源。也可以选择自定义资源,点击“自定义”按钮,定义新的资源类型并导入,如图1-19所示。

图1-19 添加自定义和预定义资源

       实验二:第一个C语言例子

       步骤一:新建解决方案“winpe”。

       步骤二:解决方案资源管理器中选中“源文件”,点击鼠标右键,点击“添加”>“新建项”,新建C语言源程序HelloWord.c,如图1-20所示。

       步骤三:编写源代码。

/*------------------------------------------------------------------------

 例2:HelloWorld.c

 (c) bcdaren, 2024

-----------------------------------------------------------------------*/

#include <windows.h>

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,

 PSTR szCmdLine, int iCmdShow)

{

     static TCHAR szAppName[] = TEXT ("Hello") ; // 窗口类名

     MessageBox(NULL, TEXT("Hello,welcome to PE!"),

         szAppName, MB_OK);

     return 0;

}

图1-20 新建C语言项目

提示

为了方便对比测试,我们需要使用VMWare创建一个XP系统的虚拟机。在虚拟机的XP系统中搭建古老的VC6.0编译环境。此外再搭建一个masm32汇编编译环境。将本书给出的示例代码,在XP系统环境中再编译一遍。VC6.0的使用方法与VS2017差不多,这是稍微古老一些。如果在使用中有所不明白的地方,请读者查阅一下相关的资料,不再赘述。

;