463 lines
19 KiB
C#
463 lines
19 KiB
C#
|
using System;
|
|||
|
using System.Collections;
|
|||
|
using System.Collections.Generic;
|
|||
|
using System.Diagnostics;
|
|||
|
using System.Drawing;
|
|||
|
using System.IO;
|
|||
|
using System.Linq;
|
|||
|
using System.Runtime.InteropServices;
|
|||
|
using System.Text;
|
|||
|
using System.Text.RegularExpressions;
|
|||
|
using System.Threading;
|
|||
|
using System.Threading.Tasks;
|
|||
|
using System.Web;
|
|||
|
using System.Web.Caching;
|
|||
|
using System.Windows.Forms;
|
|||
|
using CsharpHttpHelper;
|
|||
|
using Newtonsoft.Json;
|
|||
|
using PCRobot.Entitys;
|
|||
|
using PCRobot.Pack;
|
|||
|
using PCRobot.PCWechat.Enterprise;
|
|||
|
using PCRobot.Utils;
|
|||
|
using static PCRobot.PCWechat.Routine.Wechat_Xiaoxie_Type;
|
|||
|
|
|||
|
namespace PCRobot.PCWechat.Routine
|
|||
|
{
|
|||
|
public partial class Wechat_Xiaoxie : WechatRoutineBase
|
|||
|
{
|
|||
|
public Wechat_Xiaoxie(WechatUser User) : base(User)
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
public delegate void OnEvent(string Name, string Message);
|
|||
|
public static OnEvent ClickEvent;
|
|||
|
|
|||
|
#region 静态函数
|
|||
|
public static void Install()
|
|||
|
{
|
|||
|
if (IsInstall) return;
|
|||
|
|
|||
|
#region 自动登录新建设备信息,注册表开关
|
|||
|
try
|
|||
|
{
|
|||
|
if (Version == "3.4.0.38")
|
|||
|
{
|
|||
|
string Winrarpath = @"Software\Tencent\WeChat";
|
|||
|
string key = "FakeDeviceId";
|
|||
|
//yes为开,no为关
|
|||
|
RegistryHelper.SetRegistryKey("HKEY_CURRENT_USER", Winrarpath, key, "no");
|
|||
|
RegistryHelper.GetRegistryValue(Winrarpath, key);
|
|||
|
}
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
LogHelper.GetSingleObj().Error("自动登录新建设备信息", $"注册表操作异常:{ex.Message} - {ex.StackTrace}");
|
|||
|
}
|
|||
|
#endregion
|
|||
|
|
|||
|
ClickEvent?.Invoke("开始登录", "正在检测已登录微信,请稍等....");
|
|||
|
try
|
|||
|
{
|
|||
|
//Thread.Sleep(5000);
|
|||
|
//DllPath = HttpExtend.MapFile($"WeChatHelper_{Version}.dll", "Bin");
|
|||
|
m_AcceptCallbackFunc = WxAcceptCallback;
|
|||
|
m_RecvCallbackFunc = WxRecvCallback;
|
|||
|
m_CloseCallbackFunc = WxCloseCallback;
|
|||
|
UseUtf8();
|
|||
|
// 初始化Callback
|
|||
|
InitWeChatSocket(m_AcceptCallbackFunc, m_RecvCallbackFunc, m_CloseCallbackFunc);
|
|||
|
|
|||
|
DllPath = HttpExtend.MapFile($"WeChatHelper_{Version}.dll", "Bin");
|
|||
|
KillPc(true);
|
|||
|
}
|
|||
|
catch (Exception)
|
|||
|
{
|
|||
|
|
|||
|
}
|
|||
|
finally
|
|||
|
{
|
|||
|
IsInstall = true;
|
|||
|
ClickEvent?.Invoke("登录完成", "");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private static string DllPath;
|
|||
|
/// <summary>
|
|||
|
/// 微信WeChatWin.dll基址
|
|||
|
/// </summary>
|
|||
|
//private static IntPtr BaseAddress;
|
|||
|
|
|||
|
public delegate void AcceptCallbackFunc(uint dwClientId);
|
|||
|
public delegate void RecvCallbackFunc(uint dwClientId, IntPtr intPtr, uint dwSize);
|
|||
|
public delegate void CloseCallbackFunc(uint dwClientId);
|
|||
|
private static AcceptCallbackFunc m_AcceptCallbackFunc;
|
|||
|
private static RecvCallbackFunc m_RecvCallbackFunc;
|
|||
|
private static CloseCallbackFunc m_CloseCallbackFunc;
|
|||
|
|
|||
|
// 引入DLL导出函数
|
|||
|
[DllImport("Bin\\WeChatServer.dll")]
|
|||
|
public static extern bool InitWeChatSocket(AcceptCallbackFunc acceptCallback,
|
|||
|
RecvCallbackFunc recvCallback, CloseCallbackFunc closeCallback);
|
|||
|
[DllImport("Bin\\WeChatServer.dll")]
|
|||
|
public static extern uint InjectWeChat(byte[] strDllPath);
|
|||
|
//[DllImport("Bin\\WeChatServer.dll")]
|
|||
|
//public static extern bool SetLoginWxid(byte[] szWxid);
|
|||
|
|
|||
|
//BOOL __stdcall UseUtf8();
|
|||
|
[DllImport("Bin\\WeChatServer.dll")]
|
|||
|
public static extern bool UseUtf8();
|
|||
|
|
|||
|
[DllImport("Bin\\WeChatServer.dll")]
|
|||
|
public static extern bool GetUserWeChatVersion(StringBuilder v);
|
|||
|
|
|||
|
[DllImport("Bin\\WeChatServer.dll")]
|
|||
|
public static extern uint InjectWeChat2(byte[] dllPath, byte[] wechatPath);
|
|||
|
|
|||
|
[DllImport("Bin\\WeChatServer.dll")]
|
|||
|
public static extern uint InjectWeChatMultiOpen(byte[] dllPath, byte[] wechatPath);
|
|||
|
|
|||
|
[DllImport("Bin\\WeChatServer.dll", EntryPoint = "SendWeChatData")]
|
|||
|
public static extern bool _SendWeChatData(uint dwClienId, byte[] strJsonData);
|
|||
|
public bool SendWeChatData(uint dwClienId, string strJsonData)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
if (WechatClient.IsDebug)
|
|||
|
LogHelper.GetSingleObj().Debug("调试发送", $"{dwClienId} -> {strJsonData}");
|
|||
|
if (User != null && !string.IsNullOrEmpty(User.Wxid))
|
|||
|
{
|
|||
|
var json = HttpExtend.JsonToDictionary(strJsonData);
|
|||
|
var type = json["type"].ToString();
|
|||
|
MsgType msgType;
|
|||
|
if (!Enum.TryParse(type, out msgType)) return false;
|
|||
|
switch (msgType)
|
|||
|
{
|
|||
|
//截取发送消息 - 为是否是辅助输入提供判断
|
|||
|
case MsgType.MT_SEND_TEXTMSG:
|
|||
|
case MsgType.MT_SEND_CHATROOM_ATMSG:
|
|||
|
case MsgType.MT_SEND_CARDMSG:
|
|||
|
case MsgType.MT_SEND_XMLMSG:
|
|||
|
case MsgType.MT_SEND_IMGMSG:
|
|||
|
case MsgType.MT_SEND_FILEMSG:
|
|||
|
case MsgType.MT_SEND_VIDEOMSG:
|
|||
|
case MsgType.MT_SEND_GIFMSG:
|
|||
|
{
|
|||
|
json = json["data"] as Dictionary<string, object>;
|
|||
|
string to_wxid = json["to_wxid"].ToString();
|
|||
|
string message = string.Empty;
|
|||
|
if (json.ContainsKey("content")) message = json["content"].ToString();
|
|||
|
else if (json.ContainsKey("card_wxid")) message = json["card_wxid"].ToString();
|
|||
|
else if (json.ContainsKey("xml")) message = json["xml"].ToString();
|
|||
|
else if (json.ContainsKey("file")) message = json["file"].ToString();
|
|||
|
if (!string.IsNullOrEmpty(message))
|
|||
|
Common.SetCache(User.Wxid, to_wxid, message);
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
return _SendWeChatData(dwClienId, Encoding.UTF8.GetBytes(strJsonData));
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, $"{ex.Message} - {ex.StackTrace}");
|
|||
|
}
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
//[DllImport("Bin\\WeChatServer.dll")]
|
|||
|
[DllImport("Bin\\WeChatServer.dll")]
|
|||
|
public static extern bool DestroyWeChat();
|
|||
|
|
|||
|
[DllImport("Bin\\WeChatServer.dll")]
|
|||
|
public static extern uint InjectWeChatPid(int dwPid, byte[] dllPath);
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 卸载安装
|
|||
|
/// </summary>
|
|||
|
public static void UnInstall()
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
DestroyWeChat();
|
|||
|
LogHelper.GetSingleObj().Info(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, "卸载成功");
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#region 微信版本基础变量
|
|||
|
|
|||
|
//private const string Version = "2.9.5.41";
|
|||
|
//private const int PcOffSet = 0x1769E00;//2.9.5.41
|
|||
|
//private const string PcMd5 = "194F44DF80553326711A4F576FE7166E";//2.9.5.41
|
|||
|
|
|||
|
//private const string Version = "3.3.0.93";
|
|||
|
//private const int PcOffSet = 0x1DAEB90;//3.3.0.93
|
|||
|
//private const string PcMd5 = "5EE8A5B9D4EE63BE1813632D8A7B2E77";//3.3.0.93
|
|||
|
|
|||
|
private const string Version = "3.4.0.38";
|
|||
|
private const int PcOffSet = 0x1DEE968;//3.4.0.38
|
|||
|
private const string PcMd5 = "AB0916C9949178A786192B188892AE2C";//3.4.0.38
|
|||
|
#endregion
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 杀死注入 pc
|
|||
|
/// </summary>
|
|||
|
/// <param name="isInject"></param>
|
|||
|
private static void KillPc(bool isInject = false)
|
|||
|
{
|
|||
|
Process[] MyProcesses = Process.GetProcesses();
|
|||
|
|
|||
|
var path1 = HttpExtend.MapPath("PCWechat");
|
|||
|
var path2 = HttpExtend.MapPath("PCWechat\\" + Version);
|
|||
|
//var path3 = HttpExtend.MapPath("PCWechat\\" + "3.3.0.93");//退出上个版本的微信
|
|||
|
foreach (Process MyProcess in MyProcesses)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
var name = MyProcess.ProcessName.ToUpper();
|
|||
|
if (name == "WECHAT" && MyProcess.MainModule.FileName.StartsWith(path1))
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
#region 退掉这个版本的微信
|
|||
|
//if (MyProcess.MainModule.FileName.StartsWith(path3))
|
|||
|
//{
|
|||
|
// try
|
|||
|
// {
|
|||
|
// LogHelper.GetSingleObj().Info("主动Q", "版本不对杀死进程:" + MyProcess.Id);
|
|||
|
// MyProcess.Kill();
|
|||
|
// }
|
|||
|
// catch (Exception)
|
|||
|
// { }
|
|||
|
//}
|
|||
|
#endregion
|
|||
|
|
|||
|
//判断微信版本
|
|||
|
if (MyProcess.MainModule.FileName.StartsWith(path2))
|
|||
|
{
|
|||
|
var id = MyProcess.Id;
|
|||
|
if (isInject)
|
|||
|
{
|
|||
|
var result = Task<bool>.Factory.StartNew(delegate
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
var WechatWinFile = HttpExtend.MapFile("WeChatWin.dll", $"PCWechat\\" + Version);
|
|||
|
var md5 = Common.GetMD5Hash(WechatWinFile);
|
|||
|
if (!File.Exists(WechatWinFile) || md5 != PcMd5.ToUpper())
|
|||
|
{
|
|||
|
return false;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
LogHelper.GetSingleObj().Info("系统", $"开始注入进程:{id}...");
|
|||
|
uint uin = InjectWeChatPid(id, Encoding.UTF8.GetBytes(DllPath));
|
|||
|
LogHelper.GetSingleObj().Info("系统", $"注入成功:{id},句柄ID:{uin}");
|
|||
|
return true;
|
|||
|
}
|
|||
|
}
|
|||
|
catch (Exception)
|
|||
|
{
|
|||
|
}
|
|||
|
return false;
|
|||
|
}).Wait(30000);
|
|||
|
if (!result)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
LogHelper.GetSingleObj().Info("系统c", "杀死进程:" + MyProcess.Id);
|
|||
|
MyProcess.Kill();
|
|||
|
}
|
|||
|
catch (Exception)
|
|||
|
{ }
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
LogHelper.GetSingleObj().Info("主动d", "杀死进程:" + MyProcess.Id);
|
|||
|
MyProcess.Kill();
|
|||
|
}
|
|||
|
catch (Exception)
|
|||
|
{ }
|
|||
|
}
|
|||
|
Thread.Sleep(10);
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
catch (Exception)
|
|||
|
{ }
|
|||
|
}
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public static uint StartWechat(string wxid, bool isError = false)
|
|||
|
{
|
|||
|
var path = string.Empty;
|
|||
|
|
|||
|
var WechatWinFile = HttpExtend.MapFile("WeChatWin.dll", $"PCWechat\\" + Version);
|
|||
|
var md5 = Common.GetMD5Hash(WechatWinFile);
|
|||
|
if (!File.Exists(WechatWinFile) || md5.ToUpper() != PcMd5.ToUpper())
|
|||
|
{
|
|||
|
if (isError) throw new Exception("易转发客户端微信版本不支持,请登录易转发端手动处理");
|
|||
|
var rst = MessageBox.Show("您的微信版本暂时不支持,立即重新安装吗?", "版本不兼容", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
|
|||
|
if (rst == DialogResult.Yes)
|
|||
|
{
|
|||
|
var f = new WechatUpdate(Version);
|
|||
|
f.ShowDialog();
|
|||
|
if (!f.IsOk) return 0;
|
|||
|
}
|
|||
|
else return 0;
|
|||
|
}
|
|||
|
path = HttpExtend.MapFile("WeChat.exe", $"PCWechat\\" + Version);
|
|||
|
|
|||
|
//WechatLoginHelper.BeginLogin(wxid);
|
|||
|
|
|||
|
//var ss = SetLoginWxid(Encoding.UTF8.GetBytes(""));
|
|||
|
//返回dwClientId
|
|||
|
var pid = InjectWeChat2(Encoding.UTF8.GetBytes(DllPath), Encoding.UTF8.GetBytes(path));
|
|||
|
|
|||
|
//WechatLoginHelper.ClickLogin((int)pid);
|
|||
|
|
|||
|
return pid;
|
|||
|
|
|||
|
//return InjectWeChatMultiOpen(Encoding.UTF8.GetBytes(DllPath), Encoding.UTF8.GetBytes(path));
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 远程登录微信
|
|||
|
/// </summary>
|
|||
|
public static List<RemoteLoginCode> RemoteLoginCodes = new List<RemoteLoginCode>();
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 是否在获取二维码
|
|||
|
/// </summary>
|
|||
|
private static string RemoteCache = "get_login_code_cache";
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// pc微信登录二维码
|
|||
|
/// </summary>
|
|||
|
/// <param name="ServerMsgID"></param>
|
|||
|
public static void LoginQrcode(string wxid, string ServerMsgID)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
RemoteLoginCode result = null;
|
|||
|
try
|
|||
|
{
|
|||
|
StartWechat(wxid, true);
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
result = new RemoteLoginCode() { pid = -1, rType = RobotType.客户端微信, b64Md5 = ex.Message };
|
|||
|
}
|
|||
|
|
|||
|
if (result == null)
|
|||
|
{
|
|||
|
result = Task.Factory.StartNew<RemoteLoginCode>(delegate ()
|
|||
|
{
|
|||
|
var awaitTime = DateTime.Now.AddSeconds(10);
|
|||
|
do
|
|||
|
{
|
|||
|
Thread.Sleep(200);
|
|||
|
Cache cache = HttpRuntime.Cache;
|
|||
|
object item = cache[RemoteCache];
|
|||
|
if (item != null)
|
|||
|
{
|
|||
|
cache.Remove(RemoteCache);
|
|||
|
var r = item as RemoteLoginCode;
|
|||
|
return r;
|
|||
|
}
|
|||
|
} while (awaitTime >= DateTime.Now);
|
|||
|
return null;
|
|||
|
}).Result;
|
|||
|
}
|
|||
|
var socketClient = EasySoc.GetSocket();
|
|||
|
var msg = new CommonResult();
|
|||
|
msg.RobotUsername = string.Empty;
|
|||
|
msg.RobotUsernick = string.Empty;
|
|||
|
msg.RobotType = RobotType.客户端微信;
|
|||
|
msg.MsgId = ServerMsgID;
|
|||
|
msg.Cmd = PCRobotCMD.rcvLoginCode;
|
|||
|
msg.Data = result == null ? string.Empty : JsonConvert.SerializeObject(result);
|
|||
|
|
|||
|
socketClient.Send(msg);
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 等待登录结果
|
|||
|
/// </summary>
|
|||
|
public static Dictionary<string, string> WaitLoginResult = new Dictionary<string, string>();
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 本地解密dat图片
|
|||
|
/// </summary>
|
|||
|
/// <param name="FileName"></param>
|
|||
|
/// <param name="XorKey"></param>
|
|||
|
/// <returns></returns>
|
|||
|
public static string DecodeImage(string FileName, byte XorKey, string DecodeImagePath)
|
|||
|
{
|
|||
|
var data = File.ReadAllBytes(FileName);
|
|||
|
for (int i = 0; i < data.Length; i++)
|
|||
|
data[i] = Convert.ToByte(data[i] ^ XorKey);
|
|||
|
//var path = FileName.Replace(Path.GetFileName(FileName), Path.GetFileNameWithoutExtension(FileName) + ".jpg");
|
|||
|
File.WriteAllBytes(DecodeImagePath, data);
|
|||
|
return DecodeImagePath;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 获取微信的uin的值
|
|||
|
/// </summary>
|
|||
|
/// <param name="pid"></param>
|
|||
|
/// <returns></returns>
|
|||
|
public static string GetUin(int pid)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
Process[] processes = Process.GetProcesses();
|
|||
|
foreach (Process process in processes)
|
|||
|
{
|
|||
|
if (process.Id == pid)
|
|||
|
{
|
|||
|
foreach (ProcessModule processModule in process.Modules)
|
|||
|
{
|
|||
|
if (processModule.ModuleName == "WeChatWin.dll")
|
|||
|
{
|
|||
|
//微信基址
|
|||
|
var WeChatWinBaseAddress = processModule.BaseAddress;
|
|||
|
//Console.WriteLine("微信基址:\t" + "0x" + ((int)(processModule.BaseAddress)).ToString("X8") + Environment.NewLine);
|
|||
|
var WxNameAddress = WeChatWinBaseAddress + PcOffSet;
|
|||
|
var uinStr = Common.GetString(process.Handle, WxNameAddress, 4);
|
|||
|
//Console.WriteLine($"uinStr = {uinStr}");
|
|||
|
return uinStr;
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
catch (Exception)
|
|||
|
{ }
|
|||
|
return string.Empty;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
#endregion
|
|||
|
|
|||
|
}
|
|||
|
}
|