該項目僅為實驗性項目,主要目的是想隱藏一個Te.net后門在主板的Bios內(nèi),并讓其隨著計算機(jī)系統(tǒng)及操作系統(tǒng)成功的運行起來。運行后能反向Telnet連接到指定的計算機(jī)接受控制。
A、如何編寫B(tài)IOS模塊(如:PCI、 ISA)。
B、實模式關(guān)于HOOK磁盤中斷的問題。
C、磁盤中斷中選擇再次HOOK的問題。
D、NT保護(hù)模式下設(shè)置物理地址映射。
E、NT保護(hù)模式下線性地址尋址問題。
Bochs虛擬機(jī)可以調(diào)試BIOS及操作系統(tǒng),Bochs使用主要是配置它的配置文件,我們以實例配置文件簡單講解,Bochs實驗調(diào)試等網(wǎng)上有很多相關(guān)文章,這里簡單講解。
我的配置實例:文件名xp.bxrc,修改后的及需要設(shè)置的內(nèi)容如下:
######使用的系統(tǒng)BIOS模塊###### romimage: file=$BXSHARE/BIOS-bochs-latest ######使用的CPU 相關(guān)參數(shù)###### cpu: count=1, ips=10000000, reset_on_triple_fault=1 ######設(shè)置內(nèi)存大小 ###### megs: 128 ######添加我們的BIOS模塊###### optromimage1: file=test.bin, address=0xd0000 ######使用的VGAROM模塊###### vgaromimage: file=$BXSHARE/VGABIOS-lgpl-latest ######設(shè)置虛擬機(jī)硬盤與光盤###### ata0-master: type=disk, path="c.img", mode=flat, cylinders=4161, heads=16, spt=63 #ata0-slave: type=cdrom, path="xp.iso", status=inserted ######設(shè)置引導(dǎo)設(shè)備 ###### boot: c #boot: cdrom, disk
Bochs調(diào)試加載配置文件方法:可以設(shè)置一個bat文件,如下內(nèi)容:
set BXSHARE=d:/bochs
%BXSHARE%/bochsdbg.exe -q -f xp.bxrc
各種BIOS刷新相關(guān)工具早已在網(wǎng)上流傳,工具的使用這里不作介紹,IcLord的作者已經(jīng)給出很多編程方法實現(xiàn)。這里簡單說下。
UniFlash開源項目我也詳細(xì)分析過,如果有必要我會給出UniFlash源代碼的詳解,該項目指出可以刷寫所有BIOS芯片,但是該項目刷新BIOS存在很多問題,絕大多數(shù)情況是無法刷新的我實驗過很多次,也嘗試修改他的代碼過很多次,沒找到原因。
AWord BIOS已經(jīng)有通用的刷寫API調(diào)用,不管在NT下還是在實模式下,IcLord也作了講解。如果有時間我會給出實模式及NT下的刷寫源代碼及分析。
關(guān)于網(wǎng)上提及的,IcLord講到的我就不再做重復(fù)的分析。這里主要講下我們的模塊可以植入哪些地方以方便隱藏。以前的教程講過的方法存的問題分析。
一、 ISA模塊形式植入:這種方式只適合于較早的計算機(jī),因為目前的計算機(jī)系統(tǒng)BIOS是不會加載ISA模塊的。故只能做實驗調(diào)試用的方法。
二、 PCI模塊形式植入:該方法雖然系統(tǒng)BIOS都要加載PCI ROM,但是系統(tǒng)BIOS只加載實際存在的PCI卡的ROM模塊。而且通常BIOS設(shè)置中可以
三、 HOOK BootBlock或者說要啟動的模塊:該方法當(dāng)然我認(rèn)為是最有效的,但是又存在很多技術(shù)上的難題。檢驗和問題,不同BIOS的結(jié)構(gòu)問題,過早的HOOK還存在再次獲取CPU運行機(jī)會問題等等。
本人實驗過以上提及的所有方法,我認(rèn)為HOOK PCI、VGA及相關(guān)啟動模塊是比較可尋的辦法。為什么?一般這類的ROM模塊是必須啟動的,而且調(diào)試發(fā)現(xiàn)一般它的ROM本身代碼用不完自身設(shè)置的大小,我們可以借助剩余大小隱藏我們的代碼。例如:集成顯卡會把顯卡ROM集成到系統(tǒng)BIOS模塊中,我們可以對該模塊進(jìn)行HOOK,修改ROM頭部的跳轉(zhuǎn)指令,跳到我們的代碼開始處執(zhí)行,我們的代碼執(zhí)行完后跳轉(zhuǎn)到它的代碼開始處執(zhí)行。
BIOS是分模塊組合在一起的。這里對PCI及ISA模塊作下簡單分析,VGA模塊跟PCI模塊幾乎一樣。模塊主要是頭部有個規(guī)范,該規(guī)范適合所有BIOS系統(tǒng)。具體可以參看《PCI系統(tǒng)結(jié)構(gòu)》及其他書籍。
源代碼實例可以參看國外ROMOS開源項目,該開源項目的思想很值得學(xué)習(xí)。該項目講解了如何在BIOS中嵌入一個小型DOS,如:FreeDos。采用了把整個DOS系統(tǒng)盤鏡像植入BIOS中,跟早期的PXE引導(dǎo)DOS機(jī)制類似,然后HOOK磁盤中斷,模擬DOS系統(tǒng)盤鏡像出一個盤,源代碼編譯后只有900多字節(jié)。這種思想在早期還是很值得學(xué)習(xí)的。
很早前就有業(yè)界內(nèi)人士發(fā)貼問,為什么在我的ROM模塊中HOOK磁盤中斷會失敗呢?關(guān)于這個問題現(xiàn)在目前網(wǎng)上已經(jīng)有人作出過回答,國外的開源項目在2003年我都看到過。
由于我們的ROM模塊過早的運行,可能運行在磁盤服務(wù)前面了,這時如果HOOK Int 13h會因為BIOS加載磁盤服務(wù)時重寫Int 13h IVT值,故我們設(shè)法HOOK其他服務(wù),這個服務(wù)要求較早被BIOS安裝且不會再次修改且加載操作系統(tǒng)前調(diào)用,最佳的這個服務(wù)選擇就是int 18h、int19h服務(wù)。可以參看
BIOS源代碼,也可以參看PXE SDK說明文檔略有講過。
我們的磁盤服務(wù)代碼建議放在實模式高端內(nèi)存,通過BIOS數(shù)據(jù)區(qū)域可修改,內(nèi)存40:13,即物理地址413h處的值。降低常規(guī)內(nèi)存值,高端的內(nèi)存就留給我們用。我們的保護(hù)模式下運行的代碼建議也放在這段內(nèi)存,且要求放在以頁基址開始的內(nèi)存中,以便后面代碼的頁映射我們的保護(hù)模式代碼物理頁。頁基址:內(nèi)存物理頁地地址開始的低12位為零,參看《80386保護(hù)模式教程》。
若我們的代碼直接在內(nèi)存的ROM映射區(qū)內(nèi),可能導(dǎo)致在NT下訪問不到我們的代碼,因為NT內(nèi)核加載程序ntldr可能不會映射該段內(nèi)存,甚至可能BIOS在使用后都會關(guān)閉ROM區(qū)域這段內(nèi)存,而且ROM區(qū)域這段內(nèi)存在初始化后被系統(tǒng)BIOS設(shè)置成只讀不能寫。當(dāng)然我們可以采取用int 15h服務(wù)對ROM區(qū)域這段內(nèi)存映射。
當(dāng)然也可以在NT啟動過程中,在我們的磁盤服務(wù)中對想映射的內(nèi)存都映射。由于代碼大小的限制,故有些沒必要的代碼。盡量不使用了。
為了使我們的程序再次獲得CPU運行機(jī)會,我們不得不得再次設(shè)法。調(diào)試發(fā)現(xiàn)NTLDR進(jìn)入保護(hù)模式后在加載NT內(nèi)核文件時,會切換CPU到實模式調(diào)用Int 13H服務(wù)進(jìn)行磁盤讀。
我們掛接磁盤服務(wù)就是為了截取NTLDR的讀操作,這里我們可以HOOK 或者修改NTLDR另一部分OsLoader的代碼,跳轉(zhuǎn)到我們的代碼執(zhí)行。當(dāng)然也可以直接HOOK ntosknrl導(dǎo)出的服務(wù),參看我在2008.4.1發(fā)布的“程序從DOS/BIOS駐留內(nèi)存到WINNT下監(jiān)視內(nèi)存數(shù)據(jù)”。
注意,HOOK OsLoader的代碼時選擇HOOK指令問題,由于NTLDR切換到實模式讀取數(shù)據(jù),讀完后會在保護(hù)模式下搬移數(shù)據(jù)到規(guī)劃位置,進(jìn)行內(nèi)核的安裝。故HOOK時選擇HOOK指令就選擇FFh/15h:使用CALL NEAR [OFS32]指令進(jìn)行,該指令尋址采用絕對地址,類似指令也可以。
當(dāng)然我們的代碼再次運行就會運行在OsLoader代碼被我們HOOK處,調(diào)用我我們的代碼執(zhí)行,這時我們的代碼運行環(huán)境:DS = ES = 10h保護(hù)模式段,內(nèi)存模式: FLAT。在這里我們可以通過掃描_BlLoaderData數(shù)據(jù)結(jié)構(gòu),獲取NTOSKRNL鏡像基址。
可以通過PE搜索NTOSKRNL導(dǎo)出的API,可以參看網(wǎng)上相關(guān)教程。現(xiàn)在再次HOOK NTOSKRNL導(dǎo)出函數(shù)KeAddSystemServiceTable,HOOK該函數(shù)
可以截獲win32k.sys添加它自己的服務(wù),以便我們再再次HOOk win32.sys導(dǎo)出函數(shù)NtUserRegisterClassExWOW。HOOK該函數(shù)可以截取所有應(yīng)用層程序注冊窗口類,以便我們再再再次HOOK窗口類過程。這時我們的代碼就運行在NT的應(yīng)用層模式下。
先看一個WinDbg實例關(guān)于在我們的磁盤服務(wù)中獲取CR3值修改頁映射的分析,以前我的分析內(nèi)容:
NT內(nèi)核被加載高端的2GB內(nèi)存(80000000h~0ffffffffh)。參看NT內(nèi)存安排.. a、win2k adv ser: WINDBG 看到 NT Kernel base = 0x80400000 也就是NTOSKRNL.exe加載位置 kd
例如:在我們的代碼中把我們的代碼拷貝到SharedUserData空間未使用處去,就使用了頁映射代碼,直接修改第一個頁指向的物理頁,就是我們代碼所在的物理頁。
關(guān)于我們的代碼進(jìn)入保護(hù)模式以后,所有指令的尋址問題,這里作一下分析。當(dāng)我們代碼第一個在保護(hù)模式下執(zhí)行的指令,是前面提到的磁盤服務(wù)中對OsLoader的代碼進(jìn)入HOOK,也提到了采用什么樣的HOOK指令以便尋址。
接哪之后,我們的代碼就開始運行在保護(hù)模式未分頁情況下,我們采取的方法是把我們的代碼拷貝到SharedUserData空間未使用處,涉及到拷貝的指令也必須運行在保護(hù)模式分頁下,因為SharedUserData空間是一個虛地址。
在這里我們采用了把我們的拷貝代碼指令搬移到NTOSKRNL鏡像的MZ與PE之間的區(qū)域,設(shè)置HOOK NTOSKRNL導(dǎo)出函數(shù)KeAddSystemServiceTable首先跳轉(zhuǎn)到拷貝指令執(zhí)行,HOOK NTOSKRNL導(dǎo)出函數(shù)KeAddSystemServiceTable采用相對跳轉(zhuǎn)指令它們在同一個空間。
當(dāng)我們的拷貝指令把我們的代碼拷貝到SharedUserData空間未使用處之后,我們的代碼就有一個固定的虛地址,所有后續(xù)指令都可以采用這個虛地址進(jìn)行尋址。
新聞熱點
疑難解答