admin管理员组

文章数量:1530864

2024年7月14日发(作者:)

维普资讯

* … — …… - … 0’… ~ * |^-… … 】 

实用第--/智慧密集 

… … …… … ~… … … 一…… … … 

Win 

张镄 

摘要 介绍了用Win32汇编对PE格式EXE文件进行口令加密的基本原理和方法,并给 

出了实用的加密代码,对研究文件的加密很有参考价值。 

关键词 Win32汇编,PE格式文件,口令加密 

般程序员开发的软件并不希望别人随便使用,为了防止 

就是采用此法,但要求文件头部有足够的空隙来构建节表等。 

别人的非法使用,一般是通过加密的方法对软件进行保护,口 

第三种方法是把附加代码附在目标文件的尾部,构成一个新代 

令加密只是加密方式中的一种。虽然加密的方法对解密高手而 码节,这种方法的优点是附加代码的长度不受限制,但文件的 

言,并不能百分之百的保护,但对一般的使用者来说,加密保 长度会增加,另外,要求文件头有一定的空隙来构建节表。本 

护软件的方法,仍是有效的。 文采用第一种和第三种方法,目的是提高加密的成功率。 

Win32环境下PE格式的文件形式有EXE、DLL、OCX、 要对PE文件进行口令加密,首先要对PE文件的结构有 

SCR等 其中常用的可执行文件是EXE文件,对PE格式的 所了解,下图就是PE文件的基本结构,从这个PE文件的结 

EXE文件进行口令加密,就是在目标EXE文件上附加一段代 

构中,可以看到PE文件是由DOS头、PE文件头、节表和节 

码,通过附加代码中的对话框获取口令,并与附加代码里留存 

等组成,每一个节表对应一个节,节表的排列顺序,也就是节 

的口令进行比较,当口令一致时,表示用户是合法的,否则是 

的排列顺序 PE装载器就是根据PE文件头结构和节表结构中 

非法用户。 

的相应字段将有关的节装入内存中,当然有些节如重定位节 

本口令加密软件分为三个模块。模块1的功能是生成对话 

( reloc节)是不必装入内存的。将加密代码附在日标PE文 

框,选择目标文件,输人口令及校核口令的正确性;模块2的 件后面,就是将加密代码做成一个代码节附在PE文件的后 

功能是判断目标文件是否是PE格式的EXE文件,是否已口令 

面,为了使PE装载器正确地加载附加的加密代码节,必须构 

加密,留存口令,修改目标文件头里的有关结构中的相关字 

建一个新节表使其指向加密代码节,而新添加的节表须位于原 

段,并把加密代码附在目标文件上;模块3的功能是重定位, PE文件节表的末尾,这就要求文件头中的空隙要≥40B(因为 

搜索加密代码中所要用到的API函数的地址,以便使用这些 

节表结构的长度为28H),满足这个条件才能建立一个新的节 

API函数生成对话框,并由对话框接收口令,校核口令的正确 

表。而将加密代码插入节的空隙中,不用构建新节表。 

性,口令正确运行目标文件,口令错误则退出。由于模块1较 

▲ 

10s头 m能GE—c》0s.1H队DER 

简单,本文主要说明模块2和模块3的功能与作用。 

.. D0S Stub 

▲ 

志 PEO0” 

在目标文件上附加口令加密代码 

pE 

E文件头 IMAGE

FILE

....

HEADER 

● lMAGE_OP11ONA _HEADER32 

在对PE格式的EXE文件上附加代码的的方法常用的有三 

▲ 

IMAGE SEC11ONHEADER — 

_

种方法。第一种方法是将附加代码插入在目标文件的代码节或 

_襄 rMAGE SECTION_HEADER — 

其他节(如数据节)的空隙中,一般文件中节对齐在文件中的 

nT曲1e、 IMAGE

SECTION_MEADER — 

_

最大长度是512B(200H),如ML汇编器生成的文件默认文 

I ̄GE_SEC11ON_HEADER 一 

件对齐参数为512B,而代码至少要占用1B,所以最大空隙长 

文件头中的空隙 

度不超过51 1B。但也有一部分文件,如VC++编译器生成的 

▲ 

t瞰节 .- 

I 

文件其默认文件中节对齐的最大长度为4KB(1000H),因 

枯 蛐节 ● 

此,即使是加密代码较长,只要小于4KB,也完全可以插入其 

;c矗iOn .rs 节 ■}—一 

节中空隙。第二种方法是将附加代码分段插入文件中的不同节 

oc节 ・●—一 

的空隙中,这种方法的优点是不会增加文件的长度,CIH病毒 

● 

PE文件的基本结构图 

2008 

电麓确程 冀|技巧冀壤护 _l  

维普资讯

…… 

C0啊PUTER PR0GR^啊啊lHG MAINTENANCE……… ……… …… ………… ………… … …………… 

Characteristics dd 7l j 节的属性 

IMAGE._SECTION

HEADER ENDS 

_

在口令加密中我们要用到文件头中的以下结构及相应 

