⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.asm

📁 Nbw加密锁源代码,一个用汇编编写的加密锁源代码
💻 ASM
📖 第 1 页 / 共 2 页
字号:
;*********************************************************
;程序名称:可执行文件加密锁
;本文件是主文件的源代码
;本程序可以对有效的PE文件进行加锁,使程序运行以前必须通过密码验证
;作者:牛博威
;日期:2003-12-10
;整理:2003-12-11
;出处:http://nboy.cnwlt.com
;注意事项:如欲转载,请保持本程序的完整,并注明出处
;在此特别感谢罗聪大侠和他的论坛上的朋友们.同时感谢孙灭给我提供罗云彬老师的win32汇编书,这本书确实不错
;说明:
;1、被本程序加锁后的程序代码长度会增加4096字节,我对此表示抱歉,以后我会考虑把添加的代码嵌入到原来的程序中.
;2、我的加密水平不高,没有对密码进行加密处理,本来想进行一下异或处理,后来想想还是不献丑了,等以后会了CRC再说吧.
;4、解锁的时候在上面的文本框中写一个密码就可以了,下面的密码框不用管
;5、本程序主要供技术研究,所以很多地方作的不全面。如果哪位有兴趣改进,不妨交流一下
;*********************************************************
		.386
		.model flat, stdcall
		option casemap :none
include		windows.inc
include		user32.inc
includelib	user32.lib
include		kernel32.inc
includelib	kernel32.lib
include		comdlg32.inc
includelib	comdlg32.lib
ICO_MAIN	equ	1000
DLG_MAIN	equ	1000
IDC_INFO	equ	1001
IDM_MAIN	equ	2000
IDM_OPEN	equ	2001
IDM_EXIT	equ	2002
IDC_PATH	equ	2003	;显示指定文件的对话框	
IDC_PASS1	equ	2004	;用户密码框 
IDC_PASS2	equ	2005	;用户密码确定框 
IDC_BROWSE	equ	2006	;浏览文件按钮
IDC_CHANGE	equ	2007	;文件加锁按钮
IDC_UNCHAN	equ	2008	;文件解锁按钮
		.data?
hInstance	dd	?
hRichEdit	dd	?
hWinMain	dd	?
hWinEdit	dd	?
szFileName	db	MAX_PATH dup (?)
szNewFile	db	?
_pass1		db	9  dup(?)	;存储用户输入的密码,共8位密码,占9个字节
_pass2		db	9  dup(?)
_szErr		db	?
		.const
szz	db	"修改完毕!请保存好密码.请检查bak备份文件.....",0
szzz	db	"解锁完毕,请检查!请检查bak备份文件....",0
szDllEdit	db	'RichEd20.dll',0
szClassEdit	db	'RichEdit20A',0
szFont		db	'宋体',0
szBak		db	'.bak',0
szExtPe		db	'PE Files',0,'*.exe;*.dll;*.scr;*.fon;*.drv',0
		db	'All Files(*.*)',0,'*.*',0,0
szErr		db	'文件格式错误!',0
_Introduce	db	'	欢迎使用nbw文件加密锁', 13, 10
		db	'你可以去http://nboy.cnwlt.com下载源代码.', 13, 10
		db	'作者 : 牛博威', 13, 10
		db	'QQ   : 37122085', 13, 10
		db	'Email: advice107@sina.com', 13, 10
		db	'欢迎和我联系!',0
szErrPass	db	'两次输入的密码不一样或密码长度超出了8位,请核查!',0
szErrCheck	db	'您输入的密码错误!',0
szErr1		db	'文件无法打开!',0
szErr2		db	'无法创建文件内存映像!',0
szErr3		db	'这不是有效的PE格式文件!',0
szErr4		db	'这个文件已经被加过锁了!',0
szErr5		db	'文件没有足够空间再添加新的节表,如您想加锁,请和我联系!',0
szErr6		db	'这个文件没有被加过锁!',0
_SehM		db	'发生错误,请确定操作或找我联系!',0
_SehT		db	'提示',0
		.code
