Passerby A · 2015/02/26 17:00
0x00 wifi master key did you get root after secretly upload password?
The test version for 3.2.3, first by questionable shell position statements into doubt the problem of code: the name of the class. Com snda. Wifilocating. F.b a
Conf/wifi.conf/wifi.conf/wifi.conf/wifi.conf/wifi.conf/wifi.conf/wifi.conf/wifi.conf/wifi.conf/wifi.conf/wifi.conf/wifi.conf/wifi.conf/wifi.conf/wifi.conf .
A cross-ref lookup of the reference shows that the function is called directly in two main places. One is a com. Snda. Wifilocating. E.a v:
This is an API interface, the main function of the user registered after the ap password backup, at the same timeWpaConfUploadActivity is called directly and GetBackupActivity is called indirectly. The first Activity has been removed from AndroidManifest in the analysis version, while the second Activity is the interface for users to back up their private wifi. This confirms that the password was indeed uploaded during the backup, and that the password is completely reversible from what follows.
However, there are no other suspicious root actions in the application. I turned on SuperSu’s root execution monitoring and found only this command executing during my brief use.
0x01 overview of Android Wifi Connection API
WifiManager provides the Wifi scanning and connection interface. Applications can scan, connect, disconnect wireless, etc., after requesting the corresponding permissions. In the wireless connection function, the client basically needs to specify the SSID and pre-shared-key (i.e. password) to connect to the wireless in code mode. To connect a WPA(2) wireless typical code is as follows,
#! bash wifiConfiguration.SSID = "\"" + networkSSID + "\""; wifiConfiguration.preSharedKey = "\"" + networkPass + "\""; wifiConfiguration.hiddenSSID = true; wifiConfiguration.status = WifiConfiguration.Status.ENABLED; wifiConfiguration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP); wifiConfiguration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP); wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); wifiConfiguration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP); wifiConfiguration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP); wifiConfiguration.allowedProtocols.set(WifiConfiguration.Protocol.RSN); wifiConfiguration.allowedProtocols.set(WifiConfiguration.Protocol.WPA); int res = wifiManager.addNetwork(wifiConfiguration); Log.d(TAG, "### add Network returned " + res);Copy the code
0x02 wifi Master Key how to connect to wireless, where does the password come from?
This is also controversial. First of all, the app must have a lot of passwords stored in the cloud, because the app will guide users to back up their passwords, but we don’t know whether these passwords are abused in the client. In this test at the end of February, the author first privately backed up the test wireless set up by himself (note that it was not shared), and then used another phone to install the client test. The API request interface of the client did not return the password of the test wireless. However, this may only be an example of what can not be explained, or you are advised to test yourself, but pay attention to the test before clearing the saved wireless and set a weak password for the test wireless so as not to really leak their password.
Wireless password acquisition analysis
Back to the point, I intercepted the application’s request for wifi password through an agent. The application sends the ssiD of the target, and the MAC information is queried to the cloud. The obtained password is encrypted by AES instead of plaintext. First in order to prove its locally will eventually appear in clear text, first take a clever, didn’t go to inverse the algorithm (although the reverse is not very difficult), but direct hook the system to add wireless code (recall in the above code in NetworkConfiguration. PreSharedKey).
Part of HOOK code:
#! java Class wifimgr = XposedHelpers.findClass( "android.net.wifi.WifiManager", lpparam.classLoader); XposedBridge.hookAllMethods(wifimgr, "addNetwork", new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { WifiConfiguration configuration = (WifiConfiguration) param.args[0]; if(configuration.preSharedKey ! = null) { Log.e("FUCKFUCK", "psk: "+configuration.preSharedKey); }}}); XposedBridge.hookAllMethods(wifimgr, "updateNetwork", new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { WifiConfiguration configuration = (WifiConfiguration) param.args[0]; if(configuration.preSharedKey ! = null) { Log.e("FUCKFUCK", "psk: "+configuration.preSharedKey); }}}); }Copy the code
This is a screenshot of master key uploading wifi SSID and MAC to request password:
Response screenshot:
The password is passed back in AES reversible encryption via the JSON key PWD.
At the same time, when it tries to connect to the target wireless through this password, the local Hook module also obtains the real plaintext password:
Personal Backup analysis
The personal backup module, which reads wifi.conf directly, uses the JSON API methods findPrivateap and Saveprivateap. Specific HTTP request logic in com. Snda. Wifilocating. Can be found in the e.a v, this class also contains basically all master key API request logic.
Backup request: Upload the entire wifi.conf file.
When you restore the backup, you just drag the password down from the cloud.
Analysis of other connection modes
In addition, Wifi master Key also comes with 2000 database records in AP8.db, which records common weak passwords.For example,
These passwords are used for the so-called “deep connection” feature, which is essentially a wifi password blast by the code’s logic, trying 10 passwords at a time in the dictionary. It’s obvious if you look at logcat.
#! bash I/wpa_supplicant( 884): wlan0: WPA: 4-Way Handshake failed - pre-shared key may be incorrect I/wpa_supplicant( 884): wlan0: CTRL-EVENT-SSID-TEMP-DISABLED id=1 ssid="aaaaaaaaa" auth_failures=2 duration=20 D/SupplicantStateTracker( 818): Failed to authenticate, disabling network 1 I/wpa_supplicant( 884): wlan0: CTRL-EVENT-SSID-REENABLED id=1 ssid="aaaaaaaaa" I/wpa_supplicant( 884): wlan0: Trying to associate with 5c:a4:8a:4d:09:a0 (SSID='aaaaaaaaa' freq=2412 MHz) I/wpa_supplicant( 884): wlan0: Associated with 5c:a4:8a:4d:09:a0 I/wpa_supplicant( 884): wlan0: CTRL-EVENT-DISCONNECTED bssid=5c:a4:8a:4d:09:a0 reason=23 I/wpa_supplicant( 884): wlan0: CTRL-EVENT-SSID-TEMP-DISABLED id=1 ssid="aaaaaaaaa" auth_failures=1 duration=10 I/wpa_supplicant( 884): wlan0: WPA: 4-Way Handshake failed - pre-shared key may be incorrect I/wpa_supplicant( 884): wlan0: CTRL-EVENT-SSID-TEMP-DISABLED id=1 ssid="aaaaaaaaa" auth_failures=2 duration=20 I/wpa_supplicant( 884): wlan0: CTRL-EVENT-SSID-REENABLED id=1 ssid="aaaaaaaaa" I/wpa_supplicant( 884): wlan0: Trying to associate with 5e:aa:aa:aa:aa:aa (SSID='aaaaaaaaa' freq=2462 MHz) I/wpa_supplicant( 884): wlan0: Associated with 5e:aa:aa:aa:aa:aa D/dalvikvm(13893): GC_CONCURRENT freed 356K, 4% free 18620K/19220K, paused 9ms+2ms, total 29ms I/wpa_supplicant( 884): wlan0: CTRL-EVENT-DISCONNECTED bssid=5e:aa:aa:aa:aa:aa reason=23 I/wpa_supplicant( 884): wlan0: CTRL-EVENT-SSID-TEMP-DISABLED id=1 ssid="aaaaaaaaa" auth_failures=1 duration=10 I/wpa_supplicant( 884): wlan0: WPA: 4-Way Handshake failed - pre-shared key may be incorrect I/wpa_supplicant( 884): wlan0: CTRL-EVENT-SSID-TEMP-DISABLED id=1 ssid="aaaaaaaaa" auth_failures=2 duration=20Copy the code
Wifi password encryption and decryption analysis
Of course, it is not very difficult to reverse the encryption code, and a simple search can get the decryption code :(part of the code is directly extracted from the decomcompiled code, style is not modified)
#! Java public class AESFun {String a =// omitted; String b = // omit; String c = // omit; Cipher cipher; IvParameterSpec spec; SecretKeySpec secretKeySpec; void init() throws NoSuchAlgorithmException, NoSuchPaddingException { spec = new IvParameterSpec(b.getBytes()); secretKeySpec = new SecretKeySpec(a.getBytes(), "AES"); cipher = Cipher.getInstance("AES/CBC/NoPadding"); } public final String b(String arg7) throws Exception { byte[] array_b1; byte[] array_b = null; int i = 2; String string = null; { try { this.cipher.init(2, secretKeySpec, spec); Cipher cipher = this.cipher; if(arg7 ! = null && arg7.length() >= i) { int i1 = arg7.length() / 2; array_b = new byte[i1]; int i2; for(i2 = 0; i2 < i1; ++i2) { String string1 = arg7.substring(i2 * 2, i2 * 2 + 2); array_b[i2] = ((byte)Integer.parseInt(string1, 0x10)); } } array_b1 = cipher.doFinal(array_b); } catch(Exception exception) { StringBuilder stringBuilder = new StringBuilder("[decrypt] "); string = exception.getMessage(); StringBuilder stringBuilder1 = stringBuilder.append(string); string = stringBuilder1.toString(); exception.printStackTrace(); throw new Exception(string); } string = new String(array_b1); } return string; }Copy the code
Substitution of the hexadecimal PWD field obtained in the API request into the decryptor results in the following format: [Length][password][TIMESTAMP] format, as shown in the following figure, with the target wireless plaintext password in the middle.
In addition, one of the sign fields in the interface request is checkmarked, which actually merges the request parameters into an MD5 with the preset key, so I won’t go into details. After these two are clear, you can use this interface to achieve a Wifi key of your own.
0 x03 summary
This version of the WiFi master key will not take the initiative to keep the phone after the root of the wireless password is sent to the cloud but doing backup operation (when install the default check the automatic backup) will be sent, when you have enough users to use this application, the cloud will have a huge database of WiFi, query the WiFi password, the application will send target ssid, The MAC information is queried from the cloud, and the obtained password is encrypted using AES instead of plain text. After local decryption, the password is connected to the target WiFi. At the same time, there are 2000 common WiFi weak passwords built in, so when there is no WiFi password in the cloud, you can try to blast the target’s password.