段: 

1.DOS头结构: 

IMAGE

DOS,HEADER STRUCT 

_

本IJ令加密算法采用将代码插入节中优先,这样可保证文 

件的长度不变;当节空隙不够时,再采用构建一新代码节。在 

目标PE文件中附加口令加密代码的主要过程如下: 

e_magic WORD? ;DOS头标志,“MZ” 

e/fanew DWORD 7 ;指向PE文件头(或文件头偏移 

003ch) , 

IMAGE DOS HEADER ENDS 

(1)判断是否是PE格式的EXE文件,不是则退出; 

(2)判断该PE格式EXE文件是否已加密,加密标志设为 

zz”

已加密则退出; 

(3)循环检查节的空隙是否足够,如空隙足够则将加密代 

码插入对应节空隙中,修改对应节表中的相应字段Virtual— 

Size、Characteristics,修改文件的入 1:3地址Ac]dressOfEntry— 

2.PE文件头(NT映像头)结构 

IMAGE_NT_HEADERS STRUCT 

Signature DWORD 

_

;.PE文件头标志,“PE00” Point,指向加密代码的开始执行点,将修改后的文件头写入目 

FileHeader IMAGE

FILE EADER<> 

OptionaIHeader IMAGE_OPTIONAL HEADER32<> 

IMAGE NT HEADERS ENDS 

标PE文件的头部,将返回地址和口令写入加密代码中,加密 

完成后退出。 

(4)当节的空隙不够时,判断文件头是否有足够的空隙容 

3.映像文件头(FileHeader)结构 

IMAGE_FILE_HEADER STRUCT 

纳新的节表(节表长度28H),不足退出,放弃口令加密; 

(5)有新的节表空隙,修改NT映像头中的相关字段; 

由于新建了一个节(节表),所以要节数+1,即Num— 

berOfSections+1,并修改SizeOfCode和SizeOflmage;另外,要 

NumberOfSections WORD 

IMAGE_FILE EADER ENDS 

;节表(节)的数量 

修改文件的入口地址AddressOfEntryPoint,使其指向加密代码 

的开始执行点; 

, 

4.可选映像头(0pti0nalHeader)结构 

lMAGE OPTIONAL HEADER32 STRUCT 

(6)在文件头中的空隙处建立一新节表,并为新节表的相 

关字段赋值,使其指向新建的加密代码节; 

有Name 1、VitrualSize、VitrualAddress、SizeOfRawData、 

PointerToRawData、Characteristics。 

SizeOfCode DWORD 7 :所有含代码的节的总长度 

AddressOfEntryPoint DW0RD 7 

.:程序开始执行的入口地址RVA , 

SectionAlignment DWORD 内存中节对齐的粒度 

FileAlignment DWORD 7 ;文件中节对齐的粒度 

SizeOfImage DWORD 7 

其中新代码节的VitrualAddress:末节的VitrualAddress+末 

节的VitrualSize并按secti0nAlignment对齐,新代码节的Size— 

j内存中整个PE文件映像的大JJ、 

SizeOfHeaders DWORD 7 

OfRawData=加密代码的长度按FileAlignment对齐,新代码节 

的PointerToRawData=末节l ̄JPointerToRawData+末节的Size一 

0fRawData: 

;DOS头+PE文件头+节表的大小 

DataDirectory IMAGE_DATA_DIRECTORY 6dup(《>) 

(7)将修改后的文件头写入目标PE文件的头部; 

(8)将口令加密代码作为一新建代码节附加在目标PE文 

件的尾部; 

;数据目录结构数组 

IMAGE OPTIONAL_HEADER32 ENDS 

5.节表结构 

IMAGE SECTION HEADER STRUCT 

(9)将返回地址写入加密代码中; 

(10)将口令写入加密代码中。 

下面是附加口令加密代码的主要过程源程序,为了方便阅 

Namel db IMAGE_SIZEOF_SHORT_NAME dup《 ) 

节的名称,长度8字节 

读加了必要的注释;另一点要注意的是PE文件的头部在磁盘 

文件里和在内存映射中是完全一致的,所以我们另外申请了一 

内存块把它装在内存中来修改又快又方便,然后将其重新写入 

Unl on}Misc 

VirtualSize dd?;节的实际大JJ、 

ends 

目标文件的头部来完成对文件头的修改。实现代码如下: 

handlePeFile proc 

VirtuaIAddress dd i节装入内存后的偏移地址RVA 

SizeOfRawData dd? 

定 过程骶要禺 禺 变量 

节在文件中按FileAlignment对齐后的大JJ、 

PPointerToRawData'dd 7;节在文件中的偏移地址 

Qca\@:hFiie;@hMapFi!e,@、p emo @IpAI10c @ 

dvvRet;@SizeOfHeader 

\oca\@ @dwPENeader_off,@RieAiign,@See- 

维普资讯

实用第一 智慧密集 

tionAlign.@SectionNum 

local@NewSection

off.@AppC囱eSize,@AddCodeVirt,@ 

Tip,MB OK 

