From 0622357a64d3de05e3a79469e7399e790990eb0a Mon Sep 17 00:00:00 2001 From: tek Date: Thu, 23 Jun 2022 11:05:04 +0200 Subject: [PATCH] Adds support for MMS parsing in android backups --- mvt/android/modules/backup/sms.py | 8 +++++++- mvt/android/parsers/backup.py | 13 ++++++++++--- tests/android/test_backup_module.py | 4 ++-- tests/android/test_backup_parser.py | 6 +++--- .../d_f/000001_mms_backup | Bin 0 -> 226 bytes tests/artifacts/android_backup/backup.ab | Bin 5144 -> 679 bytes 6 files changed, 22 insertions(+), 9 deletions(-) create mode 100644 tests/artifacts/android_backup/apps/com.android.providers.telephony/d_f/000001_mms_backup diff --git a/mvt/android/modules/backup/sms.py b/mvt/android/modules/backup/sms.py index 294159d..4d4c5ca 100644 --- a/mvt/android/modules/backup/sms.py +++ b/mvt/android/modules/backup/sms.py @@ -34,5 +34,11 @@ class SMS(BackupExtraction): self.log.info("Processing SMS backup file at %s", file) data = self._get_file_content(file) self.results.extend(parse_sms_file(data)) - self.log.info("Extracted a total of %d SMS messages containing links", + + for file in self._get_files_by_pattern("apps/com.android.providers.telephony/d_f/*_mms_backup"): + self.log.info("Processing MMS backup file at %s", file) + data = self._get_file_content(file) + self.results.extend(parse_sms_file(data)) + + self.log.info("Extracted a total of %d SMS & MMS messages containing links", len(self.results)) diff --git a/mvt/android/parsers/backup.py b/mvt/android/parsers/backup.py index 7deddff..8060f29 100644 --- a/mvt/android/parsers/backup.py +++ b/mvt/android/parsers/backup.py @@ -174,7 +174,8 @@ def parse_tar_for_sms(data): tar = tarfile.open(fileobj=dbytes) res = [] for member in tar.getmembers(): - if member.name.startswith("apps/com.android.providers.telephony/d_f/") and member.name.endswith("_sms_backup"): + if member.name.startswith("apps/com.android.providers.telephony/d_f/") and \ + (member.name.endswith("_sms_backup") or member.name.endswith("_mms_backup")): dhandler = tar.extractfile(member) res.extend(parse_sms_file(dhandler.read())) @@ -183,15 +184,21 @@ def parse_tar_for_sms(data): def parse_sms_file(data): """ - Parse an SMS file extracted from a folder - Returns a list of SMS entries + Parse an SMS or MMS file extracted from a backup + Returns a list of SMS or MMS entries """ res = [] data = zlib.decompress(data) json_data = json.loads(data) for entry in json_data: + # Adapt MMS format to SMS format + if "mms_body" in entry: + entry["body"] = entry["mms_body"] + entry.pop("mms_body") + message_links = check_for_links(entry["body"]) + utc_timestamp = datetime.datetime.utcfromtimestamp(int(entry["date"]) / 1000) entry["isodate"] = convert_timestamp_to_iso(utc_timestamp) entry["direction"] = ("sent" if int(entry["date_sent"]) else "received") diff --git a/tests/android/test_backup_module.py b/tests/android/test_backup_module.py index 12e7f68..2bdb0c6 100644 --- a/tests/android/test_backup_module.py +++ b/tests/android/test_backup_module.py @@ -26,7 +26,7 @@ class TestBackupModule: files.append(os.path.relpath(os.path.join(root, fname), backup_path)) mod.from_folder(backup_path, files) run_module(mod) - assert len(mod.results) == 1 + assert len(mod.results) == 2 assert len(mod.results[0]["links"]) == 1 assert mod.results[0]["links"][0] == "https://google.com/" @@ -43,7 +43,7 @@ class TestBackupModule: files.append(member.name) mod.from_ab(fpath, tar, files) run_module(mod) - assert len(mod.results) == 1 + assert len(mod.results) == 2 assert len(mod.results[0]["links"]) == 1 def test_module_file2(self): diff --git a/tests/android/test_backup_parser.py b/tests/android/test_backup_parser.py index 6db2220..743fc0b 100644 --- a/tests/android/test_backup_parser.py +++ b/tests/android/test_backup_parser.py @@ -20,12 +20,12 @@ class TestBackupParsing: m = hashlib.sha256() m.update(ddata) - assert m.hexdigest() == "0799b583788908f06bccb854608cede375041ee878722703a39182edeb008324" + assert m.hexdigest() == "ce1ac5009fea5187a9f546b51e1446ba450243ae91d31dc779233ec0937b5d18" sms = parse_tar_for_sms(ddata) assert isinstance(sms, list) - assert len(sms) == 1 + assert len(sms) == 2 assert len(sms[0]["links"]) == 1 - assert sms[0]["links"][0] == "https://google.com/" + assert sms[0]["links"][0] == "http://google.com" def test_parsing_encryption(self): file = get_artifact("android_backup/backup2.ab") diff --git a/tests/artifacts/android_backup/apps/com.android.providers.telephony/d_f/000001_mms_backup b/tests/artifacts/android_backup/apps/com.android.providers.telephony/d_f/000001_mms_backup new file mode 100644 index 0000000000000000000000000000000000000000..e1156b68cd50930992ac7b0ba6953324d0ff4960 GIT binary patch literal 226 zcmV<803H8$oMn&Aj=~@mMqlNIt<5NQ+FIAMbv4n%7(*(M7W+fPMPp-pccHBsbqC+M z=i{=w5|LR+mOyBfq)|wdMM?tbQ--p!Zz%StX0~ewC7k=<+@A-AIXmb}ANaeGT(!#8 zpo?~7Lg(Rc6ekO^chDN9gdgQcv0eX_0;}~PW#ZXT*T^y7r{RhA+#Y@l)*g_#x cswttcwp~uAxz>3lf4Ht6Kl!M?1GbB8HoN|EoB#j- literal 0 HcmV?d00001 diff --git a/tests/artifacts/android_backup/backup.ab b/tests/artifacts/android_backup/backup.ab index bba42846aae2f01d4b96a9e0213b2356e22d73e7..ee6a07681983ffc97f20534c8ac70d31047c3ce1 100644 GIT binary patch literal 679 zcmV;Y0$BY)PDD~qNkkw*K|@PbPzo^$F$!*PZeP4hie5ocepzNpYEiLXNor1NK}LRFr9Qpm-w33BH2w!o{HMgH>C-;` zO-&7qObpG8K=E&8Y&aVKgDU>P(PS8(n_C>8l$e}dT0mO-o0*v4jDKSjBeeK8HZeD0 zP%s#cf0~1eIjQ|;`wl6HxWzwhTYFZc>{itE&84Onk4QLcO%VI-eAqQPxu$&KTB%a@ z`#YaM-n3h2Vx;FZhm0vp0zD?XdNI8SZrijmU*p?~v~Ah!s&jrnxHF%<&C>dXxBQRY z6JxfXy1JmdEXC>h!+a5S?oH(vq?WbFKXu<2`+q9a>aPl^k8TEBKVhWU<1(f84{H zen9)E_XXY?PKqI`G#75z7VEcs=e0`J`W@@!?SHP=&%CWW*NkBlP%Zx(#23>b{~H;a zqt*Yw{BJgz|LK$eUHxLY4jJ(5^Lnv4YISz0bz`}N^DC)cP0^=?AIEM!_f;1*2dTjDk@x3P!;w7zLwX6pVsVFbYP&C>RB!fC2yj N009600|58cTbX~#R+0b! literal 5144 zcmeHJON(7a5FRABxQefhl7$9Q6aqd8#L*Khtd5w#<)RH!!~2zs*!yUwHk|!#Wp2&Ky-Ry! zaf<#IUuz!xe>cdZ^KAae%atJ6`gPX@sKa5_+v(~0F67kQolbu+*oj_TlWdFAEhuTN!4^qIwfPvvxA~PPD zsOA)Ga$=Rc=>^pvB56$8v8jeVpoN-nUW|z*wUV=-{$!|XFV$L!+?66%C#C@;UUG3Y zrDCnshBCI*Yp5ZF7N}d*?5fL@l9y6@YM3G5Gz$L4sM4&OMlFeILZB59AOPw{6VPfZ zVldrg1HjuFnox}ep=NF+CdZ%wO}%xj3s$t(9wQs4p_!&6S+SfZ09dudI$iIz)#OVg zF2zOXQs9E9QT@zKELftVoXOgt-uEun6$kjL4r<+lUA(gAR6|rtS#9nq20S}QEFgBK zTpJ@amOwFfGvKQLY_=zf1ZSLE0bfuMK&Y~CGgf+nLC&3B_mO&6w5UdEv0wuN1Lj1u zT8=;&SkM(^wGLm&RGLw^VDA!l7h17dCE3IQ>w}W-TA=7F_hmk{vRolBJg$ofgbz## zhQz4kIN>YK~0 z0m#KW_Bkg-lR@LNsnF2c(I=()p_%nyMXIJsoCRnZdXkt9V4CW?lm;?EcL}K41SGh~ z!Pt&K8(@dl*L`oHaSp!40@hR4s&NjUO;po05BTbR0HHV4h3GW}<3K$qN=|6u1B7cX zr4v^lqBxU*O^5%*fFoK2pe2^XsyKw8WA~00?+L(C1A9hshN#Z;RB|&=S0E{+9JK}{ zML2_s8e1tva|3T@Ho#JM*#w{q`2xYZO2vV4UB&vj`BY8EaRxq8Mu%t9K+~y#3zPQ+ z0Z=On(v$*bp(>3WsIy1*#y4%Cy4JwFKKGolYDni!6v55NwZ-ZTC#j|-O|8^vrE%O z>h8S@=eNBg0X;O8%5AXW<-G`6t-h2Dg`>xw|YW=Z;k9>B`4bSc0cmGw-d~o3OFW-Io{5v4{r+{