# **Middle Road 中間道**
當兩邊都不行的時候,你應該試試中庸之道。從字面上看。
Attachment: [middle-road_e5e04f86fca99ad4d6bd959137562820.zip](https://file.hkcert22.pwnable.hk/middle-road_e5e04f86fca99ad4d6bd959137562820.zip)
## Analyze
---------------------------------------
Unzip apk.
Get classes.dex.
Use dex2jar to convert classes.dex to classes.jar.
Use jd-gui to de-compile classes.jar.

We found that some string are encrypted, so we need to call the **DecryptString.decryptString()** to decrypt.
So we finally got the code.

We start to analysis the code and the work flow.
First, get the RSA key parameters from the **/getKey** api.

It seems to encrypt the AES key with the RSA and send to api **/getFlag**.

It seems to create the RSA public key based on information got from the **/getKey** api.
---------------------------------------
Let's try the app.<br>


First connect to the mitm proxy and install the decrypt CA on android phone.

Press the Get Flag key button.<br>
Then we can see the https traffic from the app.<br>
First, get the RSA key parameters from the **/getKey** api.
```
POST https://middle-road.hkcert22.pwnable.hk:4433/getKey HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 13
Host: middle-road.hkcert22.pwnable.hk:4433
Connection: Keep-Alive
Accept-Encoding: gzip
User-Agent: okhttp/4.10.0
code=32933185
```
```
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 1262
{"rsa_e":"65537","rsa_n":"630791816259958205673016318224240858751136661280471188438412165447232723393914969097252787347626988321917000774733737322494449818919125260958648800263996495910600551815631575048264209421462043584096144705567721409215513579478663560574161504773513061565180193507862861434089810710400523178487707581275521520577795243670305564926506609230306209563205662716453787880405129570055856427308236053212836347739247466071945057090182041305420394821265067125791719709125731551049817247167239327835167637907528587926920743330992051512069741151473403496874341619954964058090710784149252382410520680830775602521185581289313125400239124506053645292697781762946657933842988207613736173565401062037912720334806569630800708139852384275452749639040442985616234470227456393754010233488011575792824583072056560579111260482563707424996590173055927167750726725710388553693042649995924410781689294007749036207493130036597566481094607536687014042687135417672264358144088925155507117340622725123068145705074122591740835971852863145356002433770919362756255797144813740238108754874435077344162655866048790680086970052985926804608808427216687157188698375760724339352425399301906941294728294761952114211421984549491710888098698226680830192527065831968050134441967"}
```
Second, send the encrypted AES key to the **/getFlag** api.
```
POST https://middle-road.hkcert22.pwnable.hk:4433/getFlag HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 781
Host: middle-road.hkcert22.pwnable.hk:4433
Connection: Keep-Alive
Accept-Encoding: gzip
User-Agent: okhttp/4.10.0
key=Z4Qhb9q9prV6ibvXMtSbS%2BivRVf8dI%2BJK1WTbHPph0ApYmfku4nw8M%2FDQ49qjyysuWJIDUZtoBA4%0AXaFFCUh5teB42eSjo4ngrC%2BIxV%2FvlE%2BUmVEPN8FAnpkicpl6OrYXy%2FRsqABGVc1F32Cfn%2FwS1Yhv%0AXsHCNj4RwUs731CvxCckfVWZQfsgfBe%2FAJxKIlAdgb2%2BF6SuQTlqFDzN3wfAPQOGFeP5hDQ%2FwaSM%0AF53WyandV0qigD3ciM50zufBBr6LX7WZ%2FY1rXuVIKZ%2BaZPhZF88pbX%2FSfEXT2nRrau31149p%2FnrG%0A9Jkqji4IRIDF578hIqGLcmh7r%2BXzwgjBPoandqW2bG%2BROh3XWCIMz0L0WvV6cYU94iYR0LcuAVvg%0AwyZ2VJ1nlfecX%2FAMJvsfO1lQlvejxkwLDZi9choBzmRbAiwpOq7O7ToUHyC%2FfDn2c0HhO15SVLNZ%0At%2BJVwSGAlvSK9E7kJ9cWozFuRoh%2FGZ5hrhP3J3mOnH0N3vrQ2lF3w9I9tYDetRWMlPzmST8JjtZL%0A2Pg6NcSiDwjrHWvZZPiqjCOmY6A9vhIV2pxeVvQqNAXKD33k1b4shxpchnvQs3Aaz2NzTKef3i%2B7%0Ap%2FE1SlD4FjD5uKMBqbaqDPt7rhdzWceXbni4y3vAJz2Ro93dyIwvXf%2FOcOCTVjC2TV%2FZ4ioCQx4%3D%0A&code=22011917
```
```
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 164
{"aes_cbc_iv":"XOsBZtM06DHFiIUgrwvNmw==","enc_flag":"Oi0nLfie+Hu8ZYzoAgwSbIvsWzByAT34J4GI+r08zyyPZkTUcSkKmUxX8Iv/EHDE0hNtEfockTG3ZUfu0amSFIwbWgWpsmRBwbu+MP3KNNE="}
```
Finally, server will return the IV and encrypted flag.
Solution
================
We can perform the **M**an-**I**n-**T**he-**M**iddle attack to control the encryption key.
### Step 1: Generate RSA public key
Server will return the RSA public key parameters, we can use the following code to generate the RSA public key.
```java
Cipher cipher = Cipher.getInstance("RSA/ECB/NoPadding");
BigInteger rsa_n = new BigInteger("630791816259958205673016318224240858751136661280471188438412165447232723393914969097252787347626988321917000774733737322494449818919125260958648800263996495910600551815631575048264209421462043584096144705567721409215513579478663560574161504773513061565180193507862861434089810710400523178487707581275521520577795243670305564926506609230306209563205662716453787880405129570055856427308236053212836347739247466071945057090182041305420394821265067125791719709125731551049817247167239327835167637907528587926920743330992051512069741151473403496874341619954964058090710784149252382410520680830775602521185581289313125400239124506053645292697781762946657933842988207613736173565401062037912720334806569630800708139852384275452749639040442985616234470227456393754010233488011575792824583072056560579111260482563707424996590173055927167750726725710388553693042649995924410781689294007749036207493130036597566481094607536687014042687135417672264358144088925155507117340622725123068145705074122591740835971852863145356002433770919362756255797144813740238108754874435077344162655866048790680086970052985926804608808427216687157188698375760724339352425399301906941294728294761952114211421984549491710888098698226680830192527065831968050134441967");
BigInteger rsa_e = new BigInteger("65537");//e
KeyFactory kf = KeyFactory.getInstance("RSA");
RSAPublicKeySpec rSAPublicKeySpec = new RSAPublicKeySpec(rsa_n, rsa_e);
cipher.init(1, kf.generatePublic(rSAPublicKeySpec));
```
### Step 2: Generate AES key
```java
byte[] keyBytes= keyGenerator.generateKey().getEncoded();
System.out.println("AES Key(Hex): " + bytesToHex(keyBytes));
```
```
AES Key(Hex): 956036706E73E3DC33FE38F02FEE92211D880EEC688A88402BDE4B50EED25CCD
```
### Step 3: Encrypt AES key with RSA public key
```java
BASE64Encoder encoder = new BASE64Encoder();
byte[] arrayOfByte = cipher.doFinal(keyBytes);
System.out.println("Encrypted AES Key(Base64): " + encoder.encode(arrayOfByte));
```
```
Encrypted AES Key(Base64): QR8BoTJEFV05ZSpzpP1J57j4iQ4bFE46Hv/5lhP9VWsWvaoLs8jjpjfYwn0LeAXDKLRF+/RmxMTi
GuAat2TeYuLlELy8socD93u5MEzXGDGVOQxqDJrLL4pYAO2Ry0pzHeEpIr1PhwnFoSlSvr0EjSPz
mMREWoMTXpiW+4GDZbAL6RDb4aqkhXmR84F1jFxaiY6BuTXQt9n5GciMom5YWnyss1sFqPwNY8NM
MBXeDHsm4IAA0anmy1rFIzdAZyPDfTzeG7F9FNG88uxn2KoUzE/FVXFZivQaZf/uIPifmLhUnMLb
t7WXvy0qOuz/VkSZ+utUCorPFJcFFA+wYgKuzNZCTjyhD5g5GhjUsB0xZnpa+OQYyOaemVxnxR4I
zES43+scsILXJMLrnqR3gIfuna086zhag3kcuP+uy9LGoINbgHwOZX7Q/bNb3iBXpnS/0k2eOq/X
ADfIzM9G9EVOG8XdSrpBpxUmmJPQW/oYkXJzbl1SZfqcDKhzatXDL+uW4/wBaZ9rxjjE7aGIW5Yk
gaDOebMVu6Av4/xTyRZYzKlGrMYOGv+qKqFOEMFUlVvXVdCwt8NkzfTvLZVzZ61CrlfbZQb/OJMY
oJDJaobjbRO2aXzutbc2N1iv7VNYvdy1Xh2ui9iteqk4/HR0Lv52KMStBXopOLHKvSB5sAU6pSI=
```
### Step 4: Send encrypted AES key to server
#### Intercept the request and replace the encrypted AES key with the one we generated.
The server is also validate the TOTP code and the TOTP code is valid for 30 seconds only, so we need to ~~generate the TOTP code and replace it with the one we generated~~. As I already been single for many years, I can edit the packet and replace the data within a second. :P

```
POST https://middle-road.hkcert22.pwnable.hk:4433/getFlag HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 796
Host: middle-road.hkcert22.pwnable.hk:4433
Connection: Keep-Alive
Accept-Encoding: gzip
User-Agent: okhttp/4.10.0
key=QR8BoTJEFV05ZSpzpP1J57j4iQ4bFE46Hv%2F5lhP9VWsWvaoLs8jjpjfYwn0LeAXDKLRF%2B%2FRmxMTi%0D%0AGuAat2TeYuLlELy8socD93u5MEzXGDGVOQxqDJrLL4pYAO2Ry0pzHeEpIr1PhwnFoSlSvr0EjSPz%0D%0AmMREWoMTXpiW%2B4GDZbAL6RDb4aqkhXmR84F1jFxaiY6BuTXQt9n5GciMom5YWnyss1sFqPwNY8NM%0D%0AMBXeDHsm4IAA0anmy1rFIzdAZyPDfTzeG7F9FNG88uxn2KoUzE%2FFVXFZivQaZf%2FuIPifmLhUnMLb%0D%0At7WXvy0qOuz%2FVkSZ%2ButUCorPFJcFFA%2BwYgKuzNZCTjyhD5g5GhjUsB0xZnpa%2BOQYyOaemVxnxR4I%0D%0AzES43%2BscsILXJMLrnqR3gIfuna086zhag3kcuP%2Buy9LGoINbgHwOZX7Q%2FbNb3iBXpnS%2F0k2eOq%2FX%0D%0AADfIzM9G9EVOG8XdSrpBpxUmmJPQW%2FoYkXJzbl1SZfqcDKhzatXDL%2BuW4%2FwBaZ9rxjjE7aGIW5Yk%0D%0AgaDOebMVu6Av4%2FxTyRZYzKlGrMYOGv%2BqKqFOEMFUlVvXVdCwt8NkzfTvLZVzZ61CrlfbZQb%2FOJMY%0D%0AoJDJaobjbRO2aXzutbc2N1iv7VNYvdy1Xh2ui9iteqk4%2FHR0Lv52KMStBXopOLHKvSB5sAU6pSI%3D&code=70690328
```
```
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 164
{"aes_cbc_iv":"emkizYvQp+CrvuWwsWuY7A==","enc_flag":"On2zwMGWGmKhDXNxCWBAYuuARVd39Pl7wAVEW1zSFrMTQhoXrqBH3Exxlj6ZNWzJ52z7n7I8DNFRe8G3iRQ3N8y2edaY7Dyce++PRMf2+fE="}
```
### Step 5: Decrypt encrypted flag with AES key
We can decrypt the encrypted flag with the AES key we generated.
The encryption method is AES-256-CBC.
| | |
| ----------- | ----------- |
| AES Key | 956036706E73E3DC33FE38F02FEE92211D880EEC688A88402BDE4B50EED25CCD |
| IV | emkizYvQp+CrvuWwsWuY7A== |
| Encrypted_flag | On2zwMGWGmKhDXNxCWBAYuuARVd39Pl7wAVEW1zSFrMTQhoXrqBH3Exxlj6ZNWzJ52z7n7I8DNFRe8G3iRQ3N8y2edaY7Dyce++PRMf2+fE= |

### Step 6: Got the flag
>hkcert22{CLi3NT_can_B3_reverSE_EnGIN33red_by_0ne_W4y_or_aNoTh3r}