]>
| Commit | Line | Data |
|---|---|---|
| 72731d2b JM |
1 | --- |
| 2 | title: "Reverse Engineering Mobile Apps Part Two" | |
| 3 | date: 2024-05-15T23:21:00+03:00 | |
| 4 | description: "" | |
| 5 | tags: [] | |
| 6 | type: blog | |
| 7 | draft: true | |
| 8 | --- | |
| 9 | ||
| 10 | ## Note to the git snooper - I moved these here due to revalations made later, I will deep-dive these topics at a later date. | |
| 11 | ||
| 12 | ## The smoke-test | |
| 13 | ||
| 14 | So we have a potential API endpoint, let's put it to the test. We're not going to recompile anything yet or do any byte-patching, | |
| 15 | let's try a quick smoke-test. | |
| 16 | ||
| 17 | **UPDATE 15/05/2024: It turns out this old app version uses HTTP only, instead of HTTPS. You will only need to perform the AdAway instruction here. | |
| 18 | As this information is still vastly useful for reverse engineering most apps, I will be leaving this section intact.** | |
| 19 | ||
| 20 | Ensure your phone is rooted and you have a variant of Xposed Framework installed (I used LSPosed). | |
| 21 | We will need to unarm the SSL pinning present in most apps, including this one, I used [io.github.tehcneko.sslunpinning](https://github.com/Xposed-Modules-Repo/io.github.tehcneko.sslunpinning) module. | |
| 22 | (NOTE: Users without root might want to skip to end of article where I showcase unpinning the app manually) | |
| 23 | ||
| 24 | Next, install [AdAway app from F-Droid](https://f-droid.org/packages/org.adaway/) so we can setup a redirection on any network we are on. | |
| 25 | Inside AdAway, add a redirection rule for the address we just found and point it to an IP address in your LAN that will run the API server. | |
| 26 | ||
| 27 | Generate a self-signed certificate authority and a certificate signed by it and run a webserver with both HTTP and HTTPS on the API server machine. | |
| 28 | ``` | |
| 29 | # Create an ext file containing the Subject Alternative Name (SAN) | |
| 30 | # DNS.1 should correspond to the API endpoint of the app. | |
| 31 | # NOTE! If you are changing the API endpoint to a public domain, you can just use a public cert, no need for any of this. | |
| 32 | cat > auxbrain.ext << EOF | |
| 33 | authorityKeyIdentifier=keyid,issuer | |
| 34 | basicConstraints=CA:FALSE | |
| 35 | keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment | |
| 36 | subjectAltName = @alt_names | |
| 37 | ||
| 38 | [alt_names] | |
| 39 | DNS.1 = www.auxbrain.com | |
| 40 | EOF | |
| 41 | ||
| 42 | # Create your own Certificate Authority | |
| 43 | openssl genrsa -des3 -out myCA.key 2048 | |
| 44 | openssl req -x509 -new -nodes -key myCA.key -sha256 -days 1825 -out myCA.pem | |
| 45 | # Create a CSR and lets have the new CA sign it | |
| 46 | openssl genrsa -out auxbrain.key 2048 | |
| 47 | openssl req -new -key auxbrain.key -out auxbrain.csr -nodes | |
| 48 | openssl x509 -req -in auxbrain.csr -CA myCA.pem -CAkey myCA.key -CAcreateserial -out auxbrain.crt -days 825 -sha256 -extfile auxbrain.ext | |
| 49 | cat auxbrain.crt myCA.pem > auxbrain.pem | |
| 50 | # You now have: | |
| 51 | # myCA.pem - the public certificate of your root CA | |
| 52 | # auxbrain.key - the private key for your webserver | |
| 53 | # auxbrain.pem - the public cert for your webserver. | |
| 54 | ``` | |
| 55 | ||
| 56 | Use the generated `auxbrain.pem` and `auxbrain.key` files for your webserver SSL/TLS configuration. For nginx, append following values to your server directive: | |
| 57 | ``` | |
| 58 | listen 443 ssl; | |
| 59 | ssl_certificate /path/to/auxbrain.pem; | |
| 60 | ssl_certificate_key /path/to/auxbrain.key; | |
| 61 | ssl_session_cache shared:SSL:1m; | |
| 62 | ssl_session_timeout 5m; | |
| 63 | ssl_ciphers HIGH:!aNULL:!MD5; | |
| 64 | ssl_prefer_server_ciphers on; | |
| 65 | ``` | |
| 66 | ||
| 67 | Import the self-signed CA (myCA.pem) to your phone's truststore (Check under your phone's Security/Encryption settings). Once all of that is done, run the app for first time. | |
| 68 | ||
| 69 | ||
| 70 | ## Rootless SSL Unpinning + Endpoint URL patching | |
| 71 | Let's make the app not require a VPN or root privileges - let's make user CAs work and the endpoint URL something we control on the public net. | |
| 72 | Start off by pulling the following repository | |
| 73 | ``` | |
| 74 | git clone https://github.com/ilya-kozyr/android-ssl-pinning-bypass.git | |
| 75 | python3 -m venv .venv | |
| 76 | source .venv/bin/activate | |
| 77 | pip install -r requirements.txt | |
| 78 | cp /path/to/your/apk . | |
| 79 | python3 apk-rebuild.py egginc.apk --pause | |
| 80 | ``` | |
| 81 | ||
| 82 | **NOTE!** IF you do not intend to patch the API endpoint and just want to proceed with AdAway redirecting traffic, you can stop here and press ENTER! | |
| 83 | Proceed only if you own a domain in your control (that is equal or less in length to www.auxbrain.com) and want to use the app without a VPN/redirection. | |
| 84 | ||
| 85 | Open a new terminal window, the script will wait for us to perform modifications, enter the created folder `egginc.apk-decompiled` and `lib`. | |
| 86 | ||
| 87 | We have two folders here now, `arm64-v8a` and `armeabi-v7a`, just as we saw when we pulled the .so file out of the apk earlier. Let's tackle | |
| 88 | the 64-bit build first. | |
| 89 | ||
| 90 | For arm64 build it was really simple to perform bytepatch on the said endpoint. We already know it's supposed to look as `G?www.auxbrain.com` - let's probe the .so library a bit. | |
| 91 | ``` | |
| 92 | $> hexdump -C libegginc.so | grep "ww.auxbrain.co" -A2 -B2 | |
| 93 | 00b02b40 cd cc 4c 3f 00 00 00 00 00 00 00 00 00 00 80 3f |..L?...........?| | |
| 94 | 00b02b50 00 00 00 00 00 00 00 00 00 00 00 00 14 ae 47 3f |..............G?| | |
| 95 | 00b02b60 77 77 77 2e 61 75 78 62 72 61 69 6e 2e 63 6f 6d |www.auxbrain.com| | |
| 96 | 00b02b70 00 48 54 54 50 20 52 45 51 3a 20 25 64 00 64 61 |.HTTP REQ: %d.da| | |
| 97 | 00b02b80 74 61 3d 00 65 69 2f 66 69 72 73 74 5f 63 6f 6e |ta=.ei/first_con | |
| 98 | ``` | |
| 99 | ||
| 100 | We seem to have nothing blocking our way, let's create hex representations of `G?www.auxbrain.com` and a target domain of equal length, for example `G?eggs.based.quest`. | |
| 101 | ||
| 102 | (Note: You can choose a shorter name as well, if you null-terminate the extra bytes as padding) | |
| 103 | ``` | |
| 104 | $> echo "G?www.auxbrain.com" | hexdump -ve '1/1 "%.2X"' | |
| 105 | 473F7777772E617578627261696E2E636F6D0A | |
| 106 | $> echo "G?eggs.based.quest" | hexdump -ve '1/1 "%.2X"' | |
| 107 | 473F656767732E62617365642E71756573740A | |
| 108 | ``` | |
| 109 | ||
| 110 | Remove the trailing `0A` from end of both hex strings and now proceed as follows: | |
| 111 | ``` | |
| 112 | # Place the source in first bracket of sed and the new URL at second bracket. | |
| 113 | hexdump -ve '1/1 "%.2X"' libegginc.so | sed "s/473F7777772E617578627261696E2E636F6D/473F656767732E62617365642E7175657374/g" | xxd -r -p > patched.so | |
| 114 | ``` | |
| 115 | ||
| 116 | Huzzah! We now have a patched linked-library for the arm64 build. Let's also patch the 32-bit version. | |
| 117 | ``` | |
| 118 | $> hexdump -C libegginc.so | grep "ww.auxbrain.co" -A2 -B2 | |
| 119 | 0087b770 69 67 68 5f 74 6f 6f 5f 6d 61 6e 79 5f 70 78 00 |igh_too_many_px.| | |
| 120 | 0087b780 74 61 62 6c 65 74 5f 68 64 70 69 00 00 00 00 00 |tablet_hdpi.....| | |
| 121 | 0087b790 77 77 77 2e 61 75 78 62 72 61 69 6e 2e 63 6f 6d |www.auxbrain.com| | |
| 122 | 0087b7a0 00 00 00 00 00 00 00 00 65 69 2f 66 69 72 73 74 |........ei/first| | |
| 123 | 0087b7b0 5f 63 6f 6e 74 61 63 74 00 00 00 00 00 00 00 00 |_contact........| | |
| 124 | ``` | |
| 125 | This one lacks the `G?` prefix on API endpoint, but we still have null terminators we can rely on. Let's replace the `473F` from our previous strings with `0000`. | |
| 126 | ``` | |
| 127 | # Place the source in first bracket of sed and the new URL at second bracket. | |
| 128 | hexdump -ve '1/1 "%.2X"' libegginc.so | sed "s/00007777772E617578627261696E2E636F6D/0000656767732E62617365642E7175657374/g" | xxd -r -p > patched.so | |
| 129 | ``` | |
| 130 | ||
| 131 | Replace both of the libegginc.so files with the patched.so files. Move back to main terminal window and press ENTER. | |
| 132 | ||
| 133 | We now have a patched and debug signed apk for the game that isn't SSL pinned and contains a custom API endpoint we control without a VPN. | |
| 134 |