Bläddra i källkod

v0.9.6.4 Release!
1.新增部分消息容错。
2.新增已删除但有消息记录的人员记录导出。

Suxue 1 år sedan
förälder
incheckning
0f70591cdb
10 ändrade filer med 208 tillägg och 27 borttagningar
  1. 77 17
      Export/HtmlExport.cs
  2. 4 1
      Helpers/DevicePathMapper.cs
  3. 9 0
      Model/WXModel.cs
  4. 1 1
      Pages/CreateWork.xaml
  5. 21 0
      Pages/CreateWork.xaml.cs
  6. 72 0
      Pages/Workspace.xaml.cs
  7. 1 1
      README.md
  8. 6 0
      WXUserReader.cs
  9. 14 4
      WXWorkspace.cs
  10. 3 3
      WechatBakTool.csproj

+ 77 - 17
Export/HtmlExport.cs

@@ -12,6 +12,7 @@ using Newtonsoft.Json;
 using WechatBakTool.ViewModel;
 using System.Security.Policy;
 using System.Windows;
+using System.Xml.Linq;
 
 namespace WechatBakTool.Export
 {
@@ -157,31 +158,90 @@ namespace WechatBakTool.Export
                                         }
 
                                         HtmlBody += string.Format("<p class=\"content\">{0}</p>", title);
-                                        findNode = xmlObj.DocumentElement.SelectNodes("/msg/appmsg/recorditem");
-                                        if (findNode != null)
+                                        try
                                         {
-                                            if (findNode.Count > 0)
+                                            findNode = xmlObj.DocumentElement.SelectNodes("/msg/appmsg/recorditem");
+                                            if (findNode != null)
                                             {
-                                                XmlDocument itemObj = new XmlDocument();
-                                                itemObj.LoadXml(findNode[0]!.InnerText);
-                                                XmlNodeList? itemNode = itemObj.DocumentElement.SelectNodes("/recordinfo/datalist/dataitem");
-                                                if (itemNode.Count > 0)
+                                                if (findNode.Count > 0)
                                                 {
-                                                    foreach (XmlNode node in itemNode)
+                                                    XmlDocument itemObj = new XmlDocument();
+                                                    itemObj.LoadXml(findNode[0]!.InnerText);
+                                                    XmlNodeList? itemNode = itemObj.DocumentElement.SelectNodes("/recordinfo/datalist/dataitem");
+                                                    if (itemNode.Count > 0)
                                                     {
-                                                        string nodeMsg;
-                                                        string name = node["sourcename"].InnerText;
-                                                        if (node.Attributes["datatype"].InnerText == "1")
-                                                            nodeMsg = node["datadesc1"].InnerText;
-                                                        else if (node.Attributes["datatype"].InnerText == "2")
-                                                            nodeMsg = "不支持的消息";
-                                                        else
-                                                            nodeMsg = node["datatitle"].InnerText;
-                                                        HtmlBody += string.Format("<p class=\"content\">{0}:{1}</p>", name, nodeMsg);
+                                                        foreach (XmlNode node in itemNode)
+                                                        {
+                                                            string nodeMsg;
+                                                            string name = node["sourcename"].InnerText;
+                                                            if (node.Attributes["datatype"].InnerText == "1")
+                                                                nodeMsg = node["datadesc1"].InnerText;
+                                                            else if (node.Attributes["datatype"].InnerText == "2")
+                                                                nodeMsg = "不支持的消息";
+                                                            else
+                                                                nodeMsg = node["datatitle"].InnerText;
+                                                            HtmlBody += string.Format("<p class=\"content\">{0}:{1}</p>", name, nodeMsg);
+                                                        }
                                                     }
                                                 }
                                             }
                                         }
