19. Inject JavaScript into an App!
App
JavaScript VM
Script
Host
Injects script
Receives Messages
20. Three methods for adding Frida
Use a Jailbroken iPhone Install
Frida from Cydia
(available for all apps on device)
Resign someone else’s app, and
inject the FridaGadget
(app may need decrypting first)
Add the FridaGadget to your own
App
25. 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
26. 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
27. 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
28. if(clientRandom !== "") {
send("CLIENT_RANDOM "+ clientRandom + " " + secret);
}
}
}
});
Send it to the host
30. 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
31. Areas that need more work
★ TLS Session Resumption
★ Safari
★ iOS 11
★ Transforming the packet captures into something that’s
easy for any developer to understand