Skip to content

Commit

Permalink
1.替换handle64,使用windows api直接获取文件句柄
Browse files Browse the repository at this point in the history
2.新增了分享链接的支持
  • Loading branch information
SuxueCode committed Nov 1, 2023
1 parent 97277c5 commit cd90958
Show file tree
Hide file tree
Showing 9 changed files with 328 additions and 17 deletions.
47 changes: 47 additions & 0 deletions Helpers/DevicePathMapper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace WechatPCMsgBakTool.Helpers
{
public static class DevicePathMapper
{
[DllImport("Kernel32.dll", CharSet = CharSet.Unicode)]
private static extern uint QueryDosDevice([In] string lpDeviceName, [Out] StringBuilder lpTargetPath, [In] int ucchMax);

public static string FromDevicePath(string devicePath)
{
var drive = Array.Find(DriveInfo.GetDrives(), d => devicePath.StartsWith(d.GetDevicePath(), StringComparison.InvariantCultureIgnoreCase));
return drive != null ?
devicePath.ReplaceFirst(drive.GetDevicePath(), drive.GetDriveLetter()) :
null;
}

private static string GetDevicePath(this DriveInfo driveInfo)
{
var devicePathBuilder = new StringBuilder(128);
return QueryDosDevice(driveInfo.GetDriveLetter(), devicePathBuilder, devicePathBuilder.Capacity + 1) != 0 ?
devicePathBuilder.ToString() :
null;
}

private static string GetDriveLetter(this DriveInfo driveInfo)
{
return driveInfo.Name.Substring(0, 2);
}

private static string ReplaceFirst(this string text, string search, string replace)
{
int pos = text.IndexOf(search);
if (pos < 0)
{
return text;
}
return text.Substring(0, pos) + replace + text.Substring(pos + search.Length);
}
}
}
174 changes: 172 additions & 2 deletions Helpers/ProcessHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net.NetworkInformation;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
Expand All @@ -11,7 +12,14 @@ namespace WechatPCMsgBakTool.Helpers
{
public class ProcessHelper
{
public static Process? GetProcess(string ProcessName)
private const uint STATUS_INFO_LENGTH_MISMATCH = 0xC0000004;
private const int DUPLICATE_CLOSE_SOURCE = 0x1;
private const int DUPLICATE_SAME_ACCESS = 0x2;

private const int CNST_SYSTEM_HANDLE_INFORMATION = 0x10;
private const int OBJECT_TYPE_MUTANT = 17;

public static Process GetProcess(string ProcessName)
{
Process[] processes = Process.GetProcessesByName(ProcessName);
if (processes.Length == 0)
Expand All @@ -31,7 +39,6 @@ public class ProcessHelper
else
return processes[0];
}

public static ProcessModule? FindProcessModule(int ProcessId, string ModuleName)
{
Process process = Process.GetProcessById(ProcessId);
Expand All @@ -43,6 +50,100 @@ public class ProcessHelper
return null;
}

public static List<SYSTEM_HANDLE_INFORMATION> GetHandles(Process process)
{
List<SYSTEM_HANDLE_INFORMATION> aHandles = new List<SYSTEM_HANDLE_INFORMATION>();
int handle_info_size = Marshal.SizeOf(new SYSTEM_HANDLE_INFORMATION()) * 20000;
IntPtr ptrHandleData = IntPtr.Zero;
try
{
ptrHandleData = Marshal.AllocHGlobal(handle_info_size);
int nLength = 0;

while (NtQuerySystemInformation(CNST_SYSTEM_HANDLE_INFORMATION, ptrHandleData, handle_info_size, ref nLength) == STATUS_INFO_LENGTH_MISMATCH)
{
handle_info_size = nLength;
Marshal.FreeHGlobal(ptrHandleData);
ptrHandleData = Marshal.AllocHGlobal(nLength);
}

long handle_count = Marshal.ReadIntPtr(ptrHandleData).ToInt64();
IntPtr ptrHandleItem = ptrHandleData + Marshal.SizeOf(ptrHandleData);

for (long lIndex = 0; lIndex < handle_count; lIndex++)
{
SYSTEM_HANDLE_INFORMATION? oSystemHandleInfo = new SYSTEM_HANDLE_INFORMATION();
oSystemHandleInfo = Marshal.PtrToStructure(ptrHandleItem, oSystemHandleInfo.GetType()) as SYSTEM_HANDLE_INFORMATION?;
if (oSystemHandleInfo == null)
throw new Exception("获取SYSTEM_HANDLE_INFORMATION失败");
ptrHandleItem += Marshal.SizeOf(new SYSTEM_HANDLE_INFORMATION());
if (oSystemHandleInfo.Value.ProcessID != process.Id) { continue; }
aHandles.Add(oSystemHandleInfo.Value);
}
}
catch (Exception)
{
throw;
}
finally
{
Marshal.FreeHGlobal(ptrHandleData);
}
return aHandles;
}
public static string FindHandleName(SYSTEM_HANDLE_INFORMATION systemHandleInformation, Process process)
{
IntPtr ipHandle = IntPtr.Zero;
IntPtr openProcessHandle = IntPtr.Zero;
IntPtr hObjectName = IntPtr.Zero;
try
{
PROCESS_ACCESS_FLAGS flags = PROCESS_ACCESS_FLAGS.DupHandle | PROCESS_ACCESS_FLAGS.VMRead;
openProcessHandle = OpenProcess(flags, false, process.Id);
// 通过 DuplicateHandle 访问句柄
if (!DuplicateHandle(openProcessHandle, new IntPtr(systemHandleInformation.Handle), GetCurrentProcess(), out ipHandle, 0, false, DUPLICATE_SAME_ACCESS))
{
return "";
}

int nLength = 0;
hObjectName = Marshal.AllocHGlobal(256 * 1024);

// 查询句柄名称
while ((uint)(NtQueryObject(ipHandle, (int)OBJECT_INFORMATION_CLASS.ObjectNameInformation, hObjectName, nLength, ref nLength)) == STATUS_INFO_LENGTH_MISMATCH)
{
Marshal.FreeHGlobal(hObjectName);
if (nLength == 0)
{
Console.WriteLine("Length returned at zero!");
return "";
}
hObjectName = Marshal.AllocHGlobal(nLength);
}
OBJECT_NAME_INFORMATION? objObjectName = new OBJECT_NAME_INFORMATION();
objObjectName = Marshal.PtrToStructure(hObjectName, objObjectName.GetType()) as OBJECT_NAME_INFORMATION?;
if (objObjectName == null)
return "";
if (objObjectName.Value.Name.Buffer != IntPtr.Zero)
{
string? strObjectName = Marshal.PtrToStringUni(objObjectName.Value.Name.Buffer);
if (strObjectName != null)
return strObjectName;
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
Marshal.FreeHGlobal(hObjectName);
CloseHandle(ipHandle);
CloseHandle(openProcessHandle);
}
return "";
}
// 这里开始下面是对Windows API引用声明
public static byte[]? ReadMemoryDate(IntPtr hProcess, IntPtr lpBaseAddress, int nSize = 100)
{
byte[] array = new byte[nSize];
Expand All @@ -54,5 +155,74 @@ public class ProcessHelper

[DllImport("kernel32.dll")]
public static extern int ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, int nSize, int lpNumberOfBytesRead);
[DllImport("ntdll.dll")]
private static extern uint NtQuerySystemInformation(int SystemInformationClass, IntPtr SystemInformation, int SystemInformationLength, ref int returnLength);

[DllImport("kernel32.dll")]
private static extern IntPtr OpenProcess(PROCESS_ACCESS_FLAGS dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, int dwProcessId);

[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool DuplicateHandle(IntPtr hSourceProcessHandle, IntPtr hSourceHandle, IntPtr hTargetProcessHandle, out IntPtr lpTargetHandle, uint dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, uint dwOptions);

[DllImport("kernel32.dll")]
private static extern IntPtr GetCurrentProcess();

[DllImport("ntdll.dll")]
private static extern int NtQueryObject(IntPtr ObjectHandle, int ObjectInformationClass, IntPtr ObjectInformation, int ObjectInformationLength, ref int returnLength);

[DllImport("kernel32.dll")]
private static extern bool CloseHandle(IntPtr hObject);

[DllImport("kernel32.dll")]
private static extern bool GetHandleInformation(IntPtr hObject, out uint lpdwFlags);


[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct SYSTEM_HANDLE_INFORMATION
{ // Information Class 16
public ushort ProcessID;
public ushort CreatorBackTrackIndex;
public byte ObjectType;
public byte HandleAttribute;
public ushort Handle;
public IntPtr Object_Pointer;
public IntPtr AccessMask;
}
private enum OBJECT_INFORMATION_CLASS : int
{
ObjectBasicInformation = 0,
ObjectNameInformation = 1,
ObjectTypeInformation = 2,
ObjectAllTypesInformation = 3,
ObjectHandleInformation = 4
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
private struct OBJECT_NAME_INFORMATION
{
public UNICODE_STRING Name;
}
[StructLayout(LayoutKind.Sequential)]
private struct UNICODE_STRING
{
public ushort Length;
public ushort MaximumLength;
public IntPtr Buffer;
}
[Flags]
private enum PROCESS_ACCESS_FLAGS : uint
{
All = 0x001F0FFF,
Terminate = 0x00000001,
CreateThread = 0x00000002,
VMOperation = 0x00000008,
VMRead = 0x00000010,
VMWrite = 0x00000020,
DupHandle = 0x00000040,
SetInformation = 0x00000200,
QueryInformation = 0x00000400,
Synchronize = 0x00100000
}
}

}
58 changes: 57 additions & 1 deletion HtmlExport.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
using System;
using K4os.Compression.LZ4.Encoders;
using K4os.Compression.LZ4;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WechatPCMsgBakTool.Interface;
using WechatPCMsgBakTool.Model;
using System.Xml;

namespace WechatPCMsgBakTool
{
Expand Down Expand Up @@ -86,6 +89,59 @@ public void SetMsg(WXUserReader reader,WXContact contact)
}
HtmlBody += string.Format("<p class=\"content\"><video controls style=\"max-height:300px;max-width:300px;\"><source src=\"{0}\" type=\"video/mp4\" /></video></p></div>", path);
}
else if(msg.Type== 49)
{
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 = "";
string appName = "";
string url = "";
XmlNodeList? findNode = xmlObj.DocumentElement.SelectNodes("/msg/appmsg/title");
if(findNode != null)
{
if(findNode.Count > 0)
{
title = findNode[0]!.InnerText;
}
}
findNode = xmlObj.DocumentElement.SelectNodes("/msg/appmsg/sourcedisplayname");
if (findNode != null)
{
if (findNode.Count > 0)
{
appName = findNode[0]!.InnerText;
}
}
findNode = xmlObj.DocumentElement.SelectNodes("/msg/appmsg/url");
if (findNode != null)
{
if (findNode.Count > 0)
{
url = findNode[0]!.InnerText;
}
}
HtmlBody += string.Format("<p class=\"content\">{0}|{1}</p><p><a href=\"{2}\">点击访问</a></p></div>", appName, title, url);

}
}

}

}
else if (msg.Type == 34)
{
string? path = reader.GetAttachment(WXMsgType.Audio, msg);
Expand Down
6 changes: 4 additions & 2 deletions Main.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
using Newtonsoft.Json;
using K4os.Compression.LZ4;
using K4os.Compression.LZ4.Encoders;
using K4os.Compression.LZ4.Streams;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
Expand Down Expand Up @@ -173,7 +176,6 @@ private void Button_Click(object sender, RoutedEventArgs e)
return;
}


