📜 ⬆️ ⬇️

About Stalin, Durov, cookies and parameter EncryptedPasswd

During the unsuccessful attempt of habrasuicid in the comments on the article on psychological assistance to a child injured by SMS , I told about my dream in which Stalin fed the bound Durov with chocolate cookies, and the public key of Google Play went out of base64 in place of smoke from Stalin. This dream I had a dream after a long and tedious reversing of the mobile protocol Google Play. There, in the comments, I was offered to write a separate article about it. Well, actually this article is. In it, I propose to talk about my dream, as well as the EncryptedPasswd parameter in the POST request to android.clients.google.com/auth android.clients.google.com/auth .

To begin, I will remind you what this POST request is and tell you why the EncryptedPasswd field interested me so much. A couple of years ago, using Google Apps traffic interception, it was determined that the Android device’s login on Google Play is performed using a request of the following type:

  POST / auth HTTP / 1.1
 Content-Type: application / x-www-form-urlencoded
 Content-Length: 404
 Host: android.clients.google.com
 Connection: Keep-Alive
 User-Agent: GoogleLoginService / 1.3 (a10 JZO54K)

 accountType = HOSTED_OR_GOOGLE & Email = testemail% 40gmail.com & has_permission = 1 & add_account = 1 & EncryptedPasswd = AFcb4KS9WAU3NI_-jdMDSueqT-oO1-WN2B9pxB-te_Elx3MElC9B2TgAaWqkY7kiQSnGFEwaY1KVkizxadGsRnFnHa7vlRCrB4Me1XnHBuOz9oi48eBcm0rC7r8QaC_GPp1YPI8OFa0fZU_dTJypganc2tREsgE-_TJQSKWkA7zSWnsq8g% 3D% 3D & service = ac2dm & source = android & androidId = 378b05ab23e0e8e9 & device_country = ua & operatorCountry = ua & lang = en & sdk_version = 16

