13 echo "Usage: $0 <pcap_file> [results_dir]"
15 echo " pcap_file: pcap formatted file to be processed."
16 echo " results_dir: directory where results are stored."
17 echo " By default, pcap file dirname is used."
19 echo " The utility, dumps the extracted hexadecimal content"
20 echo " and useful information as timestamps, source and"
22 echo " <results_dir>/<frame sequence>.hex"
23 echo " <results_dir>/<frame sequence>.metadata"
41 # $1: string; $2: substring
45 local substr="${1%%$2*}"
48 [ $size -ne $pos ] && result=$pos
57 echo "============================================"
58 echo "Diameter buffer extractor from PCAP raw file"
59 echo "============================================"
63 [ "$1" = "" ] && usage
67 [ ! -f $PCAP_FILE ] && _exit "Cannot found provided pcap file '$1' !!"
69 # Optional result dir:
70 RESULTS_DIR=`dirname $PCAP_FILE`
71 [ "$2" != "" ] && RESULTS_DIR=$2
72 [ ! -d $RESULTS_DIR ] && _exit "The results directory '$RESULTS_DIR' must exists !!"
74 # Get the frames with diameter content (take care about '-2' two-pass option and don't add it, because we need to get reassembled parts in their corresponding frames):
75 # Fields needed (we won't need diameter.hopbyhopid & diameter.endtoendid to verify diameter message as hint patterns; length management will be enough):
76 FIELDS="-e frame.number -e frame.time_epoch -e ip.src_host -e ip.dst_host -e tcp.len -e diameter.length -e frame.protocols -e tcp.segment"
77 tshark -E separator="|" -r $PCAP_FILE -N mntC -Tfields $FIELDS 2>/dev/null | grep -i diameter > $tmpdir/diameter_frames
80 # frame timestamp src dst TCP DIAM protocol segments
81 # 1|1427215933.697904000|gt_traf|vcbavipt|432|432|eth:ip:tcp:diameter:diameter:diameter3gpp|
82 # 3|1427215934.449523000|vcbavipt|gt_traf|292|292|eth:ip:tcp:diameter:diameter:diameter3gpp|
83 # 5|1427215934.456160000|gt_traf|vcbavipt|1400||eth:ip:tcp:diameter|
84 # 6|1427215934.456204000|gt_traf|vcbavipt|572|1972|eth:ip:tcp:diameter:diameter:diameter3gpp|5,6
85 # 8|1427215935.123559000|vcbavipt|gt_traf|248|248|eth:ip:tcp:diameter:diameter:diameter3gpp|
86 all_frames=( $(cat $tmpdir/diameter_frames | cut -d\| -f1) )
87 needs_join=( $(cat $tmpdir/diameter_frames | cut -d\| -f8) )
88 main_frames=( $(cat $tmpdir/diameter_frames | awk -F\| '{ if ($6 != "") print $1 }') )
90 # Reassemble procedure (using frame 1 as example):
91 # (for non segmented frames, it is enough with tcp or diameter length within the frame content itself)
92 # 1) Get the TCP length: 432 bytes. 432*2 = 864 characters per byte in hexadecimal string format
93 # 2) Get the frame length: `wc -c $tmpdir/block.$frame` => 997
94 # 3) Get 864 from the tail: `cat $tmpdir/block.$frame | cut -c133
96 # Dump the hex blocks for all the diameter frames:
97 cat $PCAP_FILE | rawshark -s -r - -d proto:diameter -F data 2>/dev/null > $tmpdir/all_hex_data
98 for frame in ${all_frames[@]}; do
99 grep "^$frame " $tmpdir/all_hex_data | cut -d\" -f2 | sed 's/://g' > $tmpdir/block.$frame
100 frame_info=$(grep "^${frame}|" $tmpdir/diameter_frames)
102 # Get the diameter part:
103 tcp_len=$(echo $frame_info | cut -d\| -f5)
104 frm_len=$(wc -c $tmpdir/block.$frame | awk '{ print $1 }')
105 cut_len=$((frm_len-2*tcp_len))
106 cat $tmpdir/block.$frame | cut -c${cut_len}- > $RESULTS_DIR/$frame.hex
107 echo -n "Created $RESULTS_DIR/$frame.hex"
110 ts=$(echo $frame_info | cut -d\| -f2)
112 src=$(echo $frame_info | cut -d\| -f3)
113 dst=$(echo $frame_info | cut -d\| -f4)
114 echo -e "timestamp=$ts\ndate=$date\nsrc=$src\ndst=$dst" > $RESULTS_DIR/$frame.metadata
115 echo " and $RESULTS_DIR/$frame.metadata"
118 # Join frames which need to be reassembled:
119 for group in ${needs_join[@]}; do
120 echo "Grouping frames $group ..."
121 group_array=( $(echo $group | sed 's/,/ /g') )
122 for frame in ${group_array[@]}; do
123 cat $RESULTS_DIR/$frame.hex >> $tmpdir/diam.$group
125 cat $tmpdir/diam.$group | tr -d '\n' > $RESULTS_DIR/$frame.hex
128 # Delete superfluous metadata:
129 echo "Deleting superfluous metadata ..."
130 segments=( $(cat $tmpdir/diameter_frames | awk -F\| '{ if ($6 == "") print $1 }') )
131 for s in ${segments[@]}; do rm $RESULTS_DIR/$s.metadata; done