jmp_ErrFormat:不是PE格式文件,退出 

endif 

AddCodeFile 

pushad 

:‘zz’已加密标志,判断是否已加密,用于防止重复加密 

ifwordptr【ebx+1 ah】 

tionTip,MB OK 

:创建处理异常的SHE结构 

assume fs:nothing 

push 

push 

push 

ebp 

offset ErrFormat 

offset Handler 

= zz 

invoke MessageBox,NULL,addr szCodeText,addr szCap— 

jmp E rrFormat:已加密退出 

endif 

push fs:【O】 

push【ebx】.0pt;ona1Header.FileAlignment 

movfs:【O】,esp 

:将后面要用的参数赋给局部变量 

pop@FileAlign 

:取目标PE文件的扩展名,判断是否是.exe 

invoke Istrlen,addr szFileName 

lea ecx,szFileName 

push【ebx】.0ptionalHeader.SectionAlignment 

pop@SectionAlign 

movedx,dword ptr【ecx+eax一4】 push【ebx】 0ptionalHeader.SizeOfHeaders 

pop@Size0fHeader 

or edx,20202020h :将大写字符转换为小写 

ifedx!= exe. :不是.exe则退出 

push【ebx】.0ptionalHeader.AddressOfEntryPoint 

pop@dwEntry invoke MessageBox,NULL,addr szTexttip,addr szCaption— 

Tip,MB OK 

movzxeax,【ebx】.FileHeader.NumberOfSections 

deceax 

imp_Ret 

endif 

mov@SectionNum eax 

movecx sizeof lMAGE SECTION HEADER 

mulecx . 

:以可读、可写方式打开已存在的目标PE文件,如打开只读 

文件或不存在的文件会报错 

invoke CreateFile,addr SzFileName.GENERlC READ or 

GENERlC WRITE FILE SHARE READ or\ 

FlLE SHARE WRITE,NULL,OPEN EXISTING, 

FlLE ATTRfBUTE ARCHlVE NULL 

ifeax f=fNVALfD HANDLE VALUE 

add eax.@dwPE Header off 

add eax.sizeof lMAGE NT HEADERS 

addeax.sizeoffMAGE SECTION HEADER 

mov@NewSection pff eax 

:申请一块内存,长度为Size0fHeaders,用于文件头的修改 

invoke GlobalAIIoc,GPTR,【ebx】 

OptionalHeader.SizeOfHeaders 

mov@hFile eax 

:创建内存映射对象 

invoke CreateFileMapping,@hFile,NULL, 

PAGE

READWRITE,0,0,NULL 

mov@IpAlloc eax 

movedi,eax 

 .

feax 

mov@hMapFile eax 

:将打开的内存映射文件的头部,长度为Size0fHeaders,传 

:送到申请的内存块里 

invoke RtlMoveMemory,edi,@IpMemory,f ebx】 

OptionalHeader.SizeOfHeaders 

:创建内存映射文件 

invoke MapViewOfFile,eax,FILE MAP READ or 

FILE

MAP_WRITE,0,0,0 

invoke UnmapViewOfFile @IpMemOrv 

ifeax 

:关闭内存映射文件,后面不用了。 

mOv@IpMemory eax 

invoke CloseHandle,@hMapFile 

movebx,eax 

assumeebx:ptrlMAGE D0S HEADER 

:关闭内存映射对象,后面不用了。 

addedi,dword ptr【edi 4-3ch】 :edi一一>丰旨向PE文件头 

assumeedi:ptrIMAGE NT HEADERS 

movesi,edi 

ifwordptr【ebx】!= ZM 

判断D0S头标记, ‘MZ’ 

invoke MessageBox,NULL,addr szE rror,addr szCaption— 

Tip,MB OK 

add esi.sizeof fMAGE NT HEADERS 

assumeesi:ptrlMAGE_SECTION HEADER 

jmp_ErrFormat :不是PE格式文件,退出 

endif 

mov ecx,offset APPEND CODE END—offset 

APPEND CODE 

pushecx 

moveax febx】.eJfanew 

mov@dwPE/-Ieader

off,eax 

Pop@AppCodeSize;加密代码的长度 

xorebx ebx 

addebx,【ebx】eJfanew :ebx一一>丰旨向PE文件头 

assumeebx:ptrlMAGE NT HEADERS 

;循环检查每个节中是否有足够的空隙来插入代码 

ifword ptr【ebx】!= EP 

repeat 

:判断PE文件头标记,‘PE 

invoke MessageBox,N ULL,addr szError,addr szCaption一 

mov edx,【esi】.SizeOfRawData 

_fl edx :判断SizeOfRawData是否为0,为0表示该 

84_电 与雏 

维普资讯

…… 

COMPUT矾PROGB删MING啊^l町E帅脯CE…………… …一………………………………………………… 

PEND_CODE 

mov[ebx]i Misc,\,i髓ualsize;ecx 

__

:节是未初始化数据的节,跳过 

incebx 

add esi,sizeof I MAGESECTION

HEADER 

continue 

endif 

sub edx,\esi]. isc.VirtualSize 

:如果[esil.SizeOfRawData<【esil-M;se.VitrualSize, 

:则Cf=。1, 过o. 

ifCARRY 

、 incebx 

addesi,sizeofIMAGE SECTION EADER 

continue 

endif . 

ifedx>=ecx 

:节中空隙足够,则将加密代码插入节的空隙中。 

\mp insert_code 

endif 

addesi|sizeofIMAGE_SECTION_HEADER 

incebx’ 

Until ebx>@SectionNum 

:当各节空隙都不够插入加密代码时,添加新节(表)。 

movedi @IpAIIoc 

movebx e 

add ebx,@NewSection

off 

_

:ebx—一一>丰旨向最后一个节表的尾部(新节表的头部) 

pushad 

:检查文件头是否有足够空隙构建新节表 

movledi,ex 

moval,0 

mov。ecxf sizeof IMAGE

SECTION_HEADER 

_

cld 

repe scasb 

popadI 

ifIZEROl7 

invoke Me ssage Box NULL add{szNoRoom,addr szCap- 

tionTip,MB_OK 

NoRoomRe弋 

t 

invoke Globa^Free,@IpAIIoc 

._

. 

i文件头没有足够空隙构建节表 退出司令加密 

endif 

mov edx,ebx" 

|一Subedx,sizeofIMAGE_SECTION_HEADER _ 

ledx一一一 抬 最黾一令 轰 头部 

AGE.SECT IO EA DE R 

| 

| |I I 

assume ebx:ptr IMAGE_S ECTIONJ-IEADER,edx:ptr IM- 

一ll|。

addedi,dwordptr[勖文4-3ch、 

|。j始 PE文侮头 

|一- 羹 。assumeedi 州MAGE_NT HEADERS

inc[edi、 ̄FileHeader.NumberOfSections 数 

m州eax,[edx].PointerToRawData  。

|。 0|addeax,[。edx],SizeOfRawData | ll l 。

| |I| | mov[ebx].PointerToRawData,eax 薯| l |一 

’I mov ecX ;of肆se静tA锵PPEN|D

 

_

CQDEI

j 

|乏

| 

- 

i 

l 

off

et

A P

 ̄N D  ̄ 

维普资讯

… ……一… ……… … …… …… … ……… 

实用第一 智慧密集 

… ………… ……… … ………一………………… 

, 

;关闭内存映射文件 

endif 

mov eax,{esi】VirtualAddress 

aa—aeax

【esi】.Misc VirtualSize 

mov@AddCodeV{ft,eax 

ql'10V IeCX,【esi l 】PointerToRawData 

invoke CIoseHandle,@hMapFile:关闭内存映射对象 

endif 

. 

aa~a ecx

【esi】 Misc.VirtualSize 

NoRoom Ret:invoke CloseHandle-,@hFile 

ql"lOV@AddCOdeFiIe.ecx 

:关闭打开的目标PE文件 

else 

mov eax.@ApPCodeSize 

aa—a【esi】.Misc.VirtualSize,eax;修改节的实际大小 

invoke MessageBox,NULL,8a。a。r szErrCreate,addr szCap- 

mlovwora。l0tr【edi+1 ah】, ZZ ;设置力13密标志为 zz 

;以下是二种附加加密代码的公用程序部分,这样设计是 

:为了减小程序的长度 

:修改目标PE文件的入IZl地址,使其指向口令加密代码的 

:开始执行处 

append‘

coa。e:mov eax

_

@AddCodeVirt 

aa—a eax

(offset ewEntry—offsetAPPEND C0DE) 

mov【edi】.0pt{onaIHeader.AddressOfEnt广yPoint, 

eaX 

;nvoke SetFilePointer,@hF_Ie.0,NULL,FILE BEGIeN 

:将修改后的文件头写入目标PE文件的头部 

invoke WriteFile,@hFile,@IpAIIoc,@SizeOfHeacl。一 

er,\ 

addr@dwRet.NULL 

mov eax,@AddCodeVirt 

aa—a eax

(offsetRetOldEntrv—offset 

APPEND CODE+4) 

sub@dwEntry.eax 

:@dwEntry一加密代码执行完后,返回原程序执行的地址 

mov ecx,@AddCodeFile 

add ecx ,(offset RetOIdEntry—offset 

APPEND CODE) 

invoke SetFjIePOinter,@hFile,ecx,NU LL, 

FfLE BEGfN 

将返回地址写在加密代码中0e9h(’imp机器码,1I的后面 

invoke WriteFile。@hFile,aadr@dwEntry,4 addr@ 

dwRet NULL  ‘

mov ecx,@AddCodeFile 

aa~a ecx

(offset APPEND_PASSWD_c0DE—offset 

APPEND CODE) 

invoke SetFiIePOinter,@hFiIe,ecx,NULL,FILE。一 

BEGfN 

将校核后的口令(最大长度为3O个字符) 写入附加的加密 

:代码留存口令处 

invoke WriteFile,@hFile,offset szPwdBuffer2,30, 

addr@dwRet,INULL , 

invoke GlobalFree,@IpAlloc:关闭申请的内存块 

invoke CloseHandle.@hFile 

;关闭打开的目标文件 

assume edi:nothing esi:nothing 

ervoke MessageBox,NULL,addr szOkCode,addr szCap- 

tionTip,MBOK 

jmp et 

_ErrFormat: 

assume ebx:nothing 

invoke Unma pViewOfFile,@fpMemory 

电 螭雅 

tionTip,MB OK 

endif 

et: 

popfs:10】 

addeso。0chI 

popaa。 

ret 

lhandlePeFile ena。p 

二、口令加密的主要功能 

1.重定位 

由于加密代码是在编译、连接之后附加在目标PE文件的 

尾部或节的空隙中,而各个目标文件的长度又是可变的,导致 

附加代码中的变量或过程名偏移地址在装入内存后发生变化, 

使之在目标文件中运行时寻址错误,为了使附加代码中的变量 

地址正确,必须进行重定位。其重定位的标准格式如下: 

call@F 

@@: 

pIop ebx 

:这个寄存器不一定非用ebx,也可使用其他不常用的寄存器 

sub ebx,offset@B 

2.动态获取API函数地址 

由于加密代码是附在各种目标文件的尾部或节的空隙中, 

所需要的API函数地址,各个目标PE文件不可能为你准备 

好,因此,加密代码必须自己想法解决。这就是要用LoadLi— 

brarT函数来动态装入某个DLI 模块,然后再用GetProcAddress 

函数从装入的DLL模块中获取所需要的AP[函数的人口地 

址。但是这二个函数都位于Kernel32.dll中,注意到当Ker. 

ne132.dll把目标程序装入内存后,堆栈的顶部存放有程序的返 

回地址,而这个返回地址正好位于Kernel32.dll中;因此,加 

密代码一开始执行,就从堆栈中取出该地址【esp](如果程序一 

开始就压栈后再取出返回地址,那应是此形式【esp+XXXX]7, 

搜索Kernel32.dll的基地址,然后再搜索GetProcAddress的人 

口地址,获得GetProcAddress的人口地址后,再调用GetPro— 

cAddress函数获取LoadLibrary函数的人口地址,有了这二个函 

数后加密代码所需要的AP1就可以轻松获得。 

3.在加密代码中生成对话框 

对于普通的对话框程序来说生成对话榧较简单,只要在 

Link的时候把程序的目标文件.o 和资源文件.res连接起来 

就可实现。而对于加密代码而言,生成对话框就不那么简单 

维普资讯

…… 

C0啊PUTEB PROMAMMING MAINTENANCE…………………………………………………………………… 

了,不单是需要API函数,而且还需要资源文件,对话框能否 

实现是口令加密的关键问题也是最难的问题,因为加密代码需 

要用对话框来接收输入的口令。当然用命令行输人口令也可 

ey

...

woRD 曩;JX、cy控件的宽和高 j一。 j 毫 

Q D 1 0 \D | j|j 

| 

以。好在Win32汇编提供了对话框模板结构,使我们的问题得 

以解决。无论是模态对话框还是非模态对话框,其建立的过程 

都会用到模板,而模板就是具有相对固定格式的内存块,其中 

的数据用以建立对话框的资源和控件,如菜单、子窗口控件、 

标题栏等,专供代码调用。 

对话框模板主要由二部分组成:模板头和模板控件。 

(1)模板头 

模板头定义对话框的大小、样式、菜单、CLASS、标题名 

DLG iTEMTEMP ̄TE ENDS 

称等。模板头开始的结构如下: 

DLGTEMPLATE STRUCT 

style DWORD 7:对话框样式,如WS APTl0N、 

WS_SYSMENU等 

dwExtendedStyIeDWORD 7:扩展样式,对话框不使用 

cdit 

X 

WORD ?:对话框中控件韵数目 

WORD ? 

Y 

lx 

WORD 7;x、Y对话框的屏幕坐标 

WORD 7 

f 

ly WORD ?;Ix、ly对话框的宽和高 

紧跟DLGTEMPLATE结构后面的是菜单、CLASS和对话框 

DLGTEMPLATE ENDS 

标题等组成的三种可变数组。 

菜单数组:数组元素都是字,数组边界须字对齐。若数组 

第一个元素为0,则该对话框不带菜单,并且数组只有一个元 

紊;若数组第一个元素为Offfh,则第二个元素为菜单资源的序 

数值,接着就是Unicode字符集的菜单资源的字符串名。 

CLASS数组:数组元素都是字,数组边界须字对齐。若数 

组的第一个元素为0,则为标准控件或通用控件类,并且数组只 

有一个元素;若数组第一个元素为0ffffh,则第二个元素为系统 

预定义窗口类的序数值,接着是Unicode字符集的窗口类的字符 

串名。 

标题数组:紧跟在CLASS数组后的是Unicode字符集的标 

题栏名(以0结束),如果都是0则对话框无标题栏。注意,如 

果对话框指定了样式为Ds ETFONT,则紧跟在标题栏后的字指 

定字体的点阵大小,后面跟着Unicode字符集的字体名字符串。 

(2)模板控件 

模板控件定义控件的大小、样式、CLASS、控件标题、成形 

数据等。模板控件的开始结构如下: 

DLGITEMTEMPLATE STRUCT 

style 

dwExtendedStyle 

DWORD 7:控件样式 

DWORD 7 

× WORD 7 

维普资讯

……… … ………… … … …一一 一… …… ……… 

实用第一 智慧密集 

rotoDialogBoxlndirectParam 

_

Ioca}@count 

mov@count,0 

pushad 

cId 

ApiGIobalFreetypedef ptr rotoGIobalFree 

piEndDialog typedef ptr_ProtoEndDialog. 

piGetDIgltemTexttypedef ptr_ProtoGetDIgltemText 

=ApiSetWindowText typedef ptr rotoSetWindowText 

ApiSendDIgltemMessage typedef ptr 

mov esi,_dwarg 

@@:lodsb 

inc@count 

cmpal 0 

__ProtoSendDigItemMessage 

:附加到目标PE文件上的口令加密代码从这里开始 

APPEND

C:ODE equ this byte 

_

jz exit 

jmp@b 

exit: 

popad 

include zz

GetKerne1.asm 

_

hDIIKerne132 dd 7 

hDIIUser32 dd 7 

GetProcAddress piGetProcAddress 7 

MessageBox ApiMessageBox 7 

moveax.@count 

ret 

上oadLibrary ApiLoadLibrary 7 

szLoadLibrary 

szUser32 db 

strlen ene。o 

db LoadLibraryA ,0 

:口令核对过程 

ChkEnterpswd proc 

lDushad 

szGetPrOcAddress db GetProcAddress ,O 

user32 .O 

MessageBOxA ,O szMessageBox db 

call@f 

@@: 

Popebx 

:定义指向对话框函数的指针变量及常量的定义 

etModuleHandle ApiGetModuleHandle 7 

IobalAIIoc ApiGIobalAIIoc 7 

MuItiByteToWideChar

ApiMultiByteToWideChar 7 

subebx,offset@b 

Iea Ieax,【ebx+PswdText】 

invoke strlen,eax 

一DialogBoxlndirectParam piDialogBoxlndirectParam 7 

_j3IobalFree piGIobalFree? 

_EndDialog ApiEndDialog 7 

GetDIgItemText ApiGetDIgltemText? 

SetWindowText ApiSetWindowText? 

SendDIgltemMessage ApiSendDlgltemMessage 7 

Imov【ebx-i-@strlen1 1】,eax 

lea eax,【ebx-i-OldPswdText】 

invoke strl。en,eax 

mov【ebx-i-@strlen22】,eax 

Imovecx,febx-i-@strlen1 1】 

moveax,febx+@strlen22 J 

szGetModuleHandle db GetModuleHandleA .O 

szGIobalAIloc db GlobalAIloc .O 

szMull[iByteToWideChardb MultiByteToWideChar .O 

szDialogBoxIndirectParamdb DialogBox!ndirectParamA 

0 

szGIobatFree db GIobalFree .O 

Ifecx<eax 

xchg eax,ecx 

endif :

1eaesi.【ebx--iOIdPswdText:1 

szEndDialog db EndDialog 10 

leaed 【ebx-i-PswdText】 

cld 

repe cmpsb 

szGetDIgItemText db GetDIgltemTextA ,0 

szSetWindowText db SetWindowTextA ,0 

szSendDIgltemMessage db SendDigItemMessageA O 

APPEND

PASSWD_!=ODE equ this byte 

_

ifZERO7 

popad 

OIdPswdText db30dup《O) 加密后留存的口令 

PswdText db30dup《0) :对话框输入的验证口令 

TitleName db Enter PassWord .O 

moveax,TRUE 

ret 

etse 

ButtonName db 确定 ,O 

FontName db Times NewRoman .0 

lD.PSWDequ 1O1 

lD

EXITequ 202 

_

popad 

moveax.FALSE 

ret: 

. 

endif 

ID CAPTIONequ 1 1O1 1 

ChkEnterpswd endP 

szCaIption db 问题提示: ,0 

TitleTextdb 请输入口令: ,0 

ErrPasswddb 口令错误{ ,0 

hlnstance1 dd 7 

@strlen11 dd 7 

@strlen22dd 7 ’ 

. 

:对话框过程 

DIgProc Proc hWnd:dword,uMsg:dword

wParam:dword 

IParam:dvvrord 

call@f 

@@: 

pOPebx 

:取字符串长度过程 

strlen proc-dwarg 

subebx..offset@b 

if uMsg==WM OMMAND 

电蘑鳙程技巧与维护 -与 辫赫 

维普资讯

…… 

CO啊PUTE矗PROG肌啊啊IHG眦INTEH^一CE… …………… ………………………………………………… 

invoke【ebx+_GetProcAddress】.【ebx+hD Kerne132],eax 

m 、ebx 4-_MuItiByteToWideChar、I eax-一、 

mov eax.wParam 

If ax= lD pswD 

Iea edx,【ebx 4-PswdText】 

invoke【ebx 4- etDIgltemText】,hWnd,lD_PSWD,edx,30 

elseifax::lD_EXIT 

lea eax,【ebx+szGIobalFreel :获取GlobalFree入日地址 

invoke【ebx -4 etP『_0cAddress】J【ebx -4hDIIKernel32】 eax 

mov、ebx_、_ IobaIFree、I eax 

invoke【ebx 4-_EndDialog】,hWnd,NULL 

endif 

_

:获取D_alogBoxlndirectParam入口地址 . 

lea eax,【ebx -4szDialogBoxln rectParam l 

“ 

。 。

elseif uMsg:=WM

INITDIALOG 

invoke【ebx+ etProcAddress] 【ebx+h DllUser32 eaX 

Jea ecx,f ebx 4-TitleText】 

invoke【ebx 4-_setWindowText】,hWnd,ecx 

mov f ebx+_Dia,log BoxlndirectPaFam】 eax 

e8 eax,【ebx -4szEndD_al0g】 :获取EndDialog入口地址 

invoke I ebx -_4GetProcAddress】,febx -4hDIIUser32】J eax 

mov、ebx+王ndDl\a\o eax 

lea eax,【ebx 4-szGetDigltemText】 ‘ 

}nvoke【ebx -4_sendDIgItemMessage】.hWnd 1D_PSWD, 

EM_LlMlTTEXT,1 8,NULL 

invoke【ebx -4_sendDlgltemMessage】,hWnd,ID_PSWD, 

EM_sETPASSWORDCHAR,42,NULL 

eIse 

:获取GetDigltemText入IZ!地址 

;nvoke【ebx 4- etProcAddress 【ebx 4-hDIlUser32】.eax. 

moveax,FALSE 

ret 

m刚、ebx+ etDigItemText、l eax 

lea e8x,【ebx 4-szSetWindowText】 

’ 

I 

- -

endif 

● 

获取SetWindowText入 地 

invoke【ebx+_』3etProcAddress】J【ebx+hDlIUser32],eax 

mov、ebx -4 etWindowText、1 eax 

lea—eax,【ebx+szSenaDIgltemMessage】 

mov eax TRUE 

ret 

DlgProc endp 

:口令加密代码的入口 

_NewEntry: 

1获取SendDIgltemMessage入I:q地址 

invoke【ebx+_GetProcAddress】,[ebx 4-lhDIIUser3 2】 ̄eax 

:重定位 

call@F 

。 

mov、ebx -4_SendDIg\temMessage、I eax 

@@: 

pop ebx 

sub ebx.offset@B 

lea eax, ebx -SZMessageBox、 4

I获取MessageBox入I:q地垃 

eax 

一 。。。 

invoke 【ebx+_GetProcAddress] 【ebx+hDIIUser32], 

mov【ebx+—MessageBox】,eax 

invoke GetKernelBase,I esp】 

pushad 

:获取Kernel32.dll基地址 

rnov【ebx 4-hDIIKerne132 eax 

invoke ebx 4- etModuleHandIe、.NULL 

I获 模块 甸柄 

| 

lea eax.【ebx 4-szGetProcAddress】 

mov[ebx -hi4nstanoel、I eax

:获取GetProcAddress入口地址 

invoke 

_

GetApi,【ebx+hDllKernel32】I eax 

对话框模板申请长度为4K,用O初始化,地址固定的内存 

块 甩千建立对话框模摄。 

invoke、ebx 4- IobaIAIloc] GMEM_FIXED or 

GMEM ZEROlNIT,1024 4  -

mov【ebx 4-.j3etProcAddress】,eax 

lea eax,【ebx 4-szLoadLibrary】 

。。。 

:获取LoadLibrary入IZ!地址 

invoke 

ne132】,ea× 

【ebx+ etProcAddress】.【ebx+hDllKer- 

。 mov【ebx+_LoadLlbrary eax 

lea eax,、ebx 4-szUser32、 一 

movwordptr、e 4-8 2 控悻数目 

, 

一 || 

:获取User32.d¨基地址 

invoke【ebx 4-_LoadLibrary】,eax 

mov【ebx -hDI4IUser32lI eax 

lea eax;【ebx+szGIobalAIIoc] 

I 话框 屏幕坚标 200,180)

