Skip to content

Add KakaoTalk support for iOS - #2249

Merged
abrignoni merged 4 commits into
mainfrom
feat/kakaotalk-ios
Sep 22, 2026
Merged

abrignoni merged 4 commits into
mainfrom
feat/kakaotalk-ios

Conversation

@abrignoni

Copy link
Copy Markdown
Owner

Adds KakaoTalk support for iOS. Five artifacts from the client's own stores:

  • Messages (Message.sqlite): sender, chat, type and the sent, read and updated times, all in the clear. The message body and attachment are encrypted at rest and reported as stored. Published research describes the scheme (AES-CBC under a key derived from the account's user id, with a key and IV hardcoded in the client that it does not publish); no decryption is attempted, and the citation is in the notes.
  • Chats (Talk.sqlite): rooms, member and unread counts, and the folder a chat is filed under.
  • Users: friends, chat members and official accounts the client knows, with names and profile fields. Phone numbers are encrypted and reported as stored.
  • Address Book Matches (ZCONTACT): device contacts the client synced, with the encrypted numbers as stored.
  • Chat Media: files under the per chat media folders, attributed to a chat by the folder id the store records and rendered where the bytes are a type the report can show.

Message.sqlite and Talk.sqlite are generic file names, so each store is confirmed to carry the client's own layout before a row is reported. Two epochs appear in the Message table and are converted separately: sentAt and readAt are Cocoa seconds, updateAt is Unix seconds. The raw phone and contact id columns are absent from the older of the two schemas seen and are resolved per store.

Field mapping was done against private samples, so no sample_data is recorded.

Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com

🤖 Generated with Claude Code

abrignoni and others added 2 commits September 22, 2026 16:02
Five artifacts from the KakaoTalk iOS client's own stores:

- Messages (Message.sqlite): sender, chat, type and times in the clear;
  the message body and attachment are encrypted at rest and reported as
  stored, with the published scheme cited.
- Chats (Talk.sqlite ZCHAT): rooms, member and unread counts, folder.
- Users (ZUSER): friends and chat members, names and profile fields.
- Address Book Matches (ZCONTACT): synced device contacts.
- Chat Media: files under the per chat media folders, attributed to a
  chat by the folder id the store records, rendered where the bytes are
  a type the report can show.

Message.sqlite and Talk.sqlite are generic names, so each store is
confirmed to carry the client's own layout before a row is reported.
sentAt and readAt are Cocoa seconds; updateAt in the same table is Unix
seconds, converted separately.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The client encrypts these per record with AES-CBC, under a key derived
from the owning user id by PBKDF2-HMAC-SHA1 with two iterations and a
key and IV hardcoded in the client. The derivation and the two constants
were recovered from the client binary and validated against the stored
ciphertext: two iterations decrypt every value, one and three decrypt
none, and the wrong user id decrypts none.

Message body, attachment metadata (keyed on Message.userId) and the
ZUSER phone number (keyed on the row's ZID) are now decrypted; a value
that does not decrypt is left as stored. The ZCONTACT address-book
numbers use a different, unrecovered key and stay as stored.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@abrignoni

Copy link
Copy Markdown
Owner Author

Update: the message body, attachment and phone-number fields are now decrypted rather than reported as stored ciphertext.

The client encrypts these per record with AES-CBC, keyed on the owning user id through PBKDF2-HMAC-SHA1 with two iterations, and a key and IV hardcoded in the client. The derivation and the two constants were recovered from the client binary and validated against the stored ciphertext: two iterations decrypt every value, one and three decrypt none, and the wrong user id decrypts none. On the samples tested every message body, every attachment field and every populated user phone number decrypted (the phone numbers to phone-shaped strings). A value that does not decrypt is left as stored. The device address-book numbers in ZCONTACT use a different key that was not recovered and stay as stored.

abrignoni and others added 2 commits September 22, 2026 17:44
Now that the attachment field is decrypted, a media message's attachment
shares a token with its local file name in the chat media folder. The
Messages artifact matches the file inside the message's own chat and
renders it inline in a Media column, and declares a conversation data
view so LAVA shows it too. The Chat Media artifact still lists every kept
file, including any whose message the store no longer holds.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
check_conversation_column_order required the declared role columns to
follow the timeColumn and other date columns before any other column.
Reorders Messages to Sent, Read, Updated, Sender Name, Message, Media,
then Chat ID and the rest, and reorders the row tuple in the same edit.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@abrignoni
abrignoni merged commit e63e88a into main Sep 22, 2026
11 checks passed
@abrignoni
abrignoni deleted the feat/kakaotalk-ios branch September 22, 2026 22:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant