Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5ccf928be8 | ||
|
|
11df32451a |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -360,4 +360,5 @@ MigrationBackup/
|
||||
.ionide/
|
||||
|
||||
# Fody - auto-generated XML schema
|
||||
FodyWeavers.xsd
|
||||
FodyWeavers.xsd
|
||||
/WechatPCMsgBakTool.csproj
|
||||
|
||||
36
Analyse.xaml
Normal file
36
Analyse.xaml
Normal file
@@ -0,0 +1,36 @@
|
||||
<Window x:Class="WechatPCMsgBakTool.Analyse"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:WechatPCMsgBakTool"
|
||||
mc:Ignorable="d"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
Title="溯雪微信备份工具-分析" Height="450" Width="900">
|
||||
<Grid>
|
||||
<ListView Name="list_msg_group" Margin="41,75,0,19" HorizontalAlignment="Left" Width="420" SelectionChanged="list_msg_group_SelectionChanged">
|
||||
<ListView.View>
|
||||
<GridView>
|
||||
<GridViewColumn Header="昵称" Width="120" DisplayMemberBinding="{Binding NickName}" />
|
||||
<GridViewColumn Header="原始ID" Width="120" DisplayMemberBinding="{Binding UserName}" />
|
||||
<GridViewColumn Header="数量" Width="140" DisplayMemberBinding="{Binding MsgCount}" />
|
||||
</GridView>
|
||||
</ListView.View>
|
||||
</ListView>
|
||||
<Button x:Name="btn_analyse" Content="分析" HorizontalAlignment="Left" Margin="42,43,0,0" VerticalAlignment="Top" Width="72" Click="btn_analyse_Click"/>
|
||||
<Button x:Name="btn_copy_id" Content="复制id" HorizontalAlignment="Left" Margin="366,43,0,0" VerticalAlignment="Top" Width="94" Click="btn_copy_id_Click"/>
|
||||
|
||||
<ListView Name="list_msg_search" Margin="500,75,0,19" HorizontalAlignment="Left" Width="350">
|
||||
<ListView.View>
|
||||
<GridView>
|
||||
<GridViewColumn Header="原始ID" Width="120" DisplayMemberBinding="{Binding StrTalker}" />
|
||||
<GridViewColumn Header="消息" Width="200" DisplayMemberBinding="{Binding StrContent}" />
|
||||
</GridView>
|
||||
</ListView.View>
|
||||
</ListView>
|
||||
<TextBox Name="txt_search_text" HorizontalAlignment="Left" Margin="574,43,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="120" Height="20"/>
|
||||
<Label Content="消息搜索:" HorizontalAlignment="Left" Margin="504,41,0,0" VerticalAlignment="Top"/>
|
||||
<Button x:Name="btn_search" Content="搜索" HorizontalAlignment="Left" Margin="708,43,0,0" VerticalAlignment="Top" Width="65" Click="btn_search_Click" />
|
||||
<Button x:Name="btn_search_copy_id" Content="复制id" HorizontalAlignment="Left" Margin="784,43,0,0" VerticalAlignment="Top" Width="65" Click="btn_search_copy_id_Click" />
|
||||
</Grid>
|
||||
</Window>
|
||||
106
Analyse.xaml.cs
Normal file
106
Analyse.xaml.cs
Normal file
@@ -0,0 +1,106 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Shapes;
|
||||
using WechatPCMsgBakTool.Model;
|
||||
|
||||
namespace WechatPCMsgBakTool
|
||||
{
|
||||
/// <summary>
|
||||
/// Analyse.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class Analyse : Window
|
||||
{
|
||||
private UserBakConfig UserBakConfig;
|
||||
private WXUserReader UserReader;
|
||||
public Analyse(UserBakConfig userBakConfig,WXUserReader reader)
|
||||
{
|
||||
UserBakConfig = userBakConfig;
|
||||
UserReader = reader;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void btn_analyse_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
List<WXContact>? contacts = UserReader.GetWXContacts();
|
||||
List<WXMsgGroup> list = UserReader.GetWXMsgGroup().OrderByDescending(x => x.MsgCount).ToList();
|
||||
if(contacts == null)
|
||||
contacts = new List<WXContact>();
|
||||
|
||||
foreach (WXMsgGroup item in list)
|
||||
{
|
||||
WXContact? contact = contacts.Find(x => x.UserName == item.UserName);
|
||||
if (contact != null)
|
||||
{
|
||||
item.NickName = contact.NickName;
|
||||
}
|
||||
else
|
||||
item.NickName = "已删除人员:" + item.UserName;
|
||||
}
|
||||
list_msg_group.ItemsSource = list;
|
||||
}
|
||||
|
||||
private void btn_copy_id_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
WXMsgGroup? msgGroup = list_msg_group.SelectedItem as WXMsgGroup;
|
||||
if(msgGroup == null)
|
||||
{
|
||||
MessageBox.Show("请先选择数据");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
Clipboard.SetDataObject(msgGroup.UserName);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void list_msg_group_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
WXMsgGroup? wXMsgGroup = list_msg_group.SelectedItem as WXMsgGroup;
|
||||
if(wXMsgGroup != null)
|
||||
{
|
||||
List<WXMsg>? wXMsgs = UserReader.GetWXMsgs(wXMsgGroup.UserName);
|
||||
if(wXMsgs != null)
|
||||
{
|
||||
wXMsgs = wXMsgs.OrderByDescending(x => x.CreateTime).ToList();
|
||||
list_msg_search.ItemsSource = wXMsgs;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void btn_search_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
List<WXMsg>? wXMsgs = UserReader.GetWXMsgs("",txt_search_text.Text);
|
||||
if (wXMsgs != null)
|
||||
{
|
||||
wXMsgs = wXMsgs.OrderByDescending(x => x.CreateTime).ToList();
|
||||
list_msg_search.ItemsSource = wXMsgs;
|
||||
}
|
||||
}
|
||||
|
||||
private void btn_search_copy_id_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
WXMsg? wxMsg = list_msg_search.SelectedItem as WXMsg;
|
||||
if (wxMsg == null)
|
||||
{
|
||||
MessageBox.Show("请先选择数据");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
Clipboard.SetDataObject(wxMsg.StrTalker);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ namespace WechatPCMsgBakTool.Helpers
|
||||
{
|
||||
public class OpenSSLInterop
|
||||
{
|
||||
private const string Lib = "libcrypto-1_1-x64";
|
||||
private const string Lib = "libcrypto-1_1";
|
||||
internal static unsafe int HMAC_Init(out HMAC_CTX ctx, byte[] key, int key_len, IntPtr md)
|
||||
{
|
||||
return HMAC_InitNative(out ctx, key, key_len, md);
|
||||
|
||||
@@ -30,9 +30,11 @@
|
||||
</GridView>
|
||||
</ListView.View>
|
||||
</ListView>
|
||||
<Button Content="导出所选人员聊天记录" HorizontalAlignment="Left" Margin="609,130,0,0" VerticalAlignment="Top" Width="142" Click="Button_Click"/>
|
||||
<Button Content="导出所选人员聊天记录" HorizontalAlignment="Left" Margin="609,130,0,0" VerticalAlignment="Top" Width="140" Click="Button_Click"/>
|
||||
<Label Content="搜索:" HorizontalAlignment="Left" Margin="278,92,0,0" VerticalAlignment="Top"/>
|
||||
<TextBox Name="find_user" HorizontalAlignment="Left" Margin="323,96,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="120" Height="20"/>
|
||||
<Button Name="btn_search" Content="搜索" HorizontalAlignment="Left" Margin="451,96,0,0" VerticalAlignment="Top" Width="43" Click="btn_search_Click"/>
|
||||
<TextBox Name="find_user" HorizontalAlignment="Left" Margin="323,96,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="194" Height="20"/>
|
||||
<Button Name="btn_search" Content="搜索" HorizontalAlignment="Left" Margin="525,96,0,0" VerticalAlignment="Top" Width="43" Click="btn_search_Click"/>
|
||||
<Button Name="btn_analyse" Content="消息分析工具" HorizontalAlignment="Left" Margin="609,160,0,0" VerticalAlignment="Top" Width="140" Click="btn_analyse_Click"/>
|
||||
<CheckBox Name="cb_del_search" Content="已删除人员强制从记录搜索" HorizontalAlignment="Left" Margin="610,99,0,0" VerticalAlignment="Top"/>
|
||||
</Grid>
|
||||
</Window>
|
||||
|
||||
37
Main.xaml.cs
37
Main.xaml.cs
@@ -80,9 +80,9 @@ namespace WechatPCMsgBakTool
|
||||
WXWorkspace.SaveConfig(CurrentUserBakConfig);
|
||||
LoadWorkspace();
|
||||
}
|
||||
catch (Exception)
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show("解密过程出现错误,请检查是否秘钥是否正确,如果有多开微信,请确保当前微信是选择的用户");
|
||||
MessageBox.Show("解密过程出现错误:" + ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -146,7 +146,6 @@ namespace WechatPCMsgBakTool
|
||||
string path = Path.Combine(CurrentUserBakConfig.UserWorkspacePath, wXContact.UserName + ".html");
|
||||
export.Save(path);
|
||||
MessageBox.Show("导出完成");
|
||||
|
||||
}
|
||||
|
||||
private void Button_Click_1(object sender, RoutedEventArgs e)
|
||||
@@ -167,7 +166,6 @@ namespace WechatPCMsgBakTool
|
||||
{
|
||||
MessageBox.Show("创建工作区失败,请检查路径是否正确");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,7 +176,36 @@ namespace WechatPCMsgBakTool
|
||||
MessageBox.Show("请先读取工作区数据");
|
||||
return;
|
||||
}
|
||||
list_sessions.ItemsSource = UserReader.GetWXContacts(find_user.Text);
|
||||
if(cb_del_search.IsChecked != null)
|
||||
{
|
||||
if (!(bool)cb_del_search.IsChecked)
|
||||
list_sessions.ItemsSource = UserReader.GetWXContacts(find_user.Text);
|
||||
else
|
||||
{
|
||||
List<WXMsg>? wXMsgs = UserReader.GetWXMsgs(find_user.Text);
|
||||
if(wXMsgs != null)
|
||||
{
|
||||
if(wXMsgs.Count > 0)
|
||||
{
|
||||
List<WXContact> wXContacts = new List<WXContact>() { new WXContact() { NickName = wXMsgs[0].StrTalker, UserName = wXMsgs[0].StrTalker } };
|
||||
list_sessions.ItemsSource = wXContacts;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void btn_analyse_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if(UserReader == null || CurrentUserBakConfig == null)
|
||||
{
|
||||
MessageBox.Show("请先读取数据");
|
||||
return;
|
||||
}
|
||||
Analyse analyse = new Analyse(CurrentUserBakConfig, UserReader);
|
||||
analyse.Show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,16 @@ namespace WechatPCMsgBakTool.Model
|
||||
}
|
||||
}
|
||||
|
||||
public class WXMsgGroup
|
||||
{
|
||||
[Column("StrTalker")]
|
||||
public string UserName { get; set; } = "";
|
||||
|
||||
[Column("MsgCount")]
|
||||
public int MsgCount { get; set; }
|
||||
public string NickName { get; set; } = "";
|
||||
}
|
||||
|
||||
public class WXUserInfo
|
||||
{
|
||||
public string UserName { get; set; } = "";
|
||||
|
||||
15
README.md
15
README.md
@@ -4,22 +4,25 @@
|
||||
- 支持3.9.6.33版本后,若版本更新可在version.json添加版本号和地址即可完成新版本支持
|
||||
- 导出图片、视频、音频
|
||||
- 导出Html文件
|
||||
- 支持聊天频率分析,全消息库内容搜索
|
||||
|
||||
本项目仅做学习使用,供个人备份自己的微信,请勿做其他用途使用。
|
||||
|
||||
本项目仅做学习使用,主要供个人备份自己的微信记录,请勿用于非法用途。
|
||||
本项目严禁商用。
|
||||
如果有什么好的建议或意见,或者遇到什么问题,欢迎提issue,看到会回。
|
||||
|
||||
#### 使用
|
||||
<p>1.打开微信,并登录。</p>
|
||||
<p>2.在工作区上方点击新增,选择要创建的工作区微信</p>
|
||||
<p>3.选中刚刚创建的工作区,点击解密。(如当前多开微信,请选择对应的微信进行解谜)</p>
|
||||
<p>4.选中刚刚创建的工作区,点击读取</p>
|
||||
<p>3.点新建会弹出Handle64的协议说明,同意即可。如没有内容显示,重新点一下新建即可</p>
|
||||
<p>4.选中刚刚创建的工作区,点击解密。(如当前多开微信,请选择对应的微信进行解谜)</p>
|
||||
<p>5.选中刚刚创建的工作区,点击读取</p>
|
||||
<p><b>尽情使用吧!</b></p>
|
||||
|
||||
#### 注意
|
||||
<p>本项目基于.NET开发,需要安装.NET Desktop Runtime,如未安装,双击EXE时会提示。</p>
|
||||
<p>如果使用过程中发生崩溃,请删除工作区试一下,工作区即根据用户名在运行目录下生成的md5文件夹。</p>
|
||||
<p>已解谜的工作区可以直接读取</p>
|
||||
<p>再次强调,仅供个人备份自己微信使用 </p>
|
||||
<p>已解密的工作区可以直接读取。</p>
|
||||
<p>再次强调,主要用于个人备份自己微信使用,请勿用于非法用途,严禁商用!</p>
|
||||
|
||||
#### 参考/引用
|
||||
都是站在大佬们的肩膀上完成的项目,本项目 参考/引用 了以下 项目/文章 内代码。
|
||||
|
||||
@@ -40,6 +40,15 @@ namespace WechatPCMsgBakTool
|
||||
p.StartInfo.RedirectStandardOutput = true;
|
||||
p.Start();
|
||||
string i = p.StandardOutput.ReadToEnd();
|
||||
if (i.Contains("SYSINTERNALS SOFTWARE LICENSE TERMS"))
|
||||
{
|
||||
MessageBox.Show("请先同意Handle64的使用协议,同意后关闭弹窗重新打开新增工作区即可");
|
||||
Process p1 = new Process();
|
||||
p1.StartInfo.FileName = "tools/handle64.exe";
|
||||
p1.StartInfo.Arguments = "-p wechat.exe";
|
||||
p1.Start();
|
||||
}
|
||||
|
||||
string[] lines = i.Split(new string[] { "\r\n" }, StringSplitOptions.None);
|
||||
bool hitFind = false;
|
||||
ProcessInfo processInfo = new ProcessInfo();
|
||||
|
||||
@@ -52,7 +52,7 @@ namespace WechatPCMsgBakTool
|
||||
return con.Query<WXContact>(query);
|
||||
}
|
||||
|
||||
public List<WXMsg>? GetWXMsgs(string uid)
|
||||
public List<WXMsg>? GetWXMsgs(string uid,string msg = "")
|
||||
{
|
||||
List<WXMsg> tmp = new List<WXMsg>();
|
||||
for (int i = 0; i <= 99; i++)
|
||||
@@ -63,8 +63,23 @@ namespace WechatPCMsgBakTool
|
||||
if (con == null)
|
||||
return tmp;
|
||||
|
||||
string query = "select * from MSG where StrTalker=?";
|
||||
List<WXMsg> wXMsgs = con.Query<WXMsg>(query, uid);
|
||||
List<WXMsg>? wXMsgs = null;
|
||||
if (msg == "")
|
||||
{
|
||||
string query = "select * from MSG where StrTalker=?";
|
||||
wXMsgs = con.Query<WXMsg>(query, uid);
|
||||
}
|
||||
else if(uid == "")
|
||||
{
|
||||
string query = "select * from MSG where StrContent like ?";
|
||||
wXMsgs = con.Query<WXMsg>(query, string.Format("%{0}%", msg));
|
||||
}
|
||||
else
|
||||
{
|
||||
string query = "select * from MSG where StrTalker=? and StrContent like ?";
|
||||
wXMsgs = con.Query<WXMsg>(query, uid, string.Format("%{0}%", msg));
|
||||
}
|
||||
|
||||
foreach (WXMsg w in wXMsgs)
|
||||
{
|
||||
tmp.Add(w);
|
||||
@@ -73,7 +88,6 @@ namespace WechatPCMsgBakTool
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
public WXSessionAttachInfo? GetWXMsgAtc(WXMsg msg)
|
||||
{
|
||||
SQLiteConnection con = DBInfo["MultiSearchChatMsg"];
|
||||
@@ -101,7 +115,6 @@ namespace WechatPCMsgBakTool
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public WXMediaMsg? GetVoiceMsg(WXMsg msg)
|
||||
{
|
||||
for (int i = 0; i <= 99; i++)
|
||||
@@ -120,7 +133,6 @@ namespace WechatPCMsgBakTool
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public string? GetAttachment(WXMsgType type, WXMsg msg)
|
||||
{
|
||||
if (UserBakConfig == null)
|
||||
@@ -182,7 +194,7 @@ namespace WechatPCMsgBakTool
|
||||
if (path == null)
|
||||
return null;
|
||||
|
||||
// 该相对路径
|
||||
// 改相对路径
|
||||
path = path.Replace(UserBakConfig.UserWorkspacePath + "\\", "");
|
||||
return path;
|
||||
|
||||
@@ -217,6 +229,31 @@ namespace WechatPCMsgBakTool
|
||||
}
|
||||
return file_path;
|
||||
}
|
||||
public List<WXMsgGroup> GetWXMsgGroup()
|
||||
{
|
||||
List<WXMsgGroup> g = new List<WXMsgGroup>();
|
||||
for (int i = 0; i <= 99; i++)
|
||||
{
|
||||
if (DBInfo.ContainsKey("MSG" + i.ToString()))
|
||||
{
|
||||
SQLiteConnection con = DBInfo["MSG" + i.ToString()];
|
||||
if (con == null)
|
||||
return g;
|
||||
|
||||
string query = "select StrTalker,Count(localId) as MsgCount from MSG GROUP BY StrTalker";
|
||||
List<WXMsgGroup> wXMsgs = con.Query<WXMsgGroup>(query);
|
||||
foreach (WXMsgGroup w in wXMsgs)
|
||||
{
|
||||
WXMsgGroup? tmp = g.Find(x => x.UserName == w.UserName);
|
||||
if (tmp == null)
|
||||
g.Add(w);
|
||||
else
|
||||
tmp.MsgCount += g.Count;
|
||||
}
|
||||
}
|
||||
}
|
||||
return g;
|
||||
}
|
||||
}
|
||||
|
||||
public enum WXMsgType
|
||||
|
||||
@@ -6,8 +6,9 @@
|
||||
<Nullable>enable</Nullable>
|
||||
<UseWPF>true</UseWPF>
|
||||
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
||||
<AssemblyVersion>0.2.1.0</AssemblyVersion>
|
||||
<FileVersion>0.2.1.0</FileVersion>
|
||||
<AssemblyVersion>0.4.0.0</AssemblyVersion>
|
||||
<FileVersion>0.4.0.0</FileVersion>
|
||||
<Version>0.4.0.0</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -16,10 +17,10 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="libcrypto-1_1-x64.dll">
|
||||
<None Update="libcrypto-1_1.dll">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="libssl-1_1-x64.dll">
|
||||
<None Update="libssl-1_1.dll">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Tools\ffmpeg.exe">
|
||||
|
||||
Binary file not shown.
BIN
libcrypto-1_1.dll
Normal file
BIN
libcrypto-1_1.dll
Normal file
Binary file not shown.
Binary file not shown.
BIN
libssl-1_1.dll
Normal file
BIN
libssl-1_1.dll
Normal file
Binary file not shown.
Reference in New Issue
Block a user