+                                        catch
+                                        {
+                                            HtmlBody += string.Format("<p class=\"content\">{0}</p>", "解析异常");
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                        else if (msg.SubType == 57)
+                        {
+                            using (var decoder = LZ4Decoder.Create(true, 64))
+                            {
+                                byte[] target = new byte[10240];
+                                int res = 0;
+                                if (msg.CompressContent != null)
+                                    res = LZ4Codec.Decode(msg.CompressContent, 0, msg.CompressContent.Length, target, 0, target.Length);
+
+                                byte[] data = target.Skip(0).Take(res).ToArray();
+                                string xml = Encoding.UTF8.GetString(data);
+                                if (!string.IsNullOrEmpty(xml))
+                                {
+                                    xml = xml.Replace("\n", "");
+                                    XmlDocument xmlObj = new XmlDocument();
+                                    xmlObj.LoadXml(xml);
+                                    if (xmlObj.DocumentElement != null)
+                                    {
+                                        string title = "";
+                                        XmlNodeList? findNode = xmlObj.DocumentElement.SelectNodes("/msg/appmsg/title");
+                                        if (findNode != null)
+                                        {
+                                            if (findNode.Count > 0)
+                                            {
+                                                title = findNode[0]!.InnerText;
+                                            }
+                                        }
+
+                                        HtmlBody += string.Format("<p class=\"content\">{0}</p>", title);
+
+                                        XmlNode? type = xmlObj.DocumentElement.SelectSingleNode("/msg/appmsg/refermsg/type");
+                                        if(type != null)
+                                        {
+                                            XmlNode? source = xmlObj.DocumentElement.SelectSingleNode("/msg/appmsg/refermsg/displayname");
+                                            XmlNode? text = xmlObj.DocumentElement.SelectSingleNode("/msg/appmsg/refermsg/content");
+                                            if(type.InnerText == "1" && source != null && text != null)
+                                            {
+                                                HtmlBody += string.Format("<p class=\"content\">[引用]{0}:{1}</p>", source.InnerText, text.InnerText);
+                                            }
+                                            else if(type.InnerText != "1" && source != null && text != null)
+                                            {
+                                                HtmlBody += string.Format("<p class=\"content\">[引用]{0}:非文本消息类型-{1}</p>", source.InnerText, type);
+                                            }
+                                            else
+                                            {
+                                                HtmlBody += string.Format("<p class=\"content\">未知的引用消息</p>");
+                                            }
+                                        }
                                     }
                                 }
                             }

+ 4 - 1
Helpers/DevicePathMapper.cs

@@ -15,7 +15,10 @@ namespace WechatBakTool.Helpers
 
         public static string FromDevicePath(string devicePath)
         {
-            var drive = Array.Find(DriveInfo.GetDrives(), d => devicePath.StartsWith(d.GetDevicePath(), StringComparison.InvariantCultureIgnoreCase));
+            var drive = Array.Find(
+                DriveInfo.GetDrives(), d =>
+                devicePath.StartsWith(d.GetDevicePath() + "\\", StringComparison.InvariantCultureIgnoreCase)
+            );
             return drive != null ?
                 devicePath.ReplaceFirst(drive.GetDevicePath(), drive.GetDriveLetter()) :
                 null;

+ 9 - 0
Model/WXModel.cs

@@ -158,6 +158,15 @@ namespace WechatBakTool.Model
         public string Reserved0 { get; set; } = "";
     }
 
+    public class WXContactHT
+    {
+        public string UserName { get; set; } = "";
+        public string NickName { get; set; } = "";
+        public string LastMsg { get; set; } = "";
+        public int FileCount { get; set; } = 1;
+        public string AvatarString { get; set; } = "";
+        public bool Hidden { get; set; } = false;
+    }
     [Table("Contact")]
     public class WXContact
     {

+ 1 - 1
Pages/CreateWork.xaml

@@ -39,7 +39,7 @@
         </Button>
         <Label Margin="210,350,0,0" Content="其他选项:" FontWeight="Bold" HorizontalAlignment="Left" VerticalAlignment="Top"/>
         <CheckBox Margin="215,380,0,0" Content="打包资源文件夹(功能规划中)" IsEnabled="False" HorizontalAlignment="Left" VerticalAlignment="Top" />
-        <CheckBox Margin="215,405,0,0" Content="手动模式(功能规划中)" IsEnabled="False" HorizontalAlignment="Left" VerticalAlignment="Top" />
+        <CheckBox Name="cb_manual" Checked="cb_manual_Checked"  Margin="215,405,0,0" Content="手动模式" Visibility="Visible" HorizontalAlignment="Left" VerticalAlignment="Top" />
         <Label Name="lab_status" Content="{Binding LabelStatus}" HorizontalAlignment="Left" Margin="30,450,0,0" VerticalAlignment="Top"/>
     </Grid>
 </Page>

+ 21 - 0
Pages/CreateWork.xaml.cs

@@ -97,6 +97,7 @@ namespace WechatBakTool.Pages
         private void btn_create_worksapce_Click(object sender, RoutedEventArgs e)
         {
             ViewModel.IsEnable = false;
+
             Task.Run(() => {
                 if (ViewModel.KeyType != -1)
                 {
@@ -147,5 +148,25 @@ namespace WechatBakTool.Pages
                 ViewModel.IsEnable = true;
             });
         }
+
+        private void cb_manual_Checked(object sender, RoutedEventArgs e)
+        {
+            MessageBox.Show("该功能仅限用于网络安全研究用途使用,红队同学请在合规授权下进行相关操作","重要提醒!!!!!!!!!");
+            if (MessageBox.Show("我确认获取到合规授权,仅用于网络安全用途使用", "信息确认", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
+            {
+                if (File.Exists("auth.txt"))
+                {
+
+                }
+                else
+                {
+                    MessageBox.Show("未完成声明文件,请先确认声明", "错误");
+                }
+            }
+            else
+            {
+                cb_manual.IsChecked = false;
+            }
+        }
     }
 }

+ 72 - 0
Pages/Workspace.xaml.cs

@@ -25,6 +25,8 @@ using WordCloudSharp;
 using System.Drawing;
 using System.Windows.Controls;
 using System.Text.RegularExpressions;
+using Newtonsoft.Json;
+using System.Drawing.Imaging;
 
 namespace WechatBakTool.Pages
 {
@@ -90,6 +92,21 @@ namespace WechatBakTool.Pages
                 findName = "";
 
             ViewModel.Contacts = UserReader.GetWXContacts(findName);
+            // 保底回落搜索已删除人员
+            if(ViewModel.Contacts.Count == 0)
+            {
+                var i = UserReader.GetWXMsgs(txt_find_user.Text);
+                if (i != null)
+                {
+                    var g = i.GroupBy(x => x.StrTalker);
+                    ViewModel.Contacts = new System.Collections.ObjectModel.ObservableCollection<WXContact>();
+                    foreach (var x in g)
+                    {
+                        string name = x.Key;
+                        ViewModel.Contacts.Add(new WXContact() { UserName = name, NickName = name });
+                    }
+                }
+            }
         }
 
         private void txt_find_user_GotFocus(object sender, RoutedEventArgs e)
@@ -270,6 +287,61 @@ namespace WechatBakTool.Pages
                     MessageBox.Show("用户所有表情预下载完毕");
                 });
             }
+            /*
+            if (UserReader != null && ViewModel.WXContact != null)
+            {
+                Task.Run(() =>
+                {
+                    List<WXMsg> msgs = UserReader.GetWXMsgs(ViewModel.WXContact.UserName).ToList();
+                    List<WXContactHT> users = new List<WXContactHT>();
+                    if (File.Exists("WXContact.json"))
+                    {
+                        string text = File.ReadAllText("WXContact.json");
+                        text = text.Substring(8, text.Length - 8);
+                        users = JsonConvert.DeserializeObject<List<WXContactHT>>(text);
+                    }
+
+                    int i = 1; int all = 1;
+                    List<WXMsg> tmp = new List<WXMsg>();
+                    foreach (WXMsg m in msgs)
+                    {
+                        m.BytesExtra = null;
+                        tmp.Add(m);
+                        if (all % 10000 == 0)
+                        {
+                            File.WriteAllText(ViewModel.WXContact.UserName + "-" + i.ToString() + ".json", string.Format("showMsg({0})", JsonConvert.SerializeObject(tmp)));
+                            tmp.Clear();
+                            i++;
+                        }
+                        all++;
+                    }
+
+                    if (users!.Find(x => x.UserName == ViewModel.WXContact.UserName) == null)
+                    {
+                        WXContactHT html = new WXContactHT();
+                        html.NickName = ViewModel.WXContact.NickName;
+                        html.UserName = ViewModel.WXContact.UserName;
+                        html.LastMsg = ViewModel.WXContact.LastMsg;
+                        if (ViewModel.WXContact.Avatar != null)
+                        {
+                            using (var ms = new MemoryStream())
+                            {
+                                ViewModel.WXContact.Avatar.StreamSource.CopyTo(ms);
+                                byte[] bytes = new byte[ms.Length];
+                                ms.Write(bytes, 0, bytes.Length);
+                                html.AvatarString = Convert.ToBase64String(bytes);
+                            }
+                        }
+                        html.FileCount = i;
+                        users.Add(html);
+                    }
+
+                    File.WriteAllText(ViewModel.WXContact.UserName + "-" + i.ToString() + ".json", string.Format("showMsg({0})", JsonConvert.SerializeObject(tmp)));
+                    File.WriteAllText("WXContact.json", string.Format("getUser({0})", JsonConvert.SerializeObject(users)));
+                    MessageBox.Show("json已导出");
+                });
+            }
+            */
         }
     }
 }

+ 1 - 1
README.md

@@ -29,7 +29,7 @@
 **用于网络安全用途的,请确保在国家法律法规下使用**<br/>
 **本项目完全免费,问你要钱的都是骗子**<br/>
 **使用本项目初衷是作者研究微信数据库的运行使用,您使用本软件导致的后果,包含但不限于数据损坏,记录丢失等问题,作者不承担相关责任。**<br/>
-**因软件特殊性质,请在使用时获得微信账号所有人授权,你当确保不侵犯他人个人隐私权,后果自行承担**<br/>
+**因软件特殊性质,请在使用时获得微信账号所有人授权,你当确保不侵犯他人个人隐私权,后果自行承担**<br/>
 <br/>
 
 ### 隐私声明

+ 6 - 0
WXUserReader.cs

@@ -367,8 +367,14 @@ namespace WechatBakTool
                                 w.NickName = contact.Remark;
                             else
                                 w.NickName = contact.NickName;
+
+                            w.StrTalker = contact.UserName;
                         }
                     }
+                    else
+                    {
+                        w.NickName = uid;
+                    }
 
                     // 群聊处理
                     if (uid.Contains("@chatroom"))

+ 14 - 4
WXWorkspace.cs

@@ -18,7 +18,7 @@ namespace WechatBakTool
     {
         private UserBakConfig UserBakConfig = new UserBakConfig();
         public WXWorkspace(string path,string account = "") {
-            string checkResult = Init(path, account);
+            string checkResult = Init(path, false, account);
             if (checkResult != "")
                 new Exception(checkResult);
         }
@@ -28,7 +28,7 @@ namespace WechatBakTool
             UserBakConfig = userBakConfig;
         }
 
-        public void DecryptDB(string pid,int type,CreateWorkViewModel viewModel)
+        public void DecryptDB(string pid,int type,CreateWorkViewModel viewModel,string pwd = "")
         {
             if (UserBakConfig == null)
             {
@@ -39,7 +39,17 @@ namespace WechatBakTool
             {
                 byte[]? key = null;
                 viewModel.LabelStatus = "正在获取秘钥,需要1 - 10秒左右";
-                key = DecryptionHelper.GetWechatKey(pid, type, UserBakConfig.Account);
+                if(pwd == "")
+                    key = DecryptionHelper.GetWechatKey(pid, type, UserBakConfig.Account);
+                else
+                {
+                    key = new byte[pwd.Length / 2];
+                    for(int i = 0;i<pwd.Length / 2; i++)
+                    {
+                        key[i] = Convert.ToByte(pwd.Substring(i * 2, 2), 16);
+                    }
+                }
+
                 if (key == null)
                 {
                     throw new Exception("获取到的密钥为空,获取失败");
@@ -104,7 +114,7 @@ namespace WechatBakTool
                 }
             }
         }
-        private string Init(string path,string account = "")
+        private string Init(string path,bool manual,string account = "")
         {
             string curPath = AppDomain.CurrentDomain.BaseDirectory;
             string md5 = GetMd5Hash(path);

+ 3 - 3
WechatBakTool.csproj

@@ -6,9 +6,9 @@
     <Nullable>enable</Nullable>
     <UseWPF>true</UseWPF>
     <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
-    <AssemblyVersion>0.9.6.3</AssemblyVersion>
-    <FileVersion>0.9.6.3</FileVersion>
-    <Version>0.9.6.3</Version>
+    <AssemblyVersion>0.9.6.4</AssemblyVersion>
+    <FileVersion>0.9.6.4</FileVersion>
+    <Version>0.9.6.4</Version>
   </PropertyGroup>
 
   <ItemGroup>