Skip to content

Instantly share code, notes, and snippets.

@ceres-c
Last active August 18, 2025 11:07
Show Gist options
  • Save ceres-c/cb3b69e53713d5ad9cf6aac9b8e895d2 to your computer and use it in GitHub Desktop.
Save ceres-c/cb3b69e53713d5ad9cf6aac9b8e895d2 to your computer and use it in GitHub Desktop.

Revisions

  1. ceres-c revised this gist Nov 10, 2021. No changes.
  2. ceres-c revised this gist Jun 20, 2019. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion frida-extract-keystore.py
    Original file line number Diff line number Diff line change
    @@ -38,7 +38,7 @@ def on_message(message, data):
    jscode = """
    setTimeout(function() {
    Java.perform(function () {
    keyStoreLoadStream = Java.use('java.security.KeyStore')['load'].overload('java.io.InputStream', '[C');
    var keyStoreLoadStream = Java.use('java.security.KeyStore')['load'].overload('java.io.InputStream', '[C');
    /* following function hooks to a Keystore.load(InputStream stream, char[] password) */
    keyStoreLoadStream.implementation = function(stream, charArray) {
  3. ceres-c revised this gist Dec 28, 2018. No changes.
  4. ceres-c revised this gist Dec 28, 2018. No changes.
  5. ceres-c revised this gist Dec 16, 2018. 1 changed file with 37 additions and 12 deletions.
    49 changes: 37 additions & 12 deletions frida-extract-keystore.py
    Original file line number Diff line number Diff line change
    @@ -10,24 +10,38 @@

    app_name = 'com.app.mobile'
    i = 0
    ext = ''

    def on_message(message, data):
    global i
    global i, ext
    if (message['type'] == 'send' and 'event' in message['payload']):
    print("[+] Dumping keystore" + str(i) + "...")
    print(" [+] Password: " + ''.join(message['payload']['password']))
    print(" [+] Writing to file...")
    f = open('keystore' + str(i) + '.jks', 'wb')
    f.write(bytes.fromhex(message['payload']['cert']))
    f.close()
    i += 1
    if (message['payload']['event'] == '+found'):
    i += 1
    print("\n[+] Hooked keystore" + str(i) + "...")

    elif (message['payload']['event'] == '+type'):
    print(" [+] Cert Type: " + ''.join(message['payload']['certType']))
    if (message['payload']['certType'] == 'PKCS12'):
    ext = '.jks'

    elif (message['payload']['event'] == '+pass'):
    print(" [+] Password: " + ''.join(message['payload']['password']))

    elif (message['payload']['event'] == '+write'):
    print(" [+] Writing to file: keystore" + str(i) + ext)
    f = open('keystore' + str(i) + ext, 'wb')
    f.write(bytes.fromhex(message['payload']['cert']))
    f.close()
    else:
    print(message)

    jscode = """
    setTimeout(function() {
    Java.perform(function () {
    Java.use('java.security.KeyStore')['load'].overload('java.io.InputStream', '[C').implementation = function(stream, charArray) {
    keyStoreLoadStream = Java.use('java.security.KeyStore')['load'].overload('java.io.InputStream', '[C');
    /* following function hooks to a Keystore.load(InputStream stream, char[] password) */
    keyStoreLoadStream.implementation = function(stream, charArray) {
    /* sometimes this happen, I have no idea why, tho... */
    if (stream == null) {
    @@ -36,19 +50,30 @@ def on_message(message, data):
    return;
    }
    /* just to notice the client we've hooked a KeyStore.load */
    send({event: '+found'});
    /* read the buffer stream to a variable */
    var hexString = readStreamToHex (stream);
    /* send everything over to client shell */
    send({event: '+write', password: charArray, cert: hexString});
    /* send KeyStore type to client shell */
    send({event: '+type', certType: this.getType()});
    /* send KeyStore password to client shell */
    send({event: '+pass', password: charArray});
    /* send the string representation to client shell */
    send({event: '+write', cert: hexString});
    /* call the original implementation of 'load' */
    this.load(stream, charArray);
    /* no need to return anything */
    }});
    }
    });
    },0);
    /* following function reads an InputStream and returns an ASCII char representation of it */
    function readStreamToHex (stream) {
    var data = [];
    var byteRead = stream.read();
  6. ceres-c created this gist Dec 5, 2018.
    98 changes: 98 additions & 0 deletions frida-extract-keystore.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,98 @@
    #!/usr/bin/python3

    '''
    author: ceres-c
    usage: ./frida-extract-keystore.py
    Once the keystore(s) have been exported you have to convert them to PKCS12 using keytool
    '''

    import frida, sys, time

    app_name = 'com.app.mobile'
    i = 0

    def on_message(message, data):
    global i
    if (message['type'] == 'send' and 'event' in message['payload']):
    print("[+] Dumping keystore" + str(i) + "...")
    print(" [+] Password: " + ''.join(message['payload']['password']))
    print(" [+] Writing to file...")
    f = open('keystore' + str(i) + '.jks', 'wb')
    f.write(bytes.fromhex(message['payload']['cert']))
    f.close()
    i += 1
    else:
    print(message)

    jscode = """
    setTimeout(function() {
    Java.perform(function () {
    Java.use('java.security.KeyStore')['load'].overload('java.io.InputStream', '[C').implementation = function(stream, charArray) {
    /* sometimes this happen, I have no idea why, tho... */
    if (stream == null) {
    /* just to avoid interfering with app's flow */
    this.load(stream, charArray);
    return;
    }
    /* read the buffer stream to a variable */
    var hexString = readStreamToHex (stream);
    /* send everything over to client shell */
    send({event: '+write', password: charArray, cert: hexString});
    /* call the original implementation of 'load' */
    this.load(stream, charArray);
    /* no need to return anything */
    }});
    },0);
    function readStreamToHex (stream) {
    var data = [];
    var byteRead = stream.read();
    while (byteRead != -1)
    {
    data.push( ('0' + (byteRead & 0xFF).toString(16)).slice(-2) );
    /* <---------------- binary to hex ---------------> */
    byteRead = stream.read();
    }
    stream.close();
    return data.join('');
    }
    """

    print("[.] Attaching to device...")
    try:
    device = frida.get_usb_device()
    except:
    print("[-] Can't attach. Is the device connected?")
    sys.exit()

    print("[.] Spawning the app...")
    try:
    pid = device.spawn(app_name)
    device.resume(pid)
    time.sleep(1)
    except:
    print("[-] Can't spawn the App. Is filename correct?")
    sys.exit()

    print("[.] Attaching to process...")
    try:
    process = device.attach(pid)
    except:
    print("[-] Can't connect to App.")
    sys.exit()

    print("[.] Launching js code...")
    print(" (run the app until needed, close it and then kill this script)")
    script = process.create_script(jscode)
    script.on('message', on_message)
    script.load()
    try:
    sys.stdin.read()
    except KeyboardInterrupt:
    print ("\nExiting now")
    exit(0)