-
Notifications
You must be signed in to change notification settings - Fork 218
Reverse Engineering the QR Code
The Yi home application lets you pair devices by having them scan a QR code generated by the app itself. Scanning the QR codes with a regular barcode reader reveals that the QR codes themselves are simple text.
The Yi Home camera systems are using the ZBAR QR Code Scanning library https://github.com/Zbar/Zbar.
Below is an example of a typical generated QR code
This QR code was generated at 2019-02-23 13:24 (UTC).
The wifi network was named as The Normandy
.
The wifi password was AAAAAAAAAAAA
.
Scanning this reveals a piece of text as such:
b=EU28FM4aoN1vWOML&s=VGhlIE5vcm1hbmR5&p=eXgLBxIrLnkJFCMp
The raw bytes from the QR code itself are as follows (Note this is just typical QR code encoding, there's nothing special here):
43 86 23 d4 55 53 23 84
64 d3 46 16 f4 e3 17 65
74 f4 d4 c2 67 33 d5 64
76 86 c4 94 53 57 66 36
d3 16 86 26 d5 23 52 67
03 d6 55 86 74 c4 27 84
97 24 c6 e6 b4 a4 64 34
d7 00 ec 11 ec 11 ec 11
ec 11 ec 11 ec 11 ec 11
ec 11 ec 11 ec 11 ec 11
Working through the text, the following can be broken down as follows:
b=EU28FM4aoN1vWOML&s=VGhlIE5vcm1hbmR5&p=eXgLBxIrLnkJFCMp
Component | Name | Example | Encoding | Decoded |
---|---|---|---|---|
b= | bindKey | EU28FM4aoN1vWOML | Unknown | Unknown |
s= | SSID | VGhlIE5vcm1hbmR5 | Base64 | The Normandy |
p= | Wifi Password | eXgLBxIrLnkJFCMp | Xor + Base64 | AAAAAAAAAAAA |
The bind key is a response code from the Xiaoyi servers. The YI phone application communicates to https://api.us.xiaoyi.com sending a GET for a bind key supplying the YI ID of the user, Time and Mac address [1]
GET /v2/qrcode/get_bindkey?hmac=<redact> %3D&userid=00110011&seq=1×tamp=1522268058227 HTTP/1.1
Content-Length: 0
Host: api.us.xiaoyi.com
Connection: Keep-Alive
User-Agent: YI Home/2.20.20.0_20180227 (Alcatel_4060A; Android 10.2; en-US)
Accept-Encoding: gzip
x-xiaoyi-appVersion: android;73;2.20.20.0_20180227
The Camera then appears to verify this information, if it cant it verbalises an error and disregards the configuration. On next reboot the camera will be unable to connect to wifi, and a QR code will need to be shown again.
More information is needed about this.
This is the SSID (Wifi Network) for the camera to connect to, simply Base64 encoded.
The password is also Base64 encoded, however the password is XOR'd against a static string before it's base 64 encoded:
The following string is used as a kind of obfuscation key. In reality this doesn't obfuscate much as it's trivial to reverse-engineer such a key
89JFSjo8HUbhou5776NJOMp9i90ghg7Y78G78t68899y79HY7g7y87y9ED45Ew30O0jkkl
The following example is written in C#
public static string EncodePassword(string plainText, string obfuscationKey)
{
StringBuilder sb = new StringBuilder();
// This is a standard XOR routine
for (var i = 0; i < plainText.Length; i++)
{
sb.Append((char)(plainText[i] ^ obfuscationKey[(i % obfuscationKey.Length)]));
}
var encipheredText = sb.ToString();
// We convert the XOR'd text into an array of bytes
var bytes = Encoding.ASCII.GetBytes(encipheredText);
// And convert those bytes to a Base 64 string
return Convert.ToBase64String(bytes);
}
public static string DecodePassword(string plainText, string obfuscationKey)
{
// Convert the Base 64 string back to bytes
byte[] newBytes = Convert.FromBase64String(plainText);
// Convert array of bytes back to XOR'd text
plainText = Encoding.ASCII.GetString(newBytes);
StringBuilder sb = new StringBuilder();
// This is a standard XOR routine
for (var i = 0; i < plainText.Length; i++)
{
sb.Append((char)(plainText[i] ^ obfuscationKey[(i % obfuscationKey.Length)]));
}
var encipheredText = sb.ToString();
return encipheredText;
}
public static string EncodeBase64SSID(string plainText)
{
var bytes = Encoding.ASCII.GetBytes(plainText);
// And convert those bytes to a Base 64 string
return Convert.ToBase64String(bytes);
}
public static string DecodeBase64SSID(string plainText)
{
// Convert the Base 64 string back to bytes
byte[] newBytes = Convert.FromBase64String(plainText);
plainText = Encoding.ASCII.GetString(newBytes);
return plainText;
}
The creation of a custom QR code can be done using http://qrcode.azurewebsites.net/ or similar and using above functions to create an image based on the RAW data of
b=00000001&s=BASE_64_ENCODED_SSID&p=BASE_64_AND_XOR_WIFI_PASSWORD
Or you could use this pre-made generator for Yi Cameras: https://yi.kushan.biz/