1. 程式人生 > >對360沙盒的驅動的一點逆向分析---發文於2014-1-19

對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沙盒的回收站內,同時,在登錄檔內建立被刪檔案的登錄檔項,以便下次刪除或開啟時查詢是否被刪除,如圖