本實(shí)驗(yàn)是用java實(shí)現(xiàn)的網(wǎng)絡(luò)抓包程序,在windows環(huán)境下安裝winpcap4.0和jpcap6.0后,,下載eclipse和jigloo插件(一種在eclipse底下作圖形化開發(fā)的工具),,將其安裝好,,然后就可以進(jìn)行java的網(wǎng)絡(luò)抓包圖形化開發(fā)了。
2.1 網(wǎng)絡(luò)抓包技術(shù)原理
網(wǎng)絡(luò)層上有各種各樣的數(shù)據(jù)包,,它們以不同的幀格式在網(wǎng)絡(luò)層上進(jìn)行傳輸,,但是在傳輸時(shí)它們都遵循相同的格式,即有相同的長(zhǎng)度,,如果一種協(xié)議的幀格式達(dá)不到這種長(zhǎng)度,,就讓其補(bǔ)齊,以達(dá)到我們的要求,。
2.2 網(wǎng)絡(luò)抓包關(guān)鍵技術(shù)
無(wú)論是在windows操作系統(tǒng)下還是在linux操作系統(tǒng)下,,要想捕獲網(wǎng)絡(luò)上的數(shù)據(jù)包,必須要對(duì)網(wǎng)卡進(jìn)行控制,,因?yàn)楸緳C(jī)的數(shù)據(jù)報(bào)從網(wǎng)絡(luò)上來(lái)到本機(jī)是通過網(wǎng)卡然后再保存到本地緩沖區(qū)上的,,所以要抓獲網(wǎng)包就必須調(diào)用網(wǎng)卡驅(qū)動(dòng)中的對(duì)外函數(shù),在linux系統(tǒng)中有net.h文件,,可以調(diào)用net.h文件中的函數(shù)來(lái)操作網(wǎng)卡,,可以直接編程實(shí)現(xiàn),但為了更方便的使用,,可以安裝一個(gè)叫libpcap的軟件,,這樣調(diào)用函數(shù)更好用,而在windows系統(tǒng)中,,因?yàn)樵创a不對(duì)外公開,,所以要安裝一個(gè)叫winpcap的軟件,這樣用C或VC 就可以實(shí)現(xiàn)了,,但因?yàn)槲矣玫氖?/span>java語(yǔ)言來(lái)實(shí)現(xiàn)的,,所以無(wú)論是在哪個(gè)系統(tǒng)都要安裝一個(gè)叫jpcap的軟件,它本身就把底層的函數(shù)又封裝了一下,,這樣就可以讓java來(lái)使用了,。
我的這個(gè)網(wǎng)絡(luò)抓包程序是圖形化操作界面,,在菜單欄點(diǎn)擊抓包按鈕后選擇網(wǎng)卡和過濾字還有最長(zhǎng)字長(zhǎng),,點(diǎn)擊開始,然后就可以開始抓包了,,在主界面中就會(huì)顯示出一行又一行的數(shù)據(jù),,這些數(shù)據(jù)就是抓獲到的數(shù)據(jù)包。
3.2 具體實(shí)現(xiàn)
1,、安裝winpcap4.0和jpcap6.0
2,、下載eclipse3.3和jigloo,jigloo是eclipse底下的插件,,是用來(lái)支持eclipse底下的java 圖形化開發(fā)的,。
3、編寫java抓包程序:
建立三個(gè)文件,,一個(gè)主程序,,一個(gè)抓包程序,,一個(gè)抓包選項(xiàng)程序?qū)υ捒虺绦?/font>
第一個(gè)程序:主程序如下
package netcap;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JSeparator;
import javax.swing.JMenuItem;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
import netcap.*;
import jpcap.*;
import jpcap.packet.*;
import java.util.*;
import java.sql.Timestamp;
/**
* This code was edited or generated using CloudGarden's Jigloo
* SWT/Swing GUI Builder, which is free for non-commercial
* use. If Jigloo is being used commercially (ie, by a corporation,
* company or business for any purpose whatever) then you
* should purchase a license for each developer using Jigloo.
* Please visit www.cloudgarden.com for details.
* Use of Jigloo implies acceptance of these licensing terms.
* A COMMERCIAL LICENSE HAS NOT BEEN PURCHASED FOR
* THIS MACHINE, SO JIGLOO OR THIS CODE CANNOT BE USED
* LEGALLY FOR ANY CORPORATE OR COMMERCIAL PURPOSE.
*/
public class JFrameMain extends javax.swing.JFrame implements ActionListener{
private JMenuItem exitMenuItem;
private JSeparator jSeparator2;
private JMenuItem saveAsMenuItem;
private JMenuItem saveMenuItem;
private JMenuItem stopMenuItem;
private JMenuItem startMenuItem;
private JMenu Menu;
private JMenuBar jMenuBar1;
JTable tabledisplay = null;
Vector rows,columns;
DefaultTableModel tabModel;
JScrollPane scrollPane;
JLabel statusLabel;
Netcaptor captor = new Netcaptor();
/**
* Auto-generated main method to display this JFrame
*/
public static void main(String[] args) {
JFrameMain inst = new JFrameMain();
inst.setVisible(true);
}
public JFrameMain() {
super();
initGUI();
}
private void initGUI() {
try {
setSize(400, 300);
{
jMenuBar1 = new JMenuBar();
setJMenuBar(jMenuBar1);
{
Menu = new JMenu();
jMenuBar1.add(Menu);
Menu.setText('/u6293/u5305');
Menu.setPreferredSize(new java.awt.Dimension(35, 21));
{
startMenuItem = new JMenuItem();
Menu.add(startMenuItem);
startMenuItem.setText('開始');
startMenuItem.setActionCommand('start');
startMenuItem.addActionListener(this);
}
{
stopMenuItem = new JMenuItem();
Menu.add(stopMenuItem);
stopMenuItem.setText('停止');
stopMenuItem.setActionCommand('stop');
stopMenuItem.addActionListener(this);
}
{
saveMenuItem = new JMenuItem();
Menu.add(saveMenuItem);
saveMenuItem.setText('保存');
}
{
saveAsMenuItem = new JMenuItem();
Menu.add(saveAsMenuItem);
saveAsMenuItem.setText('保存為 ...');
}
{
jSeparator2 = new JSeparator();
Menu.add(jSeparator2);
}
{
exitMenuItem = new JMenuItem();
Menu.add(exitMenuItem);
exitMenuItem.setText('Exit');
exitMenuItem.setActionCommand('exit');
exitMenuItem.addActionListener(this);
}
}
}
rows=new Vector();
columns= new Vector();
columns.addElement('數(shù)據(jù)報(bào)時(shí)間');
columns.addElement('源IP地址');
columns.addElement('目的IP地址');
columns.addElement('首部長(zhǎng)度');
columns.addElement('數(shù)據(jù)長(zhǎng)度');
columns.addElement('是否分段');
columns.addElement('分段偏移量');
columns.addElement('首部?jī)?nèi)容');
columns.addElement('數(shù)據(jù)內(nèi)容');
tabModel=new DefaultTableModel();
tabModel.setDataVector(rows,columns);
tabledisplay = new JTable( tabModel );
scrollPane= new JScrollPane(tabledisplay);
this.getContentPane().add( new JScrollPane(tabledisplay),BorderLayout.CENTER);
statusLabel=new JLabel('06610班 張琛雨 066100583');
this.getContentPane().add(statusLabel,BorderLayout.SOUTH);
} catch (Exception e) {
e.printStackTrace();
}
}
public void actionPerformed(ActionEvent event){
String cmd=event.getActionCommand();
if(cmd.equals('start')){
captor.capturePacketsFromDevice();
captor.setJFrame(this);
}
else if(cmd.equals('stop')){
captor.stopCapture();
}
else if(cmd.equals('exit')){
System.exit(0);
}
}
public void dealPacket( Packet packet )
{
try
{
Vector r=new Vector();
String strtmp;
Timestamp timestamp = new Timestamp((packet.sec * 1000) (packet.usec / 1000));
r.addElement( timestamp.toString() ); //數(shù)據(jù)報(bào)時(shí)間
r.addElement(((IPPacket)packet).src_ip.toString()); //源IP地址
r.addElement(((IPPacket)packet).dst_ip.toString()); //目的IP地址
r.addElement( packet.header.length ); //首部長(zhǎng)度
r.addElement( packet.data.length ); //數(shù)據(jù)長(zhǎng)度
r.addElement( ((IPPacket)packet).dont_frag == true ? '分段' : '不分段' ); //是否不分段
r.addElement( ((IPPacket)packet).offset ); //數(shù)據(jù)長(zhǎng)度
strtmp = '';
for(int i=0;i<packet.header.length;i ){
strtmp = Byte.toString(packet.header[i]);
}
r.addElement(strtmp); //首部?jī)?nèi)容
strtmp = '';
for(int i=0;i<packet.data.length;i ){
strtmp = Byte.toString(packet.data[i]);
}
r.addElement(strtmp); //數(shù)據(jù)內(nèi)容
rows.addElement(r);
tabledisplay.addNotify();
}
catch( Exception e)
{
}
}
}
在這里定義了一個(gè)向量r,當(dāng)有數(shù)據(jù)包產(chǎn)生時(shí),,便將數(shù)據(jù)包賦值給r,,rows.AddElement(r)語(yǔ)句便將r添加到向量rows中,然后tabledisplay.addNotify();語(yǔ)句就會(huì)刷新界面將新的數(shù)據(jù)包顯示出來(lái),。
第二個(gè)程序:抓包
package netcap;
import java.io.File;
import java.util.Vector;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import jpcap.JpcapCaptor;
import jpcap.PacketReceiver;
import jpcap.JpcapWriter;
import jpcap.packet.Packet;
public class Netcaptor {
JpcapCaptor jpcap = null;
JFrameMain frame;
public void setJFrame(JFrameMain frame){
this.frame=frame;
}
public void capturePacketsFromDevice() {
if(jpcap!=null)
jpcap.close();
jpcap = Jcapturedialog.getJpcap(frame);
if (jpcap != null) {
startCaptureThread();
}
}
private Thread captureThread;
private void startCaptureThread(){
if(captureThread != null)
return;
captureThread = new Thread(new Runnable(){
public void run(){
while(captureThread != null){
jpcap.processPacket(1, handler);
}
}
});
captureThread.setPriority(Thread.MIN_PRIORITY);
captureThread.start();
}
void stopcaptureThread(){
captureThread = null;
}
public void stopCapture(){
System.out.println(2);
stopcaptureThread();
}
private PacketReceiver handler=new PacketReceiver(){
public void receivePacket(Packet packet) {
//System.out.println(packet);
frame.dealPacket(packet);
}
};
}
定義一個(gè)抓包對(duì)象JpcapCaptor jpcap = null;但點(diǎn)擊開始時(shí)調(diào)用private void startCaptureThread()方法開始抓包,,jpcap.processPacket(1, handler);語(yǔ)句能夠反復(fù)調(diào)用handler所指向的方法,這個(gè)方法中定義的packet就是網(wǎng)絡(luò)上抓到的數(shù)據(jù)包,,經(jīng)過frame.dealPacket(packet);就可以顯示在主界面上,。
程序三:抓包選項(xiàng)
package netcap;
import javax.swing.JFrame;
import jpcap.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
/**
* This code was edited or generated using CloudGarden's Jigloo
* SWT/Swing GUI Builder, which is free for non-commercial
* use. If Jigloo is being used commercially (ie, by a corporation,
* company or business for any purpose whatever) then you
* should purchase a license for each developer using Jigloo.
* Please visit www.cloudgarden.com for details.
* Use of Jigloo implies acceptance of these licensing terms.
* A COMMERCIAL LICENSE HAS NOT BEEN PURCHASED FOR
* THIS MACHINE, SO JIGLOO OR THIS CODE CANNOT BE USED
* LEGALLY FOR ANY CORPORATE OR COMMERCIAL PURPOSE.
*/
public class Jcapturedialog extends javax.swing.JDialog implements ActionListener {
/**
* Auto-generated main method to display this JDialog
*/
static JpcapCaptor jpcap=null;
private JRadioButton wholeRadioButton;
private JPanel buttonPanel;
private JButton cancelButton;
private JButton okButton;
private JRadioButton userRadioButton;
private JRadioButton headRadioButton;
private JPanel netPanel;
private JTextField caplenTextField;
private JPanel caplenPanel;
private JTextField TextField;
private JPanel filterPanel;
private JCheckBox CheckBox;
private JComboBox netJComboBox;
private JPanel jPanel_east;
private JPanel jPanel_west;
NetworkInterface[] devices;
public static void main(String[] args) {
JFrame frame = new JFrame();
Jcapturedialog inst = new Jcapturedialog(frame);
inst.setVisible(true);
}
public Jcapturedialog(JFrame frame) {
super(frame,'選擇要檢測(cè)的網(wǎng)卡并設(shè)置參數(shù)',true);
try {
BoxLayout thisLayout = new BoxLayout(
getContentPane(),
javax.swing.BoxLayout.X_AXIS);
getContentPane().setLayout(thisLayout);
{
jPanel_west = new JPanel();
jPanel_west.setLayout(new BoxLayout(jPanel_west,BoxLayout.Y_AXIS));
getContentPane().add(jPanel_west);
{
netPanel = new JPanel();
FlowLayout netPanelLayout = new FlowLayout();
netPanelLayout.setAlignOnBaseline(true);
netPanel.setBorder(BorderFactory.createTitledBorder('選擇網(wǎng)卡'));
netPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
jPanel_west.add(netPanel);
netPanel.setLayout(netPanelLayout);
// netPanel.setPreferredSize(new java.awt.Dimension(239, 56));
{
devices = JpcapCaptor.getDeviceList();
if(devices == null){
JOptionPane.showMessageDialog(frame, '沒有找到網(wǎng)卡');
dispose();
return;
}
else{
String[] names = new String[devices.length];
for(int i=0;i < names.length;i ){
names[i] = (devices[i].description == null?devices[i].name:devices[i].description);
}
netJComboBox = new JComboBox(names);
}
netPanel.add(netJComboBox);
}
}
{
CheckBox = new JCheckBox();
jPanel_west.add(CheckBox);
FlowLayout CheckBoxLayout = new FlowLayout();
CheckBoxLayout.setAlignOnBaseline(true);
CheckBox.setText('/u662f/u5426/u8bbe/u7f6e/u4e3a/u6df7/u6742/u6a21/u5f0f');
CheckBox.setLayout(null);
}
{
filterPanel = new JPanel();
filterPanel.setBorder(BorderFactory.createTitledBorder('捕獲過濾器'));
filterPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
FlowLayout filterPanelLayout = new FlowLayout();
filterPanelLayout.setAlignment(FlowLayout.LEFT);
filterPanelLayout.setAlignOnBaseline(true);
jPanel_west.add(filterPanel);
filterPanel.setLayout(filterPanelLayout);
{
TextField = new JTextField(20);
filterPanel.add(TextField);
}
}
}
{
jPanel_east = new JPanel();
jPanel_east.setLayout(new BoxLayout(jPanel_east,BoxLayout.Y_AXIS));
getContentPane().add(jPanel_east);
{
caplenPanel = new JPanel();
caplenPanel.setBorder(BorderFactory.createTitledBorder('最長(zhǎng)字長(zhǎng)'));
caplenPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
jPanel_east.add(caplenPanel);
caplenPanel.setLayout(new BoxLayout(caplenPanel,BoxLayout.Y_AXIS));
{
caplenTextField = new JTextField(20);
caplenPanel.add(caplenTextField);
caplenTextField.setText('1514');
caplenTextField.setEnabled(false);
}
{
wholeRadioButton = new JRadioButton();
FlowLayout userRadioButtonLayout = new FlowLayout();
userRadioButtonLayout.setAlignOnBaseline(true);
caplenPanel.add(wholeRadioButton);
wholeRadioButton.setText('/u6574/u4e2a/u6570/u636e/u62a5');
wholeRadioButton.setSelected(true);
wholeRadioButton.addActionListener(this);
}
{
headRadioButton = new JRadioButton();
caplenPanel.add(headRadioButton);
headRadioButton.setText('/u4ec5/u9996/u90e8');
headRadioButton.addActionListener(this);
}
{
userRadioButton = new JRadioButton();
caplenPanel.add(userRadioButton);
userRadioButton.setText('/u5176/u4ed6/u90e8/u5206');
userRadioButton.addActionListener(this);
}
ButtonGroup group=new ButtonGroup();
group.add(wholeRadioButton);
wholeRadioButton.setActionCommand('Whole');
group.add(headRadioButton);
headRadioButton.setActionCommand('Head');
group.add(userRadioButton);
userRadioButton.setActionCommand('user');
}
{
buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
// buttonPanel.setLayout(new BoxLayout(buttonPanel,BoxLayout.X_AXIS));
jPanel_east.add(buttonPanel);
{
okButton = new JButton();
buttonPanel.add(okButton);
FlowLayout cancelButtonLayout = new FlowLayout();
cancelButtonLayout.setAlignOnBaseline(true);
okButton.setText('/u786e/u5b9a');
okButton.setActionCommand('ok');
okButton.addActionListener(this);
}
{
cancelButton = new JButton();
buttonPanel.add(cancelButton);
cancelButton.setText('/u53d6/u6d88');
cancelButton.setActionCommand('cancel');
cancelButton.addActionListener(this);
}
// buttonPanel.setAlignmentX(Component.RIGHT_ALIGNMENT);
}
}
getContentPane().setLayout(new BoxLayout(getContentPane(),BoxLayout.X_AXIS));
getContentPane().add(jPanel_west);
getContentPane().add(jPanel_east);
pack();
} catch (Exception e) {
e.printStackTrace();
}
}
public void actionPerformed(ActionEvent evt){
String cmd=evt.getActionCommand();
if(cmd.equals('Whole')){
caplenTextField.setText('1514');
caplenTextField.setEnabled(false);
}else if(cmd.equals('Head')){
caplenTextField.setText('68');
caplenTextField.setEnabled(false);
}else if(cmd.equals('user')){
caplenTextField.setText('');
caplenTextField.setEnabled(true);
caplenTextField.requestFocus();
}else if(cmd.equals('ok')){
try{
int caplen=Integer.parseInt(caplenTextField.getText());
if(caplen<68 || caplen>1514){
JOptionPane.showMessageDialog(null,'捕獲長(zhǎng)度必須介于 68 和 1514之間');
return;
}
jpcap=JpcapCaptor.openDevice(devices[netJComboBox.getSelectedIndex()],caplen,
CheckBox.isSelected(),50);
if(TextField.getText()!=null && TextField.getText().length()>0){
jpcap.setFilter(TextField.getText(),true);
}
}catch(NumberFormatException e){
JOptionPane.showMessageDialog(null,'捕獲長(zhǎng)度必須是正整數(shù)');
}catch(java.io.IOException e){
JOptionPane.showMessageDialog(null,e.toString());
jpcap=null;
}finally{
dispose();
}
}else if(cmd.equals('cancel')){
dispose();
}
}
public static JpcapCaptor getJpcap(JFrame parent){
new Jcapturedialog(parent).setVisible(true);
return jpcap;
}
}
這一部分主要是界面操作,根據(jù)jigloo插件對(duì)不同的按鈕和文本框還有其他的組件設(shè)置監(jiān)聽操作,,以激發(fā)不同的函數(shù)操作,,主要是devices = JpcapCaptor.getDeviceList();語(yǔ)句和
jpcap=JpcapCaptor.openDevice(devices[netJComboBox.getSelectedIndex()],caplen,
CheckBox.isSelected(),50);語(yǔ)句要選擇一下監(jiān)聽的網(wǎng)卡,比如說(shuō)筆記本就有兩個(gè)網(wǎng)卡,,一個(gè)無(wú)線一個(gè)有線,,選擇一下就會(huì)監(jiān)聽相應(yīng)的網(wǎng)卡。函數(shù)
publicstatic JpcapCaptor getJpcap(JFrame parent){
new Jcapturedialog(parent).setVisible(true);
returnjpcap;
}
返回jpcap,,這個(gè)jpcap就是對(duì)應(yīng)的選擇上的網(wǎng)卡對(duì)象,,接下來(lái)就從對(duì)應(yīng)的網(wǎng)卡對(duì)象jpcap上不斷得到數(shù)據(jù)包。
|
|