notes about the whatsapp web app

what other people did

as usual before bothering to do any reversing myself, i googled furiously. this is the good stuff:

there's also an annoying amount of people not doing any research at all and throwing horribly wrong guesses around. i should get used to this kind of stuff by now...

debugging the websocket protocol

the websocket protocol used by whatsapp web has both text frames (with json) and binary frames (with encrypted traffic).

ways to view its contents:

  • chrome's debugger is currently the easiest way to view the frames of a websocket connection, but it skips the binary frames
  • mitmproxy has no websocket support yet (just passthrough)
  • wireshark is supposed to have a websocket dissector, but it doesn't dissect anything inside decrypted SSL streams, apparently. (used SSLKEYLOGFILE)
  • fiddler has experimental support for it, just needed to force firefox to use its proxy for all the protocols, and used the extension mentioned here

fiddler turned out to be "decent", but the binary packets are obviously encrypted nonsense.

seems like only chat messages are sent that way (with e2e crypto), the rest of the "metadata" is known to the server

js general layout

the main javascript file (app_...js) is like 800kb, and 1.5 after beautifying

there's another file called crypto.js which is another 1.4mb or so, and... seems to return different files each time i request it. (TODO: check this again once there's no blood in my alcohol).

they seem to have switched to webpack recently, which has the habit of referring to other modules as n(123).

crypto.js has crypto-js, google's end-to-end library, a qr code library and something else. my beautifier doesn't like that it's got whole files in strings, so it's kind of a pain in the ass to look at. pretty sure it's mostly third party libs though.

"bluebird" and "xregexp" are bundled in app.js, i took them out and got app1.js with 6k lines and app2.js with 20k lines. the latter still has some third party libraries, but nothing worth moving out and clearly unrelated to the main codebase. well i could take out that exif parser...

there's no obfuscation at least in most parts (seems to be just the side effects of minifying and webpacking)

skimming for crypto

907:                var e = e2e.ecc.PrimeCurve.CURVE_25519,
908:                    t = e2e.ecc.Protocol.generateKeyPair(e),
843:                    u = e2e.ecc.PrimeCurve.CURVE_25519,
844:                    l = new e2e.ecc.Ecdh(u, Wa.secretBundle.keyPair),
846:                    p = new e2e.Hkdf(new e2e.hash.Sha256),

dem djb curves

setSharedSecret() (not going to copypaste it here) does plenty of fun stuff too (magic words: AES / CBC / PKCS7, HMAC SHA256, CURVE_25519, etc)

app logic

the class where setSharedSecret() is defined also seems to take care of most of the websocket related logic. it's preceded by a list of constants of message types and followed by a handle() function.

there's also the window.Wa global, which has Wa.debug (search for its definition with debug:), these logs are uploaded to on certain conditions, such as...

e.src.indexOf("best-deals-products") > -1 && Wa.uploadLogs("superfish-found")


for some reason there's this "mutex" thing which apparently uses the browser's localstorage to allow in-browser session takeovers (!) but mostly to only have one client connected simultaneously. thiiiis kiiiinda interferes with my goal of having yet another client (like bitlbee + web browser both connected to phone).

figuring out the rest of the protocol is left as an exercise to the reader

the "phone" side of this webapp

relevant yowsup bug:

closing notes

i love how whatsapp takes end to end crypto so seriously. i love how they managed to do a webapp that workarounds the limitations so transparently, at least for those of us who don't use iOS.

they are definitely doing things the hard way, though.

meanwhile, the telegram people are proud of their butt-based crypto disaster, just because it didn't require something as weird as what whatsapp did.