TL;DR: This is a story of how I felt nostalgic for the old Uh-Oh! ICQ sound and ended up with a quick research on how Slack stores and uses media files. Eventually I ended up developing a simple tool to customize Slack sound notifications. Please note that currently my script edits the Hummus
notification sound but this can be easily changed if needed.
slack.icq.mov
- Change Slack’s notification sound to
Hummus
(we are going to edit it)Slack-->Preferences-->Notifications-->Select Hummus
- run
python3 slack_change_sound.py sound.mp3
- Restart Slack
In essence, Slack does not allow users to customize their sound notifications as they wish but I wanted to choose my own notification sound. After a bit of research I discovered that Slack stores the sound files in multiple locations, but the most important location is a directory with cache files which have a simple yet proprietary binary structure. After a bit of playing I was able to re-create the structure of Slack cache files and I got my desired ICQ sound! I also wrote a generic tool to do this for you.
So, I wanted to change my Slack notification sound to the classical Uh-Oh! ICQ sound. Sounds easy. I went to Slack Preference --> Notifications but could not find how to choose my own customized sound. Intrigued, I looked online but still could not find how to do this. Looks like Slack limits the user to a few predefined sounds only.
OK, maybe Slack doesn't allow you to change the sound to a custom one. Let's find out where the sound files are stored on disk and just replace them manually. For example - let's try to locate Hummus.mp3
sound and just modify it. find / -name Hummus.mp3
.
The Slack application is built on the Electron framework. Electron is a free and open-source software framework developed and maintained by GitHub. The framework is designed to create desktop applications using web technologies which are rendered using a flavor of the Chromium browser engine, and a backend using the Node.js runtime environment.
To investigate where resources are stored, I went to Slack installation directory /Applications/Slack.app
and searched for resource files. I found all the resource files including Hummus.mp3
Under the ./Contents/Resources
directory.
Bingo. I changed it to my ICQ sound, restarted Slack, and asked someone to send me a message. Nothing changed. I still hear the annoying Hummus
sound.
I knew that Electron applications store resources in a proprietary archive file called .asar. So OK, maybe the resource files are extracted every single time from the .asar archive. I unpacked the app-x64.asar
file using npx asar extract app-x64.asar app-x64.asar.unpacked
and observed the Hummus.mp3
file within app-x64.asar.unpacked
directory. Cool, I modified the file, packed back the .asar archive using npx asar pack app-x64.asar.unpacked/ app-x64.asar
and restarted Slack. This time Slack did not even open.
I looked at Electron source code and found out that an integrity check was added in the form of SHA-256 hash of the .asar archive header (pure JSON structure after the first DWORD size). No problem, I wrote a simple script to calculate the hash and modified ElectronAsarIntegrity
within ./Contents/Info.plist
. Restarted Slack again and it still doesn't work. After a quick Google search I remembered that updated Mac OSX applications are signed, so Slack needed to be re-signed again because we modified its files. I used codesign --sign - --force --deep --preserve-metadata=entitlements /Applications/Slack.app
and now I was finally able to restart Slack successfully! but the sound did not change... Still Hummus
.
Frustrated, I checked all the open file descriptors that Slack is using lsof -n | grep -i slack
but I could not find any .mp3
files. Interesting. It means that probably Slack loads this dynamically and uses it in-memory somehow.
At this point I determined that Slack is probably getting the sound files remotely somehow. It was strange because why would Slack request the sound files every single time from a remote server? But it was my only explanation and I decided to research this. A split second before spinning my Burp, I decided to check how the true web application behaves. I opened slack.com and entered my workspace. Went to settings and selected one of the sound files. As expected, a remote sound file resource was requested and retrieved.
I selected the same sound file again but this time no request was fired. Probably a cache... wait! Maybe something similar happens with our Slack Electron app? but instead of asking the media every time, there will be a cache which stores the last response. This will explain why all of our file modifications didn't work and why we don't see any .mp3
file loaded in lsof
.
Using lsof
I knew where Slack stores it's temporary data (databases, cache files, downloads, index, etc). There are two options -
~/Library/Application Support/Slack
~/Library/Containers/com.tinyspeck.slackmacgap/Data/Library/Application Support/Slack
I enter the support directory and saw multiple files and directories. One of them was Cache
.
Inside Cache
there's another directory called Cache_Data
and inside thousands of files with random looking names. probably some kind of hashes and an index file pointing at them.
I used grep
to search for part of the Hummus.mp3
content and found a match!
After a bit of playing with the files there I understood that _s
cache files are the ones I needed. I started to explore the binary structure of these cache files and finally wrote my own Slack-cache-file builder. Here are some key elements of a Slack cache file -
Eventually I wrote a quick-and-dirty Python script which receives a path to a .mp3
sound file and edits the Hummus
cache file with the customized file. Great Success.
It was a fun journey into understanding how Slack stores and uses media files. The default media files within the .asar archive are probably there just in case there will be a connectivity issue in the first time Slack is loaded. The real deal are the Slack cache files which are being used heavily by Slack across many different functions, including notification sounds :)