wechatDataBackup/pkg/wechat/wechatIMGDec.go

210 lines
4.1 KiB
Go
Raw Normal View History

2024-08-26 22:56:29 +08:00
package wechat
import (
"bufio"
"encoding/hex"
"errors"
"fmt"
"io"
"log"
"os"
"path/filepath"
"sync"
"time"
)
/*
from: https://github.com/liuggchen/wechatDatDecode.git
*/
var imagePrefixBtsMap = make(map[string][]byte)
func DecryptDatByDir(inDir, outDir string) error {
startTime := time.Now()
f, er := os.Open(inDir)
if er != nil {
fmt.Println(er.Error())
return er
}
readdir, er := f.Readdir(0)
if er != nil {
fmt.Println(er.Error())
}
if stat, er := os.Stat(outDir); os.IsNotExist(er) {
er := os.MkdirAll(outDir, 0755)
if er != nil {
return er
}
} else if !stat.IsDir() {
return errors.New(outDir + "is file")
}
var taskChan = make(chan os.FileInfo, 100)
go func() {
for _, info := range readdir {
taskChan <- info
}
close(taskChan)
}()
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for info := range taskChan {
handlerOne(info, inDir, outDir)
}
}()
}
wg.Wait()
t := time.Since(startTime).Seconds()
log.Printf("\nfinished time= %v s\n", t)
return nil
}
func DecryptDat(inFile string, outFile string) error {
sourceFile, err := os.Open(inFile)
if err != nil {
log.Println(err.Error())
return err
}
var preTenBts = make([]byte, 10)
_, _ = sourceFile.Read(preTenBts)
decodeByte, _, er := findDecodeByte(preTenBts)
if er != nil {
log.Println(er.Error())
return err
}
distFile, er := os.Create(outFile)
if er != nil {
log.Println(er.Error())
return err
}
writer := bufio.NewWriter(distFile)
_, _ = sourceFile.Seek(0, 0)
var rBts = make([]byte, 1024)
for {
n, er := sourceFile.Read(rBts)
if er != nil {
if er == io.EOF {
break
}
log.Println("error: ", er.Error())
return err
}
for i := 0; i < n; i++ {
_ = writer.WriteByte(rBts[i] ^ decodeByte)
}
}
_ = writer.Flush()
_ = distFile.Close()
_ = sourceFile.Close()
// fmt.Println("output file", distFile.Name())
return nil
}
func handlerOne(info os.FileInfo, dir string, outputDir string) {
if info.IsDir() || filepath.Ext(info.Name()) != ".dat" {
return
}
fmt.Println("find file: ", info.Name())
fPath := dir + "/" + info.Name()
sourceFile, err := os.Open(fPath)
if err != nil {
fmt.Println(err.Error())
return
}
var preTenBts = make([]byte, 10)
_, _ = sourceFile.Read(preTenBts)
decodeByte, _, er := findDecodeByte(preTenBts)
if er != nil {
fmt.Println(er.Error())
return
}
distFile, er := os.Create(outputDir + "/" + info.Name())
if er != nil {
fmt.Println(er.Error())
return
}
writer := bufio.NewWriter(distFile)
_, _ = sourceFile.Seek(0, 0)
var rBts = make([]byte, 1024)
for {
n, er := sourceFile.Read(rBts)
if er != nil {
if er == io.EOF {
break
}
fmt.Println("error: ", er.Error())
return
}
for i := 0; i < n; i++ {
_ = writer.WriteByte(rBts[i] ^ decodeByte)
}
}
_ = writer.Flush()
_ = distFile.Close()
fmt.Println("output file", distFile.Name())
}
func init() {
//JPEG (jpg)文件头FFD8FF
//PNG (png)文件头89504E47
//GIF (gif)文件头47494638
//TIFF (tif)文件头49492A00
//Windows Bitmap (bmp)文件头424D
const (
Jpeg = "FFD8FF"
Png = "89504E47"
Gif = "47494638"
Tif = "49492A00"
Bmp = "424D"
)
JpegPrefixBytes, _ := hex.DecodeString(Jpeg)
PngPrefixBytes, _ := hex.DecodeString(Png)
GifPrefixBytes, _ := hex.DecodeString(Gif)
TifPrefixBytes, _ := hex.DecodeString(Tif)
BmpPrefixBytes, _ := hex.DecodeString(Bmp)
imagePrefixBtsMap = map[string][]byte{
".jpeg": JpegPrefixBytes,
".png": PngPrefixBytes,
".gif": GifPrefixBytes,
".tif": TifPrefixBytes,
".bmp": BmpPrefixBytes,
}
}
func findDecodeByte(bts []byte) (byte, string, error) {
for ext, prefixBytes := range imagePrefixBtsMap {
deCodeByte, err := testPrefix(prefixBytes, bts)
if err == nil {
return deCodeByte, ext, err
}
}
return 0, "", errors.New("decode fail")
}
func testPrefix(prefixBytes []byte, bts []byte) (deCodeByte byte, error error) {
var initDecodeByte = prefixBytes[0] ^ bts[0]
for i, prefixByte := range prefixBytes {
if b := prefixByte ^ bts[i]; b != initDecodeByte {
return 0, errors.New("no")
}
}
return initDecodeByte, nil
}