Dumps TLS keys from jailbroken iOS 10.x device - requires Frida, doesn't support session resumption
#!/usr/bin/python | |
#/usr/local/bin/python | |
import frida | |
import sys | |
def on_message(message, data): | |
try: | |
if message: | |
f = open("tlskeys.log", 'a') | |
print("{0}".format(message["payload" ])) | |
f.write(message["payload"] + "\n" ) | |
except Exception as e: | |
print(message) | |
print(e) | |
# tls_handshake_internal_prf signature from | |
# https://opensource.apple.com/source/coreTLS/coreTLS-83.20.8/lib/tls1Callouts.c.auto.html | |
# | |
# 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 | |
hook = """ | |
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 tls_handshake_internal_prf = Module.findExportByName("libsystem_coretls.dylib", "tls_handshake_internal_prf"); | |
Interceptor.attach(tls_handshake_internal_prf, {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]); | |
} | |
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]); | |
} | |
} | |
if(clientRandom !== "") { | |
send("CLIENT_RANDOM "+ clientRandom + " " + secret); | |
} | |
} | |
} | |
}); | |
""" | |
if __name__ == '__main__': | |
try: | |
print("[*] Attaching ..." ) | |
print("[*] Hooking... \n " ) | |
if sys.argv[1] == "-n": | |
session = frida.get_usb_device().spawn(["re.frida.Gadget" ]) | |
else: | |
session = frida.get_usb_device().spawn([sys.argv[1]]) | |
session1 = frida.get_usb_device().attach(session) | |
frida.get_usb_device().resume(session) | |
script = session1.create_script(hook) | |
script.on('message' , on_message) | |
script.load() | |
sys.stdin.read() | |
except KeyboardInterrupt: | |
sys.exit(0) | |
except IndexError: | |
print(""" | |
Error: No process specified. Usage: dumper.py [BundleIdentifier] | |
E.g. dumper.py com.apple.mobilesafari | |
If device is jailbroken please use -n option | |
""") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment