對360沙盒的驅動的一點逆向分析---發文於2014-1-19
主要內容:
一.360Box沙箱DriverEntry函式安裝驅動過濾框架分析
二. 360Box沙箱登錄檔監控分析
三. 360沙箱檔案系統監控分析
一.360Box沙箱DriverEntry函式安裝驅動過濾框架分析
360Box沙箱的驅動入口程式碼如下所示,下面單步跟蹤分析入口程式碼安裝360對登錄檔、程序、檔案系統等過濾函式的安裝過程。從下程式碼可以看出,360Box安裝過濾的順序為
檔案系統minifilter過濾(FltRegisterFilter 函式)->對power和create、open的hook函式(通過DriverObject的majorFunction)-> 安裝360的登錄檔、程序過濾(sub_callhookport函式)->註冊關機回撥(IoRegisterShutdownNotification函式)
NTSTATUS __stdcall DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
。。。\\省略無關程式碼
\\檢測hookport是否存在
callhookportret0x3ee();
\\初始化登錄檔路徑
RtlCopyUnicodeString(&g_str_uni_registryPath, RegistryPath);
\\安裝檔案系統的minifilter過濾驅動,在FltOperationRegistration結構中包含過濾的irp
FltRegisterFilter(DriverObject, dword_3C45C, &dword_3ABCC);
\\設定過濾irp的開發、關閉、查詢的派遣函式
DriverObject->MajorFunction[16] = (PDRIVER_DISPATCH)filter_irp_power; DriverObject->MajorFunction[0]= filter_irp_create_close;
DriverObject->MajorFunction[2] = filter_irp_create_close;
DriverObject->MajorFunction[14] =(PDRIVER_DISPATCH)filter_irp_query_security;
//開始minifilter檔案過濾
FltStartFiltering();
\\安裝360Box的登錄檔,程序等過濾函式,重點在這裡
sub_callhookport(DriverObject);
IoRegisterShutdownNotification(g_DeviceObject);\\安裝關機回撥
}
一. 先跟蹤FltRegisterFilter()函式看minifilter檔案系統的過濾安裝過程
FltRegisterFilter函式宣告如下
NTSTATUS FltRegisterFilter(
_In_ PDRIVER_OBJECT Driver,
_In_ const FLT_REGISTRATION *Registration,
_Out_ PFLT_FILTER *RetFilter
);
在函式引數flt_registration型別中含有結構成員FLT_OPERATION_REGISTRATION *OperationRegistration;
這個成員是個陣列,陣列的每個成員型別為
typedef struct _FLT_OPERATION_REGISTRATION {
UCHAR MajorFunction;
FLT_OPERATION_REGISTRATION_FLAGS Flags;
PFLT_PRE_OPERATION_CALLBACK PreOperation;
PFLT_POST_OPERATION_CALLBACK PostOperation;
PVOID Reserved1;
} FLT_OPERATION_REGISTRATION, *PFLT_OPERATION_REGISTRATION;
其中的preOperation和postOpreration就是minifilter安裝的對irp的pre和post,預處理和後處理的回撥函式地址。
按此方法找到360Box對minifilter檔案系統的回撥函式包括
Filter_irp_system_Control_pre \\新載入卷的過濾安裝
Filter_irp_system_controk_post
Filter_irp_system_create_pre \\ 對新建檔案的過濾
Filter_irp_system_create_post
Irp_set_information_pre \\對複製、刪除、剪下、重新命名檔案的過濾
二.安裝360的登錄檔、程序過濾(sub_callhookport函式)
在改函式中主要程式碼如下:
LONG_PTR __stdcall sub_callhookport(int a1)
{
// 在hookport的360過濾框架的的原過濾連結串列中新增一個360沙盒的針對SSDT的過濾表
fun_Hookport_g_port_extension_v1_for_AddRule = (int (__stdcall *)(_DWORD))*((_DWORD *)devExt_hookport + 1);
sub_Add_filter_Function(0); //新增程序等非登錄檔的相關過濾函式
sub_Add_filter_Function_register_relate(0); //添加註冊表相關的過濾函式
return PsSetCreateProcessNotifyRoutine(NotifyRoutine, 0);
}
在sub_callhookport函式的最後添加了PsSetCreateProcessNotifyRoutine(NotifyRoutine, 0);即建立程序的通知回撥。
在DriverEntry函式的最後呼叫IoRegisterShutdownNotification
註冊了系統的關機回撥,至此,360box的所有註冊框架就安裝完了
二.360Box沙箱登錄檔監控分析
360沙盒的登錄檔監控過濾分為對登錄檔的增刪改查的操作。對登錄檔的操作主要通過hook相關過濾函式,hook的目的就是沙盒內的應用程式執行時對系統的登錄檔沒有任何影響。對登錄檔的過濾主要hook了ZwCreateKey,ZwDeleteKey,ZwDeleteValueKey,ZwRenameKey,ZwSetValuekey,ZwQueryValueKey,
ZwEnumerateValueKey,ZwQueryKey,ZwEnumerateKey 九個登錄檔相關的過濾函式.
在360box沙箱中建立了兩個登錄檔項,如圖所示
其中S項用於儲存沙箱中的應用程式新建的和修改過的登錄檔項,T項用於儲存沙箱中的應用程式刪除過的登錄檔項,所有對登錄檔的修改的過濾函式中,都會先進行一步路徑過濾的操作,比如修改一個登錄檔項,360沙箱會hook ZwSetValueKey一個
[HKEY_LOCAL_MACHINE\SOFTWARE\test]
"fei"="dword:8"
360沙盒會修改新建的表項路徑為
[HKEY_USERS\360SandBox\S\Registry\Machine\Software\test]
然後將此路徑傳遞到系統本身的ZwSetValueKey函式中進行修改被改過的登錄檔項。
逆向sub_filter_ZwSetValueKey這個hook函式程式碼如下
註釋中的值為windbg單步跟後得到的引數值。
int __stdcall sub_filter_zwsetvaluekey(int array_index, int FirstParameter_address_in_Stack, int &addr_func_callBack_parameter, int &filter_result)
{
…
//建立過濾的登錄檔路徑
uni_dest_uni_registry = (const UNICODE_STRING *)sub_generate_360sandboxAndMyRegistryPath( addr_New_valuename.buffer,(int)Object, &Lookaside.L.ListHead);
// 存在已存在的鍵名和不存在該鍵名的分開處理
sub_2C10B( v15, uni_dest_uni_registry,(int)Object, (LSA_UNICODE_STRING *)&addr_new_valuename,*(_DWORD *)(handle + 8), *(_DWORD *)(handle + 12), *(const void **)(handle + 16),*(_DWORD *)(handle + 20));
在產生過濾後的登錄檔路徑後,傳入函式sub_2c10b進行處理
逆向sub_2c10b後的程式碼為
int __stdcall sub_2C10B()
{
//檢測應用層傳入的鍵值是否可讀
ProbeForRead(addr_data, DataSize, 1u);
// 如果真實登錄檔中不存在該鍵名 ,是否被刪過 }
if ( RtlEqualUnicodeString(uni_ValueName, &stru_uni_symbolicLinkValue, 1u) )
{
//為鍵名”fei”分配空間
(WCHAR *)ExAllocatePoolWithTag(PagedPool, var_datasize + 2, 0x70746B6Cu);
…
//初始化將要新增在登錄檔項前面的登錄檔過濾路徑
//\Registry\User\360SandBox
RtlInitUnicodeString(&DestinationString, L"\\Registry\\User\\360SandBox");
//檢查被測路徑中是否已經包含了360sandbox的註冊路徑字首,已經有,就不再建立
if ( RtlPrefixUnicodeString(&DestinationString, &String2, 1u))
{
ExFreePoolWithTag(String2.Buffer, 0);
}
//根據新的路徑建立登錄檔
v12 = sub_238E0(
v22 + 12 * (v23 + 1),
HANDLE_FLAG_INHERIT,
uni_ValueName,
TitleIndex,
6u,
KeyHandle.Buffer,
KeyHandle.Length);
} if ( !RtlEqualUnicodeString((PCUNICODE_STRING)(v22 + 12 * (v23 + 1)), uni_dest_uni_registry, 1u) )
{
// equal比較的前者指向test在360sandbox中的路徑,至此路徑過濾建立完成
}
登錄檔的修改即如上所分析的操作,建立和刪除過程同上。但是刪除的過濾路徑時將路徑寫到S項下,每次開啟登錄檔時,先遍歷S項的登錄檔項,如果沒有被刪,則可以開啟。
三.360沙箱檔案系統監控分析
360檔案系統的監控操作通過minifilter來過濾.360Box對minifilter檔案系統的回撥函式包括
Filter_irp_system_Control_pre \\新載入卷的過濾安裝
Filter_irp_system_controk_post
Filter_irp_system_create_pre \\ 對新建檔案的預處理過濾
Filter_irp_system_create_post \\新建檔案的後處理過濾
Irp_set_information_pre \\對複製、刪除、剪下、重新命名檔案的過濾
對power和create、open的irp的派遣函式()
這個過濾是在DriverEntry函式中
DriverObject->MajorFunction[16] = (PDRIVER_DISPATCH)filter_irp_power;\\過濾irp
DriverObject->MajorFunction[0]= filter_irp_create_close;
DriverObject->MajorFunction[2] = filter_irp_create_close;
DriverObject->MajorFunction[14] =(PDRIVER_DISPATCH)filter_irp_query_security;
檔案過濾分為對檔案的新建、拷貝、刪除、剪下、修改、讀取的過濾操作。
一. 360沙箱的過濾原理是對檔案的新建,將新建檔案到目標路徑所在卷的360SandBox目錄路徑下,如下圖所示。
對minifilter檔案建立的pre回撥前,修改目標檔案的路徑,比如原始的建立檔案路徑為
\Device\HarddiskVolume1\WINDOWS\Prefetch\TEST360BOXWRITEFILE.EXE
修改後的路徑為在\Device\HarddiskVolume1\的後面加上360SANDBOX\SHADOW,
變為\Device\HarddiskVolume1\360SANDBOX\SHADOW\WINDOWS\Prefetch\TEST360BOXWRITEFILE.EXE
然後將此路徑傳到系統原來的ZwCreateFile中,建立檔案。
逆向這個建立的pre回撥函式如下
int __cdecl sub_filter_targetFilePath()
{
。。。
//得到當前程序的控制代碼
PsGetProcessId(var_PEPROCESS);
//通過控制代碼到的檔案路徑
sub_getFilePathByHandle_parent2(var_current_process_handle);
if ( GenericMapping_readWriteExecAll)
{
//判斷新建檔案的屬性,是讀寫還是可執行等。
p_generic_mapping = IoGetFileObjectGenericMapping();
}
// 在此下斷點
if ( (unsigned int)var_uni_String1.Buffer & 1 )
{
//為新建路徑分配空間
*(_DWORD *)&v102[1] = sub_allocatepool_filled_sourcestring(pflt_conTEXT_returnedContext2, 0, 0);
//判斷目標路徑中是否包含360沙箱的字首
sub_IsUniStringInclude360SandBoxPrefix2()
。。。
//在檔案路徑中新增360sandbox\shadow
sub_appendPath_360sandbox_shadow();
FltSetCallbackDataDirty(pflt_callback_data4); //修改後路徑,通知minifilter
從程式碼中可以看出路徑的新增在sub_appendPath_360sandbox_shadow函式中,
逆向這個函式程式碼,可以得出,檔案的路徑通過三次RtlAppendUnicodeStringToString函式,先後將檔案的卷標和360shadow,檔案在卷中的路徑,檔名新增到最終路徑中。
二.對檔案的刪除,剪下,複製,重新命名是通過一個過濾函式Irp_set_information_pre,對irp的set information的pre回撥,核心是檔案的刪除,因為剪下是對原檔案刪除後,在新的路徑中建立一個新檔案。檔案刪除的過濾規則如下
真實機 沙箱回收站(登錄檔記錄) 沙箱目錄 結果
有 有 無 已被刪,返回無法刪除
有 有 有 刪除後,新建了同目錄檔案,返回刪除
有 無 有 沙箱修改過,刪除沙箱檔案
有 無 無 將真實檔案拷貝到360box回收站內,返回刪除成功。
無 無 有 沙箱新建的,刪除沙箱檔案
無 無 無 不存在的檔案,返回無法刪除--
無 有 無 沙箱裡面已被刪除的檔案,返回無法刪除
無 有 有 已被刪,但又新建的檔案,刪除沙箱檔案
過濾的規則主要在Irp_set_information_pre函式,即對檔案修改,包括複製、剪下、重新命名的預處理函式中。上表的規則含義,比如第一行,當真實機存在被刪檔案,回收站中也有被刪檔案的路徑,則當沙箱目錄中沒有這個檔案時,這個檔案應該是之前被刪除了,返回無法刪除.
檔案刪除過濾的Irp_set_information_pre過濾函式程式碼逆向如下,被實驗測試的上述表格第四項,即真實機中有,沙箱目錄沒有,然後沙箱回收站中沒有的情況
int __stdcall filter_irp_set_information_pre(int pflt_callback_data, int pcflt_related_objects, int pCompletionContext)
{
//獲取被刪檔案的相關路徑
FltGetDestinationFileNameInformation();
//取得被刪檔名
FltParseFileNameInformation(var_pflt_file_name_information);
//將真實檔案拷貝到360沙箱的回收站中
sub_copyRealFileTo360SandBoxRecycleBin()
通過上述虛擬碼可以看出,檔案的拷貝操作在sub_copyRealFileTo360SandBoxRecycleBin函式中,在該檔案中,將真實檔案拷貝到360沙箱的回收站中,逆向該函式得到
signed int __cdecl sub_copyRealFileTo360SandBoxRecycleBin() {
//下面判斷檔案是否含有360沙盒的路徑,即是否在沙盒中的檔案
sub_IsFileNameInclude360sandboxPrefiex()
//在檔案路徑新增360sandbox_shaow路徑
sub_appendPath_360sandbox_shadow(;
sub_20ED3();
//執行完此函式,路徑就變為真實機中的檔案被刪後的路徑
FltSetInformationFile(
*(_DWORD *)(pcflt_related_objects + 12),
*(_DWORD *)(pcflt_related_objects + 16),
var_P_fileInformation,
length,);// fileinformation_class_rename重新命名
}
其中var_p_fileInformation指向\Device\HarddiskVolume1\360SANDBOX\SHADOW\RECYCLER
\S-1-5-21-2000478354-73586283-1606980848-500\Dc4.txtEST",這個FltSetInformationFile函式
是刪除的主要操作,即將沙盒內的檔案重新命名到360沙盒的回收站內,同時,在登錄檔內建立被刪檔案的登錄檔項,以便下次刪除或開啟時查詢是否被刪除,如圖