giovedì 12 dicembre 2024

Published dicembre 12, 2024 by Django Faiola with 0 comment

iOS Foursquare Swarm - Check-in App

Indice dei contenuti

Introduzione

Foursquare Swarm è un’applicazione mobile gratuita sviluppata da Foursquare Labs, Inc. nata nel 2014 dalla scissione di Foursquare in due app: Foursquare destinata a raccogliere le recensioni dei luoghi e i voti degli utenti; Swarm dedicata ai check-in e alla parte social.

Swarm è un social heat map che mostra i luoghi più caldi del momento, ovvero i più frequentati da utenti e amici. Effettuato il check-in è possibile condividere la propria posizione con gli amici e la persona che ha effettuato più volte il check-in del luogo, viene insignita del badge di mayor (sindaco). E' possibile creare piani, organizzare incontri e tante altre attività.

Per maggiori dettagli sulle funzionalità dell'app consulta https://www.swarmapp.com.

App Store: https://apps.apple.com/us/app/foursquare-swarm-check-in-app/id870161082

Per lo studio di questa app sono state utilizzate le immagine pubbliche del CTF 2023 - Abe's iPhone e CTF 2024 - Otto's iPhone della Cellebrite con le versioni di Swarm 6.12.20 e 6.12.32.

Percorsi

Di seguito lo stralcio di Swarm del poster della SANS “iOS Third-Party Apps Forensics Reference Guide Poster” con le informazioni più rilevanti per l’analisi dell’app.

Account

Per la ricostruzione dell'account, come indicato nel poster, è sufficiente il database SQLite "/Library/Caches/foursquare.sqlite e nello specifico la tabella ZFSUSER. Questa tabella contiene sia l'utente come "account" che gli utenti come "contatti". Per l'account occorre solo filtrare il campo ZRELATIONSHIP che rappresenta il tipo di relazione con il valore self.

SELECT
    U.Z_PK AS "U_PK",
    FU.Z_PK AS "FU_PK",
    datetime(U.ZSWARMCREATEDAT + 978307200, 'unixepoch') AS "created",
    datetime(U.ZJOINEDAT + 978307200, 'unixepoch') AS "joined_at",
    U.ZFIRSTNAME,
    U.ZLASTNAME,
    U.ZGENDER,
    date(U.ZBIRTHDAY + 978307200, 'unixepoch') AS "birthday",
    U.ZHOMECITY,
    U.ZPHONE,
    U.ZEMAIL,
    FU.ZMONGOID AS "facebook",
    U.ZTWITTER,
    U.ZCANONICALURL,
    IIF(U.ZPHOTOPREFIX NOT NULL AND U.ZPHOTOSUFFIX NOT NULL, U.ZPHOTOPREFIX || 'original' || U.ZPHOTOSUFFIX, '') AS "original_photo",
    U.ZCHECKINPINGS AS "neighborhood_sharing_state",
    U.ZCHECKINSCOUNT AS "total_checkins",
    U.ZMONGOID AS "uid"
FROM ZFSUSER AS "U"
LEFT JOIN ZFSFACEBOOKUSER AS "FU" ON (U.ZFACEBOOKUSER = FU.Z_PK)
WHERE U.ZRELATIONSHIP = 'self' 

