PC版微信图片导出
PC微信图片存储位置:打开文件夹,FileStorage\Image目录即存储微信接收图片目录
此目录下,图片按年月进行存储,格式都为.dat文件.
经过测试发现,相同格式图片比如jpg或png,dat文件整体16进制内容格式,和jpg,png图片格式类似.且相同格式图片dat文件头部字节一致.
dat文件=原始文件+某种运算
其实网上有很多关于产生dat文件运算分析,结果就是:异或运算
dat文件=原始文件+异或运算
所以进行dat文件还原就简单了:将dat文件头两个字节和jpg/png/gif文件的格式头两个字节进行异或,如果头两个字节异或相等,就表明dat文件的原始文件为此种格式.代码如下:
/// @brief dat文件转换成jpg/gif/png文件格式
/// @param v_cstrDatPath dat文件路径
/// @param v_cstrImagePath 导出图片路径
/// @note dat文件内容为图片文件根据某个值进行异或,这个值直接通过异或jpg/png/gif的文件头两位即可获取
void CExportImagesDlg::DatConverImage(const CString& v_cstrDatPath, const CString& v_cstrImagePath)
{
BYTE byJPG1 = 0xFF;
BYTE byJPG2 = 0xD8;
BYTE byGIF1 = 0x47;
BYTE byGIF2 = 0x49;
BYTE byPNG1 = 0x89;
BYTE byPNG2 = 0x50;
HANDLE hDatFile = INVALID_HANDLE_VALUE;
HANDLE hImageFile = INVALID_HANDLE_VALUE;
CString cstrImageFile(v_cstrImagePath);
do
{
hDatFile = CreateFile(v_cstrDatPath, GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (INVALID_HANDLE_VALUE == hDatFile)
break;
// 读取内容前2个字节
BYTE byBuf[64*1024] = { 0 };
DWORD dwReadLen = 0;
BOOL bRet = ReadFile(hDatFile, byBuf, 2, &dwReadLen, NULL);
if (!bRet || 2 != dwReadLen)
break;
// 开始异或判断
BYTE byJ1 = byJPG1 ^ byBuf[0];
BYTE byJ2 = byJPG2 ^ byBuf[1];
BYTE byG1 = byGIF1 ^ byBuf[0];
BYTE byG2 = byGIF2 ^ byBuf[1];
BYTE byP1 = byPNG1 ^ byBuf[0];
BYTE byP2 = byPNG2 ^ byBuf[1];
// 判断异或值
BYTE byXOR = 0;
if (byJ1 == byJ2)
{
cstrImageFile += _T(".jpg");
byXOR = byJ1;
}
else if (byG1 == byG2)
{
cstrImageFile += _T(".gif");
byXOR = byG1;
}
else if (byP1 == byP2)
{
cstrImageFile += _T(".png");
byXOR = byP1;
}
else
break;
SetFilePointer(hDatFile, 0, NULL, FILE_BEGIN); // 设置到文件头开始
hImageFile = CreateFile(cstrImageFile, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
if (INVALID_HANDLE_VALUE == hImageFile)
break;
DWORD dwWriteLen = 0;
do
{
dwReadLen = 0;
bRet = ReadFile(hDatFile, byBuf, 64 * 1024, &dwReadLen, NULL);
if (!bRet)
break;
XOR(byBuf, dwReadLen, byXOR);
bRet = WriteFile(hImageFile, byBuf, dwReadLen, &dwWriteLen, NULL);
if (!bRet || dwReadLen != dwWriteLen)
break;
} while (dwReadLen == 64*1024);
} while (FALSE);
if (INVALID_HANDLE_VALUE != hDatFile)
{
CloseHandle(hDatFile);
hDatFile = INVALID_HANDLE_VALUE;
}
if (INVALID_HANDLE_VALUE != hImageFile)
{
CloseHandle(hImageFile);
hImageFile = INVALID_HANDLE_VALUE;
}
}
void CExportImagesDlg::XOR(BYTE* v_pbyBuf, DWORD v_dwBufLen, BYTE byXOR)
{
for (int i = 0; i < v_dwBufLen; i++)
{
v_pbyBuf[i] ^= byXOR;
}
}