├── sources ├── CMakeLists.txt ├── Makefile ├── kwm.h └── kwm.c ├── bin ├── kwm.exe ├── kwm_arm64 └── kwm_x86-64 ├── a.bat └── README.md /sources/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(kwm ./kwm.c) -------------------------------------------------------------------------------- /bin/kwm.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bczhc/kwmusic-kwm-decrypt/HEAD/bin/kwm.exe -------------------------------------------------------------------------------- /bin/kwm_arm64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bczhc/kwmusic-kwm-decrypt/HEAD/bin/kwm_arm64 -------------------------------------------------------------------------------- /bin/kwm_x86-64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bczhc/kwmusic-kwm-decrypt/HEAD/bin/kwm_x86-64 -------------------------------------------------------------------------------- /sources/Makefile: -------------------------------------------------------------------------------- 1 | kwm : kwm.o 2 | cc -o kwm kwm.o 3 | kwm.o : kwm.h 4 | .PHONY : clean 5 | clean : 6 | rm -rf ./kwm.o kwm 7 | -------------------------------------------------------------------------------- /a.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | md .\Dest 2>nul 3 | for /f "delims=" %%f in ('dir ".\Files\*.kwm" /a/b') do ( 4 | .\bin\kwm ".\Files\%%f" ".\Dest\%%~nf.flac" 5 | ) 6 | pause -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # kwmusic-kwm-decrypt 2 | 酷我音乐kwm解密 3 | 可解密原flac文件的kwm,其它没有试过。 4 | 5 | usage: Command [sourceFilePath] [destFilePath] 6 | 7 | 8 | 批量:bat同级目录下创建目录Files,放原文件;执行bat,生成Dest文件生成解密的文件。 9 | -------------------------------------------------------------------------------- /sources/kwm.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by zhc-2 on 2019/6/22. 3 | // 4 | 5 | #ifndef C99_KWM_H 6 | #define C99_KWM_H 7 | 8 | #include 9 | #include 10 | 11 | #define ARR_len(x) sizeof(x) / sizeof(x)[0] 12 | #define dl long long 13 | #define usi unsigned int 14 | #endif //C99_KWM_H 15 | //#include "../zhc.h" 16 | 17 | void PrintArr(const char arr[], int len); 18 | 19 | long long getFileSize(FILE *fp); 20 | 21 | int cmpCharArray(const char *a1, const int a1Len, const char *a2, const int a2Len); -------------------------------------------------------------------------------- /sources/kwm.c: -------------------------------------------------------------------------------- 1 | // 2 | // Created by zhc-2 on 2019/6/22. 3 | // 4 | 5 | #include "kwm.h" 6 | 7 | #define MAX_FIND_KEY_TIME 468 8 | 9 | void PrintArr(const char arr[], int len) { 10 | int l_ = len - 1; 11 | printf("[\n"); 12 | for (int i = 0; i < l_; ++i) { 13 | if (i == 16) printf("\n"); 14 | printf("%i%c", (int) arr[i], 44); 15 | } 16 | printf("\n%i]___%u", (int) arr[l_ - 1], (l_ + 1)); 17 | } 18 | 19 | long long getFileSize(FILE *fp) { 20 | long long sz; 21 | fseek(fp, 0L, SEEK_END); 22 | sz = (long long) ftell(fp); 23 | if (sz == -1) { 24 | sz = ftell(fp); 25 | printf("Get file size error.\n"); 26 | } 27 | fseek(fp, 0L, SEEK_SET); 28 | return sz; 29 | } 30 | 31 | int cmpCharArray(const char *a1, const int a1Len, const char *a2, const int a2Len) { 32 | if (a1Len != a2Len) return 0; 33 | else { 34 | for (int i = 0; i < a1Len; ++i) { 35 | if (a1[i] != a2[i]) return 0; 36 | } 37 | } 38 | return 1; 39 | } 40 | 41 | int main(const int argc, char **argv) { 42 | if (argc != 3) { 43 | printf("Command [filePath] [destFilePath]\n"); 44 | return 1; 45 | } else { 46 | int haveFoundKey = 0; 47 | char *fN = argv[1]; 48 | char *dFN = argv[2]; 49 | FILE *fp = NULL, *fpO = NULL; 50 | if ((fp = fopen(fN, "rb")) == NULL) { 51 | printf("fopen error."); 52 | return -1; 53 | } 54 | if ((fpO = fopen(dFN, "wb")) == NULL) { 55 | printf("fopen error."); 56 | return -1; 57 | } 58 | char key[32] = {0}, old_key[32] = {0}; 59 | dl fS = getFileSize(fp), a = fS / 1024; 60 | usi b = (usi) fS % 1024; 61 | fseek(fp, 1024L, SEEK_SET); 62 | for (int i = 0; i < MAX_FIND_KEY_TIME; ++i) { 63 | fread(key, 32, 1, fp); 64 | int cmpR = cmpCharArray(key, 32, old_key, 32); 65 | if (cmpR) { 66 | haveFoundKey = 1; 67 | break; 68 | } 69 | for (int j = 0; j < 32; ++j) { 70 | old_key[j] = key[j]; 71 | } 72 | } 73 | if (!haveFoundKey) { 74 | char *newKey = NULL; 75 | newKey = (char *) malloc(32); 76 | for (int i = 0; i < 16; ++i) { 77 | newKey[i] = key[i + 16]; 78 | } 79 | for (int j = 16; j < 32; ++j) { 80 | newKey[j] = key[j - 16]; 81 | } 82 | for (int k = 0; k < 32; ++k) { 83 | key[k] = newKey[k]; 84 | } 85 | free(newKey); 86 | } 87 | fseek(fp, 1024L, SEEK_SET); 88 | printf("key: "); 89 | PrintArr(key, ARR_len(key)); 90 | printf("\n"); 91 | char buf[1024] = {0}; 92 | for (int l = 1; l < a; ++l) { 93 | fread(buf, 1024, 1, fp); 94 | for (int i = 0; i < 1024; ++i) { 95 | buf[i] ^= key[i & 31]; 96 | } 97 | fwrite(buf, 1024, 1, fpO); 98 | } 99 | if (b) { 100 | fread(buf, b, 1, fp); 101 | for (int i = 0; i < b; ++i) { 102 | buf[i] ^= key[i & 31]; 103 | } 104 | fwrite(buf, b, 1, fpO); 105 | } 106 | } 107 | return 0; 108 | } --------------------------------------------------------------------------------