In order to intercept our Android device’s SSL traffic using charles, we need to install the charles certificate to our device. The normal instructions you’ll find on the web for doing this install the certificate as a user certificate, which requires a lockscreen password or pattern to be set. If you’re like me and don’t like having to enter a password or pattern every time you open your phone, then you can follow the below instructions to install the charles certificate as a system certificate, instead of a user certificate. This requires a rooted phone.

The overview of what we need to do is to put the charles certificate file into the Android device’s /system/etc/security/cacerts folder, with the correct filename, file format, file permissions, and file owner. The filename needs to be the hash of certificate, the extension needs to be .0, the file permissions need to be 644, the file owner and group need to be root, and we will massage the certificate .pem file into the correct format with some openssl commands.

First, download the charles certificate .pem file by opening the Charles app and navigating to http://charlesproxy.com/getssl in the web browser. This will open a save dialog for the certificate file.

Next, check what version of ssl you have

openssl x509 -inform PEM -subject_hash_old -in charles-proxy-ssl-proxying-certificate.pem | head -1

if this complains that there is no flag subject_hash_old, then that means you are using a version of ssl < 1.0. You can verify this with openssl version. In that case, you can just use the subject_hash flag:

openssl x509 -inform PEM -subject_hash -in charles-proxy-ssl-proxying-certificate.pem | head -1

openssl 1.0 changed the subject hash algorithm, which is why we need the subject_hash_old, to tell it to use the old hash algorithm, since this is what Android needs the filename to be.

Next, convert the charles certificate into the correct format, where SUBJECT_HASH is the hash returned from the previous command

openssl x509 -inform PEM -text -fingerprint -in charles-proxy-ssl-proxying-certificate.pem >> SUBJECT_HASH.0

This gets us close, but not quite what Android needs. We need to move the cert block (—–BEGIN CERTIFICATE—– to —–END CERTIFICATE—–) to the top, instead of the bottom

The file should look something like this:

f6401b1.0

-----BEGIN CERTIFICATE-----
MIIFkjCCBHqgAwIBAgIGAVPMUdZRMA0GCSqGSIb3DQEBCwUAMIHNMV8wXQYDVQQD
DFZDaGFybGVzIFByb3h5IEN1c3RvbSBSb290IENlcnRpZmljYXRlIChidWlsdCBv
...
...
oF+TeVLx5BQ3qaO8vBjgpqv6CzaXmSadk5ZXx8CuAFa4kpM5NAD8ypWVokMW+2Ex
wv53IUPCQxYIEY694tWnXaUkhYyfKCTJ75J0eEOxlNmY1qWsPls=
-----END CERTIFICATE-----
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 1459431828389 (0x153cc51d651)
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: CN=Charles Proxy Custom Root Certificate (built on Eliass-MacBook-Pro.local, 31 Mar 2016), OU=http://charlesproxy.com/ssl, O=XK72 Ltd, L=Auckland, ST=Auckland, C=NZ
        Validity
            Not Before: Jan  1 00:00:00 2000 GMT
            Not After : May 28 10:57:08 2045 GMT
        Subject: CN=Charles Proxy Custom Root Certificate (built on Eliass-MacBook-Pro.local, 31 Mar 2016), OU=http://charlesproxy.com/ssl, O=XK72 Ltd, L=Auckland, ST=Auckland, C=NZ
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:96:95:b7:0a:8f:e8:45:a7:fc:b3:c7:85:85:7e:
                    ...
                    ...
                    da:9c:b9:23:6d:cc:88:71:dc:e9:86:a5:6c:cc:7a:
                    90:75
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Basic Constraints: critical
                CA:TRUE
            Netscape Comment:
                ....This Root certificate was generated by Charles Proxy for SSL Proxying. If this certificate is part of a certificate chain, this means that you're browsing through Charles Proxy with SSL Proxying enabled for this website. Please see http://charlesproxy.com/ssl for more information.
            X509v3 Key Usage: critical
                Certificate Sign
            X509v3 Subject Key Identifier:
                7C:77:8B:28:F3:D7:90:6A:02:75:F0:51:EF:74:60:26:64:92:CB:8E
    Signature Algorithm: sha256WithRSAEncryption
         20:80:0a:be:82:87:6e:8e:33:88:0d:ef:22:ad:bb:df:c2:8b:
         ...
         ...
         a5:ac:3e:5b
SHA1 Fingerprint=8F:FF:22:AE:60:60:D3:71:49:20:9B:66:CB:68:D0:12:02:6B:F9:69

Next, adb push the file to the sdcard

adb push SUBJECT_HASH.0 sdcard/

Enter the device’s shell, and become the superuser

adb shell

su

Your terminal should have changed from $ to #. If it didn’t, then this means your device is not rooted, and the next command will fail

Make the system partition writable (this will become readonly again on the next reboot)

mount -o remount, rw /system

navigate to /system/etc/security/cacerts

cd /system/etc/security/cacerts

move our file into this directory

mv /sdcard/SUBJECT_HASH.0 .

change the permission of the file to 644

chmod 644 SUBJECT_HASH.0

change the owner to root

chown root:root SUBJECT_HASH.0

Done! Reboot your device and you’re good to go.

reboot

You can now go to the credential storage screen (settings -> security -> credential storage) and verify that this certificate is listed in the system certificate section

If you already had the charles certificate installed as a user certificate, you can remove it now. You can now disable your lockscreen security.

If you’re lazy and you trust me, download the .pem certificate file, plug in your rooted android device, and run the following commands, which automate some of the above steps

1) put script.sh, device_script.sh and charles-proxy-ssl-proxying-certificate.pem in the same directory

2) make scripts executable

3) ./script.sh

3) adb shell

4) su

5) mount -o remount,rw /system

6) sh /sdcard/device_script.sh

7) reboot

script.sh

#!/bin/sh
#####################

in="charles-proxy-ssl-proxying-certificate.pem"
hash=$(openssl x509 -inform PEM -subject_hash_old -in $in | head -1)
out=$hash.0

cat $in > $out
openssl x509 -inform PEM -text -fingerprint -in $in | sed '/-----BEGIN/,$ d' >> $out

# push the file and script to the android device
adb push device_script.sh /sdcard/
adb push $out /sdcard/

rm $out

device_script.sh

#!/bin/sh
# This script is executed on the device
###################################

# copy file into cacerts
echo "copying cert"
cd /system/etc/security/cacerts
file=$(ls /sdcard/*.0)
cp $file .

#get just the filename
regex="[^/]*$"
filename=$(echo $file | grep -o $regex)

# change permissions and owner
echo "Changing permissions of $filename"
chmod 644 $filename
chown root:root $filename

echo "Done"