原理:问题:在微信文档中想要查找一些图片发现不能直接浏览都为.dat格式如图
现在通过go语言实现将dat文件转化为jpg和png格式方便直接浏览删除或者保存.结果:
图片被微信采用每个字节异或的方式加密,所以只要再异或同样的密码便得到了原来的字节编码
(异或运算的规则是0⊕0=0,0⊕1=1 ,1⊕0=1,1⊕1=0)
公式:A^密码=B
A^密码 ^密码=A
所以首先我们需要求密码是多少(每个人不相同),但是图片以16进制打开
png图片开头为0x89, 0x50
加密dat(原本为png) 16进制打开:
头两位为 0x32,0xeb
(1) 0x89^密码=0x32
(2) 0x89 ^ 0x89 ^密码 = 密码
结果:(1)替换(2)中的部分 可得 0x89^0x32=密码=0xbb
通过 第二位验证: 0x50 ^ 0xbb=0xeb 正确
所以该图片格式为png,我的密码为0xbb(每个人不一样)
得到密码后,只需要将dat文件读入内存,对每个字节进行异或 *** 作再写入新文件即可.
go语言实现主要步骤: 定义图片类型结构体 及初始化type Dic struct {
name string //名称
firstIndex uint8 //第一个字节
lastIndex uint8 //第二个字节
}
var dicList = []Dic{Dic{".jpg", 0xff, 0xd8},
Dic{".png", 0x89, 0x50},
Dic{".gif", 0x47, 0x49},
Dic{"error", 0x00, 0x00},}
文件结构体:
type FileInfo struct {
filePath string //文件路径
fileName string //文件名称 不包括后缀 .dat
fileSuffix string // 文件后缀
}
//初始化 文件切片
var fileInfoArr = make([]FileInfo, 5)
计算密码
/**
* arr dat文件字节切片
* 返回 密码addcode 类型dic ,错误
*/
func getAddCode(arr []uint8) (addCode uint8, dic Dic, err error) {
//遍历 diclist 看dat原本格式
for _, dic := range dicList {
//第一个字节和字典中固定编码异或得到密码
addCode = arr[0] ^ dic.firstIndex
//判断第二个字节和密码异或是否等于字典的字节 相同则密码正确,不相同则继续循环
if arr[1]^addCode == dic.lastIndex {
return addCode, dic, nil
}
}
//遍历完成循环没有符合的
return 0, dicList[3], errors.New("不是jpg,png,gif")
}
遍历文件夹路径下所有dat文件
func getAllDatFileList(parentPath string) {
parentFileInfo, err := ioutil.ReadDir(parentPath)
if err != nil {
log.Fatalln(err)
}
for _, fi := range parentFileInfo {
if fi.IsDir() {
getAllDatFileList(parentPath + "\" + fi.Name())
} else {
if strings.Contains(fi.Name(), ".dat") {
fileInfoArr = append(fileInfoArr, FileInfo{parentPath,
strings.TrimRight(fi.Name(), ".dat"), ".dat"})
}
}
}
}
异或字符重写文件
func writeXORAddCodeIntoNewFile(arr []uint8, addCode uint8, info FileInfo, dic Dic) {
//生成目标路径
var pos= strings.LastIndex(info.filePath,"\")
var willReplace=info.filePath[pos:]
targetPath := strings.ReplaceAll(info.filePath,willReplace,"\target"+willReplace+"\")
err := os.MkdirAll(targetPath, os.ModePerm)
//打开文件
f, err := os.OpenFile(targetPath+info.fileName+dic.name, os.O_RDWR|os.O_CREATE, 0777)
defer f.Close()
if err != nil {
log.Fatalln(err)
}
//对字节切片每个字节异或
for i, v := range arr {
arr[i] = v ^ addCode
}
//写入文件
f.Write(arr)
}
主要流程
func main() {
start := time.Now()
getAllDatFileList(".\")
var wg sync.WaitGroup
for _, v := range fileInfoArr {
wg.Add(1)
go changeDat(v, &wg)
}
wg.Wait()
end := time.Now()
ms := (end.Sub(start).Milliseconds())
s := (end.Sub(start).Seconds())
fmt.Printf(" 文件数:%d 总共耗时 %d ms (%f s) \n", len(fileInfoArr), ms, s)
}
func changeDat(info FileInfo, wg *sync.WaitGroup) {
defer wg.Done()
data, err := ioutil.ReadFile(info.filePath + "\" + info.fileName + info.fileSuffix)
if err != nil {
fmt.Println(err)
return
}
addCode, dic, err := getAddCode(data)
if err != nil {
fmt.Println(err)
return
}
writeXORAddCodeIntoNewFile(data, addCode, info, dic)
}
全部代码:https://github.com/ygr000/wxwxDatTrans
生成的exe可以直接执行 https://github.com/ygr000/wxwxDatTrans/releases/tag/v1.0.0
或者 csdn下载
初学go,有问题欢迎指正
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)