go实现文档中保存的微信图片.dat格式解密为图片

go实现文档中保存的微信图片.dat格式解密为图片,第1张

go实现文档中保存的微信图片.dat格式解密为可视图片(jpg,png)

问题:在微信文档中想要查找一些图片发现不能直接浏览都为.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,有问题欢迎指正

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/996337.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-21
下一篇 2022-05-21

发表评论

登录后才能评论

评论列表(0条)

保存