Bladeren bron

v0.9.7.0 Releases!
1.优化解密的内存开销,同时修复大于2gb文件解密出错的问题。
2.现在起工作区加载联系人也开始为异步操作了。
3.现在起工作区查看聊天记录改为分页查看了。
4.保底版本支持3.9.8.25。

Suxue 1 jaar geleden
bovenliggende
commit
ef3c84a724

+ 0 - 54
Export/HtmlExport.cs

@@ -246,60 +246,6 @@ namespace WechatBakTool.Export
                                 }
                             }
                         }
-                        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>");
-                                            }
-                                        }
-                                            
-                                        
-                                    }
-                                }
-                            }
-                        }
                         else
                         {
                             using (var decoder = LZ4Decoder.Create(true, 64))

+ 94 - 24
Helpers/DecryptionHelper.cs

@@ -19,12 +19,12 @@ namespace WechatBakTool.Helpers
 {
     public class DecryptionHelper
     {
-        const int IV_SIZE = 16;
+        const long IV_SIZE = 16;
         const int HMAC_SHA1_SIZE = 20;
         const int KEY_SIZE = 32;
         const int AES_BLOCK_SIZE = 16;
         const int DEFAULT_ITER = 64000;
-        const int DEFAULT_PAGESIZE = 4096; //4048数据 + 16IV + 20 HMAC + 12
+        const long DEFAULT_PAGESIZE = 4096; //4048数据 + 16IV + 20 HMAC + 12
         const string SQLITE_HEADER = "SQLite format 3";
         public static byte[]? GetWechatKey(string pid, int find_key_type, string account)
         {
@@ -143,34 +143,112 @@ namespace WechatBakTool.Helpers
             return null;
         }
 
-        public static byte[] DecryptDB(byte[] db_file_bytes, byte[] password_bytes)
+        public static void DecryptDB(string file, string to_file, byte[] password_bytes)
         {
             //数据库头16字节是盐值
-            var salt = db_file_bytes.Take(16).ToArray();
+            byte[] salt_key = new byte[16];
+
+            FileStream fileStream = new FileStream(file, FileMode.Open, FileAccess.Read);
+            fileStream.Read(salt_key, 0, 16);
+
             //HMAC验证时用的盐值需要亦或0x3a
             byte[] hmac_salt = new byte[16];
-            for (int i = 0; i < salt.Length; i++)
+            for (int i = 0; i < salt_key.Length; i++)
             {
-                hmac_salt[i] = (byte)(salt[i] ^ 0x3a);
+                hmac_salt[i] = (byte)(salt_key[i] ^ 0x3a);
             }
             //计算保留段长度
-            int reserved = IV_SIZE;
+            long reserved = IV_SIZE;
             reserved += HMAC_SHA1_SIZE;
             reserved = ((reserved % AES_BLOCK_SIZE) == 0) ? reserved : ((reserved / AES_BLOCK_SIZE) + 1) * AES_BLOCK_SIZE;
 
             //密钥扩展,分别对应AES解密密钥和HMAC验证密钥
             byte[] key = new byte[KEY_SIZE];
             byte[] hmac_key = new byte[KEY_SIZE];
-            OpenSSLInterop.PKCS5_PBKDF2_HMAC_SHA1(password_bytes, password_bytes.Length, salt, salt.Length, DEFAULT_ITER, key.Length, key);
+            OpenSSLInterop.PKCS5_PBKDF2_HMAC_SHA1(password_bytes, password_bytes.Length, salt_key, salt_key.Length, DEFAULT_ITER, key.Length, key);
             OpenSSLInterop.PKCS5_PBKDF2_HMAC_SHA1(key, key.Length, hmac_salt, hmac_salt.Length, 2, hmac_key.Length, hmac_key);
 
-            int page_no = 0;
-            int offset = 16;
+            long page_no = 0;
+            long offset = 16;
             Console.WriteLine("开始解密...");
             var hmac_sha1 = HMAC.Create("HMACSHA1");
             hmac_sha1!.Key = hmac_key;
+
             List<byte> decrypted_file_bytes = new List<byte>();
-            while (page_no < db_file_bytes.Length / DEFAULT_PAGESIZE)
+            FileStream tofileStream = new FileStream(to_file, FileMode.OpenOrCreate, FileAccess.Write);
+
+            using (fileStream)
+            {
+                try
+                {
+                    // 当前分页小于计算分页数
+                    while (page_no < fileStream.Length / DEFAULT_PAGESIZE)
+                    {
+                        // 读内容
+                        byte[] decryped_page_bytes = new byte[DEFAULT_PAGESIZE];
+                        byte[] going_to_hashed = new byte[DEFAULT_PAGESIZE - reserved - offset + IV_SIZE + 4];
+                        fileStream.Seek((page_no * DEFAULT_PAGESIZE) + offset, SeekOrigin.Begin);
+                        fileStream.Read(going_to_hashed, 0, Convert.ToInt32(DEFAULT_PAGESIZE - reserved - offset + IV_SIZE));
+
+                        // 分页标志
+                        var page_bytes = BitConverter.GetBytes(page_no + 1);
+                        page_bytes.CopyTo(going_to_hashed, DEFAULT_PAGESIZE - reserved - offset + IV_SIZE);
+                        var hash_mac_compute = hmac_sha1.ComputeHash(going_to_hashed, 0, going_to_hashed.Length);
+
+                        // 取分页hash
+                        byte[] hash_mac_cached = new byte[hash_mac_compute.Length];
+                        fileStream.Seek((page_no * DEFAULT_PAGESIZE) + DEFAULT_PAGESIZE - reserved + IV_SIZE, SeekOrigin.Begin);
+                        fileStream.Read(hash_mac_cached, 0, hash_mac_compute.Length);
+
+                        if (!hash_mac_compute.SequenceEqual(hash_mac_cached) && page_no == 0)
+                        {
+                            Console.WriteLine("Hash错误...");
+                            return;
+                        }
+                        else
+                        {
+                            if (page_no == 0)
+                            {
+                                var header_bytes = Encoding.ASCII.GetBytes(SQLITE_HEADER);
+                                header_bytes.CopyTo(decryped_page_bytes, 0);
+                            }
+
+                            // 加密内容
+                            byte[] page_content = new byte[DEFAULT_PAGESIZE - reserved - offset];
+                            fileStream.Seek((page_no * DEFAULT_PAGESIZE) + offset, SeekOrigin.Begin);
+                            fileStream.Read(page_content, 0, Convert.ToInt32(DEFAULT_PAGESIZE - reserved - offset));
+
+                            // iv
+                            byte[] iv = new byte[16];
+                            fileStream.Seek((page_no * DEFAULT_PAGESIZE) + (DEFAULT_PAGESIZE - reserved), SeekOrigin.Begin);
+                            fileStream.Read(iv, 0, 16);
+
+                            var decrypted_content = AESDecrypt(page_content, key, iv);
+                            decrypted_content.CopyTo(decryped_page_bytes, offset);
+
+                            // 保留
+                            byte[] reserved_byte = new byte[reserved];
+                            fileStream.Seek((page_no * DEFAULT_PAGESIZE) + DEFAULT_PAGESIZE - reserved, SeekOrigin.Begin);
+                            fileStream.Read(reserved_byte, 0, Convert.ToInt32(reserved));
+                            reserved_byte.CopyTo(decryped_page_bytes, DEFAULT_PAGESIZE - reserved);
+
+                            tofileStream.Write(decryped_page_bytes, 0, decryped_page_bytes.Length);
+
+                        }
+                        page_no++;
+                        offset = 0;
+                    }
+                }catch(Exception ex)
+                {
+                    File.AppendAllText("err.log", "page=>" + page_no.ToString() + "\r\n");
+                    File.AppendAllText("err.log", "size=>" + fileStream.Length.ToString() + "\r\n");
+                    File.AppendAllText("err.log", "postion=>" + ((page_no * DEFAULT_PAGESIZE) + offset).ToString() + "\r\n");
+                    File.AppendAllText("err.log", ex.ToString() + "\r\n");
+                }
+            }
+            /*
+             * 旧版解密
+            while (page_no < fileStream.Length / DEFAULT_PAGESIZE)
             {
                 byte[] decryped_page_bytes = new byte[DEFAULT_PAGESIZE];
                 byte[] going_to_hashed = new byte[DEFAULT_PAGESIZE - reserved - offset + IV_SIZE + 4];
@@ -179,7 +257,6 @@ namespace WechatBakTool.Helpers
                 page_bytes.CopyTo(going_to_hashed, DEFAULT_PAGESIZE - reserved - offset + IV_SIZE);
                 //计算分页的Hash
                 var hash_mac_compute = hmac_sha1.ComputeHash(going_to_hashed, 0, going_to_hashed.Length);
-                //取出分页中存储的Hash
                 var hash_mac_cached = db_file_bytes.Skip((page_no * DEFAULT_PAGESIZE) + DEFAULT_PAGESIZE - reserved + IV_SIZE).Take(hash_mac_compute.Length).ToArray();
                 //对比两个Hash
                 if (!hash_mac_compute.SequenceEqual(hash_mac_cached))
@@ -208,8 +285,9 @@ namespace WechatBakTool.Helpers
                 {
                     decrypted_file_bytes.Add(item);
                 }
-            }
-            return decrypted_file_bytes.ToArray();
+            }*/
+            tofileStream.Close();
+            tofileStream.Dispose();
         }
         public static byte[] AESDecrypt(byte[] content, byte[] key, byte[] iv)
         {
@@ -297,16 +375,8 @@ namespace WechatBakTool.Helpers
             {
                 FileInfo info = new FileInfo(file);
                 viewModel.LabelStatus = "正在解密" + info.Name;
-                var db_bytes = File.ReadAllBytes(file);
-                var decrypted_file_bytes = DecryptDB(db_bytes, key);
-                if (decrypted_file_bytes == null || decrypted_file_bytes.Length == 0)
-                {
-                    Console.WriteLine("解密后的数组为空");
-                }
-                else
-                {
-                    File.WriteAllBytes(Path.Combine(decPath, info.Name), decrypted_file_bytes);
-                }
+                string to_file = Path.Combine(decPath, info.Name);
+                DecryptDB(file,to_file, key);
             }
         }
     }

+ 2 - 0
Model/WXModel.cs

@@ -114,6 +114,8 @@ namespace WechatBakTool.Model
     {
         [Column("localId")]
         public int LocalId { get; set; }
+        [Column("MsgSequence")]
+        public int MsgSequence { get; set; }
         [Column("Type")]
         public int Type { get; set; }
         [Column("SubType")]

+ 40 - 0
Pages/MsgTemplateSelector .cs

@@ -0,0 +1,40 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using WechatBakTool.Model;
+
+namespace WechatBakTool.Pages
+{
+    public class MsgTemplateSelector : DataTemplateSelector
+    {
+
+        public override DataTemplate? SelectTemplate(object item, DependencyObject container)
+        {
+            FrameworkElement? element = container as FrameworkElement;
+
+            if (element != null && item != null && item is WXMsg)
+            {
+                WXMsg? wxmsg = item as WXMsg;
+
+                if (wxmsg == null)
+                    return null;
+
+                if (wxmsg.Type == 1)
+                    return
+                        element.FindResource("MsgText") as DataTemplate;
+                else if (wxmsg.Type == 3)
+                    return
+                        element.FindResource("MsgImage") as DataTemplate;
+                else
+                    return
+                        element.FindResource("MsgText") as DataTemplate;
+            }
+            return null;
+        }
+
+    }
+}

+ 4 - 4
Pages/Workspace.xaml

@@ -3,11 +3,12 @@
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
       xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
-      xmlns:local="clr-namespace:WechatBakTool.Pages"
+      xmlns:local="clr-namespace:WechatBakTool.Pages" 
       mc:Ignorable="d" 
       d:DesignHeight="450" d:DesignWidth="720"
       Title="Workspace" Background="White">
     <Page.Resources>
+        <local:MsgTemplateSelector x:Key="MsgTemplateSelector"/>
         <Style TargetType="ToggleButton" x:Key="ComboxStyleBtn">
             <Setter Property="Template">
                 <Setter.Value>
@@ -164,9 +165,8 @@
         </DataTemplate>
         <DataTemplate x:Key="MsgImage">
             <Grid Margin="0">
-                <Image Width="40" Height="40" Margin="10" VerticalAlignment="Top" HorizontalAlignment="Left" Source="{Binding Avatar}"  />
                 <Label Margin="60,8,0,0" FontWeight="Bold" VerticalAlignment="Top" HorizontalAlignment="Left" Content="{Binding NickName}" Width="130"/>
-                <Label Margin="60,25,0,0" VerticalAlignment="Top" HorizontalAlignment="Left" Width="140" Content="{Binding LastMsg}"/>
+                <Label Margin="60,25,0,0" VerticalAlignment="Top" HorizontalAlignment="Left" Width="140" Content="1111"/>
             </Grid>
         </DataTemplate>
         <DataTemplate x:Key="MsgAudio">
@@ -214,7 +214,7 @@
             </ListView.Resources>
         </ListView>
         <Label Content="{Binding WXContact.NickName}" HorizontalAlignment="Left" Margin="258,21,0,0" VerticalAlignment="Top"/>
-        <ListView x:Name="list_msg" Margin="230,60,0,60" Background="Transparent" BorderThickness="0,1,0,1" BorderBrush="#BB2775b6" ItemTemplate="{DynamicResource MsgText}">
+        <ListView x:Name="list_msg" Margin="230,60,0,60" Background="Transparent" BorderThickness="0,1,0,1" BorderBrush="#BB2775b6" ItemTemplateSelector="{StaticResource MsgTemplateSelector}" ItemsSource="{Binding WXMsgs}" ScrollViewer.ScrollChanged="list_msg_ScrollChanged" >
 
         </ListView>
         <ComboBox Name="cb_export" Width="120" Height="30" Style="{StaticResource ComboBoxStyle}" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="30,15" ItemsSource="{Binding ExportItems}" SelectedItem="{Binding SelectExportItem}" DisplayMemberPath="Name" SelectedValuePath="Value" IsEnabled="{Binding SelectContact}" Background="#2775b6" />

+ 71 - 18
Pages/Workspace.xaml.cs

@@ -27,6 +27,8 @@ using System.Windows.Controls;
 using System.Text.RegularExpressions;
 using Newtonsoft.Json;
 using System.Drawing.Imaging;
+using System.Threading;
+using System.Runtime.CompilerServices;
 
 namespace WechatBakTool.Pages
 {
@@ -37,6 +39,9 @@ namespace WechatBakTool.Pages
     {
         public WXUserReader? UserReader;
         private WorkspaceViewModel ViewModel = new WorkspaceViewModel();
+        private int PageSize = 100;
+        private int Postion = 0;
+        private bool Loading = false;
         public Workspace()
         {
             ViewModel.ExportItems = new System.Collections.ObjectModel.ObservableCollection<ExportItem> {
@@ -56,7 +61,11 @@ namespace WechatBakTool.Pages
                 UserReader = new WXUserReader(config);
                 if (config.Decrypt)
                 {
-                    ViewModel.Contacts = UserReader.GetWXContacts();
+                    ViewModel.Contacts = null;
+                    Task.Run(() => {
+                        ViewModel.Contacts = UserReader.GetWXContacts();
+                    });
+                    
                 }
             }
         }
@@ -72,14 +81,43 @@ namespace WechatBakTool.Pages
 
         private void list_users_SelectionChanged(object sender, SelectionChangedEventArgs e)
         {
+
+            ViewModel.WXMsgs.Clear();
+            Postion = 0;
             ViewModel.ExportCount = "";
+            
+            loadMsg();
+            if (ViewModel.WXMsgs.Count == 0)
+                return;
+            
+        }
+
+        private void loadMsg()
+        {
+            Loading = true;
             ViewModel.WXContact = list_users.SelectedItem as WXContact;
-            if(ViewModel.WXContact == null || UserReader == null)
-            {
+            if (ViewModel.WXContact == null || UserReader == null)
+                return;
+
+            List<WXMsg>? list = UserReader.GetWXMsgs(ViewModel.WXContact.UserName, Postion, PageSize);
+            // Trace.WriteLine(string.Format("{0}->{1}", PageSize, Postion));
+            if (list == null)
+                return;
+            if (list.Count == 0)
                 return;
+            
+            
+            foreach (WXMsg w in list)
+            {
+                ViewModel.WXMsgs.Add(w);
             }
-            List<WXMsg>? msgs = UserReader.GetWXMsgs(ViewModel.WXContact.UserName);
-            list_msg.ItemsSource = msgs;
+
+            Postion = int.Parse(list.Max(x => x.CreateTime).ToString());
+            list_msg.ScrollIntoView(list[0]);
+            Task.Run(() => {
+                Thread.Sleep(500);
+                Loading = false;
+            });
         }
 
         private void txt_find_user_TextChanged(object sender, TextChangedEventArgs e)
@@ -91,22 +129,25 @@ namespace WechatBakTool.Pages
             if (txt_find_user.Text == "搜索...")
                 findName = "";
 
-            ViewModel.Contacts = UserReader.GetWXContacts(findName);
-            // 保底回落搜索已删除人员
-            if(ViewModel.Contacts.Count == 0)
+            Task.Run(() =>
             {
-                var i = UserReader.GetWXMsgs(txt_find_user.Text);
-                if (i != null)
+                ViewModel.Contacts = UserReader.GetWXContacts(findName);
+                // 保底回落搜索已删除人员
+                if (ViewModel.Contacts.Count == 0)
                 {
-                    var g = i.GroupBy(x => x.StrTalker);
-                    ViewModel.Contacts = new System.Collections.ObjectModel.ObservableCollection<WXContact>();
-                    foreach (var x in g)
+                    var i = UserReader.GetWXMsgs(txt_find_user.Text);
+                    if (i != null)
                     {
-                        string name = x.Key;
-                        ViewModel.Contacts.Add(new WXContact() { UserName = name, NickName = name });
+                        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)
@@ -132,9 +173,9 @@ namespace WechatBakTool.Pages
                 export.SetMsg(UserReader, ViewModel.WXContact, ViewModel);
                 export.SetEnd();
                 export.Save(path);
-            }catch(Exception ex)
+            }
+            catch (Exception ex)
             {
-                File.AppendAllText("1.log", ex.Message);
                 MessageBox.Show(ex.Message);
             }
             
@@ -343,5 +384,17 @@ namespace WechatBakTool.Pages
             }
             */
         }
+
+        private void list_msg_ScrollChanged(object sender, ScrollChangedEventArgs e)
+        {
+            if (ViewModel.WXMsgs.Count == 0)
+                return;
+
+            if (e.VerticalOffset + e.ViewportHeight == e.ExtentHeight && !Loading)
+            {
+                // 滚动条到达底部的处理逻辑
+                loadMsg();
+            }
+        }
     }
 }

+ 3 - 0
ViewModel/WorkspaceViewModel.cs

@@ -16,6 +16,9 @@ namespace WechatBakTool.ViewModel
         [NotifyPropertyChangedFor(nameof(LabelStatus))]
         private WXContact? wXContact = null;
 
+        [ObservableProperty]
+        private ObservableCollection<WXMsg> wXMsgs = new ObservableCollection<WXMsg>();
+
         [ObservableProperty]
         [NotifyPropertyChangedFor(nameof(LabelStatus))]
         private string exportCount = "";

+ 94 - 72
WXUserReader.cs

@@ -330,6 +330,25 @@ namespace WechatBakTool
             }
             return tmp;
         }
+
+        public List<WXMsg>? GetWXMsgs(string uid,int time,int page)
+        {
+            List<WXMsg> tmp = new List<WXMsg>();
+            for (int i = 0; i <= 99; i++)
+            {
+                SQLiteConnection? con = getCon("MSG" + i.ToString());
+                if (con == null)
+                    return tmp;
+
+                List<WXMsg>? wXMsgs = null;
+                string query = "select * from MSG where StrTalker=? and CreateTime>? Limit ?";
+                wXMsgs = con.Query<WXMsg>(query, uid, time, page);
+                if (wXMsgs.Count != 0) {
+                    return ProcessMsg(wXMsgs, uid);
+                }
+            }
+            return tmp;
+        }
         public List<WXMsg>? GetWXMsgs(string uid,string msg = "")
         {
             List<WXMsg> tmp = new List<WXMsg>();
@@ -356,104 +375,107 @@ namespace WechatBakTool
                     wXMsgs = con.Query<WXMsg>(query, uid, string.Format("%{0}%", msg));
                 }
 
-                foreach (WXMsg w in wXMsgs)
+                tmp.AddRange(ProcessMsg(wXMsgs, uid));
+            }
+            return tmp;
+        }
+        private List<WXMsg> ProcessMsg(List<WXMsg> msgs,string uid)
+        {
+            foreach (WXMsg w in msgs)
+            {
+                if (UserNameCache.ContainsKey(w.StrTalker))
                 {
-                    if (UserNameCache.ContainsKey(w.StrTalker))
+                    WXContact? contact = UserNameCache[w.StrTalker] as WXContact;
+                    if (contact != null)
                     {
-                        WXContact? contact = UserNameCache[w.StrTalker] as WXContact;
-                        if (contact != null)
-                        {
-                            if (contact.Remark != "")
-                                w.NickName = contact.Remark;
-                            else
-                                w.NickName = contact.NickName;
+                        if (contact.Remark != "")
+                            w.NickName = contact.Remark;
+                        else
+                            w.NickName = contact.NickName;
 
-                            w.StrTalker = contact.UserName;
-                        }
+                        w.StrTalker = contact.UserName;
                     }
-                    else
+                }
+                else
+                {
+                    w.NickName = uid;
+                }
+
+                // 群聊处理
+                if (uid.Contains("@chatroom"))
+                {
+                    string userId = "";
+
+                    if (w.BytesExtra == null)
+                        continue;
+
+                    string sl = BitConverter.ToString(w.BytesExtra).Replace("-", "");
+
+                    ProtoMsg protoMsg;
+                    using (MemoryStream stream = new MemoryStream(w.BytesExtra))
                     {
-                        w.NickName = uid;
+                        protoMsg = ProtoBuf.Serializer.Deserialize<ProtoMsg>(stream);
                     }
 
-                    // 群聊处理
-                    if (uid.Contains("@chatroom"))
+                    if (protoMsg.TVMsg != null)
                     {
-                        string userId = "";
-
-                        if (w.BytesExtra == null)
-                            continue;
+                        foreach (TVType _tmp in protoMsg.TVMsg)
+                        {
+                            if (_tmp.Type == 1)
+                                userId = _tmp.TypeValue;
+                        }
+                    }
 
-                        string sl = BitConverter.ToString(w.BytesExtra).Replace("-", "");
 
-                        ProtoMsg protoMsg;
-                        using (MemoryStream stream = new MemoryStream(w.BytesExtra))
+                    if (!w.IsSender)
+                    {
+                        if (UserNameCache.ContainsKey(userId))
                         {
-                            protoMsg = ProtoBuf.Serializer.Deserialize<ProtoMsg>(stream);
+                            WXContact? contact = UserNameCache[userId] as WXContact;
+                            if (contact != null)
+                                w.NickName = contact.Remark == "" ? contact.NickName : contact.Remark;
                         }
-
-                        if (protoMsg.TVMsg != null)
+                        else
                         {
-                            foreach (TVType _tmp in protoMsg.TVMsg)
-                            {
-                                if (_tmp.Type == 1)
-                                    userId = _tmp.TypeValue;
-                            }
+                            w.NickName = userId;
                         }
+                    }
+                }
 
 
-                        if (!w.IsSender)
-                        {
-                            if (UserNameCache.ContainsKey(userId))
-                            {
-                                WXContact? contact = UserNameCache[userId] as WXContact;
-                                if (contact != null)
-                                    w.NickName = contact.Remark == "" ? contact.NickName : contact.Remark;
-                            }
-                            else
-                            {
-                                w.NickName = userId;
-                            }
-                        }
+                // 发送人名字处理
+                if (w.IsSender)
+                    w.NickName = "我";
+
+                w.DisplayContent = w.StrContent;
+                // 额外格式处理
+                if (w.Type != 1)
+                {
+                    if (w.Type == 10000)
+                    {
+                        w.Type = 1;
+                        w.NickName = "系统消息";
+                        w.DisplayContent = w.StrContent.Replace("<revokemsg>", "").Replace("</revokemsg>", "");
                     }
-                    
-                    
-                    // 发送人名字处理
-                    if (w.IsSender)
-                        w.NickName = "我";
-
-                    w.DisplayContent = w.StrContent;
-                    // 额外格式处理
-                    if (w.Type != 1)
+                    else if (w.Type == 49 && (w.SubType == 6 || w.SubType == 19 || w.SubType == 40))
                     {
-                        if (w.Type == 10000)
+                        WXSessionAttachInfo? attachInfos = GetWXMsgAtc(w);
+                        if (attachInfos == null)
                         {
-                            w.Type = 1;
-                            w.NickName = "系统消息";
-                            w.DisplayContent = w.StrContent.Replace("<revokemsg>", "").Replace("</revokemsg>", "");
-                        }
-                        else if (w.Type == 49 && (w.SubType == 6 || w.SubType == 19 || w.SubType == 40))
-                        {
-                            WXSessionAttachInfo? attachInfos = GetWXMsgAtc(w);
-                            if (attachInfos == null)
-                            {
-                                w.DisplayContent = "附件不存在";
-                            }
-                            else
-                            {
-                                w.DisplayContent = Path.Combine(UserBakConfig!.UserResPath, attachInfos.attachPath);
-                            }
+                            w.DisplayContent = "附件不存在";
                         }
                         else
                         {
-                            w.DisplayContent = "[界面未支持格式]Type=" + w.Type;
+                            w.DisplayContent = Path.Combine(UserBakConfig!.UserResPath, attachInfos.attachPath);
                         }
                     }
-                    tmp.Add(w);
-
+                    else
+                    {
+                        w.DisplayContent = "[界面未支持格式]Type=" + w.Type;
+                    }
                 }
             }
-            return tmp;
+            return msgs;
         }
         public List<WXSessionAttachInfo>? GetWXMsgAtc()
         {

+ 4 - 1
WXWorkspace.cs

@@ -48,8 +48,11 @@ namespace WechatBakTool
                     {
                         key[i] = Convert.ToByte(pwd.Substring(i * 2, 2), 16);
                     }
+                    
                 }
-
+#if DEBUG
+                File.WriteAllText("key.log", BitConverter.ToString(key!));
+#endif
                 if (key == null)
                 {
                     throw new Exception("获取到的密钥为空,获取失败");

+ 3 - 3
WechatBakTool.csproj

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

+ 3 - 0
version.json

@@ -11,5 +11,8 @@
 	},{
 		"Version":"3.9.8.15",
 		"BaseAddr": 64997904
+	},{
+		"Version":"3.9.8.25",
+		"BaseAddr": 65002192
 	}
 ]