Win32下病毒設計入門詳細解說
描述:圖1
圖片:
本文假定你對dos下的病毒和386PM有一定的了解。
1、感染任何一個病毒都需要有寄主,把病毒代碼加入寄主程序中(伴侶病毒除外)
以下說明如何將病毒代碼嵌入PE文件中,有關PE文件的結構請看以前的文章。 PE文件的典型結構:MZ Header DOS STUB CODE PE HEADER OPTIONAL HEADER SECTION TABLE SECTION 1 SECTION 2 ... IMPORT TABLE EXPORT TABLE 和DOS的可執行文件類似,PE的代碼映象分爲幾個SECTION,在文件中會對齊頁邊界(4K)。一般來說,文件會加載在400000h開始的空間,而第一個SECTION在401000h處,同時入口地址也是401000h。
由高級語言編寫的程序,每個SECTIO-N的長度不可能剛好是4K的倍數,因此在SECTION的末尾將會存在一段未用的空間,大小可由Section的PHYSICAL SIZE-VIRTUALSIZE得到,在文件中起始位置可由 PHYSICAL OFFSET得到,這段空間可以用來存放病毒代碼。此外一般來說,MZ Header+DOS STUD+PEHEADER+OPTIONAL HEADER+SECTION TABLE不過1K左右,而SECTION 1由4K開始,空出來的地方足夠存放一個設計精良的病毒。CIH就是將代碼存放在這些空閑空間裏。
2、分配駐留所需內存
對於駐留形的病毒,分配駐留所需內存是必需的。在DOS下使用由於所有的 應用程序都映射在相同的線性地址空間裏,使用一般的內存分配調用就足夠了。而在WIN32下,每個應用程序都有自己的線性地址空間,必須使用特殊的函數分配2GB以上的係統地址。典型的如:VXD服務_PageAllocate,和kernel32的 VxDCALL _PageReserve。_PageAllocate請參看win98ddk中的說明,VxDCall _PageReserve 請參看HPS源碼中的注釋。
3、截留FILE I/O操作 駐留型的病毒通過截留FILE I/O來激活,可以通過使用VXD服務
IFSMgr_Install-FileSystemAPIHook(如CIH)或截留VxDCall中的DOS Services callback(如HPS)。
在Win32下編寫病毒不是一件困難的事。值得注意的有幾件事:
一、Win32下的係統功能調用不是通過中斷實現,而是由DLL中導出
(直接使用VxD服務除外)。直接在病毒中得到API入口不是一件容易的事,可以通過以下這個變通的方法。
在同一個版本的Windows下,同一個核心函數的入口總是固定的(指由Kernel32,gdi32,user32導出的函數)。因此可以用以下的方法得到函數入口:
(圖1)
在Intialize Code得到要用的函數入口並將它填入病毒中,在病毒運行時可以直接使用了。
本人的一台操作係統爲Win2000 Server的筆記本電腦最近被感染了病毒,我首先用相關殺毒軟件來掃描計算機,掃描報告如下:
病毒名稱:Hacktool
文件名:c:\winnt\system32\ntservice.exe
操作:刪除失敗,隔離失敗,訪問被拒絕
如何才能徹底 刪除呢?
因爲c:\winnt\system32\ntservice.exe已經在運行了,直接刪除顯然是不可能的。於是我運行Windows任務管理器,在進程選 項卡中選擇結束ntservice.exe進程,結果係統顯示“無法中止進程,拒絕訪問”。
我突然想到在Win 2000(XP)的控制台狀態下是可 以用DOS命令的。
什麽是控制台
控制台是Windows的一種簡易運行模式,它可以不啓動圖形界面而在命令行狀態下有限制地訪問 FAT和NTFS分區,並對係統進行一些設置和操作。
通過控制台,我們可以更換係統文件、關閉或者禁用某個係統服務、禁用或卸載硬件 設備、修複引導扇區、新建分區以及格式化硬盤分區等。
啓動控制台
對於Windows 2000,我們可以用光盤啓動電腦,然後在安 裝程序的選單中按R鍵選擇“修複Windows 2000安裝”,再從修複選單中按C鍵選擇“故障恢複控制台修複Windows2000”。
對於 WindowsXP,同樣是用光盤啓動電腦,然後按R選擇修複,就能直接進入控制台。
直接把控制台的相關選項安裝到啓動菜單中的方 法:把光盤放入光驅,然後直接在運行中輸入“d:\i386\winnt32/cmdcons”之後回車(這裏假設你的光驅是D),再點擊“是”,就可以把控 制台選項安裝到高級啓動菜單中,這樣以後直接從硬盤就可以進入控制台中。這個方法適用於Windows 2000和Windows XP。
在控制台的 命令提示符下,爲安全起見,我首先對ntservice.exe進行備份,然後直接運行:del c:\winnt\system32\ntservice.exe就OK了。
二、主要是要截留文件I/O操作
Windows下截留文件I/O操作有幾種方法,在病毒中使用的主要有兩種。
1、使用VxDCallIFSMgr_InstallFileSystemHook
2、截留Kernel32.dll中導出的第一個函數VxDCall對DOS
INT 21的呼叫(EAX=2A0010)。
VxDCall的代碼如下:
mov eax,dword ptr [esp+04]
pop dword ptr [esp]
call fword ptr cs:[xxxxxxxx]
^^^^^^^^只要將這個地址指向的地址改爲自己的過程入口,就捕獲了所有的VxDCall。
進入這個過程時:
eax=service number,如果是DOS INT 21將是2A0010
esp[2c]調用Int 21時eax的值
~~~~ 算漏了個pushad,應該是10h
esp[30] 調用int 21時ecx的值
~~~~14h
其他寄存器爲調用時所需的值。(段寄存器無用)
以後的就和在DOS下寫病毒沒什麽差別了。
在WINDOWS下寫病毒,如何得到API的入口是一件麻煩的事. 可以直接使用的API都在DLL中,而VXDCALL要在RING0時才能使 用,DOS的INT 21服務也不能直接調用. 得到DLL中的API入口有兩種方法:
1.加載時得到,建立一個 IMPORT TABLE,在加載時WINDOWS會根據IMPORT TABLE定位API的 入口地址.這是一般應用程序的使用的方法,但不大適合病毒。
2.運行時得到,使用GetModuleHandle和GetProcAddress得到API的入口,但前提時要知道GetModuleHandle和GetProcAddress的 入口地址.:< 這是明顯也是不可能的.除了將GetModuleHandle和GetProcAddress的代碼複制到我們的病毒中,只有使用暴力在 2GB的空間內找出API的入口了。
首先說明一下WINDOWS的內存映射,由00000000開始有一段是無效地址(我忘了到底到多少了),用來捕獲應用程序錯誤的指針。
跟著一直到0x7FFFFFFF爲應用程序的空間.0X80000000以後爲係統 的空間,DLL和VXD都映射在這裏.我們要作的就是從這2GB的空間內找到Krnl32.dll. 一般來說,Windows下的程序都是對齊在64k的邊界.首先是MZ 文件頭,跟著是由MZ HEADER中的信息可以得到PE HEADER的入口. 由這個標記就可以找出所有的DLL.由PE HEADER可以得到DLL的 EXPORT TABLE的入口,其中而NAME PTR TABLE的第一項爲DLL的名 稱,由此可以找出Krnl32.dll,並從ADDRESS TABLE中得到任何一個 API的入口.。
值得注意的是,在這2GB中並不是所有而地址都是有效的,在 一般的程序中可以通過IsXXXXXPtr來判斷地址是否有效,但在病毒 中不行.只能Hook Exception,忽略訪問無效的地址導致的Exception. Windows中的Exception Chain的結構如下: fs:[0] dword exception發生時esp的新值,該值指向一個如下 的結構 [esp] dword fs:[0]的新值 [esp+4] dword exception handler的入口 [esp+8] dword exception handler使用的數據首地址 [esp+12] dword -1詳細的彙編代碼可以用C寫一段__try...__except的代碼,然後 轉譯成彙編. 只要我們的exception handler直接跳轉到病毒中尋找Krnl32.dll 的代碼,就可以不引起GP Error而訪問任何的地址了。 範例可以參看HPS的源碼,PE HEADER,EXPORT TABLE請參看PE FORMAT.。
1、在Windows下載入的DLL在不同的process中映射到同一個地址。
2、在DLL中導出的函數在export table中記錄相對DLL Image Base 的偏移,改變這個偏移使用GetProcAddress得到的地址就會改變。 (想象一下,把CreateProcess地址指向自己的DLL中的函數,或者截獲GetDlgItemText來記錄Password)
3、在Kernel32.DLL中Section Table在0x300以前就結束了,而真正的代碼由0x1000處開始,其間有3K的未用空間,可以用來存放我們的代碼。 Kernel32.DLL的Image Base可以由GetModuleHandleA得到。
4、在任何版本的Windows中,3個基本的DLL總是被加載(Kernel32.DLL,User32.DLL,無法使用之字串32.DLL),而且對於同一個版本的Windows,它們的Image Base,和導出函數的地址總是固定的。可以將得到的地址直接用於病毒使用。