利用MoveFileEx實現程式的隱藏、自啟動與自刪除
摘要:程式的自啟動與自刪除幾乎是所有後門或者木馬所必須具備的功能。程式實現自啟動的方法有很多種,最常見的方法莫過於寫登錄檔,新增服務,或者將自身複製到啟動目錄。自刪除通常的辦法是寫批處理。但是這些方法都已經眾所周知,均被各防毒軟體、防護軟體,主動防禦軟體以及經驗豐富的管理員視為可疑行為。本文利用API函式MoveFileEx的dwFlags引數實現了上述功能,並且具有一定的隱蔽性。
一、瞭解MoveFileEx
MoveFileEx是MoveFile函式的擴充套件函式,也是用來移動檔案,不過多加了一些功能。MoveFileEx函式的原型如下:
BOOL MoveFileEx (
LPCTSTR lpExistingFileName, LPCTSTR lpNewFileName, DWORD dwFlags );
第一個引數是要移動的檔名,第二個是移動後的檔名,最後一個引數決定了移動的方式。
仔細看最後一個引數可取的值,其中一項為MOVEFILE_DELAY_UNTIL_REBOOT ,MSDN中對此標記描述如下:
The function does not move the file until the operating system is restarted. The system moves the file immediately after AUTOCHK is executed, but before creating any paging files. Consequently, this parameter enables the function to delete paging files from
previous startups.
This flag can only be used if the process is in the context of a user who belongs to the administrator group or the LocalSystem account.
This flag cannot be used with the MOVEFILE_COPY_ALLOWED flag.
當dwFlags被設為MOVEFILE_DELAY_UNTIL_REBOOT時,函式直到系統重啟後才移動檔案。注意檔案的移動是發生在AUTOCHK執行之後,在頁面檔案建立之前。而此時使用者還沒有完全的進入作業系統,所以可以應用這點刪除那些正常情況下很難刪除的檔案甚至是頁面檔案。
lpNewFileName為NULL時,MovefileEx實現的就是刪除的功能。很多防毒軟體和一些惡意程式刪除工具就是利用了MoveFileEx函式的這個特性來實現的重啟後刪除病毒。
MOVEFILE_DELAY_UNTIL_REBOOT標記使用時需要具有管理員或者LocalSystem使用者的程序上下文。
MOVEFILE_DELAY_UNTIL_REBOOT標記不能和MOVEFILE_COPY_ALLOWED標記一同使用。因為在不同的卷下實現不了真正的移動,MOVEFILE_COPY_ALLOWED標記使用的時候,函式通過模擬CopyFile 和 DeleteFile 兩個函式實現移動。正在執行的程式不能移動到不同的卷(分割槽)下,這時只實現了Copyfile,下一步DeleteFile沒有成功,正在執行的程式是不能刪除的。
當dwFlags引數被設定為MOVEFILE_DELAY_UNTIL_REBOOT時,MoveFileEx把重啟後移動的檔案和要移到的檔案的位置存在下面的多字元登錄檔值(REG_MULTI_SZ)裡:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session\Manager\PendingFileRenameOperations。如圖1。
圖 1
二、進一步探究
我們都知道Windows下正在執行的程式是不能直接刪除的(Linux下正在執行的程式則可以刪除的)。
下面的演示的是一個比較簡單後門程式(door.exe),繫結埠1985,實現了一些基本的後門功能。執行此後門。如果刪除的話會彈出如下對話方塊:
圖 2
正在執行的程式雖然不能刪除,但是一般可以改名或者移動,移動後程序依然可以執行。如圖3、4
圖 3
圖 4
可以看到正在執行的程式被移動到了另一個目錄。
圖 5
而且比較有意思的是一般的程序檢視工具檢視的此時door.exe程序的檔案映像還是在沒移動的目錄裡。
下面是Process Explorer檢視的結果:
圖 6
還有下面這個syscheck2:
圖 7
試了很多可以檢視程序的工具,發現只有IceSword可以檢測出移動後的程序所在目錄:
圖 8
這樣對方發現這個程式,到相應的目錄確找不到它,某種程度實現了隱藏檔案的目的.如果用線上程插入的dll檔案上,其隱蔽性就很好了.
三、MoveFileEx的利用與實現
利用剛才上面所提到的,我們就可以實現檔案的隱藏、自刪除以及自啟動。
我們可以將一個程式執行後,就將它移動到一個不易發現的目錄下(在我的下面的程式裡是移動到回收站目錄裡),然後利用MoveFileEx,設定dwFlags為MOVEFILE_DELAY_UNTIL_REBOOT,使檔案重啟後移動到一個可以啟動的目錄下(對於中文的Windows XP作業系統,啟動目錄為
“C:\Documents and Settings\All Users\「開始」選單\程式\啟動”)。這樣檔案執行後便立即不在它執行時的目錄了,實現了“自刪除”功能。下次重啟後,系統還沒有被登陸,便已經將檔案移動到了啟動目錄裡。當用戶登陸時,程式啟動,隨即被移到其他目錄中,此時在啟動資料夾裡也已經沒有了它的蹤跡,所以通過正常的檢查是看不出來檔案到底在那裡被啟動的。整個過程只是呼叫了一個系統API,沒有直接的寫登錄檔。現在的主動防禦和防毒軟體不會將這視為可疑操作。
下面是我編的一個示例程式碼,其中StartShell為後門函式,大家可以自己實現其功能.程式碼很簡單大家一看就懂.
//得到啟動目錄
char szPath[100]={0};
::GetSystemDirectory(szPath,MAX_PATH);
char szDst[100]={0};
for (int i=0; i<3;i++)
szDst[i]=szPath[i];
strcat(szDst,"Documents and Settings\\All Users\\「開始」選單\\程式\\啟動\\test.EXE
//得到當前程式名
TCHAR szCurPath[MAX_PATH];
memset(szCurPath, 0, MAX_PATH);
GetModuleFileName(NULL, szCurPath, sizeof(szCurPath)/sizeof(TCHAR));
if !(MoveFileEx(szCurPath,"c:\\RECYCLER\\FK.BAK",MOVEFILE_REPLACE_EXISTING)))//若是要在不同的volume下移動檔案,需要設定為MOVEFILE_COPY_ALLOWED
::MessageBox(NULL,"第一次移動檔案失敗","test",MB_OK); if(!::MoveFileEx("c:\\RECYCLER\\FK.BAK",szDst,MOVEFILE_DELAY_UNTIL_REBOOT | MOVEFILE_REPLACE_EXISTING)){
::MessageBox(NULL,"移動檔案失敗","test",MB_OK); }
else printf("任務完成\n");
//建立並等待執行緒
// StartShell 為後門執行緒函式.
HANDLE hthread=::CreateThread(NULL,NULL,StartShell,NULL,NULL,NULL);
CloseHandle(hthread);
::WaitForSingleObject(hthread,INFINITE);
return 0;
四、補充與後記
一直以來都想寫點技術上的東西,但卻總是為各種各樣的事情煩惱和忙碌著。我的四年的大學生活要結束了,我的愛情消逝了,我一直深愛著的人離開了,我也終於把這篇文章寫完了。欲哭無淚,長歌當哭……(希望編輯不要刪除我的話)
程式的缺點也是顯而易見的:如果不登陸,程式在啟動資料夾就不會執行,在伺服器上應用價值就有問題了,因為伺服器很多時間是不登陸狀態的;程式必須放到與系統分割槽下,因為不同分割槽下正在執行的程式移動不了。
除了MoveFileEx函式MoveFileWithProgress函式也可實現一樣的功能,所不同的是它提供了對檔案移動過程資訊的追蹤,具體可以查下MSDN。