無註冊表加載驅動(2)

 第二種方法如下:

一般情況下win2000啓動後會開始加載特別的驅動win2k.sys。然而它並不是以其他驅動那樣調用函數ZwLoadDriver, NtLoadDriver等。
事實上它是通過內核API函數ZwSetSystemInformation載入的。
API通常用來設置類似文件分卷等系統信息,以及加載上面提到的驅動,文件緩存等等。

該函數調用方法如下:

ZwSetSystemInformation(
IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
                                                                                                  //
識別操作指令
IN PVOID SystemInformation,         //
識別操作數
IN ULONG SystemInformationLength ) //
識別數據長度

其內部調用方法如下:

Switch (SystemInformationClass)
                      Case 0:
                      
                      Case 1:
                      .
                      .
                      .
                      Case 5:     ;this actually extends the system service descrīptor table
                               .
                               .
                       .           
                               MmLoadSystemImage(SystemInforMation,NULL,NULL,TRUE,imagehandle,baseaddress);
                               
                               call entrypoint(driverobject,NULL)   ;
                               
                               break     ; 
                         case 6:      
                        .
                        .
                        .
                        .
                        .


上述的兩種方法是我們現在已知的兩種加載驅動的方式。

下面是第三種方式(針對該方法目前沒有防毒措施對其進行監控因此它將是安全的)

像上面所講的那樣,ZwSetSystemInfomation加載鏡像函數從而將驅動載入內存然後調用它的入口點。

現在我們將具體地分析MmLoadSystemImage函數的參數。

MmLoadSystemImage(UNICODE STRING Imagepath, UNICODE STRING prefix optional,UNICODE STRING basename optional,
                      ULONG unknown=0,PVOID imagehandle,PVOID baseaddress);

ImagePathwindows下的路徑
prefix
:用在載入驅動的路徑名前
basename
:系統在加載組件後顯示的名稱
unknown
:未知
*imagehandle
:段指針(這是已經被提交的)
*baseaddress
:鏡像載入內核內存後的地址

該函數實際上就是扮演着加載鏡像入驅動,解決導入等的一些問題的角色。

在對windows平臺下進行調試的過程中,你可以找出使用d MmLoadSystemImage字段函數的地址。

注意:MmLoadSystemimage在將鏡像載入內存後會繼續內部調用和檢查鏡像,所以我們必須保證檢查後的結果是正確的。這個過程由MiCheckSystemImage實現。實現導入工作以及加載附屬的則是依靠函數MiResolveImageReferences來完成。

函數MmloadSystemimage按照如下流程工作:

1)掃描存在的組件清單以確保它已經被載入
2)
如果鏡像已經存在,則返回錯誤,提示鏡像已經存在
3)
嘗試使用函數Zwopenfile打開文件,如果文件不能被打開,則返回錯誤代碼
4)
計算鏡像的檢查結果並將其與儲存在頭文件裏的結果進行比較
5)
如果不相符則返回錯誤
6)
使用函數Zwcreatesection建立一個段然後將其作爲參考
7)
使用函數mMapViewInSystemSpace給其指定內核空間
8)
在必要的時候使用LdrRelocateImage對鏡像進行重定向
9)
調用用函數MiResolveImageReferences對鏡像參考
10)
爲組件建立已加載組件清單
11)
給其加上寫保護
12)
關閉文件指針
13)
返回


現在我們有了一個加載鏡像的函數,但是調用驅動的入口問題卻沒有解決。我們可以從載入鏡像後的PE頭文件自身那裏找到相關信息。這個方法可以用來直接在內核中加載和執行驅動,本地應用程序等。

下面給出的是內核下的彙編代碼。在windowsXP SP0 英文版下測試通過。在理論上也可以在win2000,xp,2003下執行。


__asm {
               
               
               ;
下面的代碼將驅動載入內存
loaddriver:
        mov dword [Stack],esp               //save stack
        
        ;paramters as always are passed in reverse
        push DWORD Driverbase              ;
存儲驅動基址
        push DWORD ImageHandle             ;
存儲段指針
        push dword 0               
        push dword 0
        push dword 0
        push DWORD U_STRINGloc              ;
指向一個unicode字串 ,包括將要加載的驅動


        mov edi, 0x805c03ae       ;MmLoadSystemImage
函數的地址,在Win XP SP0英文版下隨着操作系統版本不同這一地址將發生變化
        call edi
        cmp eax,0                 ;
檢查驅動是否成功載入內存
        jne   drivernotloaded    ;
如果失敗,則直接退出
        
         ;
驅動載入後 調用其內置函數,所有參數置零
        mov DWORD edi, [Driverbase]
        mov DWORD ebx ,[edi + 0x3c]      ;
獲取optional header的偏移量
        mov dword ebx,[edi + ebx + 0x18 + 0x10]   ;
從代碼基址中獲取入口地址的偏移量    
        add edi ,ebx                        ;
將基址和偏移量相加,得到入口點內存中的物理地址
        push 0 ;
        push 0
        call edi ;call entry point     (
驅動入口點,驅動不同入口點將有變化)


        drivernotloaded:
        mov dword esp,[ Stack]            ;
糾正堆棧使得可以繼續執行
        
        ret


       
       ;
下面是各種所需的代碼數據
      

; 下面是將要加載的驅動的路徑

;DosDevices@:hooka.sys length 48
db 0x5c,0x00,0x44,0x00,0x6f,0x00,0x73,0x00,0x44,0x00,0x65,0x00,0x76,0x00,0x69,0x00,0x63,0x00,0x65,0x00,0x73,0x00,0x5c,0x00
db 0x42,0x00,0x3a,0x00,0x5c,0x00,0x68,0x00,0x6f,0x00,0x6f,0x00,0x6b,0x00,0x61,0x00,0x2e,0x00,0x73,0x00,0x79,0x00,0x73,0x00,0x00,0x00

;儲存驅動基址
Driverbase:
dd 0
;
儲存段指針
ImageHandle:
dd 0;

;儲存堆棧地址
Stack:
dd 0

;在內存中構建 unicode字串
struc U_STRING
Length: resw 1
MaximumLength: resw 1
Buffer: resd 1
endstruc

}

//彙編結束


注意:這些API函數並不是由windows操作系統的內核導出的,但他們確實有內核方面的用途。這些函數並沒有被任何反病毒軟件監控,所以它們可以用來加載驅動或者本地應用程序然後運行。

這就是我們所說的在內核模式下不通過註冊表加載驅動的方式,當然,這些代碼可能存在一些錯誤,但是目前爲止還沒有發現硬件上的錯誤

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章