程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

Use Python to capture and analyze the packets and store them in the database, or directly analyze the packets caught by tcpdump and Wireshark and store them in the database

編輯:Python

preparation

The first thing you need to do is to capture packets scapy package

install scapy package

pip install scapy

stay python Reference... In the code scapy package

from scapy.all import *
# In order to save trouble , direct import *, You can also import what you want to use according to your needs 

Grab the bag

Want to analyze packages , First of all, there should be bags , Let's start with bag grabbing

Packet capturing uses scapy Medium sniff() Method

pcaps = sniff(filter="",iface="any", prn=function, count="")
#filter The rules of Berkeley Packet Filter (BPF) grammar
#iface It is used to specify which network interface to capture packets ( Usually all network interfaces are not specified )
#prn Specify the callback function , Whenever a match filter When the message is detected , Will execute the callback function , Usually use lambda Expression to write a callback function
#count Specify the maximum number of packets to sniff ( Compliance filter Conditional message , Not all messages )

among

filter Filter rules for , reference BPF Syntax fill filter rule

for example :filter="ip src www.baidu.com"  The source address is www.baidu.com Message of

iface For which network card to grab packets from , Fill in the network card name at the back

for example :iface="WLAN"    or    iface="eth0"

prn Is a callback function , Simple usage such as :prn=lambda x:x.summary()  or   prn=lambda x:x[IP].src

prn=lambda x:x.summary()  Is the brief information of the printed message

effect :Ether / IP / TCP 192.168.2.204:4963 > 180.97.162.191:8202 A

prn=lambda x:x[IP].src Is the source address of the printed message

effect :192.168.1.1

count To capture how many messages

Save package

If you catch a bag and want to save it , So that we can analyze it slowly next time , You can use the following methods to save

wrpcap("pc2.pcap", pcaps)

If you don't want to save , Then go straight to the next step

Analysis package

After catching the bag , Just now we used the method of callback function summary, Shows brief information about each package , There are also many ways to print the information of the bag , Refer to the following code for details

