萌动歌姬通信解密 (C++)
算法讲白了就是生成一个 xor key
的集合 (8 字节),然后依次对密文里的数字、字母进行 xor 操作,若结果也是数字、字母的话则保留,否则不进行更改。
每次进行更改,将 xor key
的索引 +1
, 到达尾部的时候将每个 key 的值改为 k = ((k * 3) & 0x0F)
,继续循环。
相关代码参考下方代码:
#include <cstdlib>
#include <stdio.h>
#include <string.h>
/**
* Convert a hex (0-F) to its representation.
* @param c Char ('0' ~ 'F')
* @return Char (0x0 ~ 0xF)
*/
inline char hexToChar(char c) {
if (c >= '0' && c <= '9')
return c - '0';
if (c >= 'A' && c <= 'Z')
return c - 'A' + 10;
if (c >= 'a' && c <= 'z')
return c - 'z' + 10;
return c;
}
/**
* Check if a char is valid (0-9, a-z, A-Z).
* @param c The char to check.
* @return true if valid, false otherwise.
*/
inline bool isAlphaOrDigit(char c) {
return (c >= '0' && c <= '9')
|| (c >= 'A' && c <= 'Z')
|| (c >= 'a' && c <= 'z');
}
/**
* Encode / Decode response from server.
* @param lpKey Communication key, constant.
* @param keySize Key size.
* @param lpResponse Response buffer to read and write.
* @return true if encode/decode successfully.
*/
bool encodeResponse(const char *lpKey, int keySize, char *lpResponse) {
char *xorKeys;
signed int dataLen;
if (!(lpKey && keySize >= 1 && strlen(lpKey) >= keySize && lpResponse))
return false;
dataLen = strlen(lpResponse);
if (dataLen < 1) {
return false;
}
// Reverse search for char '}'.
int jsonLength = 0;
for (int i = dataLen - 1; i >= 0; i--) {
if (lpResponse[i] == '}') {
jsonLength = i;
break;
}
}
// Hex Char Representation to binary data.
xorKeys = new char[keySize];
if (keySize >= 1) {
for (int i = 0; i < keySize; i++) {
xorKeys[i] = hexToChar(lpKey[i]);
}
}
for (int i = 0, k = 0; i < dataLen; i++) {
if (i >= jsonLength) continue;
char c = lpResponse[i];
// check if c is a valid char.
if (!isAlphaOrDigit(c)) continue;
// xor with key
c ^= xorKeys[k];
// check if xored c is a valid char.
if (!isAlphaOrDigit(c)) continue;
// Store decrypted char.
lpResponse[i] = c;
// Check if key have been looped.
k++;
if (k == keySize) {
for (int j = 0; j < keySize; j++) {
// Limit xorKey from 0~F
xorKeys[j] = (3 * xorKeys[j]) & 0x0F;
}
k = 0;
}
}
delete[] xorKeys;
return true;
}
bool getResponse(char *lpResponse) {
if (lpResponse) {
encodeResponse("EB1CEB1C", 8, lpResponse);
return true;
}
return false;
}
char szTestData[] = "{\"rkxqcnsk_oaum\":{\"ktwlesjza_zlbin\":"
"\"ojyzoRquo59NspWEMBR4rr2PLsF3cegoDmRz0DzC40vzaiaurXUnqzm"
"Y64TQzQKSKh6jSOGJZZSI5YaRGvQyHR8\"},\"sxktuz_hknl\":940}";
int main(int argc, char** argv) {
printf("encrypted: %s\n", szTestData);
getResponse(szTestData);
printf("decrypted: %s\n", szTestData);
return 0;
}
encrypted: {"rkxqcnsk_oaum":{"ktwlesjza_zlbin":"ojyzoRquo59NspWEMBR4rr2PLsF3cegoDmRz0DzC40vzaiaurXUnqzmY64TQzQKSKh6jSOGJZZSI5YaRGvQyHR8"},"sxktuz_hknl":940}
decrypted: {"response_data":{"authorize_token":"aipveRxud13GxtYNLNR4rr2PBxG3ooflDiXz1GzG40xyheovrQYdxqiS64TXqUEXJd8aRCMKYZWC4ZeRIuXuFQ1"},"status_code":200}
– Jixun.Moe 于火车