movword edi 4、. 10 

| ll? 

j|| 

:获取GIobal Al10c入口地址 

invoke【lebx 4-GetProcAddress 【ebX+hDI1Keme132】,eax 

d邸\ed、+、 

菜单2字 、 

、ea 

! 话 大j\\、、Qx ≯|l 

l I ||| 

j薯 : …0 

mov【ebx+ IobalAIloc】,eax 

lea eaX。I ebx十szeetModuleHand Je】 

2字 ,共221} 

me、 宅 +弋 

:获取GetModuleHand!e入口地址 

}nvoke【lebx -4J3etProcAddress I ebx+hDIIKerne132】.ea× 

moV【ebX+ etModuleHandle】.eax 

rn ecx

eax 

No e + 

蝇 0 

| l |l|i | |t | | 

、l cPAcP蕾i|| I i薯誊。 

C |邑心f |l j |薯 

获取 UltiByteToWideChar入 地 

1ea eax;【ebx -szMul4tiByteToWideCha rl 

1 

e弋 l、de 

J f\D 

维普资讯

…一… ~……一… …… … … …… ……… 一… 

实用第一 智慧密集 

popecx 

moveax.ecx 

序数值0081 h代表Edit类 

addedi.22 

shleax,1 

lea edx.【ebx+PswdText】 

invoke strlen,edX 

addedi,eax 

movwordptr【edi】.9 

added .2 

;字体点阵大小 

movecx,eax 

DuSh‘ecx 

lea edx,【ebx+FontName】 

invoke strlen.edx 

movecx,eax 

invoke【ebx+ ultiByteToWideChar】,CP_ACP. 

MB_PRECOMPOSED,edx,一1,edi,eax 

DODecx 

..

pushecx 

moveax,ecx 

invoke【ebx+ u t ByteToWideChar】I CP_ACP, 

shleax,1 

addedi,eax 

MB PREC0MPOSED.edx.一1,edi.eax 

popecx 

moveax,ecx 

add edi,3 

shredi,2 

shl edi,2 

shleax,1 

addedi.eax 

addedi.3 

shredi,2 

lea ecx,【ebx+DIgProc】 

创建模态对话框 

invoke 【ebx十一pialogBoxlndirectParam】, 【ebx+hln— 

stance1 1,esi,NULL.ecx,NULL 

. 

shl edi,2 :起始地址双字对齐 

:按钮控件 

movdword ptr【edi】,ws_vISIBLEorWS_CHILD:按钮样式 

movwordptr【edi+81,3O 

movWOrdptr【edi+10】.27 

:对话框关闭后释放申请的内存块 

invoke【ebx十一j3IobalFFee】J esi 

oo

oad 

..

invokeChkEnter

oswd 

按钮在对话框中的坐标(30,27) 

movwordptr【edi+12】,40 

:校对用户输入的口令的正确性 

If】eax:口令错误,则退出。 

lea ecx,【ebx+ErrPasswd】 

lea eax,【ebx+SZCaotion】 

’invo。Ke【ebx+ essageBox】,NULL,ecx,eax.MB K 

ret 

movword ptr【edi+14】,1 2 按钮的大小4O×1 2 

movword ptr【edi+16】,lD_EXIT:按钮标识 

movword ptr【edi+18】,Offffh 

movwordptr【edi+20】,O080h 

endif 

序数值O080h代表Button类 

addedi,22 

口令正确,执行原来的目标尸E文件 

dbOe9h :Oe9h是jmpXXXXXXXX的机器码 

RetOldEntw: 

lea edx,【ebx+ButtonName】 

invoke strlen,edx 

movecx.eax 。 

dd 7:用来填写返回到目标PE文件的入口地址 

APPEND

CODE

END equ this byte 

pushecx 

invoke【ebx+ ultiByteToWideChar】,CP_ACP, 

MB_PRECOMPOSED,edx,一1,edi,eax 

popecx 