IExport export = new HtmlExport();
export.InitTemplate(wXContact);
export.SetMsg(UserReader, wXContact);
Expand Down
2 changes: 2 additions & 0 deletions Model/WXModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ public class WXMsg
public string StrTalker { get; set; } = "";
[Column("StrContent")]
public string StrContent { get; set; } = "";
[Column("CompressContent")]
public byte[]? CompressContent { get; set; }
}

[Table("Media")]
Expand Down
15 changes: 10 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,23 @@
微信PC聊天记录备份工具,仅支持Windows

- 支持3.9.6.33版本后,若版本更新可在version.json添加版本号和地址即可完成新版本支持
- 导出图片、视频、音频
- 导出图片、视频、音频、分享链接
- 导出Html文件
- 支持聊天频率分析,全消息库内容搜索

本项目仅做学习使用,主要供个人备份自己的微信记录,请勿用于非法用途。
本项目严禁商用。
** 本项目仅做学习使用,主要供个人备份自己的微信记录,请勿用于非法用途。 **
** 本项目严禁商用 **

如果有什么好的建议或意见,或者遇到什么问题,欢迎提issue,看到会回。
> [!NOTE]
> 反馈群:815054692
> 如果觉得不错,欢迎右上角点个star!这是对作者的鼓励,谢谢!
#### 使用
<p>1.打开微信,并登录。</p>
<p>2.在工作区上方点击新增,选择要创建的工作区微信</p>
<p>3.点新建会弹出Handle64的协议说明,同意即可。如没有内容显示,重新点一下新建即可</p>
<p>4.选中刚刚创建的工作区,点击解密。(如当前多开微信,请选择对应的微信进行解谜)</p>
<p>3.如同时运行多个微信,请选择微信,请注意通过路径进行区别</p>
<p>4.选中刚刚创建的工作区,点击解密。(如当前多开微信,请选择对应的微信进行解密)</p>
<p>5.选中刚刚创建的工作区,点击读取</p>
<p><b>尽情使用吧!</b></p>

Expand All @@ -30,3 +34,4 @@
##### [AdminTest0/SharpWxDump](https://github.com/AdminTest0/SharpWxDump)
##### [kn007/silk-v3-decoder](https://github.com/kn007/silk-v3-decoder)
##### [吾爱破解chenhahacjl/微信 DAT 图片解密 (C#)](https://www.52pojie.cn/forum.php?mod=viewthread&tid=1507922)
##### [huiyadanli/RevokeMsgPatcher](https://github.com/huiyadanli/RevokeMsgPatcher)
Loading

0 comments on commit cd90958

Please sign in to comment.