c++ 17 代码示例
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> #include <regex> #include <string> #include <fstream> #include <cstdio> #include <string> #include <sstream> #include <streambuf> #include <filesystem> std::vector<std::string> mp3FileList(std::string const& baseDir) { std::vector<std::string> v; for (auto& entry : std::filesystem::directory_iterator(baseDir)) if (entry.is_regular_file()) { auto filename = entry.path().filename().replace_extension(); v.push_back(filename.string()); } return v; } bool save_file(std::string const& filepath, std::vector<std::byte> const& buffer) { std::ofstream ofs(filepath, std::ios::out | std::ios::binary | std::ios::trunc); if (!ofs) throw std::runtime_error(filepath + ": " + "std::strerror(errno)"); if (!ofs.write((char*)buffer.data(), buffer.size())) throw std::runtime_error(filepath + ": " + "std::strerror(errno)"); return true; } std::byte x{ 0xA3 }; std::vector<std::byte> xorVector(std::vector<std::byte>& v) { for (auto& bb : v) { bb ^= x; } return v; } std::vector<std::byte> load_file(std::string const& filepath) { std::ifstream ifs(filepath, std::ios::binary | std::ios::ate); if (!ifs) throw std::runtime_error(filepath + ": " + "std::strerror(errno)"); auto end = ifs.tellg(); ifs.seekg(0, std::ios::beg); auto size = std::size_t(end - ifs.tellg()); if (size == 0) { // avoid undefined behavior std::cout << filepath << " is emtype." << ' '; return {}; } std::vector<std::byte> buffer(size); if (!ifs.read((char*)buffer.data(), buffer.size())) throw std::runtime_error(filepath + ": " + "std::strerror(errno)"); return buffer; } int main(int argc, char** argv) { std::string baseDir = { R"(C:UserszhibinAppDataLocalNeteaseCloudMusicCacheCache)" }; // baseDir = { R"(.)" }; std::string destDir = "d:\music\"; bool is_override = false; if (argc < 2) { std::cout << argv[0] << R"( saveMP3Dir[d:\music\] neteaseMusicCacheDir[C:UserszhibinAppDataLocalNeteaseCloudMusicCacheCache] is_override[false])" << std::endl; } switch (argc) { case 4: is_override = true; case 3: baseDir = argv[2]; case 2: destDir = argv[1]; break; default: break; } destDir += "\"; // auto list = mp3FileList(destDir); for (auto& entry : std::filesystem::directory_iterator(baseDir)) if (entry.is_regular_file()) { auto filename = entry.path().filename(); //std::cout << filename.extension(); if (filename.extension().compare(".uc") == 0 || filename.extension().compare(".uc!") == 0) { std::string destFilename = entry.path().filename().replace_extension("mp3").string(); std::cout << entry.path().filename() << filename.extension() ; auto it = find(list.begin(), list.end(), filename.replace_extension().string()); if (it != list.end()) { std::cout << " *** already exists in "<< destDir <<" *** " << ' '; continue; }else std::cout << ' '; auto buff = load_file(entry.path().string()); save_file(destDir + destFilename, xorVector(buff)); //break; //just convert one file. } } } //
#include <iostream> #include <regex> #include <string> #include <fstream> #include <cstdio> #include <string> #include <sstream> #include <streambuf> #include <filesystem> std::vector<std::string> mp3FileList(std::string const& baseDir) { std::vector<std::string> v; for (auto& entry : std::filesystem::directory_iterator(baseDir)) if (entry.is_regular_file()) { auto filename = entry.path().filename().replace_extension(); v.push_back(filename.string()); } return v; } bool save_file(std::string const& filepath, std::vector<std::byte> const& buffer) { std::ofstream ofs(filepath, std::ios::out | std::ios::binary | std::ios::trunc); if (!ofs) throw std::runtime_error(filepath + ": " + "std::strerror(errno)"); if (!ofs.write((char*)buffer.data(), buffer.size())) throw std::runtime_error(filepath + ": " + "std::strerror(errno)"); return true; } std::byte x{ 0xA3 }; std::vector<std::byte> xorVector(std::vector<std::byte>& v) { for (auto& bb : v) { bb ^= x; } return v; } std::vector<std::byte> load_file(std::string const& filepath) { std::ifstream ifs(filepath, std::ios::binary | std::ios::ate); if (!ifs) throw std::runtime_error(filepath + ": " + "std::strerror(errno)"); auto end = ifs.tellg(); ifs.seekg(0, std::ios::beg); auto size = std::size_t(end - ifs.tellg()); if (size == 0) { // avoid undefined behavior std::cout << filepath << " is emtype." << ' '; return {}; } std::vector<std::byte> buffer(size); if (!ifs.read((char*)buffer.data(), buffer.size())) throw std::runtime_error(filepath + ": " + "std::strerror(errno)"); return buffer; } int main(int argc, char** argv) { std::string baseDir = { R"(C:UsersusernameAppDataLocalNeteaseCloudMusicCacheCache)" }; // baseDir = { R"(.)" }; std::string destDir = "d:\music\"; bool is_override = false; if (argc < 2) { std::cout << argv[0] << R"( saveMP3Dir[d:\music\] neteaseMusicCacheDir[C:UserszhibinAppDataLocalNeteaseCloudMusicCacheCache] is_override[false])" << std::endl; } switch (argc) { case 4: is_override = true; case 3: baseDir = argv[2]; case 2: destDir = argv[1]; break; default: break; } destDir += "\"; // auto list = mp3FileList(destDir); for (auto& entry : std::filesystem::directory_iterator(baseDir)) if (entry.is_regular_file()) { auto filename = entry.path().filename(); //std::cout << filename.extension(); if (filename.extension().compare(".uc") == 0 || filename.extension().compare(".uc!") == 0) { std::string destFilename = entry.path().filename().replace_extension("mp3").string(); std::cout << entry.path().filename() << filename.extension() ; auto it = find(list.begin(), list.end(), filename.replace_extension().string()); if (it != list.end()) { std::cout << " *** already exists in "<< destDir <<" *** " << ' '; continue; }else std::cout << ' '; auto buff = load_file(entry.path().string()); save_file(destDir + destFilename, xorVector(buff)); //break; //just convert one file. } } } //
第一步 缓存歌曲
第一步 缓存歌曲
首先打开网易云音乐随便缓存一首需要付费下载的歌曲 比如这一首
如果你想要下载是需要付费的
第二步 找到文件
点开设置->下载设置 找到缓存目录
按照修改日期排序 找到符合修改时间的那一项 后缀名为.uc
的最大的文件 就是加密过后的文件 另外一个应该是歌词文件(在这之前最好先把缓存目录清空)
第三步 解密文件
接着把文件拖到010Edit
里 我们可以查看到如下图所示的数据
我们发现一个很明显的特点——最多的数据是A3 所以可以推测A3就是加密过后的无意义字符0 一般来说音频的加密方式不会太复杂 而最简单的异或加密 异或加密是可逆的
所以只要选中所有的数据 点开菜单->工具->十六进制操作->二进制异或 修改处理数据为无符号 十六进制 然后对A3进行异或
即可对文件进行解密 如下图 解密完成之后字符变得有意义。前三个字节是ID3,这个是MP3文件格式的头部
然后我们保存修改 把文件后缀改为.mp3
用网易云音乐打开 OK 音乐正常播放 破解成功
其他的音乐播放器加密原理大致相同 不会太复杂 大家可以去尝试!