From 8a803b9d024f94da3ba6a260a54525d00c14147f Mon Sep 17 00:00:00 2001 From: Cole Deck Date: Tue, 25 Oct 2022 01:03:04 -0500 Subject: [PATCH 1/3] Add icons, firewall blocking (windows) --- auth.py | 1 + block.py | 14 ++++++- config.yml | 27 ++++++------ ippigeon.py | 72 ++++++++++++++++++++++++++++---- panel.py | 118 +++++++++++++++++++++++++++++++++++++++++++++------- 5 files changed, 191 insertions(+), 41 deletions(-) diff --git a/auth.py b/auth.py index e9a4338..ccd4354 100644 --- a/auth.py +++ b/auth.py @@ -28,6 +28,7 @@ def login(config, user, password, sysid): # try again count += 1 sleep(0.1) + filename = sysid + "success.txt" #raise ValueError("Unable to determine login status") else: return False diff --git a/block.py b/block.py index ee80967..ac6aebb 100644 --- a/block.py +++ b/block.py @@ -21,7 +21,15 @@ def get_blocklist(config): data2.append(row) data2 = [i for i in data2 if i] #fprint(data2) - data2.append(["N/A", "N/A", "N/A", "N/A", "100.115.71.78", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A"]) + data2.append(["N/A", "TCP", "N/A", "N/A", "20.112.52.29", "5000", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A"]) + data2.append(["N/A", "TCP", "N/A", "N/A", "20.81.111.85", "80", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A"]) + data2.append(["N/A", "TCP", "N/A", "N/A", "100.115.71.78", "5000", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A"]) + data2.append(["N/A", "TCP", "N/A", "N/A", "100.115.71.78", "5000", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A"]) + data2.append(["N/A", "TCP", "N/A", "N/A", "174.143.130.167", "443", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A"]) + data2.append(["N/A", "TCP", "N/A", "N/A", "216.47.134.203", "443", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A"]) + data2.append(["N/A", "TCP", "N/A", "N/A", "34.111.83.189", "443", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A"]) + + fprint(data2) with open(find_data_file("blocklist.csv"), "w", newline="") as f: writer = csv.writer(f) @@ -35,6 +43,7 @@ def block_conn(config, datafile, res): mydata = list() badapps = list() badips = list() + badlines = list() with open(find_data_file(datafile), newline='') as csvfile: csvreader = csv.reader(csvfile, delimiter=',', quotechar='|') @@ -68,7 +77,8 @@ def block_conn(config, datafile, res): fprint("FLAG " + srcip + " " + destip + " " + str(pid)) badapps.append(pid) badips.append(baddestip) + badlines.append(line) #fprint(badapps) #fprint("FLAG " + srcip + " " + destip + " " + str(pid)) #kill(pid) - return badapps, badips + return badapps, badips, badlines diff --git a/config.yml b/config.yml index 9673127..a2ba196 100644 --- a/config.yml +++ b/config.yml @@ -1,20 +1,19 @@ +core: + autostart: true + clockspeed: 20 + interval: 10 + level: 3 + localadmin: true sftp: - host: ec2-34-232-29-46.compute-1.amazonaws.com - user: ec2-user - port: 22 - keyfile: keyfile-admin.pem - filepath: - send: /home/ec2-user/Incoming/Incoming_Data - sendlogin: /home/ec2-user/Incoming/Login + filepath: receive: /home/ec2-user/Outgoing/Outgoing_Data receivelogin: /home/ec2-user/Outgoing/Login scripts: /home/ec2-user/scripts - + send: /home/ec2-user/Incoming/Incoming_Data + sendlogin: /home/ec2-user/Incoming/Login + host: ec2-34-232-29-46.compute-1.amazonaws.com + keyfile: keyfile-admin.pem + port: 22 + user: ec2-user ui: darkmode: true - -core: - autokill: false - localadmin: true - interval: 10 - clockspeed: 20 diff --git a/ippigeon.py b/ippigeon.py index 5dbd6ae..cc90e09 100644 --- a/ippigeon.py +++ b/ippigeon.py @@ -9,6 +9,7 @@ import yaml from util import find_data_file from util import fprint from util import kill +from util import run_cmd import taskbartool import util import netstat @@ -63,9 +64,10 @@ def netstat_done(res): #netstat.process(res) def process_done(res): - fprint("uploading to sftp...") - #ssh.sftp_send_data(res, config, datafile) - procdata_res = pool.apply_async(ssh.sftp_send_data, (config, datafile, 'send'), callback=upload_done) + if settings["running"] == True: + fprint("uploading to sftp...") + #ssh.sftp_send_data(res, config, datafile) + procdata_res = pool.apply_async(ssh.sftp_send_data, (config, datafile, 'send'), callback=upload_done) def upload_done(res): settings["block"] = True @@ -85,7 +87,7 @@ def blockdata_done(res): tmpkill = settings["kill"] settings["kill"] = False #block_res = pool.apply_async(block.block_conn, (config, datafile, res, settings)) - block_pids, block_ips = block.block_conn(config, datafile, res) + block_pids, block_ips, block_data = block.block_conn(config, datafile, res) tmplist = settings["badapps"] for x in block_pids: @@ -104,6 +106,16 @@ def blockdata_done(res): fprint(settings["badips"]) settings["kill"] = tmpkill + + tmplist = settings["badlines"] + for x in block_data: + fprint(x) + if not x in tmplist: + tmplist.append(x) + settings["badlines"] = tmplist + fprint(settings["badlines"]) + + settings["newdata"] = True def killall(): kids = active_children() @@ -116,7 +128,7 @@ def killall(): def mainloop(pool): # worker pool: netstat, netstat cleanup, upload, download, ui tasks - + global config global counter global netdata_res global procdata_res @@ -158,18 +170,54 @@ def mainloop(pool): settings["login"] = False - if settings["block"] == True: + if settings["block"] == True and settings["running"] == True: blockdata_res = pool.apply_async(block.get_blocklist, (config,), callback=blockdata_done) #block.get_blocklist(config) settings["block"] = False + if config["core"]["level"] == 0: + settings["kill"] = False + settings["fwll"] = False + + if config["core"]["level"] == 1: + settings["kill"] = True + settings["fwll"] = False + + if config["core"]["level"] == 2: + settings["kill"] = False + settings["fwll"] = True + + if config["core"]["level"] == 3: + settings["kill"] = True + settings["fwll"] = True + if settings["kill"] == True: tmplist = settings["badapps"] settings["badapps"] = list() - for x in tmplist: kill(x) + if settings["fwll"] == True: + tmplist = settings["badlines"] + settings["badlines"] = list() + for line in tmplist: + badproto = line[1] + badip = line[4] + badport = line[5] + fprint("Firewalling " + badip + ":" + str(badport)) + cmd = 'New-NetFirewallRule -DisplayName "IPPigeon Security Rule ' + badip + ':' + str(badport) + '" -Group "IPPigeon" -Direction Outbound -LocalPort Any -Protocol ' + badproto + ' -Action Block -RemoteAddress ' + badip + ' -RemotePort ' + str(badport) + run_cmd(cmd) + + + if settings["applyconfig"] == True: + settings["applyconfig"] = False + config = settings["config"] + #fprint(settings["config"]) + with open(find_data_file('config.yml'), 'w') as filewrite: + #global config + yaml.dump(config, filewrite) + fprint("Config saved!") + sleep(interval / (interval * config["core"]["clockspeed"])) counter += 1 if counter == interval * config["core"]["clockspeed"]: @@ -203,9 +251,9 @@ if __name__ == '__main__': with Manager() as manager: with Pool(processes=5) as pool: - with open(find_data_file('config.yml'), 'r') as file: + with open(find_data_file('config.yml'), 'r') as fileread: #global config - config = yaml.safe_load(file) + config = yaml.safe_load(fileread) #print(config['sftp']['host']) interval = config['core']['interval'] displaydata = manager.list(range(2)) # data to be printed @@ -217,8 +265,14 @@ if __name__ == '__main__': settings["killbox"] = list() settings["badapps"] = list() settings["badips"] = list() + settings["badlines"] = list() settings["block"] = False settings["kill"] = False + settings["config"] = config + settings["applyconfig"] = False + settings["fwll"] = 0 + settings["running"] = config["core"]["autostart"] + settings["newdata"] = False killme = manager.Value('d', 0) #killme = False # launch background UI app as process diff --git a/panel.py b/panel.py index cb8b19e..9e269e3 100644 --- a/panel.py +++ b/panel.py @@ -7,12 +7,14 @@ from util import sysid from util import setup_child from util import fprint from util import find_data_file +import util BG_IMG = 'icon.png' filename = sysid + "gendata.csv" COLUMN_NAMES = np.flip(['Executable', 'Proto', 'Source IP', 'Destination IP', 'Status', 'PID']) COLUMN_SIZES = np.flip([200, 50, 200, 200, 140, 100]) TEST_FILE = None +SEC_LEVELS = ["0: Backend analysis only.", "1: Kill offending processes.", "2: Block offending connections using firewall.", "3: Kill and block connections and processes."] displaydata = None settings = None @@ -40,6 +42,8 @@ class OtherFrame(wx.Frame): def __init__(self): wx.Frame.__init__(self, None, -1, 'Server Panel', size=(1000, 700)) panel = ServerPanel(self) + self.SetIcon(wx.Icon(find_data_file("icon.ico"), wx.BITMAP_TYPE_ICO)) + self.Show() def on_edit(self, event): @@ -56,6 +60,7 @@ class HelpFrame(wx.Frame): def __init__(self): wx.Frame.__init__(self, None, -1, 'Help', size=(600, 250)) panel = HelpPanel(self) + self.SetIcon(wx.Icon(find_data_file("icon.ico"), wx.BITMAP_TYPE_ICO)) self.Show() @@ -143,13 +148,13 @@ class ServerPanel(wx.Panel): self, size=(-1, 400), style=wx.LC_REPORT | wx.BORDER_SUNKEN ) - tb = wx.ToolBar( self, -1) - self.ToolBar = tb - tb.SetToolBitmapSize(wx.Size(30, 3)) - tb.AddTool(wx.ID_ANY, '',wx.Bitmap(find_data_file("WXPython_30x30.png")),) - tb.AddTool(wx.ID_ANY, '',wx.Bitmap(find_data_file("settings_30x30.png"))) - tb.Realize() - self.main_sizer.Add(tb) + #tb = wx.ToolBar( self, -1) + #self.ToolBar = tb + #tb.SetToolBitmapSize(wx.Size(30, 3)) + #tb.AddTool(wx.ID_ANY, '',wx.Bitmap(find_data_file("WXPython_30x30.png")),) + #tb.AddTool(wx.ID_ANY, '',wx.Bitmap(find_data_file("settings_30x30.png"))) + #tb.Realize() + #self.main_sizer.Add(tb) #main_sizer.SetBackgroundColour((44, 51, 51)) # self.pnl1.SetBackgroundColour(wx.BLACK) self.handle_columns() @@ -158,14 +163,14 @@ class ServerPanel(wx.Panel): wx.GetApp().ProcessPendingEvents() self.main_sizer.Add(self.list_ctrl, 0, wx.ALL | wx.EXPAND, 20) - start_button = wx.Button(self, label='Start') + start_button = wx.Button(self, label='Start IPPigeon') start_button.SetBackgroundColour((205, 215, 206)) start_button.Bind(wx.EVT_BUTTON, self.on_start) #start_button.Bind(wx.EVT_ENTER_WINDOW, self.on_start) - stop_button = wx.Button(self, label='Stop') + stop_button = wx.Button(self, label='Stop IPPigeon') stop_button.SetBackgroundColour('#F08080') - secondary_frame_button = wx.Button(self, label='Window') + secondary_frame_button = wx.Button(self, label='Settings') secondary_frame_button.Bind(wx.EVT_BUTTON, self.on_window) # wx.BORDER(stop_button, wx.BORDER_NONE) stop_button.Bind(wx.EVT_BUTTON, self.on_stop) @@ -179,15 +184,22 @@ class ServerPanel(wx.Panel): self.list_ctrl.InsertColumn(0, COLUMN_NAMES[col], width=COLUMN_SIZES[col]) def updatedata(self): + global settings + + if settings["newdata"] == True: + settings["newdata"] = False + else: + wx.CallLater(1000, self.updatedata) + return fprint("updatedata called") loaddata() - global settings if self.list_ctrl.DeleteAllItems(): fprint("Items deleted") else: fprint("Unable to delete") for i in range(len(TEST_FILE)): - + if str(TEST_FILE.iloc[i, 4]).find("TIME_WAIT") >= 0 or str(TEST_FILE.iloc[i, 4]).find("FIN_WAIT_2") >= 0: + continue idx = 0 for ip in settings["badips"]: #fprint(pid) @@ -208,18 +220,22 @@ class ServerPanel(wx.Panel): #fprint(i, j, TEST_FILE.iloc[i, j]) #self.SetSizer(self.main_sizer) - wx.CallLater(5000, self.updatedata) + wx.CallLater(1000, self.updatedata) def on_start(self, event): fprint('in on_start') - settings["kill"] = True + settings["running"] = True def on_stop(self, event): fprint('in on_stop') - settings["kill"] = False + settings["running"] = False + # JANK JANK + util.run_cmd('Remove-NetFirewallRule -Group "IPPigeon"') def on_window(self, event): - OtherFrame() + fprint("open settings") + dg = GetData(parent = None) + dg.ShowModal() def ShowImage(self, imageFile): if imageFile == "": @@ -253,14 +269,84 @@ def openwindow(data, sets, kill): loaddata() app = wx.App(False) frame = OtherFrame() + frame.SetIcon(wx.Icon(find_data_file("icon.ico"), wx.BITMAP_TYPE_ICO)) app.MainLoop() else: fprint("Creating login panel") app = wx.App(False) frame = ServerFrame() + frame.SetIcon(wx.Icon(find_data_file("icon.ico"), wx.BITMAP_TYPE_ICO)) app.MainLoop() +class GetData(wx.Dialog): + def __init__(self, parent): + wx.Dialog.__init__(self, parent, wx.ID_ANY, "User Settings: ", size = (800,500)) + self.p = wx.Panel(self, wx.ID_ANY) + + self.hostname = wx.StaticText(self.p, label="Host:", pos=(20,20)) + self.hostnametext = wx.TextCtrl(self.p, value=settings["config"]["sftp"]["host"], pos=(180,20), size=(500,-1)) + + self.user = wx.StaticText(self.p, label="User: ", pos=(20,60)) + self.usertext = wx.TextCtrl(self.p, value=settings["config"]["sftp"]["user"], pos=(180,60), size=(500,-1)) + + self.port = wx.StaticText(self.p, label="Port: ", pos=(20,100)) + self.porttext = wx.TextCtrl(self.p, value=str(settings["config"]["sftp"]["port"]), pos=(180,100), size=(500,-1)) + + self.keyfile = wx.StaticText(self.p, label="Keyfile: ", pos=(20,140)) + self.keyfiletext = wx.TextCtrl(self.p, value=settings["config"]["sftp"]["keyfile"], pos=(180,140), size=(500,-1)) + + self.filepathsend = wx.StaticText(self.p, label="Sending File Path: ", pos=(20,180)) + self.filepathsendtext = wx.TextCtrl(self.p, value=settings["config"]["sftp"]["filepath"]["send"], pos=(180,180), size=(500,-1)) + + self.filepathsendlogin = wx.StaticText(self.p, label="Sending Login Path: ", pos=(20,220)) + self.filepathsendlogintext = wx.TextCtrl(self.p, value=settings["config"]["sftp"]["filepath"]["sendlogin"], pos=(180,220), size=(500,-1)) + + self.filepathreceive = wx.StaticText(self.p, label="Receiving File Path: ", pos=(20,260)) + self.filepathreceivetext = wx.TextCtrl(self.p, value=settings["config"]["sftp"]["filepath"]["receive"], pos=(180,260), size=(500,-1)) + + self.filepathreceivelogin = wx.StaticText(self.p, label="Receiving Login Path: ", pos=(20,300)) + self.filepathreceivelogintext = wx.TextCtrl(self.p, value=settings["config"]["sftp"]["filepath"]["receivelogin"], pos=(180,300), size=(500,-1)) + + self.darkmode = wx.StaticText(self.p, label="Dark mode (On/Off): ", pos=(20,340)) + self.darkmodetext = wx.TextCtrl(self.p, value=str(settings["config"]["ui"]["darkmode"]), pos=(180,340), size=(500,-1)) + + self.interval = wx.StaticText(self.p, label="Interval (sec): ", pos=(20,380)) + self.intervaltext = wx.TextCtrl(self.p, value=str(settings["config"]["core"]["interval"]), pos=(180,380), size=(500,-1)) + + self.seclevel = wx.StaticText(self.p, label="Security Strength Level: ", pos=(20,420)) + self.seclevelslider = wx.Slider(self.p, pos=(180,410), minValue=0, maxValue=3, style=wx.SL_HORIZONTAL | wx.SL_AUTOTICKS, value=settings["config"]["core"]["level"]) + self.seclevel2 = wx.StaticText(self.p, label=SEC_LEVELS[settings["config"]["core"]["level"]], pos=(300,420)) + self.seclevelslider.Bind(wx.EVT_SCROLL, self.level_upd) + self.Bind(wx.EVT_CLOSE, self.OnQuit) + + def level_upd(self, event): + self.seclevel2.SetLabel(SEC_LEVELS[self.seclevelslider.GetValue()]) + + + def OnQuit(self, event): + # save changes + fprint("saving changes...") + config = settings["config"] + config["sftp"]["host"] = self.hostnametext.GetValue() + config["sftp"]["user"] = self.usertext.GetValue() + config["sftp"]["port"] = int(self.porttext.GetValue()) + config["sftp"]["keyfile"] = self.keyfiletext.GetValue() + config["sftp"]["filepath"]["send"] = self.filepathsendtext.GetValue() + config["sftp"]["filepath"]["sendlogin"] = self.filepathsendlogintext.GetValue() + config["sftp"]["filepath"]["receive"] = self.filepathreceivetext.GetValue() + config["sftp"]["filepath"]["receivelogin"] = self.filepathreceivelogintext.GetValue() + config["ui"]["darkmode"] = bool(self.darkmodetext.GetValue()) + config["core"]["interval"] = int(self.intervaltext.GetValue()) + config["core"]["level"] = int(self.seclevelslider.GetValue()) + settings["config"] = config + settings["applyconfig"] = True + + self.result_name = None + self.Destroy() + + def on_edit(self, event): + print('in on_edit') if __name__ == '__main__': openwindow(list(), dict(), int()) From ba0e84ee95a8a412af49689da84a6e3081fe4035 Mon Sep 17 00:00:00 2001 From: Cole Deck Date: Tue, 25 Oct 2022 01:04:10 -0500 Subject: [PATCH 2/3] Add icon to installer --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index c22fad8..963a4e7 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ debug = True #debug = not debug # Dependencies are automatically detected, but it might need fine tuning. # "packages": ["os"] is used as example only -build_exe_options = {"packages": ["os"], "excludes": ["tkinter"], "include_msvcr": True, "include_files": ["icon.png", "config.yml", "keyfile-admin.pem", "WXPython.png", "WXPython_30x30.png", "settings.png", "settings_30x30.png"], "optimize": 1} +build_exe_options = {"packages": ["os"], "excludes": ["tkinter"], "include_msvcr": True, "include_files": ["icon.png", "config.yml", "keyfile-admin.pem", "WXPython.png", "WXPython_30x30.png", "settings.png", "settings_30x30.png", "icon.ico"], "optimize": 1} # base="Win32GUI" should be used only for Windows GUI app base = None From a31cd877f219f32f35486e0fc7f0217150c20820 Mon Sep 17 00:00:00 2001 From: Cole Deck Date: Tue, 25 Oct 2022 01:21:20 -0500 Subject: [PATCH 3/3] Disable debug mode for demo, add status text --- config.yml | 2 +- panel.py | 17 +++++++++++++++-- setup.py | 2 +- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/config.yml b/config.yml index a2ba196..62fb355 100644 --- a/config.yml +++ b/config.yml @@ -1,5 +1,5 @@ core: - autostart: true + autostart: false clockspeed: 20 interval: 10 level: 3 diff --git a/panel.py b/panel.py index 9e269e3..e32904e 100644 --- a/panel.py +++ b/panel.py @@ -40,7 +40,7 @@ class OtherFrame(wx.Frame): Class used for creating frames other than the main one """ def __init__(self): - wx.Frame.__init__(self, None, -1, 'Server Panel', size=(1000, 700)) + wx.Frame.__init__(self, None, -1, 'Server Panel', size=(1000, 620)) panel = ServerPanel(self) self.SetIcon(wx.Icon(find_data_file("icon.ico"), wx.BITMAP_TYPE_ICO)) @@ -154,6 +154,12 @@ class ServerPanel(wx.Panel): #tb.AddTool(wx.ID_ANY, '',wx.Bitmap(find_data_file("WXPython_30x30.png")),) #tb.AddTool(wx.ID_ANY, '',wx.Bitmap(find_data_file("settings_30x30.png"))) #tb.Realize() + if settings["running"] == True: + txt = "Status: Running (" + str(settings["config"]["core"]["level"]) + ")" + else: + txt = "Status: Not running" + + self.statustext = wx.StaticText(self, label=txt) # pos=(20,20)) #self.main_sizer.Add(tb) #main_sizer.SetBackgroundColour((44, 51, 51)) # self.pnl1.SetBackgroundColour(wx.BLACK) @@ -174,6 +180,7 @@ class ServerPanel(wx.Panel): secondary_frame_button.Bind(wx.EVT_BUTTON, self.on_window) # wx.BORDER(stop_button, wx.BORDER_NONE) stop_button.Bind(wx.EVT_BUTTON, self.on_stop) + self.main_sizer.Add(self.statustext, 0, wx.CENTER | wx.ALL | 100, 5) self.main_sizer.Add(start_button, 0, wx.CENTER | wx.ALL | 100, 5) self.main_sizer.Add(stop_button, 0, wx.CENTER | wx.ALL | 100, 5) self.main_sizer.Add(secondary_frame_button, 0, wx.CENTER | wx.ALL | 100, 5) @@ -185,7 +192,12 @@ class ServerPanel(wx.Panel): def updatedata(self): global settings - + if settings["running"] == True: + txt = "Status: Running (" + str(settings["config"]["core"]["level"]) + ")" + else: + txt = "Status: Not running" + + if settings["newdata"] == True: settings["newdata"] = False else: @@ -220,6 +232,7 @@ class ServerPanel(wx.Panel): #fprint(i, j, TEST_FILE.iloc[i, j]) #self.SetSizer(self.main_sizer) + self.statustext.SetLabel(txt) wx.CallLater(1000, self.updatedata) def on_start(self, event): diff --git a/setup.py b/setup.py index 963a4e7..d33e010 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ import sys from cx_Freeze import setup, Executable debug = True -#debug = not debug +debug = not debug # Dependencies are automatically detected, but it might need fine tuning. # "packages": ["os"] is used as example only build_exe_options = {"packages": ["os"], "excludes": ["tkinter"], "include_msvcr": True, "include_files": ["icon.png", "config.yml", "keyfile-admin.pem", "WXPython.png", "WXPython_30x30.png", "settings.png", "settings_30x30.png", "icon.ico"], "optimize": 1}