diff --git a/Attributes/CustomEvent.cs b/Attributes/CustomEvent.cs index 90056cf..afeacf3 100644 --- a/Attributes/CustomEvent.cs +++ b/Attributes/CustomEvent.cs @@ -7,7 +7,7 @@ public class CustomEvent : Attribute { private readonly string windowName; - public string WindowName { get { return windowName; } } + public string WindowName => windowName; public CustomEvent(string windowName) { diff --git a/Attributes/TLVParser.cs b/Attributes/TLVParser.cs index d2d5914..109bf7e 100644 --- a/Attributes/TLVParser.cs +++ b/Attributes/TLVParser.cs @@ -7,7 +7,8 @@ public class TLVParser : Attribute { private readonly short cmd; - public short Cmd { get { return cmd; } } + public short Cmd => cmd; + public TLVParser(short cmd) { this.cmd = cmd; diff --git a/Common/Common.cs b/Common/Common.cs index cda2f85..4554017 100644 --- a/Common/Common.cs +++ b/Common/Common.cs @@ -46,12 +46,12 @@ public static byte[] TeaKeyLogDecrypt(byte[] In, out DecryptionKey decryptionKey { decryptionKey = null; List keys = Keys.ToList(); - for (int i = 0; i < keys.Count; i++) + foreach (DecryptionKey t in keys) { - var d = Tea.Decrypt(In, HexUtil.DecodeHex(keys[i].Key)); + var d = Tea.Decrypt(In, t.Key.DecodeHex()); if (d != null) { - decryptionKey = keys[i]; + decryptionKey = t; return d; } } diff --git a/Common/HookData.cs b/Common/HookData.cs index 6f97cc0..40d295c 100644 --- a/Common/HookData.cs +++ b/Common/HookData.cs @@ -2,7 +2,7 @@ { public static class HookData { - private static FormMain Frm { get => FormMain.Form; } + private static FormMain Frm => FormMain.Form; #region Hook Data public static string _androidId = string.Empty; diff --git a/Component/PacketAnalyzer.cs b/Component/PacketAnalyzer.cs index c99d899..612ad36 100644 --- a/Component/PacketAnalyzer.cs +++ b/Component/PacketAnalyzer.cs @@ -85,7 +85,7 @@ protected void Resolve0A01() } int qq_len = Buf.ReadInt() - 4; Uin = Buf.ReadCharSequence(qq_len, Encoding.UTF8).ToString(); - byte[] remaining = Util.ReadRemainingBytes(Buf); + byte[] remaining = Buf.ReadRemainingBytes(); byte[] decrypt_data = Common.TeaKeyLogDecrypt(remaining, out _); if (decrypt_data == null) return; var buf_part1 = Unpooled.WrappedBuffer(decrypt_data); @@ -126,7 +126,7 @@ protected void Resolve0A02() Buf.ReadByte(); int qq_len = Buf.ReadInt() - 4; Uin = Buf.ReadCharSequence(qq_len, Encoding.UTF8).ToString(); - byte[] remaining = Util.ReadRemainingBytes(Buf); + byte[] remaining = Buf.ReadRemainingBytes(); byte[] decrypt_data = Tea.Decrypt(remaining, new byte[16]); if (decrypt_data == null) return; var buf_part1 = Unpooled.WrappedBuffer(decrypt_data); @@ -203,7 +203,7 @@ protected void Resolve0B01() Buf.ReadByte(); int qq_len = Buf.ReadInt() - 4; Uin = Buf.ReadCharSequence(qq_len, Encoding.UTF8).ToString(); - byte[] remaining = Util.ReadRemainingBytes(Buf); + byte[] remaining = Buf.ReadRemainingBytes(); byte[] decrypt_data = Common.TeaKeyLogDecrypt(remaining, out _); if (decrypt_data == null) return; var buf_part1 = Unpooled.WrappedBuffer(decrypt_data); @@ -227,7 +227,7 @@ protected void Resolve0B02() Buf.ReadByte(); int qq_len = Buf.ReadInt() - 4; Uin = Buf.ReadCharSequence(qq_len, Encoding.UTF8).ToString(); - byte[] remaining = Util.ReadRemainingBytes(Buf); + byte[] remaining = Buf.ReadRemainingBytes(); byte[] decrypt_data = Tea.Decrypt(remaining, new byte[16]); if (decrypt_data == null) return; var buf_part1 = Unpooled.WrappedBuffer(decrypt_data); @@ -244,7 +244,7 @@ protected void Resolve0B02() Buf.ReadByte(); int qq_len = Buf.ReadInt() - 4; Uin = Buf.ReadCharSequence(qq_len, Encoding.UTF8).ToString(); - byte[] remaining = Util.ReadRemainingBytes(Buf); + byte[] remaining = Buf.ReadRemainingBytes(); byte[] decrypt_data = Tea.Decrypt(remaining, new byte[16]); if (decrypt_data == null) return; var buf_part1 = Unpooled.WrappedBuffer(decrypt_data); diff --git a/Component/PacketFormatter.cs b/Component/PacketFormatter.cs index 6aeef66..b48d68e 100644 --- a/Component/PacketFormatter.cs +++ b/Component/PacketFormatter.cs @@ -16,7 +16,7 @@ public string Parse(IByteBuffer value) ReadPacketLen(); int packet_type = Buf.ReadInt(); byte encrypt_type = Buf.ReadByte(); - + if (packet_type == 0x0A) { Sb.Append(packet_type.HexPadLeft().HexDump()).Append(" //packet_type").AppendLine(); @@ -69,7 +69,7 @@ public string Parse(IByteBuffer value) } return Sb.ToString(); } - + private void ReadPacketLen() { int packet_len = Buf.ReadInt(); @@ -95,7 +95,7 @@ private void Resolve0A02() Sb.Append((uin_len + 4).HexPadLeft().HexDump()).Append(" //uin_len").AppendLine(); Sb.Append(Encoding.UTF8.GetBytes(Uin).HexDump()).Append($" //uin {Uin}").AppendLine(); - byte[] remaining = Util.ReadRemainingBytes(Buf); + byte[] remaining = Buf.ReadRemainingBytes(); Sb.Append(remaining.HexDump()).AppendLine().AppendLine(); byte[] decrypt_data = Common.TeaKeyLogDecrypt(remaining, out DecryptionKey decryptionKey); diff --git a/Component/PacketLogLVI.cs b/Component/PacketLogLVI.cs new file mode 100644 index 0000000..8f20cf7 --- /dev/null +++ b/Component/PacketLogLVI.cs @@ -0,0 +1,34 @@ +using System.Windows.Forms; + +namespace YgAndroidQQSniffer.Component +{ + public class PacketLogLVI + { + public string Index { get; set; } + public string Orientation { get; set; } + public string SrcIp { get; set; } + public string DstIp { get; set; } + public string CaptureTime { get; set; } + public string PayloadLen { get; set; } + public string PayloadData { get; set; } + public object Tag { get; set; } + + public ListViewItem BuildLVI() + { + return new ListViewItem() + { + Text = Index, + SubItems = + { + Orientation, + SrcIp, + DstIp, + CaptureTime, + PayloadLen, + PayloadData + }, + Tag = Tag + }; + } + } +} diff --git a/Component/RealTimePacketsAnalyzer.cs b/Component/RealTimePacketsAnalyzer.cs new file mode 100644 index 0000000..7208eea --- /dev/null +++ b/Component/RealTimePacketsAnalyzer.cs @@ -0,0 +1,164 @@ +using DotNetty.Buffers; +using DotNetty.Common.Utilities; +using NLog; +using PacketDotNet; +using System; +using System.Collections; +using System.Drawing; +using System.Net; +using System.Threading; +using System.Windows.Forms; +using static System.Collections.StructuralComparisons; + +namespace YgAndroidQQSniffer.Component +{ + public class RealTimePacketsAnalyzer + { + public string MatchedSrcIp { get; private set; } + public string MatchedDstIp { get; private set; } + public string MatchedSrcPort { get; private set; } + public string MatchedDstPort { get; private set; } + private IByteBuffer MatchedPayloadBuf { get; set; } + + private readonly byte[] ZERO_BYTES = { 0 }; + private static FormMain Frm => FormMain.Form; + private static Logger Logger { get; } = LogManager.GetCurrentClassLogger(); + + public void ProcessPackets(TcpPacket tcpPacket) + { + IPPacket ipPacket = (IPPacket)tcpPacket.ParentPacket; + IPAddress srcIp = ipPacket.SourceAddress; + IPAddress dstIp = ipPacket.DestinationAddress; + int srcPort = tcpPacket.SourcePort; + int dstPort = tcpPacket.DestinationPort; + + if (tcpPacket.PayloadData.Length == 0 || tcpPacket.PayloadData == ZERO_BYTES) return; + + if (MatchedDstIp == null) + { + //首次捕获 + IByteBuffer buf = Unpooled.WrappedBuffer(tcpPacket.PayloadData); + try + { + if (IsAndroidQQProtocol(buf)) + { + MatchedPayloadBuf.WriteBytes(tcpPacket.PayloadData); + MatchedSrcIp = srcIp.ToString(); + MatchedDstIp = dstIp.ToString(); + MatchedSrcPort = srcPort.ToString(); + MatchedDstPort = dstPort.ToString(); + } + } + finally + { + buf.SafeRelease(); + } + } + else + { + if (srcIp.ToString() == MatchedDstIp || dstIp.ToString() == MatchedDstIp) + { + MatchedPayloadBuf.WriteBytes(tcpPacket.PayloadData); + } + } + } + + public void StartAnalysisThread() + { + MatchedPayloadBuf = Unpooled.Buffer(); + new Thread(() => + { + while (Frm.Device.Started) + { + try + { + while (MatchedPayloadBuf.IsReadable()) + { + if (IsAndroidQQProtocol(MatchedPayloadBuf)) + { + string orientation = (MatchedPayloadBuf.GetInt(MatchedPayloadBuf.ReaderIndex + 9) == 0) ? "Recv" : "Send"; + int pkg_len = MatchedPayloadBuf.GetInt(MatchedPayloadBuf.ReaderIndex); + byte[] pkg_payload = new byte[pkg_len]; + if (MatchedPayloadBuf.ReadableBytes >= pkg_payload.Length) + { + MatchedPayloadBuf.ReadBytes(pkg_payload, 0, pkg_payload.Length); + AppendPacketLogItems(orientation, pkg_payload); + MatchedPayloadBuf.DiscardReadBytes(); + } + } + else if (MatchedPayloadBuf.ReadableBytes >= 9) + { + MatchedPayloadBuf.ReadBytes(9); + } + else + { + Thread.Sleep(1000); + } + } + } + catch (Exception ex) + { + Logger.Error(ex, ex.Message); + } + Thread.Sleep(1000); + } + Logger.Info("The analysis thread has stopped."); + MatchedSrcIp = null; + MatchedDstIp = null; + MatchedSrcPort = null; + MatchedDstPort = null; + MatchedPayloadBuf.SafeRelease(); + }).Start(); + } + + private void AppendPacketLogItems(string orientation, byte[] payload) + { + PacketLogLVI pl = new PacketLogLVI() + { + Index = (Frm.lv_packet_log.Items.Count + 1).ToString(), + Orientation = orientation, + + CaptureTime = DateTime.Now.ToString(), + PayloadLen = payload.Length.ToString(), + PayloadData = payload.HexDump(), + Tag = new PacketAnalyzer() { HexPayload = payload.HexDump() } + }; + if (orientation == "Send") + { + pl.SrcIp = $"{MatchedSrcIp}:{MatchedSrcPort}"; + pl.DstIp = $"{MatchedDstIp}:{MatchedDstPort}"; + } + else + { + pl.SrcIp = $"{MatchedDstIp}:{MatchedDstPort}"; + pl.DstIp = $"{MatchedSrcIp}:{MatchedSrcPort}"; + } + + Frm.ThreadSafeUpdate(() => + { + ListViewItem lv = pl.BuildLVI(); + lv.ForeColor = orientation == "Send" ? Color.Red : Color.Blue; + Frm.lv_packet_log.Items.Add(lv); + }); + } + + private readonly byte[] ANDROIDQQ_PROTOCOL_MARK1 = { 0x00, 0x00, 0x00, 0x0A, 0x00 }; + private readonly byte[] ANDROIDQQ_PROTOCOL_MARK2 = { 0x00, 0x00, 0x00, 0x0A, 0x01 }; + private readonly byte[] ANDROIDQQ_PROTOCOL_MARK3 = { 0x00, 0x00, 0x00, 0x0A, 0x02 }; + private readonly byte[] ANDROIDQQ_PROTOCOL_MARK4 = { 0x00, 0x00, 0x00, 0x0B, 0x00 }; + private readonly byte[] ANDROIDQQ_PROTOCOL_MARK5 = { 0x00, 0x00, 0x00, 0x0B, 0x01 }; + private readonly byte[] ANDROIDQQ_PROTOCOL_MARK6 = { 0x00, 0x00, 0x00, 0x0B, 0x02 }; + private bool IsAndroidQQProtocol(IByteBuffer buffer) + { + if (buffer.ReadableBytes < 9) return false; + byte[] tag = new byte[5]; + buffer.GetBytes(buffer.ReaderIndex + 4, tag, 0, 5); + return ((IStructuralEquatable)tag).Equals(ANDROIDQQ_PROTOCOL_MARK1, StructuralEqualityComparer) || + ((IStructuralEquatable)tag).Equals(ANDROIDQQ_PROTOCOL_MARK2, StructuralEqualityComparer) || + ((IStructuralEquatable)tag).Equals(ANDROIDQQ_PROTOCOL_MARK3, StructuralEqualityComparer) || + ((IStructuralEquatable)tag).Equals(ANDROIDQQ_PROTOCOL_MARK4, StructuralEqualityComparer) || + ((IStructuralEquatable)tag).Equals(ANDROIDQQ_PROTOCOL_MARK5, StructuralEqualityComparer) || + ((IStructuralEquatable)tag).Equals(ANDROIDQQ_PROTOCOL_MARK6, StructuralEqualityComparer); + } + } +} \ No newline at end of file diff --git a/Form/FormMain.Designer.cs b/Form/FormMain.Designer.cs index 8ce9468..cc719ed 100644 --- a/Form/FormMain.Designer.cs +++ b/Form/FormMain.Designer.cs @@ -134,6 +134,7 @@ private void InitializeComponent() this.btn_tool_read_keys = new System.Windows.Forms.Button(); this.txt_tool_keys = new System.Windows.Forms.TextBox(); this.tabPage4 = new System.Windows.Forms.TabPage(); + this.btn_decrypt_byte_by_byte = new System.Windows.Forms.Button(); this.btn_tea_key_log_decrypt = new System.Windows.Forms.Button(); this.btn_tea_copy_decrypt_data = new System.Windows.Forms.Button(); this.btn_tea_decrypt = new System.Windows.Forms.Button(); @@ -168,12 +169,11 @@ private void InitializeComponent() this.Orientation = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.SrcIp = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.DstIp = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.time = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.CaptureTime = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.PayloadLen = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.PayloadData = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.r_txt_log = new System.Windows.Forms.RichTextBox(); this.tabControl1 = new System.Windows.Forms.TabControl(); - this.btn_decrypt_byte_by_byte = new System.Windows.Forms.Button(); this.ctxMenuStrip_analysis_tools.SuspendLayout(); this.ctxMenuStrip_packets.SuspendLayout(); this.ctxMenuStrip_trace_flow.SuspendLayout(); @@ -1138,6 +1138,15 @@ private void InitializeComponent() this.tabPage4.Text = "TEA加解密"; this.tabPage4.UseVisualStyleBackColor = true; // + // btn_decrypt_byte_by_byte + // + this.btn_decrypt_byte_by_byte.Location = new System.Drawing.Point(804, 8); + this.btn_decrypt_byte_by_byte.Name = "btn_decrypt_byte_by_byte"; + this.btn_decrypt_byte_by_byte.Size = new System.Drawing.Size(121, 23); + this.btn_decrypt_byte_by_byte.TabIndex = 10; + this.btn_decrypt_byte_by_byte.Text = "逐字节KEY日志解密"; + this.btn_decrypt_byte_by_byte.UseVisualStyleBackColor = true; + // // btn_tea_key_log_decrypt // this.btn_tea_key_log_decrypt.Location = new System.Drawing.Point(693, 8); @@ -1424,7 +1433,7 @@ private void InitializeComponent() this.Orientation, this.SrcIp, this.DstIp, - this.time, + this.CaptureTime, this.PayloadLen, this.PayloadData}); this.lv_packet_log.ContextMenuStrip = this.ctxMenuStrip_packets; @@ -1457,10 +1466,10 @@ private void InitializeComponent() this.DstIp.Text = "目的地址"; this.DstIp.Width = 120; // - // time + // CaptureTime // - this.time.Text = "捕获时间"; - this.time.Width = 126; + this.CaptureTime.Text = "捕获时间"; + this.CaptureTime.Width = 126; // // PayloadLen // @@ -1500,15 +1509,6 @@ private void InitializeComponent() this.tabControl1.Size = new System.Drawing.Size(1128, 609); this.tabControl1.TabIndex = 7; // - // btn_decrypt_byte_by_byte - // - this.btn_decrypt_byte_by_byte.Location = new System.Drawing.Point(804, 8); - this.btn_decrypt_byte_by_byte.Name = "btn_decrypt_byte_by_byte"; - this.btn_decrypt_byte_by_byte.Size = new System.Drawing.Size(121, 23); - this.btn_decrypt_byte_by_byte.TabIndex = 10; - this.btn_decrypt_byte_by_byte.Text = "逐字节KEY日志解密"; - this.btn_decrypt_byte_by_byte.UseVisualStyleBackColor = true; - // // FormMain // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); @@ -1629,7 +1629,7 @@ private void InitializeComponent() private System.Windows.Forms.ColumnHeader Orientation; private System.Windows.Forms.ColumnHeader SrcIp; private System.Windows.Forms.ColumnHeader DstIp; - private System.Windows.Forms.ColumnHeader time; + private System.Windows.Forms.ColumnHeader CaptureTime; private System.Windows.Forms.ColumnHeader PayloadLen; private System.Windows.Forms.ColumnHeader PayloadData; private System.Windows.Forms.TabControl tabControl1; diff --git a/Form/FormMain.cs b/Form/FormMain.cs index 16e7757..af7abc5 100644 --- a/Form/FormMain.cs +++ b/Form/FormMain.cs @@ -7,7 +7,6 @@ using System.Collections.Generic; using System.Drawing; using System.Linq; -using System.Net; using System.Text; using System.Threading; using System.Windows.Forms; @@ -21,7 +20,9 @@ public partial class FormMain : Form { public static FormMain Form { get; private set; } - public static Logger Logger { get; set; } = LogManager.GetCurrentClassLogger(); + private static Logger Logger { get; } = LogManager.GetCurrentClassLogger(); + + private RealTimePacketsAnalyzer RealTimePacketsAnalyzer { get; } = new RealTimePacketsAnalyzer(); public FormMain() { @@ -110,6 +111,7 @@ public void Log(string text) Clipboard.SetText(text); r_txt_log.Paste(); Clipboard.SetText(old_text); + r_txt_log.Select(old_start + old_length, 0); } public void Log(string text, params object[] args) { @@ -121,7 +123,7 @@ public void Log(string text, params object[] args) /// /// 当前下拉框选中的网卡 /// - private ICaptureDevice Device { get; set; } + public ICaptureDevice Device { get; set; } /// /// 当前下拉框选中的网卡的IP /// @@ -300,8 +302,9 @@ private void Button_start_capture_Click(object sender, EventArgs e) lv_packet_log.Items.Clear(); Device.Open(DeviceMode.Normal, 1000); Device.Filter = "tcp port 8080 or tcp port 14000 or tcp port 443"; - Device.OnPacketArrival += new PacketArrivalEventHandler(Device_OnPacketArrival); + Device.OnPacketArrival += Device_OnPacketArrival; Device.StartCapture(); + RealTimePacketsAnalyzer.StartAnalysisThread(); } private void Button_stop_capture_Click(object sender, EventArgs e) @@ -310,12 +313,14 @@ private void Button_stop_capture_Click(object sender, EventArgs e) { try { - _dstIp = null; Device.OnPacketArrival -= new PacketArrivalEventHandler(Device_OnPacketArrival); Device.StopCapture(); Device.Close(); } - catch (Exception) { } + catch (Exception) + { + // ignored + } } } @@ -323,247 +328,17 @@ private void Button_clear_packet_log_Click(object sender, EventArgs e) { lv_packet_log.Items.Clear(); } - private string _dstIp { get; set; } + private void Device_OnPacketArrival(object sender, CaptureEventArgs e) { - var time = e.Packet.Timeval.Date.ToLocalTime(); - var len = e.Packet.Data.Length; + var captureTime = e.Packet.Timeval.Date.ToLocalTime(); var packet = PacketDotNet.Packet.ParsePacket(e.Packet.LinkLayerType, e.Packet.Data); var tcpPacket = packet.Extract(); - if (tcpPacket != null) - { - var ipPacket = (PacketDotNet.IPPacket)tcpPacket.ParentPacket; - IPAddress srcIp = ipPacket.SourceAddress; - IPAddress dstIp = ipPacket.DestinationAddress; - int srcPort = tcpPacket.SourcePort; - int dstPort = tcpPacket.DestinationPort; - string data = tcpPacket.PayloadData.HexDump(); - int payload_len = tcpPacket.PayloadData.Length; - - if (payload_len == 0 || data == "00") return; - - string orientation = string.Empty; - if (srcIp.ToString() == SelectedDeviceIpAddr) - { - orientation = "Send"; - } - else - { - orientation = "Recv"; - } - ListViewItem lv = null; - if (_dstIp == null) - { - //首次捕获 - var buf = Unpooled.WrappedBuffer(HexUtil.DecodeHex(data)); - try - { - if (buf.ReadableBytes < 9) return; - byte[] tag = new byte[5]; - buf.GetBytes(buf.ReaderIndex + 4, tag, 0, 5); - switch (tag.HexDump()) - { - case "00 00 00 0A 00": - case "00 00 00 0A 01": - case "00 00 00 0A 02": - case "00 00 00 0B 00": - case "00 00 00 0B 01": - case "00 00 00 0B 02": - _dstIp = dstIp.ToString(); - lv = new ListViewItem() - { - Text = (lv_packet_log.Items.Count + 1).ToString(), - SubItems = - { - orientation, - $"{srcIp}:{srcPort}", - $"{dstIp}:{dstPort}", - time.ToString(), - payload_len.ToString(), - data, - tcpPacket.SequenceNumber.ToString(), - tcpPacket.AcknowledgmentNumber.ToString() - }, - Tag = new PacketAnalyzer() { HexPayload = data } - }; - break; - default: - break; - } - } - finally - { - ReferenceCountUtil.Release(buf); - } - } - else - { - if (srcIp.ToString() == _dstIp || dstIp.ToString() == _dstIp) - { - lv = new ListViewItem() - { - Text = (lv_packet_log.Items.Count + 1).ToString(), - SubItems = - { - orientation, - $"{srcIp}:{srcPort}", - $"{dstIp}:{dstPort}", - time.ToString(), - payload_len.ToString(), - data, - tcpPacket.SequenceNumber.ToString(), - tcpPacket.AcknowledgmentNumber.ToString() - }, - Tag = new PacketAnalyzer() { HexPayload = data } - }; - } - } - - ThreadSafeUpdate(() => - { - if (lv != null) - { - if (orientation == "Send") - { - lv.ForeColor = Color.Red; - } - else - { - lv.ForeColor = Color.Blue; - } - lv_packet_log.Items.Add(lv); - } - }); - } - } - - private void 追踪流ToolStripMenuItem_Click(object sender, EventArgs e) - { - if (lv_packet_log.SelectedItems.Count != 1) return; - ListViewItem selected_item = lv_packet_log.SelectedItems[0]; - string selected_item_seq = selected_item.SubItems[7].Text; - string selected_item_ack = selected_item.SubItems[8].Text; - - Console.WriteLine("selected: " + selected_item_seq + " " + selected_item_ack); - var pkgs = lv_packet_log.Items; - List sends = new List(); - List recvs = new List(); - StringBuilder sb_send = new StringBuilder(); - StringBuilder sb_recv = new StringBuilder(); - StringBuilder sb_packets = new StringBuilder(); - foreach (ListViewItem pkg in pkgs) - { - string index = pkg.Text; - string pkg_seq = pkg.SubItems[7].Text; - string pkg_ack = pkg.SubItems[8].Text; - string data = string.Empty; - if (pkg.Tag is PacketAnalyzer analysisPacket) - { - data = analysisPacket.HexPayload; - } - if (pkg_seq == selected_item_ack) - { - Console.WriteLine($"recv: {data}"); - } - else if (pkg_ack == selected_item_seq) - { - Console.WriteLine($"send: {data}"); - } - // 如果这个recv的包很大,比如收到了3个包,当我们检测到第一个包为recv包后 - // 需要再查找它余下的包 - selected_item_seq = pkg_seq; - selected_item_ack = pkg_ack; - sb_packets.Append(data); - } - List bytes = new List(); - List analysisPackets = new List(); - var buf = Unpooled.WrappedBuffer(HexUtil.DecodeHex(sb_packets.ToString())); - - try - { - while (buf.IsReadable()) - { - int pkg_len = buf.ReadInt(); - byte[] tag = new byte[5]; - buf.GetBytes(buf.ReaderIndex, tag, 0, 5); - switch (tag.HexDump()) - { - case "00 00 00 0A 00": - case "00 00 00 0A 01": - case "00 00 00 0A 02": - case "00 00 00 0B 00": - case "00 00 00 0B 01": - case "00 00 00 0B 02": - byte[] pkg_payload = new byte[pkg_len - 4]; - if (buf.ReadableBytes >= pkg_payload.Length) - { - buf.ReadBytes(pkg_payload, 0, pkg_payload.Length); - bytes.Add(pkg_payload); - } - break; - default: - - break; - } - /*byte[] pkg_payload = new byte[pkg_len - 4]; - if (buf.ReadableBytes >= pkg_payload.Length) - { - buf.ReadBytes(pkg_payload, 0, pkg_payload.Length); - bytes.Add(pkg_payload); - } - else - { - Logger.Warn("剩余字节大小不足,请检查追踪的流是否有问题!"); - Console.WriteLine(Util.ReadRemainingBytes(buf).HexDump()); - break; - }*/ - } - } - catch (Exception ex) - { - Logger.Error(ex, ex.Message); - } - foreach (byte[] payload in bytes) - { - analysisPackets.Add(new PacketAnalyzer() - { - Payload = payload - }); - } - lv_analysis_log.Items.Clear(); - foreach (var item in analysisPackets) + if (tcpPacket != null) { - try - { - item.Deserialize(); - Logger.Info(item.ToString()); - var lvi = new ListViewItem() - { - Text = item.Orientation, - SubItems = - { - item.ServiceCmd, - item.SSOReq, - (item.Payload.Length + 4).ToString(), - item.HexPayload - } - }; - if (item.Orientation == "Send") - { - lvi.BackColor = Color.FromArgb(251, 237, 237); - } - else - { - lvi.BackColor = Color.FromArgb(237, 237, 251); - } - ThreadSafeUpdate(() => lv_analysis_log.Items.Add(lvi)); - } - catch (Exception ex) - { - Logger.Error(ex, ex.Message + " hex: " + item.Payload.HexDump()); - } + RealTimePacketsAnalyzer.ProcessPackets(tcpPacket); } } diff --git a/Form/Tab/TabAnalysis.cs b/Form/Tab/TabAnalysis.cs index d879d94..f829928 100644 --- a/Form/Tab/TabAnalysis.cs +++ b/Form/Tab/TabAnalysis.cs @@ -7,11 +7,12 @@ namespace YgAndroidQQSniffer.Tab [Attributes.CustomEvent(nameof(TabAnalysis))] public class TabAnalysis : ICustomControlEvents { - private static FormMain Frm { get => FormMain.Form; } + private static FormMain Frm => FormMain.Form; + public void Register() { - Frm.copy_payload.Click += new EventHandler(CopyPayload_Click); - Frm.clear_analysis_listview.Click += new EventHandler(ClearAnalysisListView_Click); + Frm.copy_payload.Click += CopyPayload_Click; + Frm.clear_analysis_listview.Click += ClearAnalysisListView_Click; } #region ctx_menu_trace_flow diff --git a/Form/Tab/TabCapture/CtxMenuAnalysisTools.cs b/Form/Tab/TabCapture/CtxMenuAnalysisTools.cs index 4168ce4..70de244 100644 --- a/Form/Tab/TabCapture/CtxMenuAnalysisTools.cs +++ b/Form/Tab/TabCapture/CtxMenuAnalysisTools.cs @@ -12,25 +12,25 @@ namespace YgAndroidQQSniffer.Tab.TabCapture [Attributes.CustomEvent(nameof(CtxMenuAnalysisTools))] public class CtxMenuAnalysisTools : ICustomControlEvents { - private static FormMain Frm { get => FormMain.Form; } + private static FormMain Frm => FormMain.Form; public void Register() { - Frm.计算字节数ToolStripMenuItem.Click += new EventHandler(计算字节数ToolStripMenuItem_Click); - Frm.TLV格式化ToolStripMenuItem.Click += new EventHandler(TLV格式化ToolStripMenuItem_Click); - Frm.选中字节计算换行ToolStripMenuItem.Click += new EventHandler(选中字节计算换行ToolStripMenuItem_Click); - Frm.一键格式化ToolStripMenuItem.Click += new EventHandler(一键格式化ToolStripMenuItem_Click); - - Frm.十六个0ToolStripMenuItem.Click += new EventHandler(十六个0ToolStripMenuItem_Click); - Frm.kEY日志ToolStripMenuItem.Click += new EventHandler(KEY日志ToolStripMenuItem_Click); - - Frm.到10进制ToolStripMenuItem1.Click += new EventHandler(到10进制ToolStripMenuItem1_Click); - Frm.到文本ToolStripMenuItem.Click += new EventHandler(到文本ToolStripMenuItem_Click); - Frm.到QQToolStripMenuItem.Click += new EventHandler(到QQToolStripMenuItem_Click); - Frm.Dec到时间ToolStripMenuItem.Click += new EventHandler(Dec到时间ToolStripMenuItem_Click); - Frm.Hex到时间ToolStripMenuItem.Click += new EventHandler(Hex到时间ToolStripMenuItem_Click); - Frm.Hex到IPToolStripMenuItem.Click += new EventHandler(Hex到IPToolStripMenuItem_Click); - Frm.Inflater解压ToolStripMenuItem.Click += new EventHandler(Inflater解压ToolStripMenuItem_Click); + Frm.计算字节数ToolStripMenuItem.Click += 计算字节数ToolStripMenuItem_Click; + Frm.TLV格式化ToolStripMenuItem.Click += TLV格式化ToolStripMenuItem_Click; + Frm.选中字节计算换行ToolStripMenuItem.Click += 选中字节计算换行ToolStripMenuItem_Click; + Frm.一键格式化ToolStripMenuItem.Click += 一键格式化ToolStripMenuItem_Click; + + Frm.十六个0ToolStripMenuItem.Click += 十六个0ToolStripMenuItem_Click; + Frm.kEY日志ToolStripMenuItem.Click += KEY日志ToolStripMenuItem_Click; + + Frm.到10进制ToolStripMenuItem1.Click += 到10进制ToolStripMenuItem1_Click; + Frm.到文本ToolStripMenuItem.Click += 到文本ToolStripMenuItem_Click; + Frm.到QQToolStripMenuItem.Click += 到QQToolStripMenuItem_Click; + Frm.Dec到时间ToolStripMenuItem.Click += Dec到时间ToolStripMenuItem_Click; + Frm.Hex到时间ToolStripMenuItem.Click += Hex到时间ToolStripMenuItem_Click; + Frm.Hex到IPToolStripMenuItem.Click += Hex到IPToolStripMenuItem_Click; + Frm.Inflater解压ToolStripMenuItem.Click += Inflater解压ToolStripMenuItem_Click; } #region 计算字节数 @@ -59,7 +59,7 @@ private void TLV格式化ToolStripMenuItem_Click(object sender, EventArgs e) if (string.IsNullOrEmpty(selected_text)) return; try { - var buf = Unpooled.WrappedBuffer(HexUtil.DecodeHex(selected_text)); + var buf = Unpooled.WrappedBuffer(selected_text.DecodeHex()); string ret = new TLVParser.TLVFormatter().Parse(buf); Frm.Log($"\n{ret}\n"); Console.WriteLine(ret); @@ -84,14 +84,17 @@ private void 选中字节计算换行ToolStripMenuItem_Click(object sender, Even int old_length = Frm.r_txt_log.SelectionLength; try { - long calc_len = Util.HexToDec(selected_text); + long calc_len = selected_text.HexToDec(); Frm.r_txt_log.SelectionStart = ((int)calc_len * 3) + old_start + old_length; Frm.r_txt_log.SelectionLength = 0; Clipboard.SetText(Environment.NewLine + Environment.NewLine); Frm.r_txt_log.Paste(); Clipboard.SetText(old_text); } - catch (Exception) { } + catch (Exception) + { + // ignored + } } #endregion @@ -100,7 +103,7 @@ private void 一键格式化ToolStripMenuItem_Click(object sender, EventArgs e) { string selected_text = Frm.r_txt_log.Text.ClearSpecialSymbols(); if (string.IsNullOrEmpty(selected_text)) return; - string ret = new PacketFormatter().Parse(Unpooled.WrappedBuffer(HexUtil.DecodeHex(selected_text))); + string ret = new PacketFormatter().Parse(Unpooled.WrappedBuffer(selected_text.DecodeHex())); Frm.Log("\n\n{0}\n\n", ret); } #endregion @@ -111,7 +114,7 @@ private void 十六个0ToolStripMenuItem_Click(object sender, EventArgs e) { try { - byte[] data = HexUtil.DecodeHex(Frm.r_txt_log.SelectedText); + byte[] data = Frm.r_txt_log.SelectedText.DecodeHex(); byte[] decrypt_data = Common.TeaKeyLogDecrypt(data, out DecryptionKey decryptionKey); if (decrypt_data != null) { @@ -128,7 +131,7 @@ private void KEY日志ToolStripMenuItem_Click(object sender, EventArgs e) { string selected_text = Frm.r_txt_log.SelectedText.ClearSpecialSymbols(); if (string.IsNullOrEmpty(selected_text)) return; - byte[] decrypt_data = Common.TeaKeyLogDecrypt(HexUtil.DecodeHex(selected_text), out DecryptionKey decryptionKey); + byte[] decrypt_data = Common.TeaKeyLogDecrypt(selected_text.DecodeHex(), out DecryptionKey decryptionKey); if (decrypt_data != null) { Frm.Log(Common.PrettyKeyDecryptDump(decrypt_data, decryptionKey)); @@ -189,7 +192,7 @@ private void Dec到时间ToolStripMenuItem_Click(object sender, EventArgs e) if (string.IsNullOrEmpty(selected_text)) return; try { - Frm.Log($" //[Time: {Util.UnixTimeStampToDateTime(double.Parse(selected_text))}]"); + Frm.Log($" //[Time: {double.Parse(selected_text).UnixTimeStampToDateTime()}]"); } catch (Exception ex) { @@ -233,7 +236,7 @@ private void Inflater解压ToolStripMenuItem_Click(object sender, EventArgs e) try { - using MemoryStream compressedStream = new MemoryStream(HexUtil.DecodeHex(selected_text)); + using MemoryStream compressedStream = new MemoryStream(selected_text.DecodeHex()); using DeflateStream deflateStream = new DeflateStream(compressedStream, CompressionMode.Decompress); using MemoryStream outputStream = new MemoryStream(); deflateStream.CopyTo(outputStream); @@ -245,7 +248,10 @@ private void Inflater解压ToolStripMenuItem_Click(object sender, EventArgs e) Log($"\n\n[{outputStream.ToArray().HexDump()}]\n\n"); }*/ } - catch (Exception) { } + catch (Exception) + { + // ignored + } } #endregion } diff --git a/Form/Tab/TabCapture/CtxMenuPackets.cs b/Form/Tab/TabCapture/CtxMenuPackets.cs index 0523a23..ba64d91 100644 --- a/Form/Tab/TabCapture/CtxMenuPackets.cs +++ b/Form/Tab/TabCapture/CtxMenuPackets.cs @@ -13,14 +13,14 @@ namespace YgAndroidQQSniffer.Tab.TabCapture [Attributes.CustomEvent(nameof(CtxMenuPackets))] public class CtxMenuPackets : ICustomControlEvents { - private static FormMain Frm { get => FormMain.Form; } + private static FormMain Frm => FormMain.Form; public void Register() { - Frm.copy_choose_payload.Click += new EventHandler(CopyChoosePayload_Click); - Frm.copy_whole_payload.Click += new EventHandler(CopyWholePayload_Click); - Frm.read_capture_packets_logs.Click += new EventHandler(ReadCapturePacketsLogs_Click); - Frm.save_capture_packets_logs.Click += new EventHandler(SaveCapturePacketsLogs_Click); + Frm.copy_choose_payload.Click += CopyChoosePayload_Click; + Frm.copy_whole_payload.Click += CopyWholePayload_Click; + Frm.read_capture_packets_logs.Click += ReadCapturePacketsLogs_Click; + Frm.save_capture_packets_logs.Click += SaveCapturePacketsLogs_Click; } #region ctxMenuPackets diff --git a/Form/Tab/TabCapture/TabCapture.cs b/Form/Tab/TabCapture/TabCapture.cs index 43a5d8f..e33c6c0 100644 --- a/Form/Tab/TabCapture/TabCapture.cs +++ b/Form/Tab/TabCapture/TabCapture.cs @@ -13,7 +13,7 @@ namespace YgAndroidQQSniffer.Tab.TabCapture [Attributes.CustomEvent(nameof(TabCapture))] public partial class TabCapture : ICustomControlEvents { - private static FormMain Frm { get => FormMain.Form; } + private static FormMain Frm => FormMain.Form; public void Register() { diff --git a/Form/Tab/TabECDH.cs b/Form/Tab/TabECDH.cs index 67cef72..05e8630 100644 --- a/Form/Tab/TabECDH.cs +++ b/Form/Tab/TabECDH.cs @@ -6,14 +6,15 @@ namespace YgAndroidQQSniffer.Tab [Attributes.CustomEvent(nameof(TabECDH))] public class TabECDH : ICustomControlEvents { - private static FormMain Frm { get => FormMain.Form; } + private static FormMain Frm => FormMain.Form; + public void Register() { - Frm.btnClientGenKeys.Click += new EventHandler(BtnClientGenKeys_Click); - Frm.btnServerGenKeys.Click += new EventHandler(BtnServerGenKeys_Click); - Frm.btnExchangePubkey.Click += new EventHandler(BtnExchangePubkey_Click); - Frm.btnClientGenShakey.Click += new EventHandler(BtnClientGenShakey_Click); - Frm.btnServerGenShakey.Click += new EventHandler(BtnServerGenShakey_Click); + Frm.btnClientGenKeys.Click += BtnClientGenKeys_Click; + Frm.btnServerGenKeys.Click += BtnServerGenKeys_Click; + Frm.btnExchangePubkey.Click += BtnExchangePubkey_Click; + Frm.btnClientGenShakey.Click += BtnClientGenShakey_Click; + Frm.btnServerGenShakey.Click += BtnServerGenShakey_Click; } private void BtnClientGenKeys_Click(object sender, EventArgs e) diff --git a/Form/Tab/TabHttpServer.cs b/Form/Tab/TabHttpServer.cs index bc5dbbc..b4d41e1 100644 --- a/Form/Tab/TabHttpServer.cs +++ b/Form/Tab/TabHttpServer.cs @@ -6,7 +6,8 @@ namespace YgAndroidQQSniffer.Tab [Attributes.CustomEvent(nameof(TabHttpServer))] public class TabHttpServer : ICustomControlEvents { - private static FormMain Frm { get => FormMain.Form; } + private static FormMain Frm => FormMain.Form; + public void Register() { Frm.btn_start_httpserver.Click += new EventHandler(Btn_start_httpserver_ClickAsync); diff --git a/Form/Tab/TabTEA.cs b/Form/Tab/TabTEA.cs index 50e15ae..68c8ee1 100644 --- a/Form/Tab/TabTEA.cs +++ b/Form/Tab/TabTEA.cs @@ -6,15 +6,15 @@ namespace YgAndroidQQSniffer.Tab [Attributes.CustomEvent(nameof(TabTEA))] public class TabTEA : ICustomControlEvents { - private static FormMain Frm { get => FormMain.Form; } + private static FormMain Frm => FormMain.Form; public void Register() { - Frm.btn_tea_encrypt.Click += new EventHandler(Btn_tea_encrypt_Click); - Frm.btn_tea_decrypt.Click += new EventHandler(Btn_tea_decrypt_Click); - Frm.btn_tea_copy_decrypt_data.Click += new EventHandler(Btn_tea_copy_decrypt_data_Click); - Frm.btn_tea_key_log_decrypt.Click += new EventHandler(Btn_tea_key_log_decrypt_Click); - Frm.btn_decrypt_byte_by_byte.Click += new EventHandler(Btn_decrypt_byte_by_byte_Click); + Frm.btn_tea_encrypt.Click += Btn_tea_encrypt_Click; + Frm.btn_tea_decrypt.Click += Btn_tea_decrypt_Click; + Frm.btn_tea_copy_decrypt_data.Click += Btn_tea_copy_decrypt_data_Click; + Frm.btn_tea_key_log_decrypt.Click += Btn_tea_key_log_decrypt_Click; + Frm.btn_decrypt_byte_by_byte.Click += Btn_decrypt_byte_by_byte_Click; } #region TAB TEA加解密 @@ -22,30 +22,36 @@ private void Btn_tea_encrypt_Click(object sender, EventArgs e) { try { - byte[] key = HexUtil.DecodeHex(Frm.txt_tea_key.Text); - byte[] data = HexUtil.DecodeHex(Frm.txt_tea_encrypt_data.Text); + byte[] key = Frm.txt_tea_key.Text.DecodeHex(); + byte[] data = Frm.txt_tea_encrypt_data.Text.DecodeHex(); byte[] ret = Tea.Encrypt(data, key); if (ret != null) { Frm.txt_tea_decrypt_data.Text = ret.HexDump(); } } - catch (Exception) { } + catch (Exception) + { + // ignored + } } private void Btn_tea_decrypt_Click(object sender, EventArgs e) { try { - byte[] key = HexUtil.DecodeHex(Frm.txt_tea_key.Text); - byte[] data = HexUtil.DecodeHex(Frm.txt_tea_encrypt_data.Text); + byte[] key = Frm.txt_tea_key.Text.DecodeHex(); + byte[] data = Frm.txt_tea_encrypt_data.Text.DecodeHex(); byte[] ret = Tea.Decrypt(data, key); if (ret != null) { Frm.txt_tea_decrypt_data.Text = ret.HexDump(); } } - catch (Exception) { } + catch (Exception) + { + // ignored + } } private void Btn_tea_copy_decrypt_data_Click(object sender, EventArgs e) @@ -61,7 +67,7 @@ private void Btn_tea_key_log_decrypt_Click(object sender, EventArgs e) { string encrypt_data = Frm.txt_tea_encrypt_data.Text; if (string.IsNullOrEmpty(encrypt_data)) return; - byte[] data = HexUtil.DecodeHex(encrypt_data); + byte[] data = encrypt_data.DecodeHex(); byte[] decrypt_data = Common.TeaKeyLogDecrypt(data, out DecryptionKey decryptionKey); if (decrypt_data != null) { @@ -74,7 +80,7 @@ private void Btn_decrypt_byte_by_byte_Click(object sender, EventArgs e) { string encrypt_data = Frm.txt_tea_encrypt_data.Text.ClearSpecialSymbols(); if (string.IsNullOrEmpty(encrypt_data)) return; - for (int i = 0; i < encrypt_data.Length; i+=2) + for (int i = 0; i < encrypt_data.Length; i += 2) { byte[] data = encrypt_data.Substring(i, encrypt_data.Length - i).DecodeHex(); byte[] decrypt_data = Common.TeaKeyLogDecrypt(data, out DecryptionKey decryptionKey); diff --git a/Form/Tab/TabTool.cs b/Form/Tab/TabTool.cs index 70a3909..5b4f74b 100644 --- a/Form/Tab/TabTool.cs +++ b/Form/Tab/TabTool.cs @@ -10,17 +10,17 @@ namespace YgAndroidQQSniffer.Tab [Attributes.CustomEvent(nameof(TabTool))] public class TabTool : ICustomControlEvents { - private static FormMain Frm { get => FormMain.Form; } + private static FormMain Frm => FormMain.Form; public void Register() { - Frm.btn_tool_read_keys.Click += new EventHandler(Btn_tool_read_keys_Click); - Frm.btn_tool_save_keys.Click += new EventHandler(Btn_tool_save_keys_Click); - Frm.btn_tool_md5_calc.Click += new EventHandler(Btn_tool_md5_calc_Click); - Frm.btn_tool_md5_copy_once.Click += new EventHandler(Btn_tool_md5_copy_once_Click); - Frm.btn_tool_qqencrypt_calc.Click += new EventHandler(Btn_tool_qqencrypt_calc_Click); - Frm.btn_tool_qqencrypt_copy.Click += new EventHandler(Btn_tool_qqencrypt_copy_Click); - Frm.btn_tool_hookdata_showPwd.Click += new EventHandler(Btn_tool_hookdata_showPwd_Click); + Frm.btn_tool_read_keys.Click += Btn_tool_read_keys_Click; + Frm.btn_tool_save_keys.Click += Btn_tool_save_keys_Click; + Frm.btn_tool_md5_calc.Click += Btn_tool_md5_calc_Click; + Frm.btn_tool_md5_copy_once.Click += Btn_tool_md5_copy_once_Click; + Frm.btn_tool_qqencrypt_calc.Click += Btn_tool_qqencrypt_calc_Click; + Frm.btn_tool_qqencrypt_copy.Click += Btn_tool_qqencrypt_copy_Click; + Frm.btn_tool_hookdata_showPwd.Click += Btn_tool_hookdata_showPwd_Click; } #region TAB 工具 diff --git a/TLVParser/TLVFormatter.cs b/TLVParser/TLVFormatter.cs index f8da487..c6414fa 100644 --- a/TLVParser/TLVFormatter.cs +++ b/TLVParser/TLVFormatter.cs @@ -9,7 +9,7 @@ namespace YgAndroidQQSniffer.TLVParser { public class TLVFormatter : IParser { - private static Logger Logger { get; set; } = LogManager.GetCurrentClassLogger(); + private static Logger Logger { get; } = LogManager.GetCurrentClassLogger(); private static readonly Dictionary Parsers = new Dictionary(); public static void RegTLVParsers() @@ -60,7 +60,7 @@ public string Parse(IByteBuffer buf) { Dictionary tlv_map = buf.ReadTLVMap(); StringBuilder sb = new StringBuilder(); - sb.Append($"{Util.HexDump(tlv_map.Count.HexPadLeft())} //{tlv_map.Count}tlvs").AppendLine().AppendLine(); + sb.Append($"{tlv_map.Count.HexPadLeft().HexDump()} //{tlv_map.Count}tlvs").AppendLine().AppendLine(); tlv_map.ToList().ForEach(tlv => { string text = string.Empty; @@ -69,7 +69,7 @@ public string Parse(IByteBuffer buf) string value = tlv.Value.HexDump(); //注册一个map key=tag value=IParser //根据tlv tag到map中找到对应的IParser,存在则调用parse方法,并使用其返回值,否则默认hexDump() - var parser = Parsers.Where(p => p.Key == tlv.Key).FirstOrDefault(); + KeyValuePair parser = Parsers.FirstOrDefault(p => p.Key == tlv.Key); if (parser.Key != 0 && parser.Value != null) { //parse失败返回原样字节并备注解析失败 @@ -84,7 +84,7 @@ public string Parse(IByteBuffer buf) tlv.Value.HexDump()); } } - if (tlv_map.Where(d => d.Key == tlv.Key).Count() > 1) + if (tlv_map.Count(d => d.Key == tlv.Key) > 1) { text += $"{tag} //tlv{tag} 重复的tag {Environment.NewLine}"; } diff --git a/Utils/Util.cs b/Utils/Util.cs index 22e4d26..f932dee 100644 --- a/Utils/Util.cs +++ b/Utils/Util.cs @@ -28,7 +28,7 @@ public static byte[] ToBytes(this string hexStr) returnBytes[i] = Convert.ToByte(hexStr.Substring(i * 2, 2), 16); return returnBytes; } - public static string HexDump(this string hexStr) => HexDump(Unpooled.WrappedBuffer(HexUtil.DecodeHex(hexStr))); + public static string HexDump(this string hexStr) => HexDump(Unpooled.WrappedBuffer(hexStr.DecodeHex())); public static string HexDump(this byte[] array) => HexDump(Unpooled.WrappedBuffer(array)); public static string HexDump(this IByteBuffer buffer) { diff --git a/YgAndroidQQSniffer.csproj b/YgAndroidQQSniffer.csproj index 80d63f0..b93d143 100644 --- a/YgAndroidQQSniffer.csproj +++ b/YgAndroidQQSniffer.csproj @@ -317,6 +317,8 @@ + +