SAD: slack-anti-delete
TL;DR: I patched my Slack client to keep messages that others delete.
Let's say someone sent me a message, immediately regretted it and tried to delete it. They will think the message got deleted on both ends ("delete for everyone"), but using this patch my client will keep the message anyway and notify me that someone tried to delete it 😬. This is a follow-up research I did on how Slack is working internally.
As a bonus, you'll also get a nice notification telling you who tried to delete a message.
Demo
demo.mov
Instructions (Mac OSX, Windows, Linux)
run python3 slack_patch_delete.py
.
Backstory
The backstory is kind of funny - not so long ago my friend had a rant about his former boss. He told me a story of how his former boss accidently sent him a nasty message and then immediately deleted it. My friend wanted to confront him but had no proof because the message was gone too quickly..
Technical Details
After my previous research on how Slack manages local cache media files, I moved forward to research how the JS code files are stored. I opened Slack in debug mode and started to dig in. Turns out the JS files are also kept in special offline static cache files with proprietary binary format.
The first stop is SLACK_DIR/Code Cache/js
. (BTW on Mac OSX Slack dir can be ~/Library/Application Support/Slack
or ~/Library/Containers/com.tinyspeck.slackmacgap/Data/Library/Application Support/Slack
).
These cache files contain binary formatted data of the requests and responses that Slack client is sending and receiving to/from the server. Slack devs probably wanted to create a balance between the statically offline Electron ASAR archive versus the overhead of sending online requests all the time - so they created a simple yet powerful trade-off. They are sending "live" HTTP requests but with heavy use of static cache files storing both the requests and the responses. Therefore, if a new request is fired, the request will never leave the machine; the entire loop will be closed locally offline and only static JS files will be read from the disk.
But the journey to full JS execution is longer than I thought. The JS code cache files under the Code Cache/js
directory are binary serialized JS files and this is the first stop when receiving new JS code from the server.
Next, Slack unpacks the JS code and stores it in a different JS code cache directory under SLACK_DIR/Service Worker/CacheStorage
Here, the JS code is unpacked and looks much like the regular obfuscated Slack code we are used to see while debugging it.
Cool, so now we know where the actual code is found. But what do we need to patch in order to keep deleted messages? I used Chrome debugging tools to inspect all HTTP requests and WebSocket traffic. I quickly found out that most of the action takes place through WebSocket messages.
The ongoing WebSocket session is very chatty and there are a lot of different message subtypes
s but the most important one for us is message_delete
.
Cool. So all we need to do now is modify the JS flow so it will ignore this message type when received. We need to locate the main switch
that handles incoming message types and modify the message_delete
case.
Bingo. Now we can patch the JS cache files and force our client to ignore 'delete message' requests ;)