wechatDataBackup/pkg/wechat/wechatIMGDec.go
2024-08-26 22:56:29 +08:00

210 lines
4.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
}