This request was still used in one clever attack on Google’s two-factor authentication about a year ago. In principle, all the parameters of this request are more or less obvious, except for the EncryptedPasswd parameter. Enhanced googling gave only that EncryptedPasswd - this is possibly a google account password encrypted with the Google public key. And yet, no more technical details. This vague answer, of course, did not suit me, and I climbed inside com.google.android.gsf.login .
')
Inside, I discovered the com.google.android.gsf.loginservice.PasswordEncrypter class - this is the one that is responsible for encrypting the password. Reverse engineering of this class showed that encryption ... but I will not bother my dear reader with tons of Dalvik bytecode, I'd rather give you a working javascript in Java (the encoder is so-so):

 //   Google private static final String googleDefaultPublicKey = "AAAAgMom/1a/v0lblO2Ubrt60J2gcuXSljGFQXgcyZWveWLEwo6prwgi3iJIZdodyhKZQrNWp5nKJ3srRXcUW+F1BD3baEVGcmEgqaLZUNBjm057pKRI16kB0YppeGx5qIQ5QjKzsR8ETQbKLNWgRY0QRNVz34kMJR3P/LgHax/6rmf5AAAAAwEAAQ=="; //  : // login -   myemail@gmail.com // password -  //  : // base64     // !     ,  //        login+password //   80  (      -  //       ) @SuppressWarnings("static-access") public static String encrypt(String login, String password) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, UnsupportedEncodingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { //    Google login public   base64 //  PublicKey   SHA-1    : // 1.  Google login public   base64  byte[] byte[] binaryKey = Base64.decode(googleDefaultPublicKey, 0); // 2.   BigInteger int i = readInt(binaryKey, 0); byte [] half = new byte[i]; System.arraycopy(binaryKey, 4, half, 0, i); BigInteger firstKeyInteger = new BigInteger(1, half); // 3.   BigInteger int j = readInt(binaryKey, i + 4); half = new byte[j]; System.arraycopy(binaryKey, i + 8, half, 0, j); BigInteger secondKeyInteger = new BigInteger(1, half); // 4.  SHA-1        signature: // signature[0] = 0 (  !) // signature[1...4] =  4  SHA-1     byte[] sha1 = MessageDigest.getInstance("SHA-1").digest(binaryKey); byte[] signature = new byte[5]; signature[0] = 0; System.arraycopy(sha1, 0, signature, 1, 4); // 5.    BigInteger'   //   PublicKey publicKey = KeyFactory.getInstance("RSA"). generatePublic(new RSAPublicKeySpec(firstKeyInteger, secondKeyInteger)); //    : // 1.    Cipher: Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWITHSHA1ANDMGF1PADDING"); // 2.       "\u0000"  : String combined = login + "\u0000" + password; // 3.      : byte[] plain = combined.getBytes("UTF-8"); // 4.       cipher.init(cipher.PUBLIC_KEY, publicKey); byte[] encrypted = cipher.doFinal(plain); // 5.     output  133 : // output[0] = 0 ( 0) // output[1...4] =  4  SHA-1     // output[5...132] =   +  (  "\u0000") byte[] output = new byte [133]; System.arraycopy(signature, 0, output, 0, signature.length); System.arraycopy(encrypted, 0, output, signature.length, encrypted.length); // !   output  base64      :) return Base64.encodeToString(output, Base64.URL_SAFE + Base64.NO_WRAP); } //  ,  4     int private static int readInt(byte[] arrayOfByte, int start) { return 0x0 | (0xFF & arrayOfByte[start]) << 24 | (0xFF & arrayOfByte[(start + 1)]) << 16 | (0xFF & arrayOfByte[(start + 2)]) << 8 | 0xFF & arrayOfByte[(start + 3)]; } / 1a / v0lblO2Ubrt60J2gcuXSljGFQXgcyZWveWLEwo6prwgi3iJIZdodyhKZQrNWp5nKJ3srRXcUW + F1BD3baEVGcmEgqaLZUNBjm057pKRI16kB0YppeGx5qIQ5QjKzsR8ETQbKLNWgRY0QRNVz34kMJR3P / LgHax / 6rmf5AAAAAwEAAQ =="; //   Google private static final String googleDefaultPublicKey = "AAAAgMom/1a/v0lblO2Ubrt60J2gcuXSljGFQXgcyZWveWLEwo6prwgi3iJIZdodyhKZQrNWp5nKJ3srRXcUW+F1BD3baEVGcmEgqaLZUNBjm057pKRI16kB0YppeGx5qIQ5QjKzsR8ETQbKLNWgRY0QRNVz34kMJR3P/LgHax/6rmf5AAAAAwEAAQ=="; //  : // login -   myemail@gmail.com // password -  //  : // base64     // !     ,  //        login+password //   80  (      -  //       ) @SuppressWarnings("static-access") public static String encrypt(String login, String password) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, UnsupportedEncodingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { //    Google login public   base64 //  PublicKey   SHA-1    : // 1.  Google login public   base64  byte[] byte[] binaryKey = Base64.decode(googleDefaultPublicKey, 0); // 2.   BigInteger int i = readInt(binaryKey, 0); byte [] half = new byte[i]; System.arraycopy(binaryKey, 4, half, 0, i); BigInteger firstKeyInteger = new BigInteger(1, half); // 3.   BigInteger int j = readInt(binaryKey, i + 4); half = new byte[j]; System.arraycopy(binaryKey, i + 8, half, 0, j); BigInteger secondKeyInteger = new BigInteger(1, half); // 4.  SHA-1        signature: // signature[0] = 0 (  !) // signature[1...4] =  4  SHA-1     byte[] sha1 = MessageDigest.getInstance("SHA-1").digest(binaryKey); byte[] signature = new byte[5]; signature[0] = 0; System.arraycopy(sha1, 0, signature, 1, 4); // 5.    BigInteger'   //   PublicKey publicKey = KeyFactory.getInstance("RSA"). generatePublic(new RSAPublicKeySpec(firstKeyInteger, secondKeyInteger)); //    : // 1.    Cipher: Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWITHSHA1ANDMGF1PADDING"); // 2.       "\u0000"  : String combined = login + "\u0000" + password; // 3.      : byte[] plain = combined.getBytes("UTF-8"); // 4.       cipher.init(cipher.PUBLIC_KEY, publicKey); byte[] encrypted = cipher.doFinal(plain); // 5.     output  133 : // output[0] = 0 ( 0) // output[1...4] =  4  SHA-1     // output[5...132] =   +  (  "\u0000") byte[] output = new byte [133]; System.arraycopy(signature, 0, output, 0, signature.length); System.arraycopy(encrypted, 0, output, signature.length, encrypted.length); // !   output  base64      :) return Base64.encodeToString(output, Base64.URL_SAFE + Base64.NO_WRAP); } //  ,  4     int private static int readInt(byte[] arrayOfByte, int start) { return 0x0 | (0xFF & arrayOfByte[start]) << 24 | (0xFF & arrayOfByte[(start + 1)]) << 16 | (0xFF & arrayOfByte[(start + 2)]) << 8 | 0xFF & arrayOfByte[(start + 3)]; } 

This code is far from perfect, but it works and may well serve


This is all I wanted to say about the EncryptedPasswd parameter. If you have any questions or clarifications - please in the comments.

Now about my dream in more detail. I dreamed of Stalin's office as it was usually painted on agitation posters of the USSR times — some kind of indistinct room with a large, rough table on which papers and maps were laid out. In my dream, a large and clearly modern natural leather office chair stood at the table, to which Durov was tied with thick hemp rope. There were no signs of beatings or torture on the founder of VK, but he still looked miserable. On the table in front of Durov, on top of papers and cards, was a white saucer with chocolate cookies, and just to the side of the table Stalin himself stood in his tunic, smoking a pipe and smiling at his mustache. In his right hand, Stalin kept all the same cookies that he continuously fed Durov. Having pushed one cookie into the Durov family, the leader immediately took the next one from the saucer - and the “feeding” process was repeated from the beginning. Durov crumbled with crumbs chewed cookies, twisted ruddy red tears in his eyes and sometimes moaned helplessly. This scene seemed even more bizarre and frightening because Stalin’s pipe wasn’t the smoke, but the very public key of Google in base64:

  AAAAgMom / 1a / v0lblO2Ubrt60J2gcuXSljGFQXgcyZWveWLEwo6prwgi3iJIZdodyhKZQrNWp5nKJ3srRXcUW + F1BD3baEVGcmEgqaLZUNBjm057pKRI16kB0YppeGx5qIQ5QjKzsR8ETQbKLNWgRY0QRNVz34kMJR3P / LgHax / 6rmf5AAAAAwEAAQ ==

This dream caused me a serious psychological trauma, which I propose to discuss in the comments, since the week of mysticism and psychology on Habré.

Source: https://habr.com/ru/post/220521/


All Articles