數(shù)字取證分析人員在分析macOS時,很難獲得關(guān)于程序執(zhí)行的相關(guān)信息,但現(xiàn)在情況已有所改觀。在macOS 10.13(High Sierra)中,Apple推出了CoreAnalytics,這是一種系統(tǒng)診斷機制,可以獲取系統(tǒng)上執(zhí)行過的Mach-O程序記錄,時間跨度大約為1個月左右。CoreAnalytics可以為內(nèi)部威脅調(diào)查任務(wù)以及應(yīng)急事件響應(yīng)提供許多非常有價值的信息,可以用于以下場景:
1、確定系統(tǒng)的使用時長,粒度以天為單位;
2、確定特定日期有哪些程序被運行過,是以前臺還是以后臺模式運行;
3、大致確定程序處于運行或活動狀態(tài)的時長,也能大致給出程序啟動或者以交互式前臺方式運行的次數(shù)。
本文從技術(shù)角度大致介紹并分析了macOS 10.13中的CoreAnalytics機制,同時也介紹了如何將這類信息解析為更容易理解的格式,幫助調(diào)查人員分析取證。
CoreAnalytics可以提供關(guān)于程序執(zhí)行的歷史紀(jì)錄以及當(dāng)前記錄,基本上以天為單位。這些數(shù)據(jù)來自于兩個源:
1、/Library/Logs/DiagnosticReports/
目錄中以.core_analytics
為擴展名的文件,內(nèi)容為JSON格式:解析前兩條記錄可以獲得有關(guān)診斷過程的啟動及結(jié)束時間戳信息,解析后面的數(shù)據(jù)可以獲得診斷期間系統(tǒng)及應(yīng)用的使用情況;
2、/private/var/db/analyticsd/aggregates/
目錄中文件名類似GUID的文件,內(nèi)容為嵌套數(shù)組:在當(dāng)前診斷過程期間,子系統(tǒng)將臨時階段性程序執(zhí)行數(shù)據(jù)以聚合文件形式報告給數(shù)據(jù)分析守護程序。階段性數(shù)據(jù)通常會在診斷周期結(jié)束時推送到.core_analytics
文件中。
診斷周期由.core_analytics
文件的前兩行定義,分別確定診斷周期的開始及結(jié)束時間。每個診斷周期在在00:00:00 UTC后的系統(tǒng)首次休眠或者關(guān)閉時就會結(jié)束。前面提到過,在診斷周期結(jié)束時,當(dāng)日的數(shù)據(jù)在提交到.core_analytics
文件用作長期存儲前,會先存放在聚合文件中。因此,CoreAnalytics無法用來確定程序運行的時間范圍(只能大約給出24小時的時間區(qū)域)。
為了處理這種場景,我們編寫了一個Python腳本(請訪問我們的GitHub下載),該腳本可以解析CoreAnalytics以及聚合文件,將結(jié)果寫入到更加清晰的JSON或者CSV文件中。CoreAnalyticsParser腳本可以支持如下功能:
1、解析每個.core_analytics
文件中記錄的診斷周期開始及結(jié)束時間,并將其轉(zhuǎn)換為UTC以及IOS8601時間;
2、從每個.core_analytics
文件中提取與每條記錄相關(guān)的可用字段;
3、將以秒數(shù)表示的原始值轉(zhuǎn)換為更容易理解的%H:%M:%S
strftime
格式;
4、將與comappleosanalyticsappUsage
子系統(tǒng)關(guān)聯(lián)的聚合文件解析為每個 .core_analytics
文件中該子系統(tǒng)所生成的相同字段。
在.core_analytics
文件中某個應(yīng)用的執(zhí)行記錄大致如下所示:
{ ‘message’: { ‘a(chǎn)ctivations’: 105,
‘a(chǎn)ctiveTime’: 4250,
‘a(chǎn)ctivityPeriods’: 12,
‘a(chǎn)ppDescription’: ‘com.google.Chrome ||| 67.0.3396.87 (3396.87)’,
‘foreground’: ‘YES’,
‘idleTimeouts’: 4,
‘launches’: 0,
‘powerTime’: 12537,
‘processName’: ‘Google Chrome’,
‘uptime’: 26110},
‘name’: ‘comappleosanalyticsappUsage’,
‘uuid’: ‘4d7c9e4a-8c8c-4971-bce3-09d38d078849’}
表1. Google Chrome對應(yīng)的CoreAnalytics記錄樣例
由CoreAnalyticsParser解析后,同一個記錄會被解析成如下結(jié)果:
{ ‘src_report’: ‘/path/to/Analytics_2018-06-29-173717_ML-C02PA037R9QZ.core_analytics’,
‘diag_start’: ‘2018-06-29T00:00:09Z’,
‘diag_end’: ‘2018-06-30T00:37:17.660000Z’,
‘name’: ‘comappleosanalyticsappUsage’,
‘uuid’: ‘4d7c9e4a-8c8c-4971-bce3-09d38d078849’,
‘processName’: ‘Google Chrome’,
‘a(chǎn)ppDescription’: ‘com.google.Chrome ||| 67.0.3396.87 (3396.87)’,
‘a(chǎn)ppName’: ‘com.google.Chrome’,
‘a(chǎn)ppVersion’: ‘67.0.3396.87 (3396.87)’,
‘foreground’: ‘YES’,
‘uptime’: ‘26110’,
‘uptime_parsed’: ‘7:15:10’,
‘powerTime’: ‘12537’,
‘powerTime_parsed’: ‘3:28:57’,
‘a(chǎn)ctiveTime’: ‘4250’,
‘a(chǎn)ctiveTime_parsed’: ‘1:10:50’,
‘a(chǎn)ctivations’: ‘105’,
‘launches’: ‘0’,
‘a(chǎn)ctivityPeriods’: ’12’,
‘idleTimeouts’: ‘4’}
表2. CoreAnalyticsParser腳本將圖1中CoreAnalytics的結(jié)果解析成JSON數(shù)據(jù)
注意:如上解析結(jié)果為JSON格式數(shù)據(jù),可以使用-j
選項輸出為JSON數(shù)據(jù)。默認(rèn)情況下,解析腳本會將結(jié)果輸出為CSV格式。
該腳本可以在實時系統(tǒng)上運行,也可以處理包含CoreAnalytics或者聚合文件的目錄。
.core_analytics
文件中包含JSON記錄,這些記錄可以表示程序執(zhí)行歷史及時間戳信息,時間戳可以劃出歷史數(shù)據(jù)所對應(yīng)的特定診斷周期。這些文件位于/Library/Logs/DiagnosticReports/
目錄中,文件名采用Analytics_YYYY_MM_DD_HHMMSS_<systemname>.core_analytics
格式。文件名中的時間戳基于的是系統(tǒng)的本地時間信息。在10.13版本之前,DiagnosticReports
目錄只包含程序故障及崩潰報告,現(xiàn)在,不論程序是否崩潰,該目錄中都會包含與程序執(zhí)行有關(guān)的數(shù)據(jù)。
負(fù)責(zé)生成和收集系統(tǒng)分析及診斷數(shù)據(jù)的守護程序同樣會維護/private/var/db/analyticsd
目錄中已預(yù)先寫好的CoreAnalytics文件信息。在該目錄中,currentConfiguration.json
文件貌似維護著一個字典集,對應(yīng)與子系統(tǒng)相匹配的名稱、UUID以及數(shù)據(jù)類型。
在/private/var/db/analyticsd/journals
目錄中,da2-identity.json
文件包含最近生成的CoreAnalytics文件中的_marker
記錄列表。第一條記錄通常會比當(dāng)前可用的第一個CoreAnalytics文件要早上7-10天,最后一條記錄對應(yīng)最近寫入后的報告。通常情況下,這些數(shù)據(jù)可以用來確認(rèn)預(yù)期的所有.core_analytics
文件都存在且未被篡改。
定義診斷周期
.core_analytics
文件的首條記錄包含一個時間戳字段,字段值對應(yīng)診斷周期結(jié)束的時間。雖然時間戳以本地時間為基礎(chǔ),但帶有時區(qū)信息。如果該字段值未被修改,則應(yīng)當(dāng)匹配該文件的上次修改時間戳。換句話說,只有在診斷周期結(jié)束后,.core_analytics
文件才會被寫入到這個目錄中。
{ ‘bug_type’: ‘211’,
‘os_version’: ‘Mac OS X 10.13.5 (17F77)’,
‘timestamp’: ‘2018-06-05 17:16:48.19 -0700’}
表3. .core_analytics
文件的第一行記錄,包含診斷周期結(jié)束時間戳信息
我們可以在以_marker
開頭的JSON記錄中找到診斷周期的開始時間,即startTimestamp
字段中的UTC時間戳。
{ ‘_marker’: ”,
‘_preferredUserInterfaceLanguage’: ‘en’,
‘_userInterfaceLanguage’: ‘en’,
‘_userSetRegionFormat’: ‘US’,
‘startTimestamp’: ‘2018-06-05T00:19:13Z’,
‘version’: ‘1.0’}
表4. .core_analytics
文件的第二行記錄,包含診斷周期開始時間戳信息
CoreAnalytics文件基本上每天都會寫入到DiagnosticReports
目錄中,并且在系統(tǒng)使用期間,兩個記錄文件的時間間隔基本上無縫連接。在診斷期間,如果系統(tǒng)處于睡眠或者關(guān)機狀態(tài),則不會生成CoreAnalytics文件。
診斷周期開始時間 | 診斷周期結(jié)束時間 |
---|---|
2018-06-08T01:51:23Z | 2018-06-09T01:50:01.370000Z |
2018-06-10T16:49:09Z | 2018-06-11T03:53:15.140000Z |
2018-06-11T03:53:14Z | 2018-06-12T02:50:17.410000Z |
2018-06-12T02:50:17Z | 2018-06-13T00:17:45.870000Z |
2018-06-13T00:17:45Z | 2018-06-14T01:17:06.340000Z |
表5. 系統(tǒng)連續(xù)使用幾天時,.core_analytics
文件之間無縫連接,當(dāng)系統(tǒng)未激活時則會出現(xiàn)斷檔
根據(jù)我們對/private/var/db/analyticsd/Library/Preferences/analyticsd.plist
這個二進制plist文件的分析結(jié)果,這些文件通常會在每天00:00:00 UTC時間后系統(tǒng)首次睡眠或關(guān)閉時在DiagnosticReports
目錄中生成。該plist文件以Unix Epoch格式記錄了.core_analytics
的上次提交時間以及下次提交時間。
Key: cadence
Type: String
Value:
{ ‘bootToken’: 1530574585000000,
‘lastSubmission’: 1531256233,
‘nextSubmission’: 1531267200,
‘osVersion’: ’17E202′,
‘version’: 1}
表6. analyticsd.plist
文件內(nèi)容,包含上次提交及下次提交時間戳信息
然而我們的測試顯示,報告通常會在提交時間過后的首次睡眠或者關(guān)機時寫入。
系統(tǒng)使用信息
在時間戳及marker記錄之后,comappleosanalyticssystemUsage
子系統(tǒng)所生成的數(shù)據(jù)反映了系統(tǒng)的運行時長(以秒為單位)。該子系統(tǒng)可能會在主機睡眠或關(guān)閉后生成新的紀(jì)錄。將這些記錄中的uptime
字段值加起來后就可以得到系統(tǒng)處于活躍狀態(tài)下的總時間。Uptime
字段非常簡單,為uptime
值的千位數(shù)。activeTime
字段很有可能表示的是系統(tǒng)運行狀態(tài)下被使用的時長(以秒為單位),如下兩條記錄所示,系統(tǒng)有兩個階段處于喚醒狀態(tài)下(時長分別為4分鐘以及40分鐘),總時長為44分38秒,但使用時長僅為14分26秒。
{ ‘message’: { ‘Uptime’: 0,
‘a(chǎn)ctivations’: 2,
‘a(chǎn)ctiveTime’: 42,
‘idleTimeouts’: 1,
‘uptime’: 247},
‘name’: ‘comappleosanalyticssystemUsage’,
‘uuid’: ‘00866801-81a5-466a-a51e-a24b606ce5f1’}
{ ‘message’: { ‘Uptime’: 2000,
‘a(chǎn)ctivations’: 2,
‘a(chǎn)ctiveTime’: 824,
‘idleTimeouts’: 1,
‘uptime’: 2431},
‘name’: ‘comappleosanalyticssystemUsage’,
‘uuid’: ‘00866801-81a5-466a-a51e-a24b606ce5f1’}
表7. 反應(yīng)系統(tǒng)使用狀態(tài)的兩條記錄
接下來的兩條記錄分別為2小時的心跳記錄一次1天的心跳記錄。這些記錄的作用尚未澄清,因為這些心跳記錄似乎與診斷周期的時長或者任何程序的運行時間無關(guān)。BogusFieldNotActuallyEverUsed
這個字段名很可能表示不僅該字段已被棄用,甚至這條數(shù)據(jù)本身已被棄用。
{ ‘message’: { ‘BogusFieldNotActuallyEverUsed’: ‘null’, ‘Count’: 7},
‘name’: ‘TwoHourHeartbeatCount’,
‘uuid’: ‘7ad14604-ce6e-45f3-bd39-5bc186d92049’}{ ‘message’: { ‘BogusFieldNotActuallyEverUsed’: ‘null’, ‘Count’: 1},
‘name’: ‘OneDayHeartBeatCount’,
‘uuid’: ‘a(chǎn)4813163-fd49-44ea-b3e1-e47a015e629c’}
表8. 心跳記錄
應(yīng)用使用信息
后面開始的每一行都包含3個鍵:name
、uuid
以及message
。name
以及uuid
鍵可以映射到生成該記錄的特定子系統(tǒng),message
字段包含一個嵌套JSON記錄,其中包含其他一些數(shù)據(jù)。我們所觀察到的一些最為常見的子系統(tǒng)以及UUID值如下所示:
子系統(tǒng)名 | UUID |
---|---|
comappleosanalyticsappUsage | 4d7c9e4a-8c8c-4971-bce3-09d38d078849 |
comappleosanalyticssystemUsage | 00866801-81a5-466a-a51e-a24b606ce5f1 |
comappleosanalyticsMASAppUsage | 0fd0693a-3d0a-48be-bdb2-528e18a3e86c |
TwoHourHeartbeatCount | 7ad14604-ce6e-45f3-bd39-5bc186d92049 |
OneDayHeartBeatCount | a4813163-fd49-44ea-b3e1-e47a015e629c |
表9. 向守護程序報告數(shù)據(jù)的常見子系統(tǒng)及對應(yīng)的UUID
我們的測試表明,這些UUID在運行macOS 10.13.4以及10.13.5系統(tǒng)上均保持一致,這表明UUID僅與子系統(tǒng)及子系統(tǒng)的版本有關(guān),如果Apple將來修改子系統(tǒng)時,這些值可能也會發(fā)生改變。
comappleosanalyticsappUsage
子系統(tǒng)會為執(zhí)行的每個程序生成一條記錄。
{ ‘message’: { ‘a(chǎn)ctivations’: 105,
‘a(chǎn)ctiveTime’: 4250,
‘a(chǎn)ctivityPeriods’: 12,
‘a(chǎn)ppDescription’: ‘com.google.Chrome ||| 67.0.3396.87 (3396.87)’,
‘foreground’: ‘YES’,
‘idleTimeouts’: 4,
‘launches’: 0,
‘powerTime’: 12537,
‘processName’: ‘Google Chrome’,
‘uptime’: 26110},
‘name’: ‘comappleosanalyticsappUsage’,
‘uuid’: ‘4d7c9e4a-8c8c-4971-bce3-09d38d078849’}
表10. comappleosanalyticsappUsage
子系統(tǒng)生成的.core_analytics
示例記錄
message
下包含的9個字段可能會為分析人員的取證工作提供大量信息:
1、activeTime
可能提供程序處于前臺運行時的秒數(shù);
2、activityPeriods
可能提供程序被調(diào)到前臺運行的次數(shù);
3、appDescription
直接來自于應(yīng)用程序包中Info.plist
的相關(guān)信息。如果Info.plist
中的相關(guān)鍵值信息格式錯誤或者為空,這里字段的值則會顯示為???
;
在CoreAnalytics記錄中存放的數(shù)據(jù)滿足如下格式:
<CFBundleIdentifier> ||| <CFBundleShortVersionString> (<CFBundleVersion>)
表11. CoreAnalytics記錄的數(shù)據(jù)格式
例如,Google Chrome.app
的Info.plist
文件中可以根據(jù)如下鍵值提取出所需的信息:
<key>CFBundleIdentifier</key>
<string>com.google.Chrome</string>
<key>CFBundleShortVersionString</key>
<string>67.0.3396.99</string>
<key>CFBundleVersion</key>
<string>3396.99</string>
表12. Google Chrome.app
應(yīng)用Info.plist
中的相關(guān)鍵值
如果程序以獨立的Mach-O可執(zhí)行文件形式運行,或者Info.plist
不可用、格式錯誤或者不完整,那么appDescription
就會顯示為UNBUNDLED ||| ???
。
例如,GlobalProtect中Info.plist
的CFBundleVersion
鍵值就無法獲取到:
com.paloaltonetworks.GlobalProtect ||| 4.0.2-19 (???)
表13. GlobalProtect的CoreAnalytics記錄中對應(yīng)的appDescription
值
其他字段的意義如下:
4、foreground
字段的值為YES
或者NO
,表示程序是否在前臺運行;
5、idleTimeouts
的含義目前尚未澄清;
6、launches
可能表示的是診斷報告期間應(yīng)用的啟動次數(shù)。如果應(yīng)用在診斷周期開始前啟動,那么launches
的值為0;
7、根據(jù)我們的測試結(jié)果,powerTime
可能表示的是程序處于運行狀態(tài)并消耗AC電源的時間(以秒為單位);
8、processName
的值來自于應(yīng)用程序包中Info.plist
文件的CFBundleExecutable
鍵值;
舉個例子,Google Chrome.app
中Info.plist
文件的該鍵值信息如下:
<key>CFBundleExecutable</key>
<string>Google Chrome</string>
表14. Google Chrome.app
應(yīng)用Info.plist
中的CFBundleExecutable
鍵值
如果程序為獨立的Mach-O可執(zhí)行文件,或者Info.plist
不可用、格式錯誤或者不完整,這個字段仍然會在CoreAnalytics記錄正確生成。根據(jù)我們的測試結(jié)果,目前我們尚未澄清守護程序獲取該數(shù)據(jù)所使用的是哪個輔助來源。
如下所示,在某些情況下,processName
字段將會留空。在這些場景中,我們實際上無法通過CoreAnalytics中推測執(zhí)行的是哪個程序。
{ ‘message’: { ‘a(chǎn)ctivations’: 0,
‘a(chǎn)ctiveTime’: 0,
‘a(chǎn)ctivityPeriods’: 0,
‘a(chǎn)ppDescription’: ‘UNBUNDLED ||| ???’,
‘foreground’: ‘NO’,
‘idleTimeouts’: 0,
‘launches’: 2,
‘powerTime’: 0,
‘processName’: ”,
‘uptime’: 24},
‘name’: ‘comappleosanalyticsappUsage’,
‘uuid’: ‘4d7c9e4a-8c8c-4971-bce3-09d38d078849’}
表15. 無名程序所對應(yīng)的CoreAnalytics記錄
9、uptime
可能表示的是程序運行的總時長(以秒為單位),該數(shù)字并未包含系統(tǒng)睡眠或者關(guān)閉的時間。在診斷期間,某些程序(如Dock)的運行時間很可能與系統(tǒng)運行時間相近或完全匹配。在上文的系統(tǒng)使用信息部分中,兩個uptime
(247及2431)的總和與Dock應(yīng)用的uptime
值(2678)完全匹配,如下所示:
{ ‘message’: { ‘a(chǎn)ctivations’: 0,
‘a(chǎn)ctiveTime’: 0,
‘a(chǎn)ctivityPeriods’: 0,
‘a(chǎn)ppDescription’: ‘com.apple.dock ||| 1.8 (1849.16)’,
‘foreground’: ‘NO’,
‘idleTimeouts’: 0,
‘launches’: 0,
‘powerTime’: 0,
‘processName’: ‘Dock’,
‘uptime’: 2678},
‘name’: ‘comappleosanalyticsappUsage’,
‘uuid’: ‘4d7c9e4a-8c8c-4971-bce3-09d38d078849’}
表16. Dock應(yīng)用對應(yīng)的CoreAnalytics記錄
在我們的測試中,我們發(fā)現(xiàn)另一個子系統(tǒng)(即comappleosanalyticsMASAppUsage
)往CoreAnalytics文件中寫入了與Microsoft OneNote有關(guān)的記錄。JSON嵌套數(shù)據(jù)中的鍵值與comappleosanalyticsappUsage
子系統(tǒng)所寫的鍵值有所不同。這條記錄并沒有使用一個appDescription
字段,而是將CFBundleIdentifier
和CFBundleShortVersionString
(以及CFBundleVersion
)寫入identifier
以及version
字段中。除了launches
之外,該記錄還缺少其他所有字段。
{ ‘message’: { ‘identifier’: ‘com.microsoft.onenote.mac’,
‘launches’: 1,
‘version’: ‘15.32 (15.32.17030400)’},
‘name’: ‘comappleosanalyticsMASAppUsage’,
‘uuid’: ‘0fd0693a-3d0a-48be-bdb2-528e18a3e86c’}
表17. Microsoft OneNote對應(yīng)的CoreAnalytics記錄,由另一個子系統(tǒng)生成
可能其他子系統(tǒng)所生成的數(shù)據(jù)結(jié)構(gòu)也會有所不同。
在診斷周期結(jié)束時,CoreAnalytics數(shù)據(jù)會被寫入到文件中,在此之前我們有可能能恢復(fù)這些數(shù)據(jù)。
在數(shù)據(jù)提交并推送到當(dāng)天的CoreAnalytics文件之前,/private/var/db/analyticsd/aggregates/
目錄充當(dāng)了每個子系統(tǒng)的臨時性暫存目錄。每個子系統(tǒng)在該目錄中都對應(yīng)一個階段性文件,文件名為子系統(tǒng)的UUID值。比如,4d7c9e4a-8c8c-4971-bce3-09d38d078849
文件包含了1.0版comappleosanalyticsappUsage
子系統(tǒng)所生成的報告數(shù)據(jù)(這些數(shù)據(jù)在00:00:00 UTC時間后的首次睡眠或者關(guān)機時會寫入到/Library/Logs/DiagnosticReports/
目錄的CoreAnalytics文件中)。這些文件的內(nèi)容似乎為嵌套數(shù)組,比如Google Chrome所對應(yīng)的數(shù)組如下所示:
[ [‘Google Chrome’, ‘com.google.Chrome ||| 67.0.3396.99 (3396.99)’, ‘YES’],
[5660, 145, 0, 0, 5, 2, 1020]]
表18. Google Chrome所對應(yīng)的聚合數(shù)據(jù)
這些值對應(yīng)comappleosanalyticsappUsage
子系統(tǒng)所生成的CoreAnalytics記錄中的一些字段,具體如下:
[ [processName, appDescription, foreground],
[uptime, activeTime, launches, idleTimeouts, activations, activityPeriods, powerTime]]
表19. 聚合數(shù)據(jù)的數(shù)組結(jié)構(gòu)
解析聚合文件中中數(shù)組的值,將其與上述字段一一對應(yīng)后,我們現(xiàn)在就可以在當(dāng)天分析數(shù)據(jù)被提交至CoreAnalytics文件前,分析當(dāng)天應(yīng)用的使用情況。
CoreAnalytics可以為我們提供關(guān)于系統(tǒng)及應(yīng)用程序使用情況的大量信息,程序執(zhí)行歷史跨度長達(dá)一個月的,可以在調(diào)查任務(wù)中起到關(guān)鍵作用,由于調(diào)查行為本身特性,證據(jù)往往無法在現(xiàn)場第一時間收集,此時能起到的作用也就更加明顯。盡管Apple提供的官方文檔可能會進一步澄清某些字段的用途及含義,研究人員可以以本文為基礎(chǔ),開始研究macOS系統(tǒng)上的應(yīng)用活動數(shù)據(jù)。