為PE文件添加新節顯示啟動信息
?| 下載本節例子程序和源代碼 (7.66 KB) |
病毒并不神秘,也不復雜。相當多的大俠已經在這方面作出了杰出的貢獻,例如 29A 組織,我對他們的崇拜之情啊,真是……咳咳,先別扔雞蛋。其實我想說的是:技術是一柄雙刃劍,我們應該把它運用在對社會有益的事情上。所以請勿利用本文的代碼進行違法違紀的活動,否則本人保留追究的權利。
本文的技術其實早已是老掉牙的東西了,so如果你已經懂得了編寫病毒的方法,請跳過本文;如果你對病毒抱有好奇心,但是還沒知道怎么編寫,那么本文應該適合你。??:)
言歸正傳。在 Windows 環境下,所有的可執行文件都是 PE 格式,因此編寫病毒最重要的環節之一就是對 PE 文件進行操作。但是在此我不打算對 PE 格式進行講解,請讀者自行參考有關資料。我只對我在實際編寫中遇到的難點進行分析:
首先,計算機病毒之所以叫做病毒,是因為它跟自然界中病毒一樣,都需要有一個宿主——它本身是無法單獨執行的。那么,當病毒寄生在宿主上后,怎樣讓它的代碼執行呢?我們先來看一些概念。
PE 的代碼映象分為幾個 SECTION,在文件中會對齊頁邊界(4K)。一般來說,文件會加載在 400000h 開始的空間,而第一個 SECTION 在 401000h 處,同時入口地址也是 401000h。這個入口地址 401000h 是怎么計算出來的呢?如果你查看 PE 頭的 IMAGE_OPTIONAL_HEADER ,就會發現它的 ImageBase 一般是 400000h ,而 AddressOrEntryPoint 一般是 1000h 。 400000 + 1000 = 401000h ,明白了吧?掌握了這一點,我們就可以在 PE 中添加我們自己的新節,然后把這個入口地址改成指向新節的第一條代碼。當新節執行完畢后,再把原入口恢復,這樣一來就能繼續執行宿主的代碼了。
在幾乎每個 Win32 病毒的開頭都有這樣的語句:
| ????call nStart nStart: ????popebp ????subebp,offset nStart |
這些語句是用來干嘛的呢?好像是吃飽了飯沒事干哦……其實不然。讓我們來仔細考慮一下。當正常的 PE 程序執行時,它的基址(如前所述)一般是 400000h ,這個地址會由操作系統為你重定位,因此總是能保證程序被成功地裝載運行。但是,如果我們在 PE 中插入了一段新的代碼,假設它要從 654321h 處開始執行,那么事情就沒有那么簡單了。因為宿主程序并沒有預料到這段代碼的存在,而操作系統也不可能為你修正這個偏移。因此我們就要自己進行重定位操作。上面的語句就是取得病毒在宿主中的實際偏移地址。Call 指令實際上是 push 和 jmp 的組合。當 call nStart 時,實際上是把 call nStart 的下一條指令(也就是pop ebp)的地址壓入堆棧然后 jmp 到 nStart ,由于之前已經把 pop ebp 的地址壓入了堆棧,所以當真正執行到 pop ebp 這條指令的時候,實際上就是把 pop ebp 這條指令的地址放到了 ebp 中。這樣就得到了當前病毒代碼的真正的偏移地址。這也是病毒中常用的手法。幾乎無一例外。
接下來還有一個關鍵的問題。我們的病毒代碼是附屬在宿主上的,如果要在病毒中使用 API ,則必須首先得到 API 的入口地址。不過這可不是一件容易的事情啊。為什么這樣說呢?讓我們先來看看下面的代碼:
| invoke ExitProcess,0 |
在經過編譯器的編譯、連接后,它在內存中形如:
| :00401015????Call0040101A :0040101A????Jmpdwordptr[00402000] |
也就是說,ExitProcess 的調用是通過 Call 0040101A ,而 0040101A 處的代碼是一個 Jmp ,指向 [00402000] ,這個 [00402000] 處儲存的才是真正的 ExitProcess 的入口地址。
為什么要經過那么多周折呢?呵呵,其實我也不知道。但是我們知道的是,調用一個 API 實際上是調用它在內存中的地址。而病毒由于是在宿主編譯完之后才附屬上去的,所以如果病毒要運行 API ,則必須自己指定 API 的入口地址。
是不是很煩呢?Hoho,堅持一下吧,就快大功告成了。
要得到 API 的入口地址,方法有很多種,例如可以通過硬編碼,這是比較簡單的方法,但是它的缺陷是不能在不同的 Windows 版本下運行,不過由于它實現起來比較簡便,因此本文還是采用這種方法。
在同一個版本的 Windows 下,同一個核心函數的入口總是固定不變的(指由 Kernel32, Gdi32, User32 導出的函數),所以我們就可以利用下面的方法得到 API 的入口:
在病毒中我們就可以用 Call MessageBoxA_Addr[ebp] 來執行 MessageBoxA 這個 API 了。
好啦,我已經把我認為比較重要的難點解釋了一次了,如果你還有什么不清楚的地方,歡迎給我來信。lcother at 163 dot net
下面我給出了一個例子程序,它的作用是為 PE 文件添加一個新節以顯示啟動信息。這個東東會在 PE 文件的末尾添加一個新節,我給這個節命名為“.LC”,被附加的程序在運行的時候會先彈出一個對話框,顯示我們的提示信息。你可以對它稍作修改,例如加上自己的版權信息,然后給 CS 的主程序打上這個“病毒”,接著……呵呵,等著看舍友的驚訝的目光吧!實際上只要對它進行一些額外的補充,它就可以算是一個小小的病毒了。
值得注意的是,本程序要對代碼段進行寫操作(也就是SMC),所以在編譯連接的時候應該這樣做:
| rc Add_Section.rc ml /c /coff Add_Section.asm link /subsystem:windows /section:.text,RWE Add_Section.res Add_Section.obj |
Have fun!
它的資源文件:
| #include "resource.h" #define IDC_STATIC????????-1 #define IDI_LC????????????1 #define IDC_BUTTON_OPEN?? 3000 IDI_LC????ICON????"lc.ico" LC_DIALOG DIALOGEX 10, 10, 195, 115 STYLE DS_SETFONT | DS_CENTER | WS_MINIMIZEBOX | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "Section Add demo by LC, 2002-11-10" FONT 9, "宋體", 0, 0, 0x0 BEGIN ????GROUPBOX???????? "Info", IDC_STATIC, 5, 5, 185, 75 ????CTEXT????????????"- 為PE文件添加新節顯示啟動信息 -", IDC_STATIC, 10, 20, 175, 10 ????CTEXT????????????"-= Virus Tutorial Series =-", IDC_STATIC, 10, 30, 175, 10 ????CTEXT????????????"老羅的繽紛天地", IDC_STATIC, 10, 50, 175, 10 ????CTEXT????????????"www.LuoCong.com", IDC_STATIC, 10, 60, 175, 10 ????DEFPUSHBUTTON????"打開文件(&O)",IDC_BUTTON_OPEN, 70, 90, 55, 15, BS_FLAT | BS_CENTER END |
老羅
2002-11-10
posted on 2006-05-08 17:48 楊粼波 閱讀(426) 評論(0) 編輯 收藏 引用 所屬分類: 文章收藏