;********************************************************************
_Handler	proc	_lpExceptionRecord,_lpSEH,_lpContext,_lpDispatcherContext
		local	@szBuffer[256]:byte
		pushad
		mov	esi,_lpExceptionRecord
		mov	edi,_lpContext
		assume	esi:ptr EXCEPTION_RECORD,edi:ptr CONTEXT
		mov	[edi].regEip,offset _SafePlace
		assume	esi:nothing,edi:nothing
		popad
		mov	eax,ExceptionContinueExecution
		ret
_Handler	endp
;********************************************************************
_Init		proc
		local	@stCf:CHARFORMAT
		invoke	GetDlgItem,hWinMain,IDC_INFO
		mov	hWinEdit,eax
		invoke	LoadIcon,hInstance,ICO_MAIN
		invoke	SendMessage,hWinMain,WM_SETICON,ICON_BIG,eax
		invoke	SendMessage,hWinEdit,EM_SETTEXTMODE,TM_PLAINTEXT,0
		invoke	SetWindowText,hWinEdit,addr _Introduce
		invoke	RtlZeroMemory,addr @stCf,sizeof @stCf
		mov	@stCf.cbSize,sizeof @stCf
		mov	@stCf.yHeight,9 * 20
		mov	@stCf.dwMask,CFM_FACE or CFM_SIZE or CFM_BOLD
		invoke	lstrcpy,addr @stCf.szFaceName,addr szFont
		invoke	SendMessage,hWinEdit,EM_SETCHARFORMAT,0,addr @stCf
		invoke	SendMessage,hWinEdit,EM_EXLIMITTEXT,0,-1
		ret
_Init		endp
;********************************************************************
_OpenFileA	proc	uses eax,hWnd			;打开文件,找出指定的文件路径,指向szFileName
		LOCAL	@stOF:OPENFILENAME
		invoke	RtlZeroMemory,addr @stOF,sizeof @stOF
		mov	@stOF.lStructSize,sizeof @stOF
		push	hWinMain
		pop	@stOF.hwndOwner
		mov	@stOF.lpstrFilter,offset szExtPe
		mov	@stOF.lpstrFile,offset szFileName
		mov	@stOF.nMaxFile,MAX_PATH
		mov	@stOF.Flags,OFN_PATHMUSTEXIST or OFN_FILEMUSTEXIST
		invoke	GetOpenFileName,addr @stOF
		invoke	SetDlgItemText,hWnd,IDC_PATH,addr szFileName
;**********;保存原来的文件
		invoke lstrcat, addr szNewFile, addr szFileName        
		invoke lstrcat, addr szNewFile, addr szBak             
		invoke CopyFile, addr szFileName, addr szNewFile, FALSE		
;**********	
		xor	eax,eax
		ret
_OpenFileA	endp
;********************************************************************
_ChangeFile	proc	hwnd
		LOCAL   hFile    : DWORD
		LOCAL   hMapping : DWORD
		LOCAL   pMapping : DWORD
		LOCAL   ByteWrite: DWORD
		LOCAL	HostEntry: DWORD
		pushad
		invoke	CreateFile,addr szFileName,GENERIC_READ+GENERIC_WRITE,FILE_SHARE_READ + \
			FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL
		.if	eax ==	INVALID_HANDLE_VALUE
			invoke	MessageBox,hwnd,addr szErr1,NULL,MB_OK or MB_ICONWARNING
			jmp	_exit
		.endif
		mov	hFile,eax
		invoke	CreateFileMapping,hFile,NULL,PAGE_READWRITE,0,0,NULL
		or	eax,eax
		jz	IF_F3
		mov	hMapping , eax 
		xor	edi,edi
		push	edi              
		push	edi
		push	edi                  
		push	FILE_MAP_READ+FILE_MAP_WRITE 
		push	hMapping
		call	MapViewOfFile
		or	eax,eax
		jnz	@F
		invoke	MessageBox,hwnd,addr szErr2,NULL,MB_OK or MB_ICONWARNING
		jmp	IF_F2
