猴子尝试解析Google Takeout(活动检测篇)
注意饮食安全,猴子!
一位猴子的同事(Troy)通过查看设备所有者的Google Takeout “Location History.json"文件,为调查人员提供了一个重要位置信息。具体来说,Troy查看了DetectedActivity分类字符串,这些字符串被Google(Play服务)用来估算设备是静止状态、在车辆中、步行等。从IN_VEHICLE到STILL的状态转换表明车辆在某个位置停了下来(而不仅仅是经过)。
作为Google Play服务的一部分,意味着这些DetectedActivity数据可能仅适用于涉及Android设备的Google账户。我们尚未在iOS设备相关的Google Takeout中看到任何DetectedActivity。
特别感谢:
- Troy分享他的发现
- Rasmus Riis Kristensen、Mike Lacombe、Heather Mahalik和Lee Crognale检查他们的Google Takeout数据并进行脚本测试
- Josh Hickman提供更多测试Android Takeout数据以及关于新Takeout格式和速度/航向/海拔字段的额外反馈
主要的DetectedActivity类别定义如下:
- IN_VEHICLE 设备在车辆中,例如汽车
- ON_BICYCLE 设备在自行车上
- ON_FOOT 设备在行走或跑步的用户身上
- RUNNING 设备在跑步的用户身上
- STILL 设备静止(未移动)
- TILTING 设备相对于重力的角度发生显著变化
- UNKNOWN 无法检测当前活动
- WALKING 设备在步行的用户身上
更多详细信息请参见此处。
注意:我们还观察到未记录的活动类型,如IN_ROAD_VEHICLE、IN_FOUR_WHEELER_VEHICLE、IN_CAR、IN_RAIL_VEHICLE。
虽然一些取证工具已经显示Google Takeout信息,但通过这些工具按DetectedActivity进行高亮/过滤并不容易/不可能。
对于Troy的Takeout(以及Josh Hickman的Android 12 Google Takeout),有一个"Location History"文件夹,该文件夹的根目录中有"Location History.json"文件。还有一些子文件夹,但它们受账户所有者编辑的影响。显然,“Location History.json"是原始数据,不受用户删除位置/行程的影响。
Ross Donnelly的这篇博客文章有更多详细信息。
最初,猴子为"Location History.json"编写了一个原型Python3脚本,但随后注意到最近的测试Takeout(在2022年1月至2月完成)不再有此JSON文件。
更新 2022年2月28日:用于"Location History.json"的原型"gLocationHistoryActivity.py"脚本现已在GitHub上提供。
注意:这仅使用15-30 MB的小文件进行测试,并且不使用"ijson"库。
相反,Google似乎用一个名为"Records.json"的文件替换了它。较新的文件也是JSON格式,但有一些细微差异,例如时间戳格式、额外字段。
猴子找不到关于此文件格式的任何文档。与其他数字取证人员确认后,证实他们的Takeout也有"Records.json"而不是"Location History.json”。
目前尚不清楚此更改是在Google服务器端实施的,还是设备上的Android/Google Play版本影响创建哪个.json文件。
更新 2022年2月28日:Josh Hickman在他的测试Android 12数据上执行了另一个Takeout,得到了一个"Records.json"而不是"Location History.json”。因此,更改似乎是在Google服务器端实施的。
因此,假设任何Takeout现在都将导出到"Records.json",猴子编写了一个脚本来处理"Records.json"文件,该文件可以描述如下:
1个位置列表,可以存储许多位置元素记录。
每个位置元素具有以下字段:
- “source”(通常为"UNKNOWN",但在此处也见过"CELL")
- “deviceTag”(设备标识符)
- “platformType”(通常为"ANDROID")
- “formFactor”(例如"PHONE")
- “serverTimestamp”(例如"2022-02-04T04:40:17.685Z",并非始终存在,多个位置元素可以相同)
- “deviceTimestamp”(例如"2022-02-04T04:40:16.214Z",并非始终存在,多个位置元素可以相同)
- “timestamp”(例如"2022-02-02T00:55:06.311Z",随每个元素记录变化,为避免混淆,猴子称此为"元素时间戳")
- “latitudeE7”(以度为单位,缩放10,000,000倍)
- “longitudeE7”(以度为单位,缩放10,000,000倍)
- “altitude”(并非始终存在,单位据Josh Hickman称为米)
- “heading”(并非始终存在,单位据Josh Hickman称为从真北顺时针的度数,例如90 = 东,180 = 南)
- “velocity”(并非始终存在,单位据Josh Hickman称为米/秒)
- “accuracy”(单位未知,怀疑为米)
- “verticalAccuracy”(并非始终存在,单位未知,怀疑为米)
每个位置元素可能/可能没有"activity"列表。
每个活动列表有一个活动"timestamp",可以存储1个或多个"subactivitys"。
注意:“subactivity"是猴子用来标记活动列表中列出的任何子活动的术语(参见下面的示例)。
每个"subactivity"可以有多个类型和置信度(百分比)对(例如type = ON_FOOT, confidence = 3 和 type = STILL, confidence = 89)。
以下是"Records.json"中父活动声明的示例:
|
|
在上面的示例中,我们可以看到1个父活动列表[红色高亮],它有一个活动时间戳(“2022-02-04T05:52:43.071Z”,黄色)和1个子活动[蓝色]。子活动有多个类型/置信度字段[绿色],这些字段分类了Google认为设备正在进行的活动(例如89% STILL)。
我们观察到每个父活动可以列出多个子活动。
脚本编写
最初,猴子使用标准的Python json库将整个"Records.json"加载到内存中。虽然这对于MB大小范围的.json文件有效,但在处理大的1.3GB数据集(约10年的数据)时导致了内存错误。
在Rasmus有帮助地将猴子指向以下文章后:
- https://stackoverflow.com/questions/40399933/memoryerror-when-loading-a-json-file
- https://stackoverflow.com/questions/40330820/load-an-element-with-python-from-large-json-file
猴子使用了第三方的"ijson"库来成功迭代加载1.3 GB的"Records.json"文件。
修订后的脚本(gRecordsActivity_ijson_date.py)搜索所有位置元素中具有"activity"的元素。然后,它处理/存储每个元素时间戳的DetectedActivity到Python字典中。每个元素时间戳可以有多个活动。
然后,每个元素时间戳日期的DetectedActivity数据输出到制表符分隔变量(TSV)文件和Keyhole标记语言(KML)文件进行分析。
以下是使用脚本(gRecordsActivity_ijson_date.py)的方法,该脚本可在GitHub上获得。
第一步 - 通过pip安装ijson库。在Ubuntu 20.04 LTS上,您可以使用以下命令:
|
|
现在,您可以通过将脚本指向Takeout Records.json和输出目录来运行它。
以下是使用帮助:
|
|
以下是一些测试数据的缩写示例命令输出:
|
|
这导致在records4_output目录中创建了以下文件:
- 2022-02-04.kml
- 2022-02-04.tsv
虽然先前的命令将提取所有日期,但脚本也可以接受ISO格式的日期范围。
日期范围筛选参数是:
- -a 开始isodate_string(例如2021-01-31)
- -b 结束isodate_string
日期参数可以单独使用或一起使用。例如,在xxx之前的所有内容将使用”-b xxx",在zzz之后的所有内容将使用"-a zzz"。
要指定日期范围,请使用两个参数,即"-a zzz -b xxx"。
例如:
|
|
将提取2022-01-01和2022-02-03(包括)之间的日期到给定的outputdir中。
如果Takeout中有多年的数据,但只有某些日期是感兴趣的,这可能会有帮助。
一旦您有了包含每日.KML和.TSV的输出目录,您可以将感兴趣日期的TSV加载到电子表格应用程序(例如Excel、OpenOffice Calc)中,并搜索DetectedActivity转换等。
示例TSV输出
注意1:行按"element_timestamp"排序。在图片中,显示了3行选中的行,具有相同的"element_timestamp"值,但它们有3个不同的"activity_timestamp"。这是一个具有多个(子)活动的元素示例。每个子活动都有自己的时间戳。
注意2:“detected_activity"列可用于更容易地检测DetectedActivity之间的转换。
注意3:“num_subactivity_types"列显示每个(子)活动列出的DetectedActivity数量。
一旦您找到了感兴趣的DetectedActivity条目,您可以在Google Earth Desktop中打开相应的.KML文件,以绘制位置并查看选定的属性。
编辑过的示例KML输出在Google Earth Desktop中查看
注意1:地图已被编辑以保护猴子的丛林健身房。
注意2:每个点的标签由"element timestamp"和(子)活动类型的数量组成。例如"2022-02-04T04:30:36.434Z, num_subactivity_types = 11”。
注意3:“accuracy"字段可以指示应信任位置图的程度。
注意4:选择父ISO日期文件夹名称(例如"2022-02-04”)旁边的复选框将绘制文件夹中的所有点。默认情况下,所有点不会在屏幕上绘制,以提高Google Earth Desktop性能。
最终想法
已经编写了一个脚本来解析Google Takeout “Records.json"中的DetectedActivity。
通过使用此脚本,分析人员可以最小化混乱/最大化Google Earth性能,并且仍然可以可视化DetectedActivity位置和转换(例如IN_VEHICLE到STILL)。
希望此脚本在分析用户的生活模式/寻找异常时证明有用。