前言
關於異或值怎麼計算
代碼
第二種方式,適合不懂怎麼計算,想直接用的代碼
前言
偶然看到有可以解密微信dat的文檔,上網查了查,找到了一篇可以用的文章,不過轉換過程代碼是有問題的,在這裡改了下發布上來。
提取碼:ymw6
關於異或值怎麼計算
首先使用十六進制器打開微信dat文件,顯示如下
jpg圖片文件頭一般為FF D8 開頭的,所以此處使用科學計算器,計算異或值
計算後的值
所以此處異或值就是0x9D
代碼
以下是java代碼,創建一個weChatImgRevert .java後複製進去就好啦。
此處的jdk版本需要1.8以上…,另外三個參數需要改成自己的哦~
<code>package main.java.com.example.demo;import
java.io.*;import
java.util.Arrays;import
java.util.HashMap;import
java.util.Map;import
java.util.concurrent.atomic.AtomicReference;public
class
weChatImgRevert
{public
static
void
main
(String[] args)
{ String path ="C:\\Users\\Administrator\\Documents\\WeChat Files\\xxx\\FileStorage\\Image\\2019-07"
; String targetPath ="D:\\weChat\\2019-07"
;int
xor
=0xCB
; convert(path, targetPath,xor
); }private
static
void
convert
(String path, String targetPath,
int
xor
) { File[] file =new
File(path).listFiles();if
(file == null) {return
; }int
size = file.length; System.out.println("總共"
+ size +"個文件"
); AtomicReference integer =new
AtomicReference<>(0
); Arrays.stream(file).parallel().forEach(file1 -> {try
(InputStream reader =new
FileInputStream(file1); OutputStream writer =new
FileOutputStream(targetPath + file1.getName().split("\\."
)[0
] +".jpg"
)) { byte[] bytes =new
byte[1024
*10
];int
b;while
((b = reader.read(bytes)) !=-1
) {for
(int
i =0
; i < bytes.length; i++) { bytes[i] = (byte) (int
) (bytes[i] ^xor
);if
(i == (b -1
)) {break
; } } writer.write(bytes,0
, b); writer.flush(); } integer.set
(integer.get() +1
); System.out.println(file1.getName() +"(大小:"
+ ((double
) file1.length() /1000
) +"kb),進度:"
+ integer.get() +"/"
+ size); }catch
(Exception e) { e.printStackTrace(); } }); System.out.println("解析完畢!"
); }private
static
int
getXor
(String PhotoPath)
{ File file =new
File(PhotoPath);try
(InputStream reader =new
FileInputStream(file)) {int
[] xors =new
int
[4
]; xors[0
] = reader.read() &0xFF
^0xFF
; xors[1
] = reader.read() &0xFF
^0xD8
; reader.skip(file.length() -1
); xors[2
] = reader.read() &0xFF
^0xFF
; xors[3
] = reader.read() &0xFF
^0xD9
; Mapmap
=new
HashMap<>();for
(int
xor
: xors) {if
(map
.containsKey(xor
)) {map
.put(xor
,map
.get(xor
) +1
); }else
{map
.put(xor
,1
); } }return
map
.values().stream().max(Integer::compareTo).get(); }catch
(Exception e) { e.printStackTrace(); }return
0
; } }/<code>
執行main方法後就可以在目標文件夾中去看轉換後的圖片了
以下是轉換後的效果圖片:
第二種方式,適合不懂怎麼計算,想直接用的代碼
以下是java代碼,創建一個WxChatImgRevert.java後複製進去就好啦。
此處的jdk版本需要1.8以上…,另外兩個參數需要改成自己的哦~
此處的原理是判斷圖片文件的十六進制特徵碼。
<code>package main.java.com.example.demo;import
java.io.*;import
java.util.Arrays;import
java.util.HashMap;import
java.util.Map;import
java.util.concurrent.atomic.AtomicInteger;import
java.util.concurrent.atomic.AtomicReference;public
class
WxChatImgRevert2 {public
static
void
main(String
[] args) {String
path ="C:\\Users\\Administrator\\Documents\\WeChat Files\\xxx\\FileStorage"
;String
targetPath ="D:\\weChat\\temp"
; convert(path, targetPath); }private
static
void
convert(String
path,String
targetPath) { File[] file =new
File(path).listFiles();if
(file ==null
) {return
; } int size = file.length; System.out.println("總共"
+ size +"個文件"
); AtomicReference integer =new
AtomicReference<>(0
); AtomicInteger x =new
AtomicInteger();for
(File file1 : file) {if
(file1.isFile()) {Object
[] xori = getXor(file1);if
(xori !=null
&& xori[1
] !=null
){ x.set((int)xori[1
]); }break
; } } Arrays.stream(file).parallel().forEach(file1 -> {if
(file1.isDirectory()) {String
[] newTargetPath = file1.getPath().split("/|\\"
); File targetFile =new
File(targetPath+File.separator+newTargetPath[newTargetPath.length -1
]);if
(!targetFile.exists()) { targetFile.mkdirs(); } convert(file1.getPath(),targetPath+File.separator+newTargetPath[newTargetPath.length -1
]);return
; }Object
[] xor = getXor(file1);if
(x.get() ==0
&& xor[1
] !=null
&& (int) xor[1
] !=0
) { x.set((int) xor[1
]); } xor[1
] = xor[1
] ==null
? x.get() : xor[1
];try
(InputStream reader =new
FileInputStream(file1); OutputStream writer =new
FileOutputStream(targetPath + File.separator + file1.getName().split("\\."
)[0
] + (xor[0
] !=null
?"."
+ xor[0
] :""
))) { byte[] bytes =new
byte[1024
*10
]; int b;while
((b = reader.read(bytes)) !=-1
) {for
(int i =0
; i < bytes.length; i++) { bytes[i] = (byte) (int) (bytes[i] ^ (int) xor[1
]);if
(i == (b -1
)) {break
; } } writer.write(bytes,0
, b); writer.flush(); } integer.set(integer.get() +1
); System.out.println(file1.getName() +"(大小:"
+ ((double) file1.length() /1000
) +"kb,異或值:"
+ xor[1
] +"),"
+"進度:"
+ integer.get() +"/"
+ size); }catch
(Exception e) { e.printStackTrace(); } }); System.out.println("解析完畢!"
); }private
static
Object
[] getXor(File file) {Object
[] xor =null
;if
(file !=null
) { byte[] bytes =new
byte[4
];try
(InputStream reader =new
FileInputStream(file)) { reader.read(bytes,0
, bytes.length); }catch
(Exception e) { e.printStackTrace(); } xor = getXor(bytes); }return
xor; }private
static
Object
[] getXor(byte[] bytes) {Object
[] xorType =new
Object
[2
]; int[] xors =new
int[3
];for
(Map.Entry<String
,String
>type
: FILE_TYPE_MAP.entrySet()) {String
[] hex = {String
.valueOf(type
.getKey().charAt(0
)) +type
.getKey().charAt(1
),String
.valueOf(type
.getKey().charAt(2
)) +type
.getKey().charAt(3
),String
.valueOf(type
.getKey().charAt(4
)) +type
.getKey().charAt(5
) }; xors[0
] = bytes[0
] &0xFF
^ Integer.parseInt(hex[0
],16
); xors[1
] = bytes[1
] &0xFF
^ Integer.parseInt(hex[1
],16
); xors[2
] = bytes[2
] &0xFF
^ Integer.parseInt(hex[2
],16
);if
(xors[0
] == xors[1
] && xors[1
] == xors[2
]) { xorType[0
] =type
.getValue(); xorType[1
] = xors[0
];break
; } }return
xorType; }private
finalstatic
Map<String
,String
> FILE_TYPE_MAP =new
HashMap<String
,String
>();static
{ getAllFileType(); }private
static
void
getAllFileType() { FILE_TYPE_MAP.put("ffd8ffe000104a464946"
,"jpg"
); FILE_TYPE_MAP.put("89504e470d0a1a0a0000"
,"png"
); FILE_TYPE_MAP.put("47494638396126026f01"
,"gif"
); FILE_TYPE_MAP.put("49492a00227105008037"
,"tif"
); FILE_TYPE_MAP.put("424d228c010000000000"
,"bmp"
); FILE_TYPE_MAP.put("424d8240090000000000"
,"bmp"
); FILE_TYPE_MAP.put("424d8e1b030000000000"
,"bmp"
); FILE_TYPE_MAP.put("41433130313500000000"
,"dwg"
); FILE_TYPE_MAP.put("3c21444f435459504520"
,"html"
); FILE_TYPE_MAP.put("3c21646f637479706520"
,"htm"
); FILE_TYPE_MAP.put("48544d4c207b0d0a0942"
,"css"
); FILE_TYPE_MAP.put("696b2e71623d696b2e71"
,"js"
); FILE_TYPE_MAP.put("7b5c727466315c616e73"
,"rtf"
); FILE_TYPE_MAP.put("38425053000100000000"
,"psd"
); FILE_TYPE_MAP.put("46726f6d3a203d3f6762"
,"eml"
); FILE_TYPE_MAP.put("d0cf11e0a1b11ae10000"
,"doc"
); FILE_TYPE_MAP.put("d0cf11e0a1b11ae10000"
,"vsd"
); FILE_TYPE_MAP.put("5374616E64617264204A"
,"mdb"
); FILE_TYPE_MAP.put("252150532D41646F6265"
,"ps"
); FILE_TYPE_MAP.put("255044462d312e360d25"
,"pdf"
); FILE_TYPE_MAP.put("2e524d46000000120001"
,"rmvb"
); FILE_TYPE_MAP.put("464c5601050000000900"
,"flv"
); FILE_TYPE_MAP.put("00000020667479706973"
,"mp4"
); FILE_TYPE_MAP.put("49443303000000000f76"
,"mp3"
); FILE_TYPE_MAP.put("000001ba210001000180"
,"mpg"
); FILE_TYPE_MAP.put("3026b2758e66cf11a6d9"
,"wmv"
); FILE_TYPE_MAP.put("524946464694c9015741"
,"wav"
); FILE_TYPE_MAP.put("52494646d07d60074156"
,"avi"
); FILE_TYPE_MAP.put("4d546864000000060001"
,"mid"
); FILE_TYPE_MAP.put("504b0304140000000800"
,"zip"
); FILE_TYPE_MAP.put("526172211a0700cf9073"
,"rar"
); FILE_TYPE_MAP.put("235468697320636f6e66"
,"ini"
); FILE_TYPE_MAP.put("504b03040a0000000000"
,"jar"
); FILE_TYPE_MAP.put("4d5a9000030000000400"
,"exe"
); FILE_TYPE_MAP.put("3c25402070616765206c"
,"jsp"
); FILE_TYPE_MAP.put("4d616e69666573742d56"
,"mf"
); FILE_TYPE_MAP.put("3c3f786d6c2076657273"
,"xml"
); FILE_TYPE_MAP.put("efbbbf2f2a0d0a53514c"
,"sql"
); FILE_TYPE_MAP.put("7061636b616765207765"
,"java"
); FILE_TYPE_MAP.put("406563686f206f66660d"
,"bat"
); FILE_TYPE_MAP.put("1f8b0800000000000000"
,"gz"
); FILE_TYPE_MAP.put("6c6f67346a2e726f6f74"
,"properties"
); FILE_TYPE_MAP.put("cafebabe0000002e0041"
,"class"
); FILE_TYPE_MAP.put("49545346030000006000"
,"chm"
); FILE_TYPE_MAP.put("04000000010000001300"
,"mxp"
); FILE_TYPE_MAP.put("504b0304140006000800"
,"docx"
); FILE_TYPE_MAP.put("d0cf11e0a1b11ae10000"
,"wps"
); FILE_TYPE_MAP.put("6431303a637265617465"
,"torrent"
); FILE_TYPE_MAP.put("494d4b48010100000200"
,"264"
); FILE_TYPE_MAP.put("6D6F6F76"
,"mov"
); FILE_TYPE_MAP.put("FF575043"
,"wpd"
); FILE_TYPE_MAP.put("CFAD12FEC5FD746F"
,"dbx"
); FILE_TYPE_MAP.put("2142444E"
,"pst"
); FILE_TYPE_MAP.put("AC9EBD8F"
,"qdf"
); FILE_TYPE_MAP.put("E3828596"
,"pwl"
); FILE_TYPE_MAP.put("2E7261FD"
,"ram"
); } }/<code>
簡要介紹下小工具:
打開小工具後的頁面是這樣子的,如果沒有安裝jdk8的話,可以在這裡下載安裝,不然是運行不了的
微信的數據存儲地址一般是:C:\Users\Administrator\Documents\WeChat Files\xxx
可以整個扔進去,但是要注意,輸出地址一定不能和存儲地址相同,最好不要在同一個文件夾裡面!!!
本質上,第一個是讀取操作,第二個是寫入操作,讀取並不會破壞原文件,但是寫入如果是同一個文件夾,並且存在同名文件,會被覆蓋掉。轉換後就是在你指定的輸出目錄裡面
s:小工具是花了一晚上隨手寫的,樓主估計都找不到源碼在哪裡了,所以將就著用吧。