moveax,ecx 

三、结语 

本文在WindowsXP中文版下对多个PE文件进行测试,效 

果良好。还有可以改进的地方,如埘输入的}]令进 加密,增 

加防静态分析和反动态跟踪的功能,使加密软件更加安全可 

靠。另外,有兴趣的读者可以在此加密原 的基础上,开发出 

・ 

shleax.1 

addedi,eax 

addedi,3 

对应的解密程序(或防病毒免疫程序),以更加方便实用。 

shredi,2 

shl edi,2 :起始地址双字对齐 

编辑控件 

mov dword ptr【edi】,WS ISIBLE or ws cHILD or 

WS

TABSTOP orws 8ORDER:编辑框样式 

_

参考文献 

l罗云彬编著.Windows环境下32化 :编 言程序设计(第2 

版).北京:电子工业出版社,2006. 

movword ptr【edi+8】.13 

movwordptr【e +10】,10 

(1 3 X 10) 

编辑框在对话框中的坐标 

. 

2吴中平编著.Windows汇编语言程序设计.北京:清华大学 

出版社,2004. 

movword ptr【edi+1 2】,8O 

3严义,包健等编著.Win32汇编语占’程序设计教程.北京: 

机械工业出版社,2004. 

(收稿日期:2008年1月17日) 

movword ptr【edi+14】,1 2 编辑框的大小80 X 1 2 

movwordptr【edi+16】,ID_PSWD 编辑框标识 

movword ptr【edi+18】,0ffffh 

movword ptr【edi+2O】,0081h 

‘ 

, ‘ 

柏 

本文标签: 文件加密代码口令对话框