210 lines
4.1 KiB
Go
210 lines
4.1 KiB
Go
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
|
||
}
|