La tabella ZFSUSER:

  • Z_PK1 (chiave primaria);
  • ZSWARMCREATEDAT2022-04-24 20:10:20 (data di creazione nel formato MAC Absolute Time 24  aprile 2022 20:10:20);
  • ZJOINEDAT2022-04-24 20:10:19 (data di iscrizione nel formato MAC Absolute Time 24  aprile 2022 20:10:19);
  • ZFIRSTNAMEAbe (nome);
  • ZLASTNAMERudder (cognome);
  • ZGENDERmale (identità di genere, ad es. malefemale, etc.);
  • ZBIRTHDAYxxxx-10-25 (data di nascita/compleanno);
  • ZHOMECITYRedmond, WA (città natale);
  • ZPHONE2065937xxx (numero di telefono);
  • ZEMAILaberudderxxx@gmail.com (indirizzo email);
  • ZFACEBOOKUSER1 (chiave esterna dell'account Facebook, Z_PK della tabella ZFSFACEBOOKUSER);
  • ZTWITTER: null (identificativo dell'account Twitter);
  • ZCANONICALURLhttps://foursquare.com/user/1386806998 (URL del profilo);
  • ZPHOTOPREFIXhttps://fastly.4sqi.net/img/user/ (parte inziale dell'URL della foto del profilo);
  • ZPHOTOSUFFIX/1386806998_CHK2mA3y_vX4zXNuaCm-JkzaQxDcBnaAlgnKA1FgbUsgikmV9wHGHBNv9nv5C2ya4hyoYvWhQ.jpg (parte finale dell'URL della foto del profilo);
  • ZCHECKINPINGSoff (stato di condivisione del vicinato, ad es. on, off);
  • ZCHECKINSCOUNT38 (numero di check-in fatti);
  • ZMONGOID1386806998 (identificatore univoco);
  • ZRELATIONSHIPself (tipo di relazione, ad  es. self (owner), friend (amico), pendingMe (follower), pendingThem (follower) e followingThem (following)).

L'URL della foto è formattato come "ZPHOTOPREFIX<formato>ZPHOTOSUFFIX", dove <formato> è la dimensione della foto; il valore original permette di visualizzare la foto originale. Con i valori sopra riportati il percorso completo è: "https://fastly.4sqi.net/img/user/original/1386806998_CHK2mA3y_vX4zXNuaCm-JkzaQxDcBnaAlgnKA1FgbUsgikmV9wHGHBNv9nv5C2ya4hyoYvWhQ.jpg". L'originale ha una dimensione (WxH) di 1024x1024. Per esempio un valore di <formato>=400x400 produce un'immagine scalata dell'originale.

La tabella ZFSFACEBOOKUSER (FU_PK=1):

  • Z_PK1 (chiave primaria);
  • ZMONGOID109289358430659 (identificatore dell'account di Facebook).

API: https://docs.foursquare.com/developer/reference/foursquare-apis-overview

Contatti

I contatti sono presenti sempre nel database SQLite "/Library/Caches/foursquare.sqlite", come già anticipato sopra, nella tabella ZFSUSER . Per ottenere l'elenco completo, escluso l'account, occorre filtrare ZRELATIONSHIP diverso da self o uguale a IS NULL

SELECT
    U.Z_PK AS "U_PK",
    FU.Z_PK AS "FU_PK",
    CASE U.ZUSERTYPE
        WHEN 'user' Then 'User'
        WHEN 'brand' Then 'Brand'
        WHEN 'celebrity' Then 'Celebrity'
        WHEN 'venuePage' Then 'Venue Page'
        WHEN 'page' Then 'Page'
        WHEN 'chain' Then 'Chain'
        ELSE U.ZUSERTYPE
    END AS "user_type",
    CASE U.ZRELATIONSHIP
        WHEN 'self' THEN 'Owner'
        WHEN 'friend' THEN 'Friend'
        WHEN 'pendingMe' THEN 'Follower'
        WHEN 'pendingThem' THEN 'Follower'
        WHEN 'followingThem' THEN 'Following'
        ELSE 'Other'
    END AS "relationship",
    U.ZFIRSTNAME, 
    U.ZLASTNAME,
    U.ZGENDER,
    date(U.ZBIRTHDAY + 978307200, 'unixepoch') AS "birthday",
    U.ZHOMECITY,
    U.ZPHONE,
    U.ZEMAIL,
    FU.ZMONGOID AS "facebook",
    U.ZTWITTER,
    U.ZCANONICALURL,
    IIF(U.ZPHOTOPREFIX NOT NULL AND U.ZPHOTOSUFFIX NOT NULL, U.ZPHOTOPREFIX || 'original' || U.ZPHOTOSUFFIX, '') AS "original_photo",
    U.ZMONGOID AS "uid"
FROM ZFSUSER AS "U"
LEFT JOIN ZFSFACEBOOKUSER AS "FU" ON (U.ZFACEBOOKUSER = FU.Z_PK)
WHERE (U.ZRELATIONSHIP != 'self') OR (U.ZRELATIONSHIP IS NULL)

La tabella ZFSUSER (i campi sono più o meno gli stessi dell'account):

  • ZUSERTYPE: null (tipo di utente, ad es. user (utente), brand (marca), celebrity (celebrità), venuePage (luogo), page (pagina), chain (catene di negozi/attività), etc.);
  • ZRELATIONSHIPself (tipo di relazione, ad  es. self (owner), friend (amico), pendingMe (follower), pendingThem (follower) e followingThem (following)).

Check-in

I check-in è l'artefatto di maggior interesse dal punto di vista forense in quanto contiene sia le posizioni GPS che i timestamp dei luoghi visitati. Questi sono presenti nella tabella ZFSCHECKIN. Per ottenere solo i check-in bisogna filtrare ZCHECKINTYPE che rappresenta il tipo con il valore checkin.

SELECT
    CI.Z_PK AS "CI_PK",
    V.Z_PK AS "V_PK",
    U.Z_PK AS "U_PK",
    datetime(CI.ZCREATEDAT + 978307200, 'unixepoch') AS "created",
    CASE U.ZRELATIONSHIP
        WHEN 'self' THEN 'Owner'
        WHEN 'friend' THEN 'Friend'
        WHEN 'pendingMe' THEN 'Follower'
        WHEN 'pendingThem' THEN 'Follower'
        WHEN 'followingThem' THEN 'Following'
        ELSE 'Other'
    END AS "relationship",
    IIF(U.ZLASTNAME IS NULL OR length(U.ZLASTNAME) = 0, coalesce(U.ZFIRSTNAME, ''), IIF(U.ZFIRSTNAME IS NULL OR length(U.ZFIRSTNAME) = 0, coalesce(U.ZLASTNAME, ''), U.ZFIRSTNAME || ' ' || coalesce(U.ZLASTNAME, ''))) AS "full_name",
    IIF(CI.ZPRIVATE = 1, 'Private', 'Public') AS "privacy",
    V.ZNAME AS "venue_name",
    V.ZDISTANCE AS "distance (m)",
    V.ZGEOLAT AS "latitude",
    V.ZGEOLONG AS "longitude",
    V.ZADDRESS AS "address",
    V.ZNEIGHBORHOOD AS "neighborhood",
    V.ZCOUNTRY AS "country",
    V.ZSTATE AS "state",
    V.ZCITY AS "city",
    V.ZCROSSSTREET,
    V.ZPOSTALCODE,
    V.ZPHONE,
    V.ZFACEBOOKID,
    V.ZTWITTER,
    V.ZINSTAGRAM,
    V.ZCANONICALURL AS "checkin_url",
    V.ZURL AS "website",
    IIF(CI.ZISMAYOR = 0, '', 'Yes') AS "is_major",
    CI.ZSHOUT,
    CI.ZMONGOID AS "checkin_uid"
FROM ZFSCHECKIN AS "CI"
LEFT JOIN ZFSVENUE AS "V" ON (CI.ZVENUE = V.Z_PK)
LEFT JOIN ZFSUSER AS "U" ON (CI.ZUSER = U.Z_PK)
WHERE CI.ZCHECKINTYPE = 'checkin'
ORDER BY CI.ZCREATEDAT DESC

La tabella ZFSCHECKIN (esempio CI_PK=517):

  • Z_PK: 517 (chiave primaria);
  • ZCREATEDAT2023-06-12 10:58:58 (data di creazione nel formato MAC Absolute Time 12  giugno 2023 10:58:58);
  • ZTIMEZONEOFFSET: -420 (offset del fuso orario in minuti, -7 ore); 
  • ZTIMEZONE: null (fuso orario del luogo, ad es. America/Denver);
  • ZPRIVATE: null (tipo di privacy, 1=privato);
  • ZISMAYOR: 0 (l'utente è un mayor del luogo del checkin? 0=no);
  • ZSOURCENAMESwarm for iOS (nome della sorgente, ad es. Swarm for iOS);
  • ZMONGOID: 6486fa721efb251c01a199f6 (identificatore univoco);
  • ZCHECKINTYPE: checkin (tipo di checkin, ad es. checkinpassive=l'aggiornamento passivo delle posizioni);
  • ZSHOUT: null (messaggio "gridato");
  • ZVENUE: 2 (chiave esterna dei luoghi, Z_PK della tabella ZFSVENUE);
  • ZUSER1 (chiave esterna del contatto, Z_PK della tabella ZFSUSER).

La tabella ZFSVENUE contiene i luoghi visitati (V_PK=2):

  • Z_PK: 2 (chiave primaria);
  • ZNAME: Seattle-Tacoma International Airport (SEA) (nome del luogo);
  • ZDISTANCE: 26486.0 (distanza in metri dal luogo);
  • ZGEOLAT: 47.4435885341923 (latitudine del luogo);
  • ZGEOLONG: -122.302508354187 (longitudine del luogo);
  • ZADDRESS: 17801 International Blvd (indirizzo);
  • ZNEIGHBORHOOD: null (vicinato/quartiere);
  • ZCOUNTRY: United States (paese);
  • ZSTATE: WA (stato);
  • ZCITY: SeaTac (città);
  • ZCROSSSTREET: at S 188th St (traversa/incrocio);
  • ZPOSTALCODE: 98158 (codice postale);
  • ZPHONE: 2067875388 (numero di telefono);
  • ZFACEBOOKID126440017409096 (identificativo dell'account Facebook);
  • ZTWITTER: flysea (identificativo dell'account Twitter);
  • ZINSTAGRAM: flysea (identificativo dell'account Instagram);
  • ZCANONICALURL: https://foursquare.com/v/seattletacoma-international-airport-sea/45f555cef964a5200e441fe3 (URL del luogo);
  • ZURL: www.portseattle.org/sea-tac (sito web).

La tabella ZFSUSER (U_PK=1):

  • Z_PK1 (chiave primaria);
  • ZRELATIONSHIPOwner (tipo di relazione);
  • ZFIRSTNAME: Abe (nome);
  • ZLASTNAME: Rudder (cognome).

Consigli

I consigli (tips) sono un modo di condividere approfondimenti con la comunità, offrire raccomandazioni o mettere in guardia contro determinate esperienze. La tabella in questione è ZFSTIP.

SELECT
    T.Z_PK AS "T_PK",
    U.Z_PK AS "U_PK",
    V.Z_PK AS "V_PK",
    datetime(T.ZCREATEDAT + 978307200, 'unixepoch') AS "created",
    CASE U.ZRELATIONSHIP
        WHEN 'self' THEN 'Owner'
        WHEN 'friend' THEN 'Friend'
        WHEN 'pendingMe' THEN 'Follower'
        WHEN 'pendingThem' THEN 'Follower'
        WHEN 'followingThem' THEN 'Following'
        ELSE 'Other'
    END AS 'relationship',
    IIF(U.ZLASTNAME IS NULL OR length(U.ZLASTNAME) = 0, coalesce(U.ZFIRSTNAME, ''), IIF(U.ZFIRSTNAME IS NULL OR length(U.ZFIRSTNAME) = 0, coalesce(U.ZLASTNAME, ''), U.ZFIRSTNAME || ' ' || coalesce(U.ZLASTNAME, ''))) AS "full_name",
    T.ZTEXT AS "tip",
    V.ZNAME AS "venue_name",
    V.ZDISTANCE AS "distance (m)",
    V.ZGEOLAT AS "latitude",
    V.ZGEOLONG AS "longitude",
    T.ZURL AS "url_tip" ,
    T.ZMONGOID AS "uid"
FROM ZFSTIP AS "T"
LEFT JOIN ZFSUSER AS "U" ON (T.ZUSER = U.Z_PK)
LEFT JOIN ZFSVENUE AS "V" ON (T.ZVENUE = V.Z_PK)
ORDER BY T.ZCREATEDAT DESC

La tabella ZFSTIP (esempio T_PK=46):

  • Z_PK46 (chiave primaria);
  • ZCREATEDAT: 2023-06-12 11:32:03 (data di creazione nel formato MAC Absolute Time 12  giugno 2023 11:32:03);
  • ZTEXT: On he mooove (testo del tip);
  • ZURL: null (URL del tip);
  • ZMONGOID: 64870233df69a377fc1f6c30 (identificatore univoco);
  • ZUSER1 (chiave esterna del contatto, Z_PK della tabella ZFSUSER);
  • ZVENUE2 (chiave esterna dei luoghi, Z_PK della tabella ZFSVENUE).

Adesivi

Gli adesivi (stickers) sono ricompense visive che possono essere aggiunte a messaggi, foto, nei successivi check-in per guadagnare monete, bonus e altro.

SELECT
    S.Z_PK AS "S_PK",
    S.ZNAME AS "title",
    S.ZCATEGORYNAME AS "category",
    S.ZTEASETEXT AS "preview_text",
    IIF(S.ZUNLOCKED = 0, '', 'Yes') AS "unlocked",
    S.ZUNLOCKTEXT,
    S.ZBONUSSTATUS,
    S.ZBONUSTEXT,
    IIF(S.ZIMAGEPREFIX NOT NULL AND S.ZIMAGENAME NOT NULL, S.ZIMAGEPREFIX || 'original' || S.ZIMAGENAME, '') AS "original_image",
    S.ZMONGOID AS "uid"
FROM ZFSSTICKER AS "S"

La tabella ZFSSTICKER (esempio S_PK=37):

  • Z_PK37 (chiave primaria);
  • ZNAME: Baggs (nome/titolo);
  • ZCATEGORYNAME: Food & Drink Shop (categoria);
  • ZTEASETEXT: Check in at food & drink shops to unlock this sticker. (anteprima del testo);
  • ZUNLOCKED: Yes (adesivo sbloccato? 0=No, 1=Yes);
  • ZUNLOCKTEXT: They're out of milk, your cart's wheel is busted, and that lady has way more than 10 items! Here's hoping Baggs doesn't dump your eggs on the ground. (testo quando è sbloccato);
  • ZBONUSSTATUS: Use once per week. Recharges Sunday at midnight. (stato del bonus);
  • ZBONUSTEXT: Use at Food & Drink Shops for a bonus. (testo del bonus);
  • ZIMAGEPREFIXhttps://fastly.4sqi.net/img/sticker/ (parte inziale dell'URL dell'immagine);
  • ZSUFFIX/groceries_2a2425.png (parte finale dell'URL dell'immagine);
  • ZMONGOID55563bd52beaa0fbc4d1dc3f (identificatore univoco).

La cronologia dei luoghi

La tabella ZFSVENUE contiene tutti i luoghi visitati mentre la tabella ZFSCATEGORY contiene le categorie associate ai luoghi, ad es. Airport, Medical Center, Men's Store, etc. 

SELECT
    V.Z_PK AS "V_PK",
    C.Z_PK AS "C_PK",
    U.Z_PK AS "U_PK",
    C.ZNAME AS "category_name",
    V.ZNAME AS "venue_name",
    V.ZDISTANCE AS "distance (m)",
    V.ZGEOLAT AS "latitude",
    V.ZGEOLONG AS "longitude",
    V.ZADDRESS AS "address",
    V.ZNEIGHBORHOOD AS "neighborhood",
    V.ZCOUNTRY AS "country",
    V.ZSTATE AS "state",
    V.ZCITY AS "city",
    V.ZCROSSSTREET,
    V.ZPOSTALCODE,
    V.ZPHONE,
    V.ZFACEBOOKID,
    V.ZTWITTER,
    V.ZINSTAGRAM,
    V.ZCANONICALURL AS "foursquare_url",
    V.ZURL AS "website",
    V.ZDESCRIPTIONTEXT,
    U.ZMONGOID AS "mayor_uid",
    IIF(U.ZLASTNAME IS NULL OR length(U.ZLASTNAME) = 0, coalesce(U.ZFIRSTNAME, ''), IIF(U.ZFIRSTNAME IS NULL OR length(U.ZFIRSTNAME) = 0, coalesce(U.ZLASTNAME, ''), U.ZFIRSTNAME || ' ' || coalesce(U.ZLASTNAME, ''))) AS "full_name",
    V.ZMAYORSUMMARY,
    V.ZFRIENDVISITSSUMMARY,
    V.ZEVENTSSUMMARY,
    V.ZREASONSUMMARY,
    V.ZLIKESCOUNT,
    V.ZUSERSCOUNT AS "visiters_count",
    V.ZCHECKINSCOUNT,
    V.ZPHOTOSCOUNT,
    V.ZTIPSCOUNT,
    V.ZEVENTSCOUNT
FROM ZFSVENUE AS "V"
LEFT JOIN ZFSCATEGORY AS "C" ON (V.ZPRIMARYCATEGORY = C.Z_PK)
LEFT JOIN ZFSUSER AS "U" ON (V.ZMAYOR = U.Z_PK)
ORDER BY V.ZNAME ASC

La tabella ZFSVENUE (esempio V_PK=3):

  • Z_PK: 3 (chiave primaria);
  • ZPRIMARYCATEGORY: 336 (chiave esterna della categoria, Z_PK della tabella ZFSCATEGORY);
  • ZNAMESeattle-Tacoma International Airport (SEA) (nome del luogo);
  • ZDISTANCE26486.0 (distanza in metri dal luogo);
  • ZGEOLAT47.4435885341923 (latitudine del luogo);
  • ZGEOLONG-122.302508354187 (longitudine del luogo);
  • ZADDRESS17801 International Blvd (indirizzo);
  • ZNEIGHBORHOODnull (vicinato/quartiere);
  • ZCOUNTRYUnited States (paese);
  • ZSTATEWA (stato);
  • ZCITYSeaTac (città);
  • ZCROSSSTREETat S 188th St (traversa/incrocio);
  • ZPOSTALCODE98158 (codice postale);
  • ZPHONE2067875388 (numero di telefono);
  • ZFACEBOOKID126440017409096 (identificativo dell'account Facebook);
  • ZTWITTERflysea (identificativo dell'account Twitter);
  • ZINSTAGRAMflysea (identificativo dell'account Instagram);
  • ZCANONICALURLhttps://foursquare.com/v/seattletacoma-international-airport-sea/45f555cef964a5200e441fe3 (URL del luogo);
  • ZURLwww.portseattle.org/sea-tac (sito web).
  • ZDESCRIPTIONTEXT: The 8th busiest airport in U.S., owned and operated by Port of Seattle. (descrizione del luogo);
  • ZMAYOR244 (chiave esterna dell'utente sindaco, Z_PK della tabella ZFSUSER);
  • ZMAYORSUMMARY: Andz M. is the Mayor with 31 check-ins in the last 30 days (riepilogo sul mayor);
  • ZFRIENDVISITSSUMMARYYou've been here (riepilogo delle visite degli amici);
  • ZEVENTSSUMMARY (riepilogo dell'evento);
  • ZREASONSUMMARYYou're here! (motivo per cui la sede è stata consigliata);
  • ZLIKESCOUNT5506 (numero totale di mi piace);
  • ZUSERSCOUNT254175 (numero totale di visitatori);
  • ZCHECKINSCOUNT1409015 (numero totale di checkin);
  • ZPHOTOSCOUNT21706 (numero totale di foto);
  • ZTIPSCOUNT2031 (numero totale di consigli);
  • ZEVENTCOUNTnull (numero totale di eventi).
La tabella ZFSCATEGORY (C_PK=336):
  • Z_PK336 (chiave primaria);
  • ZNAME: International Airport (nome della categoria, ad es. AirportOfficeHospital, etc.).

Le foto dei luoghi

La tabella ZFSPHOTO contiene tutte le foto, sia quelle dei luoghi che dei suggerimenti, etc. Per le foto dei luoghi occorre solo filtrare il campo ZPHOTOTYPE che rappresenta il tipo di foto con il valore venue.

SELECT
    P.Z_PK AS "P_PK",
    V.Z_PK AS "V_PK",
    U.Z_PK AS "U_PK",
    datetime(P.ZCREATEDAT + 978307200, 'unixepoch') AS "created",
    IIF(U.ZLASTNAME IS NULL OR length(U.ZLASTNAME) = 0, coalesce(U.ZFIRSTNAME, ''), IIF(U.ZFIRSTNAME IS NULL OR length(U.ZFIRSTNAME) = 0, coalesce(U.ZLASTNAME, ''), U.ZFIRSTNAME || ' ' || coalesce(U.ZLASTNAME, ''))) AS "full_name",
    U.ZMONGOID AS "user_uid",
    V.ZNAME AS "venue_name",
    V.ZDISTANCE AS "distance (m)",
    V.ZGEOLAT AS "latitude",
    V.ZGEOLONG AS "longitude",
    V.ZADDRESS AS "address",
    V.ZNEIGHBORHOOD AS "neighborhood",
    V.ZCOUNTRY AS "country",
    V.ZSTATE AS "state",
    V.ZCITY AS "city",
    V.ZCROSSSTREET,
    V.ZPOSTALCODE,
    V.ZPHONE,
    V.ZFACEBOOKID AS "facebook",
    V.ZTWITTER,
    V.ZINSTAGRAM,
    V.ZCANONICALURL AS "foursquare_url",
    V.ZURL AS "website",
    V.ZDESCRIPTIONTEXT,
    IIF(P.ZPREFIX NOT NULL AND P.ZSUFFIX NOT NULL, P.ZPREFIX || 'original' || P.ZSUFFIX, '') AS "original_photo",
    (P.ZWIDTH || 'x' || P.ZHEIGHT) AS "photo_size",
    P.ZSWARMPRIVACYSETTING,
    P.ZSOURCENAME
FROM ZFSPHOTO AS "P"
LEFT JOIN ZFSVENUE AS "V" ON (P.ZPREVIEWVENUE = V.Z_PK)
LEFT JOIN ZFSUSER AS "U" ON (P.ZUSER = U.Z_PK)
WHERE P.ZPHOTOTYPE = 'venue'

La tabella ZFSPHOTO (esempio P_PK=161):

  • Z_PK161 (chiave primaria);
  • ZCREATEDAT2018-01-16 03:06:52 (data di creazione nel formato MAC Absolute Time 16  gennaio 2018 03:06:52);
  • ZPHOTOTYPEvenue (tipo di foto, ad es. venue, tipcheckin, etc.);
  • ZPREFIXhttps://fastly.4sqi.net/img/general/ (parte inziale dell'URL della foto);
  • ZSUFFIX/17614142_64fOoDi-kXxehbuaFAdfOJS1bEaGHLgau0Sbb_z_Gdk.jpg (parte finale dell'URL della foto);
  • ZWIDTH1440 (larghezza in pixel);
  • ZHEIGHT1920 (altezza in pixel);
  • ZSWARMPRIVACYSETTINGpublic (privacy, ad es. public o private);
  • ZSOURCENAMESwarm for iOS (sorgente/provenienza della foto, ad es. Instagram, Swarm for AndroidSwarm for iOS, Foursquare for iOS, etc.);
  • ZPREVIEWVENUE2 (chiave esterna del luogo, Z_PK della tabella ZFSVENUE).

Commenti sui check-in

La tabella ZFSCOMMENT contiene tutti i commenti, sia quelli dei check-in, dei piani, dei suggerimenti, degli adesivi etc.

SELECT
    C.Z_PK AS "C_PK",
    U.Z_PK AS "U_PK",
    CI.Z_PK AS "CI_PK",
    V.Z_PK AS "V_PK",
    datetime(C.ZCREATEDAT + 978307200, 'unixepoch') AS "created",
    CASE U.ZRELATIONSHIP
        WHEN 'self' THEN 'Owner'
        WHEN 'friend' THEN 'Friend'
        WHEN 'pendingMe' THEN 'Follower'
        WHEN 'pendingThem' THEN 'Follower'
        WHEN 'followingThem' THEN 'Following'
        ELSE 'Other'
    END AS "relationship",
    IIF(U.ZLASTNAME IS NULL OR length(U.ZLASTNAME) = 0, coalesce(U.ZFIRSTNAME, ''), IIF(U.ZFIRSTNAME IS NULL OR length(U.ZFIRSTNAME) = 0, coalesce(U.ZLASTNAME, ''), U.ZFIRSTNAME || ' ' || coalesce(U.ZLASTNAME, ''))) AS "full_name",
    C.ZTEXT AS "text",
    C.ZLAT AS "latitude",
    C.ZLNG AS "longitude",
    V.ZNAME AS "venue_name",
    V.ZGEOLAT AS "venue_latitude",
    V.ZGEOLONG AS "venue_longitude",
    C.ZMONGOID AS "uid"
FROM ZFSCOMMENT AS "C"
LEFT JOIN ZFSUSER AS "U" ON (C.ZUSER = U.Z_PK)
LEFT JOIN ZFSCHECKIN AS "CI" ON (C.ZCHECKIN = CI.Z_PK)
LEFT JOIN ZFSVENUE AS "V" ON (CI.ZVENUE = V.Z_PK)

La tabella ZFSCOMMENT:

  • Z_PK(chiave primaria);
  • ZCREATEDAT(data di creazione nel formato MAC Absolute Time);
  • ZTEXT(testo);
  • ZLAT: (latitudine del commento?);
  • ZLNG: (latitudine del commento?);
  • ZMONGOID: (identificatore univoco);
  • ZUSER(chiave esterna dell'utente, Z_PK della tabella ZFSUSER);
  • ZCHECKIN(chiave esterna del check-in, Z_PK della tabella ZFSCHECKIN).

Come si nota, non ho inserito volutamente i dati di esempio come nei casi precedenti in quanto non sono nella disponibilità di una banca dati completa. La query va quindi considerata come sperimentale!

Da fare

Lo studio svolto finora è focalizzato principalmente sull'utilizzo tipico dell'app, ovvero quello di fare check-in nei luoghi. Un'analisi più completa dovrebbe comprendere anche le altre funzioni come gli Eventi, le Liste, l'elenco delle foto per gli altri tipi (ad es. suggerimenti,  liste, etc.), i commenti per gli altri tipi, etc.

Poco è meglio di niente 😂.

iLEAPP 💖

Come di consueto, al fine di aggiungere un nuova app del poster della SANS iOS Third-Party Apps Forensics Reference Guide Poster al progetto iLEAPP (iOS Logs, Events, And Plists Parser) di Alexis Brignoni ho creato il plugin foursquareSwarm.py che alla data odierna è in “pull request” e comunque disponibile sul mio GitHub.

Di seguito alcuni "screenshot" del report di Foursquare Swarm:

Read More

sabato 26 ottobre 2024

Published ottobre 26, 2024 by Django Faiola with 3 comments

Happy 3rd Birthday to dfAPKdngrader

Il 27 ottobre 2021 ho iniziato il progetto di dfAPKdngrader con lo scopo di fornire alla comunità forense uno strumento di semplice utilizzo e robusto allo stesso tempo, in grado di eseguire il metodo del downgrade delle app su dispositivi Android.

E' la prima volta che lo senti nominare? Leggi il post di riferimento del programma dfAPKdngrader (Forensic extraction tool for Android Backup APK Downgrade method).

Da allora sono trascorsi 3 anni e ad oggi posso dire che il progetto ha riscosso un discreto successo sia in Italia che all'estero.

Per festeggiare questo anniversario ho deciso di rilasciare la versione v0.4.0:

  • Added: Riconoscimento automatico della lingua locale e caricamento del file .po/.mo con la lingua associata se esiste.
  • Added: Forzatura della lingua passando il parametro --lang <code> all'avvio del programma; <code>=es per caricare il file con la lingua spagnola o <code>=de per quella tedesca etc. se presenti.
  • Added: Schermata di riepilogo dei pacchetti sincronizzati online: nuovi, cambiati ed eliminati.
  • Added: Schermata dispositivo: il messaggio di attenzione "Abilita resta attivo", se cliccato, svolge in automatico l'operazione.
  • Changed: La struttura del file APKs.ini per il supporto della schermata di riepilogo (trasparente all'utente); "isCustom": true è obsoleto, sostituito con "state": "custom".
  • Added: Migliorata l'interfaccia grafica per l'elenco dei pacchetti disponibili: aggiunto menu contestuale.
  • Added: Opzione "Forza il caricamento di tutte le app (fallite o eseguite con successo" per il metodo di RIPRISTINO.
  • Fixed: bug minori.

Oltre 400 sono ora le app disponibili per il downgrade, quasi 100 in più della precedente lista. Un pacchetto enorme e comunque piccolo se si considerano le app localizzate più popolari dei vari paesi.

Ribadisco, l'APK downgrade non è un metodo sostitutivo per l'estrazione dei dati ma un'alternativa, come dire di "ultima spiaggia", quando tutti gli altri non sono praticabili.

Schermata di riepilogo:

Riepilogo del package (doppio click) sulla riga:

Inoltre è possibile aprire il browser alla pagina dell'app all'interno del Play Store  (link WhatsApp Messenger nel caso in figura).

Colgo l'occasione per sottolineare che ho fornito con l'eseguibile anche i file PO (Portable Object) per chi fosse interessato a dare il suo contributo per il supporto multilingua. Inoltre se avete package personalizzati non inclusi nella mia lista, sentitevi liberi di condividerli 😂 .

👏 Grazie a tutti per aver apprezzato il mio lavoro. Un ringraziamento speciale va fatto a Andrea Lazzarotto per avermi spinto a creare questo blog e per aver contribuito con i suoi preziosi suggerimenti a migliorare il prodotto. 

Ultima versione

Windows | Linux

Il software è proprietario (Freeware - closed source) e per l'uso commerciale considera una piccola donazione valida come autorizzazione implicita al suo utilizzo.

 

Elenco delle nuove app supportate

  1. Airalo
  2. AlfredCamera
  3. Allegro
  4. AM - Ashley Madison
  5. Auto.ru
  6. Bonjour RATP (RATP)
  7. CallApp (CallApp Contacts)
  8. Cartão Continente
  9. Cashify
  10. com.l
  11. DAILYHOTEL (데일리호텔)
  12. Daraz
  13. Disco
  14. Dolap
  15. DoorDash
  16. droom
  17. EatSure (Faasos)
  18. eHarmony
  19. Eyecon
  20. Familo (Familonet)
  21. Favor
  22. Feeld
  23. Finally
  24. Fiverr
  25. foodora (OnlinePizza)
  26. Foody
  27. FREENOW for drivers (mytaxi)
  28. GMX Mail (Mail)
  29. Grab Driver
  30. GrubHub
  31. Hacoo (Hacoo SaraMart, Doop, SaraMart)
  32. Hungama
  33. iFood comida e mercado em casa
  34. immowelt
  35. ixigo
  36. Jaumo
  37. JD Sports
  38. Justdial
  39. Kaufland
  40. Klook
  41. Lalamove
  42. Lazada
  43. Lovely
  44. Mail.ru
  45. Match (match.com)
  46. Mercado Libre
  47. Mingle2
  48. Myntra
  49. Neenbo
  50. Nextcloud
  51. noon
  52. OpenSooq (السوق المفتوح)
  53. Ourtime Date, Meet 50+ Singles
  54. ownCloud
  55. OZON (OZON.ru)
  56. pCloud
  57. PedidosYa
  58. Pegasus
  59. PlantNet Plant Identification (Pl@ntNet)
  60. Polarsteps
  61. priceline
  62. PURE
  63. Ruhavik
  64. Save Location GPS
  65. Shop Samsung
  66. Snapdeal
  67. Spicy
  68. Star Taxi
  69. talabat
  70. Tappsi Easy (Tappsi)
  71. TAXI 18300
  72. TAXI Deutschland
  73. taxi.eu
  74. TaxiMe Driver
  75. Tchibo
  76. Tellonym
  77. TicketSwap
  78. Tokopedia
  79. Traveloka
  80. Trendyol
  81. TripCase
  82. Turo
  83. Vivino
  84. Waiter
  85. Wapa
  86. Weather Underground
  87. WEB.DE Mail (Mail)
  88. Whoosh
  89. Wikiloc
  90. wine-searcher
  91. Xe (Currency)
  92. Yandex Disk
  93. Yandex Weather
  94. Yanolja (야놀자)
  95. Yassir
  96. Zipcar
Read More

giovedì 26 settembre 2024

Published settembre 26, 2024 by Django Faiola with 0 comment

iOS Burner - Update

Introduzione

Lo scopo di questo post è quello di mettere in risalto le differenze tra le vecchie versioni e le attuali, nonché aggiornare le query precedenti. Diversi passaggi sono dati per scontato, quindi prima di iniziare la lettura di questo approfondimento, consiglio di dare un'occhiata se non l'hai già fatto ai precedenti articoli: iOS BurneriOS Burner - Cache.db.

App Store: https://apps.apple.com/us/app/burner-private-phone-line/id505800761

Percorsi

Di seguito lo stralcio di Burner del poster della SANS “iOS Third-Party Apps ForensicsReference Guide Poster” con le informazioni più rilevanti per l’analisi dell’app.

Analisi degli artefatti

Per lo studio di questa app ho utilizzato tutte le immagini pubbliche di Josh Hickman disponibili su DigitalCorpora: la versione iOS 13.3.1, 13.4.1, 14.3, 15.3.1, 16.1.2 e 17.3 con le relative versioni di Burner 4.0.18, 4.0.18, 4.3.3, 5.3.8, 5.4.11 e 5.4.11.

Purtroppo alla data odierna l'ultima versione di Burner è la 5.13.1 dell'11 settembre 2024 mentre la 5.4.11 è del 9 gennaio 2024; oltre una quindicina di versioni sono state rilasciate per risolvere bug e per migliorare le prestazioni, ma alcune hanno introdotto anche delle novità come la possibilità di condividere video ad alta qualità. Quindi non ho modo di verificare la correttezza del procedimento di analisi di seguito esposto per queste versioni e/o vedere cosa è cambiato. 

Phoenix.sqlite

Per quanto riguarda l'analisi del database SQLite le vecchie query diciamo che hanno qualche problema. Infatti dalle prime versioni in esame fino alla recente 5.4.11 le tabelle hanno subito una ristrutturazione durante questa evoluzione e non solo: sono rimasti campi inutilizzati (vuoti), successivamente rimossi, inseriti nuovi identificatori e per completare l'opera alcune relazioni tra le tabelle sono cambiate.

Accounts

Fino alla versione di Burner 4.3.3 inclusa, la tabella ZBURNER è in relazione con la tabella ZUSER (account) per mezzo della chiave esterna ZBURNER.ZUSER-> ZUSER.Z_PK. Nella versione 5.3.8 il campo ZBURNER.ZUSER è vuoto e nella 5.4.11 è stato rimosso. In iLEAPP la query è dinamica ed è basata sulla presenza o meno del campo ZUSER.

La versione aggiornata "diciamo adattata":

SELECT
    U.Z_PK AS "U_PK",
    datetime(U.ZDATECREATED + 978307200, 'unixepoch') AS "dateCreated",
    U.ZPHONENUMBER AS "mobilePhone",
    U.ZCOUNTRYCODE AS "countryCode",
    ("0" || "/" || U.ZTOTALNUMBERBURNERS) AS "nBurners",
    CASE U.ZDNDENABLED WHEN 1 THEN "On" ELSE "Off" END AS "dndEnabled",
    U.ZVOICEMAILURL AS "voicemailUrl",
    U.ZUSERID AS "userId"
FROM ZUSER AS "U"

Contatti

Non ci sono modifiche, la query è la stessa.

Numeri Burner

Stesso discorso dell'Account, non avendo più il riferimento tra le tabelle ZBURNER e ZUSER la query è adattata sempre sulla base della presenza del campo ZBURNER.ZUSER.

La versione aggiornata:

SELECT
    B.Z_PK AS "B_PK",
    substr(B.ZIMAGE, 2, length(B.ZIMAGE) - 2) AS "image",
    B.ZPHONENUMBER AS "burnerNumber",
    B.ZNAME AS "displayName",
    datetime(B.ZDATECREATED + 978307200, 'unixepoch') AS "dateCreated",
    datetime(B.ZEXPIRATIONDATE + 978307200, 'unixepoch') AS "expirationDate",
    CASE B.ZNOTIFICATIONS WHEN 1 THEN "On" ELSE "Off" END AS "notifications",
    CASE B.ZCALLERIDENABLED WHEN 0 THEN "Burner Number" ELSE "Caller Number" END AS "inboundCallerId",
    CASE B.ZUSESIP WHEN 0 THEN "Standard Voice" ELSE "VoIP" END AS "VoIPinAppCalling",
    CASE B.ZAUTOREPLYACTIVE WHEN 0 THEN "No" ELSE "Yes" END AS "autoReplyActive",
    B.ZAUTOREPLYTEXT AS "autoReplyText",
    coalesce(B.ZREMAININGMINUTES, "0") || "/" || coalesce(B.ZTOTALMINUTES, "0") AS "minutes",
    coalesce(B.ZREMAININGTEXTS, "0") || "/" || coalesce(B.ZTOTALTEXTS, "0") AS "texts",
  B.ZBURNERID AS "burnerId"
FROM ZBURNER AS "B"

Messaggi

Per i messaggi la questione si fa un po' più spinosa: diverse sono le colonne (campi) che entrano in gioco. Le relazioni principali sono sempre la ZMESSAGE.ZMESSAGETHREAD->ZMESSAGETHREAD.Z_PK e la ZMESSAGETHREAD.ZCONTACT->ZCONTACT.Z_PK.

Il problema sorge quando i valori ZMESSAGE.ZMESSAGETHREAD e/o ZMESSAGETHREAD.ZCONTACT sono nulli: viene a mancare il collegamento tra il messaggio e il thread e di conseguenza quello tra il thread e il contatto. Come risultato si ha solo il numero di telefono del contatto e non il nome completo.

Come mettere di nuovo in relazione queste tabelle per ottenere i nomi dei contatti?

Nella versione 5.4.11 è presente un nuovo campo sia in ZMESSAGETHREAD.ZCONVERSATIONID che in ZMESSAGE.ZCONVERSATIONID, l'identificatore della conversazione (in pratica il numero di telefono con il prefisso internazionale), utile per creare il nuovo legame. Ma il numero di telefono del contatto, ovvero il contatto, può essere associato a diversi burner quindi bisogna impostare un'ulteriore restrizione su questo nuovo legame tenendo conto dell'identificatore del burner.

Con l'aggiunta della seguente espressione è possibile ristabilire il legame tra il thread e il messaggio.

 OR (M.ZMESSAGETHREAD IS NULL AND M.ZBURNERID = MT.ZBURNERID AND M.ZCONVERSATIONID = MT.ZCONVERSATIONID)

Nella versione 5.3.8, ZCONVERSATIONID non esiste, quindi il legame si ottiene con ZCONTACTID o ZCONTACTPHONENUMBER.

 OR (M.ZMESSAGETHREAD IS NULL AND M.ZBURNERID = MT.ZBURNERID AND coalesce(M.ZCONTACTID, M.ZCONTACTPHONENUMBER) = MT.ZCONTACTPHONENUMBER)

Per le versioni precedenti alla 4.3.3 inclusa i campi non sono nulli quindi non viene aggiunta nessuna espressione.

Ora bisogna ripristinare il legame dei contatti tra le tabelle ZMESSAGETHREAD e ZCONTACT. Se è presente il campo ZMESSAGE->ZCONTACTID (per la versioni 5.3.8 e 5.4.11) e tenuto conto che nella versione 5.3.8 i valori di ZCONTACTID sono nulli mentre nella 5.4.11 invece sono i valori di ZCONTACTPHONENUMBER ad essere nulli, allora l'espressione finale è:

 OR (MT.ZCONTACT IS NULL AND coalesce(M.ZCONTACTID, M.ZCONTACTPHONENUMBER) = C.ZPHONENUMBER)

altrimenti non si aggiunge nulla.

La versione aggiornata:

SELECT
    MT.Z_PK AS "MT_PK",
    C.Z_PK AS "C_PK",
    M.Z_PK AS "M_PK",
    B.Z_PK AS "B_PK",
    IIF(C.ZNAME IS NOT NULL, C.ZPHONENUMBER || " (" || C.ZNAME || ")", C.ZPHONENUMBER) AS "thread",
    datetime(M.ZDATECREATED + 978307200, 'unixepoch') AS "dateCreated",
    IIF(M.ZDIRECTION = 1, "Incoming", "Outgoing") AS "direction",
    IIF(M.ZREAD = 1, "Read", "Not read") AS "read",
    IIF (M.ZDIRECTION = 1, 
    IIF(C.ZNAME IS NOT NULL, C.ZPHONENUMBER || " (" || C.ZNAME || ")", C.ZPHONENUMBER),
IIF(B.ZNAME IS NOT NULL, B.ZPHONENUMBER || " (" || B.ZNAME || ")", B.ZPHONENUMBER)
  ) AS "sender",
  IIF (M.ZDIRECTION = 2, 
IIF(C.ZNAME IS NOT NULL, C.ZPHONENUMBER || " (" || C.ZNAME || ")", C.ZPHONENUMBER),
    IIF(B.ZNAME IS NOT NULL, B.ZPHONENUMBER || " (" || B.ZNAME || ")", B.ZPHONENUMBER) 
  ) AS "recipient",
    CASE 
        WHEN (M.ZDIRECTION = 1) AND (M.ZSTATE = 3) THEN "Completed incoming call"
        WHEN (M.ZDIRECTION = 2) AND (M.ZSTATE = 3) THEN "Completed outgoing call"
        WHEN (M.ZDIRECTION = 1) AND (M.ZSTATE = 4) THEN "Missed incoming call"
        WHEN (M.ZDIRECTION = 2) AND (M.ZSTATE = 4) THEN "Missed outgoing call"
        WHEN (M.ZDIRECTION = 1) AND (M.ZSTATE = 5) THEN "Missed incoming call with voicemail"
        WHEN (M.ZDIRECTION = 2) AND (M.ZSTATE = 5) THEN "Missed outgoing call with voicemail"
        ELSE M.ZBODY
    END AS "message",
    CASE 
        WHEN (M.ZTYPE = 1) AND (M.ZSTATE in (3, 4)) THEN "Call"
        WHEN (M.ZTYPE = 1) AND (M.ZSTATE = 5) THEN "Voicemail"
        WHEN (M.ZTYPE = 2) AND (M.ZASSETURL IS NULL) THEN "Text"
        WHEN (M.ZTYPE = 2) THEN "Picture"
        ELSE M.ZTYPE
    END AS "mType",
    M.ZLOCALASSETURL AS "localAsset",
    M.ZLOCALTHUMBNAILURL AS "localThumbnail",
    M.ZASSETURL AS "mediaUrl",
    M.ZVOICEMAILURL AS "voiceUrl",
    M.ZMESSAGEID AS "messageId",
    M.ZBURNERID AS "burnerId",
    MT.ZMESSAGETHREADID AS "threadId"
FROM ZMESSAGE AS "M"
LEFT JOIN ZBURNER AS "B" ON (M.ZBURNERID = B.ZBURNERID)
LEFT JOIN ZMESSAGETHREAD AS "MT" ON (M.ZMESSAGETHREAD = MT.Z_PK)  OR (M.ZMESSAGETHREAD IS NULL AND M.ZBURNERID = MT.ZBURNERID AND coalesce(M.ZCONTACTID, M.ZCONTACTPHONENUMBER) = MT.ZCONTACTPHONENUMBER)
LEFT JOIN ZCONTACT AS "C" ON (MT.ZCONTACT = C.Z_PK) OR (MT.ZCONTACT IS NULL AND coalesce(M.ZCONTACTID, M.ZCONTACTPHONENUMBER) = C.ZPHONENUMBER)

Cache.db

Con il rilascio delle nuove immagini per iOS 16 e 17 da parte di Josh Hickman ho eseguito iLEAPP per verificare se i miei plugin svolgono il loro compito. Purtroppo non è stato così. La vecchia query basata solo sulle interrogazioni relative ai messaggi non produce alcun risultato significativo, quindi ho deciso di affrontare la questione.

Le analisi che seguono fanno riferimento all'iOS 17.3 e versione di Burner 5.4.11. Ispezionando la cache ho visto che sono presenti diversi file JSON, qualche immagine e anche la voicemail; quindi ho analizzato i singoli JSON e ho trovato particolarmente interessante alcuni file relativi alle conversazioni e non ai singoli messaggi. Ripercorrendo il percorso all'indietro sono risalito nel database a due tipi di richiesta:

https://phoenix.burnerapp.com/v2/user/<user_id>/burners/<burner_id>/conversations/<phone_number>/messages?pageSize=50&page=1 

https://phoenix.burnerapp.com/v2/user/<user_id>/burners/<burner_id>/conversations/<phone_number>/messages/conversations/<phone_number>/messages

La nuova query: 

SELECT
    cr.request_key AS "URL",
    crd.isDataOnFS,
    crd.receiver_data AS "data"
FROM cfurl_cache_response AS "cr"
LEFT JOIN cfurl_cache_receiver_data AS "crd" ON (cr.entry_ID = crd.entry_ID)
WHERE cr.request_key REGEXP "https:\/\/phoenix\.burnerapp\.com(\/v\d)?\/user\/[a-fA-F\d-]{36}(\/messages($|\?.*contactPhoneNumber=.+)|(\/burners\/[a-fA-F\d-]{36}\/conversations\/.+\/messages($|\?.*pageSize=.+)))"

Il file JSON (isDataOnFS=121B2F296-61C6-48FB-AA53-55D632FE4757 nell'Internal App Path "/Library/Caches/com.adhoclabs.burner/fsCachedData/" per esempio contiene le conversazioni.

Per la visualizzazione ho usato dfDataViewer, il mio visualizzatore di (B)Plist, JSON(B), (B)XML, ASN.1, Protobuf, LevelDB, etc. ancora in fase di sviluppo e non pubblico.

21B2F296-61C6-48FB-AA53-55D632FE4757

La struttura tipica di una chiamata vocale: (per esempio l'oggetto [1])

  • [1].dateCreated1720381116752 (data di creazione nel formato Unix Epoch in millisecondi, 07 luglio 2024 19:38:36);
  • [1].directionOutbound (direzione della conversazione, Outbound=uscita o Inbound=entrata);
  • [1].readtrue (flag che indica se il messaggio è stato letto, true=letto, false=non letto);
  • [1].conversation
    • conversationId+19192059xxx (numero di telefono della conversazione);
  • [1].textnull (testo del messaggio);
  • [1].messageTypeVoice (tipo di messaggio, Text=testo/immagine o Voice=chiamata/voicemail);
  • [1].stateCallCompleted (stato della conversazione, CallCompleted=fine chiamata, Voicemail=segreteria telefonica, Delivered=consegnato, CallMissed=chiamata persa);
  • [1].callDetails
    • durationMinutes: 3 (durata della chiamata in minuti);
  • [1].burnerId4f6141ae-48dc-408a-8c95-18f830aaaxxx (identificatore del burner);
  • [1].userId21d2ca9c-aba1-4ada-b7f5-23b0d97acxxx (identificatore univoco dell'utente);
  • [1].id: 32361dba-1733-4606-8df3-c8b4289a2xxx (identificatore univoco della conversazione).

La struttura tipica di un messaggio vocale: (per esempio l'oggetto [4])

    • [4]. ...
    • [4].messageTypeVoice (chiamata vocale);
    • [4].stateVoicemail (segreteria telefonica);
    • [4].voicemail
      • audioUrl: https://s3.amazonaws.com/burner-voicemail/prod/b245df6b-a316-417f-9ad8-64bf5c7fbdcd.wav (URL della registrazione audio);
      • durationSeconds: 3 (durata dell'audio in secondi).
    La struttura tipica di una immagine: (per esempio l'oggetto [7])
    • [7]. ...
    • [7].messageTypeText (testo o immagine con testo);
    • [7].stateDelivered (consegnato);
    • [7].mediaUrl: https://s3.amazonaws.com/burner-mms/prod/5196a5b3-f089-49c9-a25d-5e654d43583d.jpg (URL dell'immagine).

    Ho rimesso insieme tutti questi "pezzi" e il risultato è "stupendo", da zero a 34 messaggi.

    iLEAPP 💖

    Come di consueto, a supporto del progetto iLEAPP (iOS Logs, Events, And Plists Parser) di Alexis Brignoni ho aggiornato i plugin burner.py e burnerCache.py che alla data odierna sono in “pull request” e comunque disponibili sul mio GitHub.

    Di seguito due "screenshot" del report di Burner Cache Messages: iOS 15.3.1 e iOS 17.3

    Read More