@@:
		mov	pMapping,eax  
		mov	esi,eax 
		assume	esi:ptr IMAGE_DOS_HEADER 	
		cmp	[esi].e_magic,IMAGE_DOS_SIGNATURE
		jnz	IF_F1
		cmp	[esi].e_lfarlc,040h  
		jnz	IF_F1
		add	esi,[esi].e_lfanew
		assume	esi:ptr IMAGE_NT_HEADERS
		cmp	[esi].Signature,IMAGE_NT_SIGNATURE    ;是PE文件吗?
		jnz	IF_F1
		cmp	[esi].OptionalHeader.Subsystem,2
		jnz	IF_F1           
		cmp	[esi].OptionalHeader.CheckSum,0	;判断文件校验和,由于这个加密锁目前在XP或2000下不支持,所以这里的校验和可以不用判断	
		jz	@F                    ;合法性判断完毕,开始修改文件
		invoke	MessageBox,hwnd,addr szErr3,NULL,MB_OK or MB_ICONWARNING
		jmp	IF_F1
@@:
		mov	eax,[esi].OptionalHeader.AddressOfEntryPoint 
		add	eax,[esi].OptionalHeader.ImageBase 
		mov	HostEntry,eax                    ;保存原入口 
		movzx	eax,[esi].FileHeader.NumberOfSections         
		mov	ecx,sizeof IMAGE_SECTION_HEADER 
		mul	ecx			;计算所有节表的长度
		add	eax,sizeof IMAGE_NT_HEADERS                
		add	eax,esi		
;******************
;令eax指向文件最后一个节表,并判断节表名称是不是77626e2e(即.nbw)
		sub	eax,sizeof  IMAGE_SECTION_HEADER 
		push	eax
		mov	eax,[eax]
		cmp	eax,77626e2eh 
		pop	eax
		jnz	@F
		invoke	MessageBox,hwnd,addr szErr4,NULL,MB_OK or MB_ICONWARNING
		jmp	IF_F1
@@:
		add	eax,sizeof IMAGE_SECTION_HEADER
;******************
		mov	edi,eax			;edi指向文件头的尾部
		add	eax,sizeof IMAGE_SECTION_HEADER
		sub	eax,pMapping                       
		cmp	eax,[esi].OptionalHeader.SizeOfHeaders ;判断文件头是否可以再添加一个节表.
		jna     @F
		invoke	MessageBox,hwnd,addr szErr5,NULL,MB_OK or MB_ICONWARNING
		jmp	IF_F1 
@@:
;*****************************************	;下面正式修改文件
		inc	[esi].FileHeader.NumberOfSections                      
		assume	edi:ptr IMAGE_SECTION_HEADER         
		mov	dword ptr[edi],'wbn.'         ;填写新的节表名称"nbw."
		push	VEnd-VStart
		pop	[edi].Misc.VirtualSize        ;填写要添加的代码的长度
		push	[esi].OptionalHeader.SizeOfImage 
		pop	[edi].VirtualAddress         ;新节(注意不是节表)的地址
		mov	eax,[edi].Misc.VirtualSize
		mov	ecx,[esi].OptionalHeader.FileAlignment
		div	ecx
		inc	eax 
		mul	ecx
		mov	[edi].SizeOfRawData,eax        ;按文件粒度对齐
		lea	eax,[edi-28h+14h]              ;上一个节的文件地址(OA)
		mov	eax,[eax]
		lea	ecx,[edi-28h+10h]              ;上一个节的大小
		add	eax,[ecx]
		mov	[edi].PointerToRawData,eax     ;填写新节的OA
		mov	[edi].Characteristics,0E0000020h  ;可读可写可执行 