from scapy.all import *
dpkt = sniff(iface="WLAN", count=10)
print(dpkt)
# Print out the total information of the package , Printing effect :
#<Sniffed: TCP:2 UDP:0 ICMP:0 Other:0>
print(dpkt[0])
# Print the first package , In fact, this printing is useless , I can't see anything , Because it's all 16 Base number , That's what the warning means. Printing doesn't make any sense , Printing effect
#WARNING: Calling str(pkt) on Python 3 makes no sense!
#b'X\x00\xe3Df\xfbh\xa8(/\xd7\t\x08\x00E\x00\x01{\xa6)@\x005\x11 \xef=\x97\xb4\xa2\xac\x1c\xdf\x03\[email protected]\x0f\xb1\x01g\x06>\x02:-\x00\x17\xab\r2\xc2o\n\x00\x00\nF.v\x8e+\x80\x0e\x14\xa3/\'\x7f+_\xba%\xd86\xb8\x00\xda\n\x7f\xff\xc16\x13
-#\x15\t\xe4\xb6[U\xdcT\xfb\xf6\xfb\xc5!%~\x92U\xdd\x96\x88\xf6\x12\xc8.\xda9\xd0\x85\x9d{\xd7/,\xf6\xb2\x9a\xe9\xbcg\x1bw\xec-\xab9\xab\x8e\xc0\x94\xef\xdbneT\x8f\xe3c\xa0h=\xc0\n+\xec\xdf\xa2x\xb3\x03\xc7GR\x90~D\xa4\xbe\x8a\xf8\xa
#d\xb9I\x05\x16&%\xa6B\xabM\xd1\x1bh\xa8\xb1\xe8=\xc7HG\x11Qv\xa3\x11\x14\xf0\x98\xb2\x9c\xd3\x94\xd1\xa1&\x99;\x86\xa6.\x10\x1e\x1d\xf5\xa3H(\xa7I\x84\xf9\xa8k\x9f\r\x86\x05\xf9p\x0b\xc0\x8e\xda\xcer\x0e<\xaf\x16\xccT|\xae\xack\x1a\
#xd1\xae\\1\xc9\x98\xb4\xc4Um\xb6\xa1\xdfAoa\xc5\xa6N\xe9\xbd\x9fB\xed\x94\xf2\xe2\xb4\xa4O\xa46,\xbc\xe8\x86h,\x19\x0e\x01\x93\xa9*\\\xd0mW\x03\xb2r\xc6\x8cN\xf8#8\x8e\t\xfc\x08O.\x13\x9er2\x86\x81*[\xb1\xfb\xaaD\xc8\x83\xab\xc9\xda
#`\xac:\x02\xaf\x1a\xf9\xfb\x08\x93,\xd7q\x8b\xaev/\xd3}\xf3t*\xcf\xebUt\xe5[\x06\xe7\xab\x03eg\xe6hd\x81\xe3EH\\\x99MZW\x1c\xb9\x87"\xa4\xff\x03y\xf9Q#\x00B9qK\xbf\x99a"\n75\xc8Z\xa2\x03'
print(dpkt[0].show())
# Show package details , Because each package is different , So the effect of printing may be different , I only showed the printing effect of this kind of package , The effect is as follows :
# ###[ Ethernet ]###
# dst = 68:a8: 28:2
# f: d7:0
# 9
# src = 58:00: e3:44: 66:fb
# type = IPv4
# ###[ IP ]###
# version = 4
# ihl = 5
# tos = 0x4
# len = 58
# id = 19004
# flags = DF
# frag = 0
# ttl = 200
# proto = tcp
# chksum = 0x6875
# src = 172.28.223.3
# dst = 172.31.200.200
# \options \
# ###[ TCP ]###
# sport = 49688
# dport = 9988
# seq = 2674031876
# ack = 3838184596
# dataofs = 5
# reserved = 0
# flags = PA
# window = 513
# chksum = 0xbe17
# urgptr = 0
# options = []
# ###[ Raw ]###
# load = "\x01LVSIs'\\x9e0\n\x00\x00\x00\x00\x00\x00\x00\x00"
#
#
# None
print(dpkt[0].time)
# Print time , The printing effect is as follows :
# 1639643824.65736
print(dpkt[0].fields)
# {'dst': '01:00:5e:7f:ff:fa', 'src': '58:00:e3:44:66:fb', 'type': 2048}
# Print dpkt[0].show() Information in
# For example, print the above IP Inside src
print(dpkt[0][IP].src)
# Such as print TCP Medium sport
print(dpkt[0]["TCP"].sport)
#0 It means the 0 A package , If you want to see the second bag , Can be 0 Change it to 1, If you want to traverse all the packages , You can replace the numbers inside with a loop
# Be careful , Some bags may not have TCP, Not even IP, You need to judge when traversing

Insert database

I won't talk about it here , Refer to other materials

The overall code

capture.yp


import Database
from scapy.all import *
def get_all_pcap(ifs, size=10, filter=""):
# Grab the bag
pcaps = sniff(iface=ifs, count=size, filter=filter)
# Save package to file
# wrpcap("pc2.pcap", dpkt)
data = []
for item in pcaps:
if item['Ethernet'].type == 2048:
# ipv4
ethernet_type = 'IPV4'
# Judge tcp still udp
if item["IP"].proto == 6:
sport = item['TCP'].sport
dport = int(re.sub(r'[\(\)\,]', "", str(item['TCP'].dport)))
tcp_udp = 'TCP'
tcp_type = item['TCP'].flags
else:
sport = item['UDP'].sport
dport = re.sub(r'[\(\)\,]', "", str(item['UDP'].dport))
tcp_udp = 'UDP'
tcp_type = 'null'
src_ip = re.sub(r'[\(\)\,]', "", str(item['IP'].src))
dst_ip = re.sub(r'[\(\)\,]', "", str(item['IP'].dst))
elif item['Ethernet'].type == 2054:
# ARP
ethernet_type = 'ARP'
src_ip = item['ARP'].psrc
dst_ip = item['ARP'].pdst
sport = 'null'
dport = 'null'
tcp_udp = 'null'
tcp_type = 'null'
else:
# ipv6
ethernet_type = 'IPV6'
src_ip = item['IPv6'].src
dst_ip = item['IPv6'].dst
sport = 'null'
dport = 'null'
tcp_udp = 'null'
tcp_type = 'null'
time = item.time
# Insert data into the array
data.append([
ethernet_type,
src_ip,
dst_ip,
sport,
dport,
tcp_udp,
str(tcp_type),
int(time)
])
return data
def insertToSQL(data):
field = ['ethernet_type', 'src_ip', 'dst_ip', 'sport', 'dport', 'TCP_UDP', 'tcp_type', 'time']
# insert data
result = Database.Database().insert_all('pack_info', field, data)
if result == 0:
return 'success'
else:
return 'error'
def main():
# Grab the bag
# ifs = 'WLAN' # network card
data = get_all_pcap('WLAN', 100, 'tcp')
# Insert database
result = insertToSQL(data)
print(result)
if __name__ == '__main__':
main()

Datebase.py

import pymysql.cursors
class Database:
connected = False
__conn = None
# Constructors , Connect to the database directly during initialization
def __init__(self):
conf = {
'host': 'ip',
'port': 3306,
'user': ' user name ',
'pw': ' password ',
'db': ' database '}
if type(conf) is not dict:
print(' error : Parameter is not a dictionary type !')
else:
for key in ['host', 'port', 'user', 'pw', 'db']:
if key not in conf.keys():
print(' error : Parameter dictionary is missing %s' % key)
if 'charset' not in conf.keys():
conf['charset'] = 'utf8'
try:
self.__conn = pymysql.connect(
host=conf['host'],
port=conf['port'],
user=conf['user'],
passwd=conf['pw'],
db=conf['db'],
charset=conf['charset'],
cursorclass=pymysql.cursors.DictCursor)
self.connected = True
except pymysql.Error as e:
print(' Database connection failed :', end='')
# Insert a piece of data into the data table
def insert_one(self, table, val_obj):
sql_top = 'INSERT INTO ' + table + ' ('
sql_tail = ') VALUES ('
try:
for key, val in val_obj.items():
sql_top += key + ','
if isinstance(val,int):
sql_tail += str(val) + ','
else:
sql_tail += '\'' + val + '\'' + ','
sql = sql_top[:-1] + sql_tail[:-1] + ')'
# Print sql sentence
# print(sql)
# exit()
with self.__conn.cursor() as cursor:
cursor.execute(sql)
self.__conn.commit()
return self.__conn.insert_id()
except pymysql.Error as e:
self.__conn.rollback()
return False
def insert_all(self,table,field,record):
sql_top = 'INSERT INTO ' + table + ' ('
sql_tail = ') VALUES ('
try:
for val in field:
sql_top += val + ','
for i in record:
for j in i:
if isinstance(j, int):
sql_tail += str(j) + ','
else:
sql_tail += '\'' + j + '\'' + ','
sql_tail = sql_tail[:-1] + '),('
sql = sql_top[:-1] + sql_tail[:-2]
# Print sql sentence
# print(sql)
# exit()
with self.__conn.cursor() as cursor:
cursor.execute(sql)
self.__conn.commit()
return self.__conn.insert_id()
except pymysql.Error as e:
self.__conn.rollback()
return False
# Close database connection when destroying object
def __del__(self):
try:
self.__conn.close()
except pymysql.Error as e:
pass
# Close database connection
def close(self):
self.__del__()

It is purely to record the personal learning process , I'm just beginning to learn python, I feel that there must be something wrong with the above code , If there is something incorrect or unclear , Welcome to correct ..

Some of this knowledge refers to the following links , Thank you, big brother

python Capture and unpack _ Yi Ran -CSDN Blog _python Grab the bag


  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved