Upgrade to Pro — share decks privately, control downloads, hide ads and more …

LDNWebPerf December 2017 - Andy Davies

LDNWebPerf December 2017 - Andy Davies

Inspecting iOS App Traffic with JavaScript

A session presented by Andy Davies
Tuesday, 5th December 2017

Skill level: Intermediate / Advanced

What do you do when you've been asked to look at an app that's slow but you can't get the source code?

Andy will show you what he did when he was faced with this situation and yes he really did use JavaScript!

London Web Performance Group

December 05, 2017
Tweet

More Decks by London Web Performance Group

Other Decks in Technology

Transcript

  1. https://opensource.apple.com/source/coreTLS/coreTLS-83.20.8/lib/tls1Callouts.c.auto.html /* * The TLS pseudorandom function, defined in RFC2246,

    section 5. * This takes as its input a secret block, a label, and a seed, and produces * a caller-specified length of pseudorandom data. * * Optimization TBD: make label optional, avoid malloc and two copies if it's * not there, so callers can take advantage of fixed-size seeds. */ // Note: This is exported as SPI. int tls_handshake_internal_prf( tls_handshake_t ctx, const void *vsecret, size_t secretLen, const void *label, // optional, NULL implies that seed contains // the label size_t labelLen, const void *seed, size_t seedLen, void *vout, // mallocd by caller, length >= outLen size_t outLen) { int serr = errSSLInternal; … Master Secret Client & Server Randoms
  2. var hexChar = ["0", "1", "2", "3", "4", "5", "6",

    "7","8", "9", "A", "B", "C", "D", "E", "F"]; function byteToHex(byte) { return hexChar[(byte >> 4) & 0x0f] + hexChar[byte & 0x0f]; } var f = Module.findExportByName("libsystem_coretls.dylib", "tls_handshake_internal_prf"); Interceptor.attach(f, {onEnter: function (args) { var secretLength = parseInt(args[2], 16); var seedLength = parseInt(args[6], 16); if(secretLength == 48 && (seedLength == 64 || seedLength == 77)) { var secretAddr = new NativePointer(args[1]) var secretBytes = new Uint8Array(Memory.readByteArray(secretAddr, secretLength)); var secret = ""; for(var i = 0; i < secretLength; i++) { secret += byteToHex(secretBytes[i]); } Find function Hook function Extract master secret
  3. var seedLength = parseInt(args[6], 16); var seedAddr = new NativePointer(args[5]);

    var seedBytes = new Uint8Array(Memory.readByteArray(seedAddr, seedLength)); var clientRandom = ""; var serverRandom = ""; if(seedLength == 64) { for(i = 0; i < 32; i++) { clientRandom += byteToHex(seedBytes[i]); } for( ; i < 64; i++) { serverRandom += byteToHex(seedBytes[i]); } } else if(seedLength == 77) { // key expansion var offset = 13; for(i = offset; i < 32 + offset; i++) { serverRandom += byteToHex(seedBytes[i]); } for( ; i < 64 + offset; i++) { clientRandom += byteToHex(seedBytes[i]); } } Extract client and server randoms
  4. So what did I learn? ★ Just like on the

    web… sometimes we forget to Compress JSON responses Reuse connections Optimise images And a whole bunch of other things