;*****************************************
;更新文件头,使新节可以正确加载并首先执行 
		push	_NewEntry-VStart		;使新的eop定位到newentry而不是VStart,这样做是因为新的代码部分定义了变量,
							;我们要为这些代码预留出相应的空间
		pop	ecx
		mov	eax,[edi].VirtualAddress
		add	eax,ecx
		push	eax
		pop	[esi].OptionalHeader.AddressOfEntryPoint     ;修改文件eop
		mov	eax,[edi].Misc.VirtualSize 
		mov	ecx,[esi].OptionalHeader.SectionAlignment 
		div	ecx 
		inc	eax 
		mul	ecx 
		add	eax,[esi].OptionalHeader.SizeOfImage 
		mov	[esi].OptionalHeader.SizeOfImage,eax 
;********************************
;把新节的内容写到文件中
		push	FILE_BEGIN
		push	0 
		push    [edi].PointerToRawData
		push    hFile
		call    SetFilePointer
		push    0
		lea     eax,ByteWrite
		push    eax
		push    [edi].SizeOfRawData
		push    offset VStart
		push    hFile
		call    WriteFile	       ;设置文件指针到结尾后,写入从VStart开始的代码,大小已经计算过了
		push    FILE_BEGIN
		push    0 
		push    [edi].PointerToRawData
		push    hFile
		call    SetFilePointer		;重新把文件指针指到新节的开始,把程序原来的入口地址写入新节中的return变量处
		invoke	WriteFile,hFile,addr HostEntry,4,addr ByteWrite,NULL
		invoke	WriteFile,hFile,addr _pass1,8,addr ByteWrite,NULL	;把8位密码写入文件中的password变量(看下面的变量定义)处
		assume	esi:nothing  ;消对esi的定义.这里如果不写,编译器或许不出问题,但是当程序写大的时候,编译时候会发生意外难以查找的错误
;**********************************
		invoke	SetWindowText,hWinEdit,addr szz
IF_F1:
		push	pMapping
		call    UnmapViewOfFile
IF_F2: 
		push    hMapping
		call    CloseHandle
IF_F3:
		push    hFile
		call    CloseHandle
IF_Exit:
		popad
		jmp	_exit
;********************************************
;********************************************
;下面是添加到文件中的内容
_ProtoGetProcAddress	typedef	proto	:dword,:dword
_ProtoLoadLibrary	typedef	proto	:dword
_ProtoInitialize	typedef	proto	:dword,:dword
_ApiGetProcAddress	typedef	ptr	_ProtoGetProcAddress
_ApiLoadLibrary		typedef	ptr	_ProtoLoadLibrary
_ApiInitialize		typedef	ptr	_ProtoInitialize
VStart		equ	this byte
return		dd	1  dup(?)		;保存原来的入口地址
password	dd	9  dup(?) 
_GetProcAddress	_ApiGetProcAddress	?	;声明用到的函数
_LoadLibrary	_ApiLoadLibrary		?
_Initialize	_ApiInitialize		?
hDllCounter	dd	?
_hModule	dd	?	;模块基址
_lpszApi	dd	?	;指向目的函数名
@dwReturn	dd	?	;保存查找到的函数入口地址
@dwStringLength	dd	?	;保存函数的长度
szLoadLibrary	db	'LoadLibraryA',0
szGetProcAddress db	'GetProcAddress',0
szCounter	db	'Counter',0
szInitialize	db	'szInitialize',0
_NewEntry:			
		call	@F
		@@:
		pop	ebp
		sub	ebp,offset @B		;重定位,不用说了吧
;********获取Kernel32.dll的模块首地址
		mov	edi,[esp]   
		mov	[ebp+@dwReturn],0
		and	edi,0ffff0000h
		.while	TRUE
			.if	word ptr [edi] == IMAGE_DOS_SIGNATURE
				mov	esi,edi

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -