如何让C++读取的外部可执行文件资源数据转为可读格式?
问题描述
我尝试用C++读取外部可执行文件的资源,使用Resource Tuner工具查看时,资源数据呈现为可读格式。我编写了如下代码:
std::filesystem::path exeSignalPath{ LR"__(c:\Users\user\AppData\Local\Programs\signal-desktop\Signal.exe)__" }; const HMODULE hExe = ::LoadLibrary(exeSignalPath.c_str()); if (NULL == hExe) { return 0; } const HRSRC handleIntegrity = ::FindResourceW(hExe, L"ElectronAsar", L"Integrity"); if (handleIntegrity == NULL) { return 0; } LPVOID lpResLock = ::LockResource(handleIntegrity); if (NULL == lpResLock) { ::FreeResource(handleIntegrity); return 0; } DWORD resorcesSize = ::SizeofResource(hExe, handleIntegrity); if (0 == resorcesSize) { UnlockResource(handleIntegrity); ::FreeResource(handleIntegrity); return 0; } std::string res(std::bit_cast<uint8_t*>(lpResLock), std::bit_cast<uint8_t*>(lpResLock) + resorcesSize);
但运行后得到的结果字符串是二进制数据,请问有没有办法将这些数据转换为像Resource Tuner中那样的可读格式?
解决方案
- 检查资源编码格式:Resource Tuner显示的可读内容大概率是UTF-16LE编码(Windows资源默认常用的Unicode编码),直接转
std::string会导致二进制显示或乱码,可转成std::wstring:// 资源字节数除以2得到UTF-16字符数 std::wstring res(reinterpret_cast<wchar_t*>(lpResLock), resorcesSize / sizeof(wchar_t)); - 若资源是Base64编码的二进制数据(Electron的Integrity资源常为此类),需对读取到的二进制做Base64解码,可使用Windows API
CryptStringToBinaryW(需链接crypt32.lib):DWORD decodedSize = 0; // 先获取解码后的数据长度 if (CryptStringToBinaryW(reinterpret_cast<LPCWSTR>(lpResLock), resorcesSize, CRYPT_STRING_BASE64, nullptr, &decodedSize, nullptr, nullptr)) { std::vector<uint8_t> decodedData(decodedSize); if (CryptStringToBinaryW(reinterpret_cast<LPCWSTR>(lpResLock), resorcesSize, CRYPT_STRING_BASE64, decodedData.data(), &decodedSize, nullptr, nullptr)) { std::string readableStr(reinterpret_cast<char*>(decodedData.data()), decodedSize); // readableStr即为可读格式内容 } } - 修正资源释放逻辑:从Windows XP开始,
LockResource返回的指针无需解锁,FreeResource也不再需要调用,只需用FreeLibrary释放加载的模块即可,删除代码中多余的UnlockResource和FreeResource调用。
内容的提问来源于stack exchange,提问作者Capitone Moguchi
相关产品推荐
相关产品推荐

