public bool checkIfExist(List <cyberPhysicalState> states, cyberPhysicalState c) { var status = false; foreach (var item in states) { var x = item.exploits.FirstOrDefault(); var y = c.exploits.FirstOrDefault(); if (x == y) { return(true); } } return(status); }
// State Space creation /* * Optimal policy for different states */ //public int[] optimalAct = { 1, 3, 3, 3, 3, 3, 3, 2, 3, 2, 2, 4, 4, 4, 5, 5, 5 }; public List <cyberPhysicalState> createMDPStates() { // for example we have 8 host.. currently the list of host are taken for testing purpose hence they are hardcoded. List <host> hosts = new List <host>(); hosts.Add(new host { hostId = "H1A", vulns = new List <vulnerability> { new vulnerability { vuln_name = "v1", score = 4.567, isExploited = false, isPatched = true } } }); hosts.Add(new host { hostId = "H2A", vulns = new List <vulnerability> { new vulnerability { vuln_name = "v2", score = 8.767, isExploited = false, isPatched = true } } }); hosts.Add(new host { hostId = "RA", vulns = new List <vulnerability>() }); hosts.Add(new host { hostId = "H1B", vulns = new List <vulnerability> { new vulnerability { vuln_name = "v3", score = 5.467, isExploited = false, isPatched = true }, new vulnerability { vuln_name = "v2", score = 8.767, isExploited = false, isPatched = true } } }); hosts.Add(new host { hostId = "H2B", vulns = new List <vulnerability> { new vulnerability { vuln_name = "v1", score = 4.567, isExploited = false, isPatched = true } } }); hosts.Add(new host { hostId = "RB", vulns = new List <vulnerability>() }); hosts.Add(new host { hostId = "H1C", vulns = new List <vulnerability> { new vulnerability { vuln_name = "v4", score = 2.567, isExploited = false, isPatched = true } } }); hosts.Add(new host { hostId = "RC", vulns = new List <vulnerability>() }); hosts.Add(new host { hostId = "H1D", vulns = new List <vulnerability> { new vulnerability { vuln_name = "v1", score = 4.567, isExploited = false, isPatched = true } } }); hosts.Add(new host { hostId = "H2D", vulns = new List <vulnerability> { new vulnerability { vuln_name = "v2", score = 8.767, isExploited = false, isPatched = true } } }); hosts.Add(new host { hostId = "RD", vulns = new List <vulnerability>() }); hosts.Add(new host { hostId = "H1E", vulns = new List <vulnerability> { new vulnerability { vuln_name = "v3", score = 5.467, isExploited = false, isPatched = true }, new vulnerability { vuln_name = "v2", score = 8.767, isExploited = false, isPatched = true } } }); hosts.Add(new host { hostId = "H2E", vulns = new List <vulnerability> { new vulnerability { vuln_name = "v1", score = 4.567, isExploited = false, isPatched = true } } }); hosts.Add(new host { hostId = "RE", vulns = new List <vulnerability>() }); // List of attackpaths List <string> attackPaths = new List <string> { "H1A(v1):H2A(v2):RA", "H2A(v2):RA", "H1B(v3):H2B(v1):RB", "H2B(v1):RB", "H1B(v2):RB", "H1C(v4):RC", "H1D(v1):H2D(v2):RD", "H2D(v2):RD", "H1E(v3):H2E(v1):RE", "H2E(v1):RE", "H1E(v2):RE" }; // for time being lets consider all are neighbor to each other in a given substation for (int i = 0; i < attackPaths.Count; i++) { var elements = attackPaths[i].Split(':'); for (int j = 0; j < elements.Length - 1; j++) { host h = hosts.Single(a => a.hostId == elements[j].Split('(')[0]); host neigh = hosts.Single(a => a.hostId == elements[j + 1].Split('(')[0]); if (!h.neighbors.Contains(neigh)) { h.neighbors.Add(neigh); } } } // After the neighbors are formed create cyber states where Phy Normal List <cyberPhysicalState> states = new List <cyberPhysicalState>(); var normal = new cyberPhysicalState { ID = 0, exploits = new List <host>(), layer = 0 }; states.Add(normal); int stateCount = 1; // Layer 1 states for (int i = 0; i < hosts.Count; i++) { if (hosts[i].neighbors.Count != 0) { // get the list of exploits possible var c = new cyberPhysicalState { ID = stateCount++, exploits = new List <host> { hosts[i] }, layer = 1 }; normal.neighbors.Add(c); // downward link c.neighbors.Add(normal); // upward link // Add the state if doesnt exist states.Add(c); } } // Layer 2 states var firstLayercount = states.Count; for (int i = 1; i < firstLayercount; i++) // excluding the first normal state { for (int j = 0; j < states[i].exploits.Count; j++) { var x = states[i].exploits[j]; foreach (var item in x.neighbors) { if (item.neighbors.Count != 0) { var c = new cyberPhysicalState { ID = stateCount++, exploits = new List <host> { x, item }, layer = 2 }; states[i].neighbors.Add(c); // downward link c.neighbors.Add(states[i]); // upward link states.Add(c); } else // Layer 3 states .. all the Relays compromised { var c = new cyberPhysicalState { ID = stateCount++, exploits = new List <host> { item }, layer = 3 }; if (!checkIfExist(states, c)) { states[i].neighbors.Add(c); // downward link c.neighbors.Add(states[i]); // upward link states.Add(c); } else { stateCount--; } } } } } // Add the links for the newly added states in Layer 2 and Layer 3 /* * for (int i = firstLayercount; i < states.Count; i++) * { * if(states[i].exploits.Count>1 && states[i].layer == 2) * { * states[i].neighbors.Add(states[i + 1]); // since all the Layer 3 states are placed after the Layer 2 states hence this logic works, need to change later * } * } */ // // Add the power system states to the cyber states // There are 2*no_of_Relays = breakers that could be opened by the relays .. for all the layer 3 states add the possible power system states possible // breaker openings are related to the transmission lines connectivity.. Dictionary <string, List <string> > relay_tx = new Dictionary <string, List <string> >(); List <string> relays = new List <string> { "RA", "RB", "RC", "RD", "RE" }; relay_tx["RA"] = new List <string> { "L1", "L2" }; relay_tx["RB"] = new List <string> { "L1", "L3" }; relay_tx["RC"] = new List <string> { "L2", "L4" }; relay_tx["RD"] = new List <string> { "L3", "L4", "L5" }; relay_tx["RE"] = new List <string> { "L5" }; // state count from cyber side int cyberstatesCount = states.Count; List <string> checker = new List <string>(); for (int m = 0; m < cyberstatesCount; m++) { if (states[m].layer == 3) // relays { List <host> hs = states[m].exploits; foreach (var h in hs) { if (relays.Contains(h.hostId)) { var g = relay_tx[h.hostId]; for (int i = 0; i < g.Count; i++) { if (checker.Contains(g[i])) { continue; } var cyberInduced_breakerOpen = new cyberPhysicalState { ID = stateCount++, exploits = new List <host> { new host { hostId = g[i] } }, layer = 100 }; // assign a very high layer to physical states states[states.IndexOf(states[m])].neighbors.Add(cyberInduced_breakerOpen); // downward cyberInduced_breakerOpen.neighbors.Add(states[states.IndexOf(states[m])]); // upward states.Add(cyberInduced_breakerOpen); checker.Add(g[i]); } } } } } // Add physical states after switch to manual and add them as the neighbors of the compromised normal states List <cyberPhysicalState> manualEmergencyStates = new List <cyberPhysicalState>(); foreach (var s in states) { if (s.layer == 100) { var cyberIsolatedBreakerOpen = new cyberPhysicalState { ID = stateCount++, layer = 101 }; s.neighbors.Add(cyberIsolatedBreakerOpen); // add cyber compromised normal to manual state cyberIsolatedBreakerOpen.neighbors.Add(states[0]); // add manual state connectivity normal state states[0].neighbors.Add(cyberIsolatedBreakerOpen); // add normal state connectivity to uncompromised fault state manualEmergencyStates.Add(cyberIsolatedBreakerOpen); } } foreach (var item in manualEmergencyStates) { states.Add(item); } //foreach (var s in states) //{ // if (s.layer == 100) // { // s.neighbors.Add(states[0]); // all normal state, temporarily // } //} //return states; return(states); }