From 72731d2bb816f4800a91fb3adcb1ea99af5f401e Mon Sep 17 00:00:00 2001 From: =?utf8?q?Joann=20M=C3=B5ndresku?= Date: Wed, 15 May 2024 23:26:28 +0300 Subject: [PATCH] Truncate reverse engineering post, move some stuff for part two --- ...e-engineering-a-mobile-app-protobuf-api.md | 122 +--------------- ...everse-engineering-mobile-apps-part-two.md | 134 ++++++++++++++++++ 2 files changed, 140 insertions(+), 116 deletions(-) create mode 100644 content/posts/reverse-engineering-mobile-apps-part-two.md diff --git a/content/posts/reverse-engineering-a-mobile-app-protobuf-api.md b/content/posts/reverse-engineering-a-mobile-app-protobuf-api.md index 2fb1f57..2f412e4 100644 --- a/content/posts/reverse-engineering-a-mobile-app-protobuf-api.md +++ b/content/posts/reverse-engineering-a-mobile-app-protobuf-api.md @@ -97,61 +97,14 @@ certain global values. ## The smoke-test -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, -let's try a quick smoke-test. +So we have a potential API endpoint, let's put it to the test. We can do a quick smoke test by setting up a webserver. -**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. -As this information is still vastly useful for reverse engineering most apps, I will be leaving this section intact.** - -Ensure your phone is rooted and you have a variant of Xposed Framework installed (I used LSPosed). -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. -(NOTE: Users without root might want to skip to end of article where I showcase unpinning the app manually) - -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. +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. 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. -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. -``` -# Create an ext file containing the Subject Alternative Name (SAN) -# DNS.1 should correspond to the API endpoint of the app. -# 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. -cat > auxbrain.ext << EOF -authorityKeyIdentifier=keyid,issuer -basicConstraints=CA:FALSE -keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment -subjectAltName = @alt_names - -[alt_names] -DNS.1 = www.auxbrain.com -EOF - -# Create your own Certificate Authority -openssl genrsa -des3 -out myCA.key 2048 -openssl req -x509 -new -nodes -key myCA.key -sha256 -days 1825 -out myCA.pem -# Create a CSR and lets have the new CA sign it -openssl genrsa -out auxbrain.key 2048 -openssl req -new -key auxbrain.key -out auxbrain.csr -nodes -openssl x509 -req -in auxbrain.csr -CA myCA.pem -CAkey myCA.key -CAcreateserial -out auxbrain.crt -days 825 -sha256 -extfile auxbrain.ext -cat auxbrain.crt myCA.pem > auxbrain.pem -# You now have: -# myCA.pem - the public certificate of your root CA -# auxbrain.key - the private key for your webserver -# auxbrain.pem - the public cert for your webserver. -``` - -Use the generated `auxbrain.pem` and `auxbrain.key` files for your webserver SSL/TLS configuration. For nginx, append following values to your server directive: -``` -listen 443 ssl; -ssl_certificate /path/to/auxbrain.pem; -ssl_certificate_key /path/to/auxbrain.key; -ssl_session_cache shared:SSL:1m; -ssl_session_timeout 5m; -ssl_ciphers HIGH:!aNULL:!MD5; -ssl_prefer_server_ciphers on; -``` - -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. +(NOTE: AdAway doesn't detect any subdomains nor can it do wildcard, you will need to include the FQDN of the API endpoint `www.auxbrain.com`) +Once you're done setting up the redirection, run any webserver such as nginx for a quick and dirty test. ``` 192.168.1.212 - - [...] "POST /ei/first_contact HTTP/1.1" 404 0 "-" ``` @@ -611,71 +564,6 @@ Now, the above code could be a lot neater. For your homework, if you're not skip a contract database and try scheduling them like the game originally did - a "Leggacy" contract every Friday and regular contracts showing up every 1-2 weeks for roughly 2 weeks. -## Rootless SSL Unpinning + Endpoint URL patching -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. -Start off by pulling the following repository -``` -git clone https://github.com/ilya-kozyr/android-ssl-pinning-bypass.git -python3 -m venv .venv -source .venv/bin/activate -pip install -r requirements.txt -cp /path/to/your/apk . -python3 apk-rebuild.py egginc.apk --pause -``` - -**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! -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. - -Open a new terminal window, the script will wait for us to perform modifications, enter the created folder `egginc.apk-decompiled` and `lib`. - -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 -the 64-bit build first. - -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. -``` -$> hexdump -C libegginc.so | grep "ww.auxbrain.co" -A2 -B2 -00b02b40 cd cc 4c 3f 00 00 00 00 00 00 00 00 00 00 80 3f |..L?...........?| -00b02b50 00 00 00 00 00 00 00 00 00 00 00 00 14 ae 47 3f |..............G?| -00b02b60 77 77 77 2e 61 75 78 62 72 61 69 6e 2e 63 6f 6d |www.auxbrain.com| -00b02b70 00 48 54 54 50 20 52 45 51 3a 20 25 64 00 64 61 |.HTTP REQ: %d.da| -00b02b80 74 61 3d 00 65 69 2f 66 69 72 73 74 5f 63 6f 6e |ta=.ei/first_con -``` - -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`. - -(Note: You can choose a shorter name as well, if you null-terminate the extra bytes as padding) -``` -$> echo "G?www.auxbrain.com" | hexdump -ve '1/1 "%.2X"' -473F7777772E617578627261696E2E636F6D0A -$> echo "G?eggs.based.quest" | hexdump -ve '1/1 "%.2X"' -473F656767732E62617365642E71756573740A -``` - -Remove the trailing `0A` from end of both hex strings and now proceed as follows: -``` -# Place the source in first bracket of sed and the new URL at second bracket. -hexdump -ve '1/1 "%.2X"' libegginc.so | sed "s/473F7777772E617578627261696E2E636F6D/473F656767732E62617365642E7175657374/g" | xxd -r -p > patched.so -``` - -Huzzah! We now have a patched linked-library for the arm64 build. Let's also patch the 32-bit version. -``` -$> hexdump -C libegginc.so | grep "ww.auxbrain.co" -A2 -B2 -0087b770 69 67 68 5f 74 6f 6f 5f 6d 61 6e 79 5f 70 78 00 |igh_too_many_px.| -0087b780 74 61 62 6c 65 74 5f 68 64 70 69 00 00 00 00 00 |tablet_hdpi.....| -0087b790 77 77 77 2e 61 75 78 62 72 61 69 6e 2e 63 6f 6d |www.auxbrain.com| -0087b7a0 00 00 00 00 00 00 00 00 65 69 2f 66 69 72 73 74 |........ei/first| -0087b7b0 5f 63 6f 6e 74 61 63 74 00 00 00 00 00 00 00 00 |_contact........| -``` -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`. -``` -# Place the source in first bracket of sed and the new URL at second bracket. -hexdump -ve '1/1 "%.2X"' libegginc.so | sed "s/00007777772E617578627261696E2E636F6D/0000656767732E62617365642E7175657374/g" | xxd -r -p > patched.so -``` - -Replace both of the libegginc.so files with the patched.so files. Move back to main terminal window and press ENTER. - -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. - ## Conclusion so far We have created a (rather ugly looking) server emulator for the game. It functions, but it needs a lot of work still before we can call it ready. If you have followed this far, give yourself pat on the back - if you actually tried to run this code, give yourself an extra pat on the back. @@ -691,5 +579,7 @@ about the project you are currently doing - refactoring becomes an essential par I won't give any promises for a part 2 any time soon, but I will be trying to make this feature complete, so without further ado, here are the git repository links: [github.com](https://github.com/cernodile/reEgg), [git.based.quest](https://git.based.quest/?p=reEgg.git;a=tree;h=refs/heads/master;hb=refs/heads/master). +Next time we will dive into apps that use SSL/TLS and making onboarding for your friends easier. + Thank you for reading and making it all the way to the end, - Cernodile diff --git a/content/posts/reverse-engineering-mobile-apps-part-two.md b/content/posts/reverse-engineering-mobile-apps-part-two.md new file mode 100644 index 0000000..ecdf100 --- /dev/null +++ b/content/posts/reverse-engineering-mobile-apps-part-two.md @@ -0,0 +1,134 @@ +--- +title: "Reverse Engineering Mobile Apps Part Two" +date: 2024-05-15T23:21:00+03:00 +description: "" +tags: [] +type: blog +draft: true +--- + +## Note to the git snooper - I moved these here due to revalations made later, I will deep-dive these topics at a later date. + +## The smoke-test + +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, +let's try a quick smoke-test. + +**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. +As this information is still vastly useful for reverse engineering most apps, I will be leaving this section intact.** + +Ensure your phone is rooted and you have a variant of Xposed Framework installed (I used LSPosed). +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. +(NOTE: Users without root might want to skip to end of article where I showcase unpinning the app manually) + +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. +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. + +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. +``` +# Create an ext file containing the Subject Alternative Name (SAN) +# DNS.1 should correspond to the API endpoint of the app. +# 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. +cat > auxbrain.ext << EOF +authorityKeyIdentifier=keyid,issuer +basicConstraints=CA:FALSE +keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment +subjectAltName = @alt_names + +[alt_names] +DNS.1 = www.auxbrain.com +EOF + +# Create your own Certificate Authority +openssl genrsa -des3 -out myCA.key 2048 +openssl req -x509 -new -nodes -key myCA.key -sha256 -days 1825 -out myCA.pem +# Create a CSR and lets have the new CA sign it +openssl genrsa -out auxbrain.key 2048 +openssl req -new -key auxbrain.key -out auxbrain.csr -nodes +openssl x509 -req -in auxbrain.csr -CA myCA.pem -CAkey myCA.key -CAcreateserial -out auxbrain.crt -days 825 -sha256 -extfile auxbrain.ext +cat auxbrain.crt myCA.pem > auxbrain.pem +# You now have: +# myCA.pem - the public certificate of your root CA +# auxbrain.key - the private key for your webserver +# auxbrain.pem - the public cert for your webserver. +``` + +Use the generated `auxbrain.pem` and `auxbrain.key` files for your webserver SSL/TLS configuration. For nginx, append following values to your server directive: +``` +listen 443 ssl; +ssl_certificate /path/to/auxbrain.pem; +ssl_certificate_key /path/to/auxbrain.key; +ssl_session_cache shared:SSL:1m; +ssl_session_timeout 5m; +ssl_ciphers HIGH:!aNULL:!MD5; +ssl_prefer_server_ciphers on; +``` + +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. + + +## Rootless SSL Unpinning + Endpoint URL patching +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. +Start off by pulling the following repository +``` +git clone https://github.com/ilya-kozyr/android-ssl-pinning-bypass.git +python3 -m venv .venv +source .venv/bin/activate +pip install -r requirements.txt +cp /path/to/your/apk . +python3 apk-rebuild.py egginc.apk --pause +``` + +**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! +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. + +Open a new terminal window, the script will wait for us to perform modifications, enter the created folder `egginc.apk-decompiled` and `lib`. + +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 +the 64-bit build first. + +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. +``` +$> hexdump -C libegginc.so | grep "ww.auxbrain.co" -A2 -B2 +00b02b40 cd cc 4c 3f 00 00 00 00 00 00 00 00 00 00 80 3f |..L?...........?| +00b02b50 00 00 00 00 00 00 00 00 00 00 00 00 14 ae 47 3f |..............G?| +00b02b60 77 77 77 2e 61 75 78 62 72 61 69 6e 2e 63 6f 6d |www.auxbrain.com| +00b02b70 00 48 54 54 50 20 52 45 51 3a 20 25 64 00 64 61 |.HTTP REQ: %d.da| +00b02b80 74 61 3d 00 65 69 2f 66 69 72 73 74 5f 63 6f 6e |ta=.ei/first_con +``` + +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`. + +(Note: You can choose a shorter name as well, if you null-terminate the extra bytes as padding) +``` +$> echo "G?www.auxbrain.com" | hexdump -ve '1/1 "%.2X"' +473F7777772E617578627261696E2E636F6D0A +$> echo "G?eggs.based.quest" | hexdump -ve '1/1 "%.2X"' +473F656767732E62617365642E71756573740A +``` + +Remove the trailing `0A` from end of both hex strings and now proceed as follows: +``` +# Place the source in first bracket of sed and the new URL at second bracket. +hexdump -ve '1/1 "%.2X"' libegginc.so | sed "s/473F7777772E617578627261696E2E636F6D/473F656767732E62617365642E7175657374/g" | xxd -r -p > patched.so +``` + +Huzzah! We now have a patched linked-library for the arm64 build. Let's also patch the 32-bit version. +``` +$> hexdump -C libegginc.so | grep "ww.auxbrain.co" -A2 -B2 +0087b770 69 67 68 5f 74 6f 6f 5f 6d 61 6e 79 5f 70 78 00 |igh_too_many_px.| +0087b780 74 61 62 6c 65 74 5f 68 64 70 69 00 00 00 00 00 |tablet_hdpi.....| +0087b790 77 77 77 2e 61 75 78 62 72 61 69 6e 2e 63 6f 6d |www.auxbrain.com| +0087b7a0 00 00 00 00 00 00 00 00 65 69 2f 66 69 72 73 74 |........ei/first| +0087b7b0 5f 63 6f 6e 74 61 63 74 00 00 00 00 00 00 00 00 |_contact........| +``` +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`. +``` +# Place the source in first bracket of sed and the new URL at second bracket. +hexdump -ve '1/1 "%.2X"' libegginc.so | sed "s/00007777772E617578627261696E2E636F6D/0000656767732E62617365642E7175657374/g" | xxd -r -p > patched.so +``` + +Replace both of the libegginc.so files with the patched.so files. Move back to main terminal window and press ENTER. + +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. + -- 2.25.1