一、实验目的
- 熟悉TC
- P/IP数据包的结构。
- 掌握Wireshark的使用方法。
- 能够利用JNet Pcap编程实现数据包的抓取与分析。
二、实验准备
1、通过抓包,可以进行网络故障分析、流量监控、隐私盗取等操作,相关的抓包工具有很多,主要有Fiddler、Wireshark、Charles等。
2、本实验需要提前安装Wireshark、配置java环境、下载并导入JNetPcap.jar包。Windows系统下需要安装WinPcap, Linux下需要安装Libcap。 WinPcap官网:WinPcap - Home。
3、在数据包监听与分析方面,Java常用的类库有JPcap和JNetPcap等。由于JPcap已经好久不更新了,本实验使用JNetPcap,其抓包的过程可以概括为获取设备网卡列表、打开选中的网卡、设置过滤器、开始监听、数据包分析与展示这五个步骤。
三、实验内容
1、使用WireShark进行抓包分析
(1)打开Wireshark,选择要监控的网卡,右键后点击"start capture"按钮开始抓包。然后,打开浏览器输入任意http网址,例如:百度一下,你就知道,接着,回到Wireshark界面,点击左上角的停止按键。查看此时Wireshark的抓包信息。
(2)在Wireshark的filter中输入过滤语句http.request.method==POST,即只抓取http协议中post请求的包。然后登录学校教务网站,就可以抓到表单提交的post请求包。分析包的结构,查找用户名和密码信息。
2.分析、调试下面的代码,体会利用JNetPacp进行抓包和分析的过程
JNetPcap抓包类:
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import javax.swing.JOptionPane;
import org.jnetpcap.Pcap;
import org.jnetpcap.PcapBpfProgram;
import org.jnetpcap.PcapIf;
import org.jnetpcap.packet.PcapPacket;
import org.jnetpcap.packet.PcapPacketHandler;
import org.jnetpcap.packet.format.FormatUtils;
import org.jnetpcap.protocol.network.Arp;
import org.jnetpcap.protocol.network.Icmp;
import org.jnetpcap.protocol.network.Ip4;
import org.jnetpcap.protocol.tcpip.Http;
import org.jnetpcap.protocol.tcpip.Tcp;
import org.jnetpcap.protocol.tcpip.Udp;
public class capture {
private static Ip4 ip = new Ip4();
private static Udp udp=new Udp();
private static Tcp tcp=new Tcp();
private static Icmp icmp=new Icmp();
private static Arp arp=new Arp();
private static Http http=new Http();
//获得网卡设备列表
public static ArrayList<PcapIf> getDevices()
{ //用于存储搜索到的网卡
ArrayList<PcapIf> alldevs = new ArrayList<PcapIf>();
//错误信息
StringBuilder errbuf = new StringBuilder();
//Pcap.findAllDevs(alldevs, errbuf)取得设备列表
int r = Pcap.findAllDevs(alldevs, errbuf);
if (r == Pcap.NOT_OK || alldevs.isEmpty()) {
// 如果获取失败,或者获取到列表为空,则输出错误信息退出
System.err.printf("Can't read list of devices, error is %s", errbuf.toString());
return null;
}
return alldevs;
}
//打开设备并进行抓包分析
public static String[] openDevice(ArrayList<PcapIf> alldevs,int choose,String expression)
{ StringBuilder errbuf = new StringBuilder();
int snaplen = Pcap.DEFAULT_SNAPLEN; // 默认长度为65535
int flags = Pcap.MODE_PROMISCUOUS; // 混杂模式
int timeout = 10 * 1000; // 10 seconds in millis
Pcap pcap = Pcap.openLive(alldevs.get(choose).getName(), snaplen, flags, timeout, errbuf);
if (pcap == null) {JOptionPane.showMessageDialog(null,errbuf.toString(),"错误",JOptionPane.ERROR_MESSAGE);
return null;
}
// System.out.print(alldevs.get(choose).getName());
//如果过滤器不为none,设置相应过滤器
if (expression!="none")
{PcapBpfProgram filter = new PcapBpfProgram();
int res = pcap.compile(filter, expression, 1, 0);
pcap.setFilter(filter);
}
//存储分析结果
String[] data= new String[8];
PcapPacketHandler<String> jpacketHandler = new PcapPacketHandler<String>() {
public void nextPacket(PcapPacket packet, String user) {
int no=(int) (packet.getFrameNumber());
//编号
data[0]= String.valueOf(no);
//长度
data[5]=String.valueOf(packet.getCaptureHeader().caplen());
//封包具体信息
data[7]=String.valueOf(packet);
//tcp
if (packet.hasHeader(tcp))
{ packet.getHeader(tcp);
data[4]="tcp";
Stringstod=String.valueOf(tcp.source())+"->"+String.valueOf(tcp.destination());
String seq="Seq="+String.valueOf(tcp.seq());
String ack="Ack="+String.valueOf(tcp.ack());
String win="Win="+String.valueOf(tcp.window());
String len="Len="+String.valueOf(tcp.getLength());
String syn="SYN="+String.valueOf(tcp.flags_SYN());
String fin="FIN="+String.valueOf(tcp.flags_FIN());
data[6]=stod+" "+seq+" "+ack+" "+win+" "+len+" "+syn+" "+fin;
formMain.tcpnum++;
}
//udp
if (packet.hasHeader(udp))
{ packet.getHeader(udp);
data[4]="udp";
String stod=String.valueOf(udp.source())+" -> "+String.valueOf(udp.destination());
String len="Len="+String.valueOf(udp.length());
data[6]=stod+" "+len;
formMain.udpnum++;
}
//icmp
if (packet.hasHeader(icmp))
{ packet.getHeader(icmp);
data[4]="icmp";
formMain.icmpnum++;
}
//arp
if (packet.hasHeader(arp))
{ packet.getHeader(arp);
String hardwareType=arp.hardwareTypeDescription();
data[4]="arp";
data[6]="hardwareTypeDescription:"+hardwareType;
formMain.arpnum++;
}
//http
if (packet.hasHeader(http))
{ packet.getHeader(http);
data[4]="http";
formMain.httpnum++;
}
//ip
if (packet.hasHeader(ip)) {
if (formMain.IPhashMap.containsKey(FormatUtils.ip(ip.source())+"->" +FormatUtils.ip(ip.destination())))
{
int num=formMain.IPhashMap.get(FormatUtils.ip(ip.source())+" -> "+FormatUtils.ip(ip.destination()));
num++;
formMain.IPhashMap.put(FormatUtils.ip(ip.source())+" -> "+FormatUtils.ip(ip.destination()),num);
}
else
formMain.IPhashMap.put(FormatUtils.ip(ip.source())+" -> "+FormatUtils.ip(ip.destination()),1);
packet.getHeader(ip);
data[2]=FormatUtils.ip(ip.source());
data[3]=FormatUtils.ip(ip.destination());
formMain.ipnum++;
}
}
};
pcap.loop(1, jpacketHandler, "jNetPcap");
pcap.close();
return data;
}
}
界面类:
public void actionPerformed(ActionEvent arg0) { import java.awt.BorderLayout;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.table.DefaultTableModel;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartFrame;
import org.jfree.chart.JFreeChart;
import org.jfree.data.general.DefaultPieDataset;
import org.jnetpcap.PcapIf;
import jpcap.NetworkInterface;
import javax.swing.JLabel;
import javax.swing.JComboBox;
import java.awt.Font;
import javax.swing.JButton;
import javax.swing.JTable;
import javax.swing.JScrollPane;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.awt.event.ActionEvent;
import javax.swing.JTextField;
import javax.swing.JTextArea;
import javax.swing.JScrollBar;
public class formMain extends JFrame {
private JPanel contentPane;
private JTable table = new JTable();
private JTextArea textArea = new JTextArea();
//记录当前选中设备号
private int chooseFlag=0;
DefaultTableModel model=(DefaultTableModel)table.getModel();
//记录运行时间
public int minute;
private JTextField textField;
private JComboBox comboBox = new JComboBox();
private ArrayList<String> datas=new ArrayList<String>();
//数量统计
public static int tcpnum=0;
public static int udpnum=0;
public static int icmpnum=0;
public static int ipnum=0;
public static int httpnum=0;
public static int arpnum=0;
public static HashMap<String, Integer> IPhashMap=new HashMap<>();
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
formMain frame = new formMain();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public formMain() {
setTitle("\u6293\u5305");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(450, 100, 800, 979);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
JLabel label_tcp = new JLabel("0");
label_tcp.setBounds(166, 773, 72, 18);
contentPane.add(label_tcp);
JLabel label_udp = new JLabel("0");
label_udp.setBounds(167, 820, 72, 18);
contentPane.add(label_udp);
JLabel label_icmp = new JLabel("0");
label_icmp.setBounds(166, 865, 72, 18);
contentPane.add(label_icmp);
JLabel label_ip = new JLabel("0");
label_ip.setBounds(449, 773, 72, 18);
contentPane.add(label_ip);
JLabel label_arp = new JLabel("0");
label_arp.setBounds(449, 820, 72, 18);
contentPane.add(label_arp);
JLabel label_http = new JLabel("0");
label_http.setBounds(449, 865, 72, 18);
contentPane.add(label_http);
//label
JLabel lblS = new JLabel("请选择设备:");
lblS.setBounds(106, 32, 115, 18);
lblS.setFont(new Font("黑体", Font.PLAIN, 18));
contentPane.add(lblS);
//下拉框
JComboBox<String> comboDevices = new JComboBox<String>();
comboDevices.setBounds(221, 30, 454, 24);
comboDevices.setFont(new Font("黑体", Font.PLAIN, 16));
contentPane.add(comboDevices);
//添加设备
ArrayList<PcapIf> dlist=capture.getDevices();
for (int i=0;i<dlist.size();i++)
{
comboDevices.addItem(dlist.get(i).getName());
}
//执行时间
textField = new JTextField();
textField.setBounds(314, 110, 100, 30);
textField.setText("0");
String time=textField.getText();
minute=Integer.valueOf(time);
textField.setFont(new Font("黑体", Font.PLAIN, 18));
contentPane.add(textField);
textField.setColumns(10);
//开始按钮
JButton btnStart = new JButton("Start");
btnStart.setBounds(496, 111, 113, 27);
btnStart.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
//确定所选设备号
for (int i=0;i<dlist.size();i++)
{
if(dlist.get(i).getName()==comboDevices.getSelectedItem())
chooseFlag=i;
}
int count=1;
//获得执行时间
String time=textField.getText();
minute=Integer.valueOf(time);
long startTime = System.currentTimeMillis();
System.out.print("time:"+time);
long nowTime = System.currentTimeMillis();
while (startTime + minute * 60 * 1000 >= nowTime) {
nowTime = System.currentTimeMillis();
System.out.println(nowTime);
String expression=(String) comboBox.getSelectedItem();
String data[]=capture.openDevice(dlist,chooseFlag,expression);
data[0]=String.valueOf(count);
SimpleDateFormat sdff=new SimpleDateFormat("HH:mm:ss");
data[1]=sdff.format(nowTime);
//将获得的数据加入表格中
model.addRow(data);
datas.add(data[7]);
count++;
table.validate();
label_tcp.setText(String.valueOf(tcpnum));
label_udp.setText(String.valueOf(udpnum));
label_icmp.setText(String.valueOf(icmpnum));
label_ip.setText(String.valueOf(ipnum));
label_http.setText(String.valueOf(httpnum));
label_arp.setText(String.valueOf(arpnum));
}
}
});
btnStart.setFont(new Font("黑体", Font.PLAIN, 18));
contentPane.add(btnStart);
//表格
JScrollPane scrollPane = new JScrollPane();
scrollPane.setBounds(27, 150, 720, 280);
contentPane.add(scrollPane);
String[] titles = { "No.", "Time","Source","Destination","Protocal","Length","Info" };
model.setColumnIdentifiers(titles);
scrollPane.setViewportView(table);
table.setFont(new Font("黑体", Font.PLAIN, 15));
table.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent arg0) {
int index = table.getSelectedRow();
textArea.setText(datas.get(index));
}
});
JLabel label = new JLabel("\u6267\u884C\u65F6\u957F\uFF1A\uFF08\u5206\u949F\uFF09");
label.setBounds(167, 118, 162, 18);
label.setFont(new Font("黑体", Font.PLAIN, 15));
contentPane.add(label);
JScrollPane scrollPane_1 = new JScrollPane();
scrollPane_1.setBounds(27, 443, 720, 300);
contentPane.add(scrollPane_1);
scrollPane_1.setViewportView(textArea);
scrollPane_1.setVerticalScrollBarPolicy( JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
textArea.setBounds(27, 443, 720, 300);
JLabel label_1 = new JLabel("\u8FC7\u6EE4\u5668\u9009\u62E9\uFF1A");
label_1.setFont(new Font("黑体", Font.PLAIN, 15));
label_1.setBounds(167, 79, 132, 18);
contentPane.add(label_1);
//过滤器下拉框
comboBox.setBounds(262, 76, 347, 24);
contentPane.add(comboBox);
comboBox.addItem("none");
comboBox.addItem("ip");
comboBox.addItem("tcp");
comboBox.addItem("udp");
comboBox.addItem("arp");
comboBox.addItem("icmp");
comboBox.addItem("http");
JLabel label_2 = new JLabel("\u7EDF\u8BA1\uFF1A");
label_2.setFont(new Font("黑体", Font.PLAIN, 17));
label_2.setBounds(27, 772, 72, 18);
contentPane.add(label_2);
JLabel lblTcp = new JLabel("TCP\u5305\uFF1A");
lblTcp.setBounds(96, 773, 72, 18);
contentPane.add(lblTcp);
JLabel lblUdp = new JLabel("UDP\u5305\uFF1A");
lblUdp.setBounds(96, 820, 72, 18);
contentPane.add(lblUdp);
JLabel lblIcmp = new JLabel("ICMP\u5305\uFF1A");
lblIcmp.setBounds(96, 865, 72, 18);
contentPane.add(lblIcmp);
JLabel lblIp = new JLabel("IP\u5305\uFF1A");
lblIp.setBounds(378, 773, 72, 18);
contentPane.add(lblIp);
JLabel lblArp = new JLabel("ARP\u5305\uFF1A");
lblArp.setBounds(376, 823, 72, 18);
contentPane.add(lblArp);
JLabel lblHttp = new JLabel("HTTP\u5305\uFF1A");
lblHttp.setBounds(374, 866, 72, 18);
contentPane.add(lblHttp);
JButton btnDetails = new JButton("Details");
btnDetails.addActionListener(new ActionListener() {
if (comboBox.getSelectedItem()=="none")
{
DefaultPieDataset dpd=new DefaultPieDataset(); //建立一个默认的饼图
//添加数据
dpd.setValue("tcp",tcpnum);
dpd.setValue("udp",udpnum);
dpd.setValue("ip", ipnum);
dpd.setValue("icmp",icmpnum);
dpd.setValue("arp",arpnum);
dpd.setValue("http",httpnum);
JFreeChart chart=ChartFactory.createPieChart("数据包统计分析",dpd,true,true,false);
ChartFrame chartFrame=new ChartFrame("数据包统计分析",chart);
chartFrame.pack(); //以合适的大小展现图形
chartFrame.setVisible(true);//图形是否可见
}
else
{
DefaultPieDataset dpd=new DefaultPieDataset(); //建立一个默认的饼图
//添加数据
Set set=IPhashMap.entrySet();
Iterator it=set.iterator();
while(it.hasNext()){
Map.Entry me=(Map.Entry)it.next();
dpd.setValue(String.valueOf(me.getKey()), (int)me.getValue());
}
JFreeChart chart=ChartFactory.createPieChart("数据包统计分析",dpd,true,true,false);
ChartFrame chartFrame=new ChartFrame("数据包统计分析",chart);
chartFrame.pack(); //以合适的大小展现图形
chartFrame.setVisible(true);//图形是否可见
}
}
});
btnDetails.setFont(new Font("宋体", Font.BOLD, 15));
btnDetails.setBounds(634, 816, 113, 27);
contentPane.add(btnDetails);
}
}