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:
- rough summary of the flow http://www.reddit.com/r/AskNetsec/comments/2t9gn6/how_is_whatsapp_doing_endtoend_encryption_with/cnx59bl (not sure how accurate, sounds about right)
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
- 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
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
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
app.js: 907: var e = e2e.ecc.PrimeCurve.CURVE_25519, 908: t = e2e.ecc.Protocol.generateKeyPair(e), app2.js: 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:
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
there's also the
window.Wa global, which has
Wa.debug (search for its definition with
debug:), these logs are uploaded to https://web-crashlog.whatsapp.net/upload.php 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: https://github.com/tgalal/yowsup/issues/585
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.