From 0645982090ffd7a21cc6d11958dbb8874565df31 Mon Sep 17 00:00:00 2001 From: = <=> Date: Wed, 20 Aug 2025 15:04:57 -0400 Subject: [PATCH] testing --- AirlockTools.py | 10 ++++- utils/__pycache__/allowlist.cpython-313.pyc | Bin 1837 -> 1950 bytes .../getdeviceevents.cpython-313.pyc | Bin 3012 -> 3125 bytes .../__pycache__/hashfunctions.cpython-313.pyc | Bin 0 -> 4826 bytes utils/allowlist.py | 5 ++- utils/getdeviceevents.py | 7 +++- utils/hashfunctions.py | 35 +++++++++++++++--- 7 files changed, 47 insertions(+), 10 deletions(-) create mode 100644 utils/__pycache__/hashfunctions.cpython-313.pyc diff --git a/AirlockTools.py b/AirlockTools.py index de6960b..2458e07 100644 --- a/AirlockTools.py +++ b/AirlockTools.py @@ -2,7 +2,9 @@ import dotenv import os import utils.getdeviceevents import utils.allowlist +import utils.hashfunctions import urllib3 +import pandas as pd urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) @@ -26,9 +28,13 @@ def menu(): while True: choice = input("Enter Menu Item: ") if choice == '1': - utils.getdeviceevents.devicehistory(url) + utils.getdeviceevents.devicehistory(url,False) if choice == '2': - utils.allowlist.allowlistexechistories(url) + utils.allowlist.allowlistexechistories(url,False) + if choice == '3': + executionhist = utils.allowlist.allowlistexechistories(url,True) + aggregated = utils.hashfunctions.aggregateHashes(executionhist) + print(aggregated) if __name__ == "__main__": apivalidation() \ No newline at end of file diff --git a/utils/__pycache__/allowlist.cpython-313.pyc b/utils/__pycache__/allowlist.cpython-313.pyc index f029c4b9dc17a515bd978c618585a58a0ec30fd9..83afc71df8519b3a6a2b7e00379b6ad4613bbe42 100644 GIT binary patch delta 774 zcmY*XOK;Oa5Z;X+aUI(wq=lw5l2iJihcqqFLjyuWeopV$cw4MbsHV0!qOp)Uaj z2o_jM5;Zue04T9Gh)u8ph|qsigkt~O`P3X1kc^V+5|R3U@=%IqU~W<_0+M8^)Y3x& zEJqcX%e@{^;xPjt4Xa3(SdjrP3DHNGUmE12E#5`qEaHC*M>brI5C+pL`}eUJa=M83{j@E2|%6Q z6qe?|@y_!ymXX5w(FC^{u)%gG`UzGYO-6>0g=eA*!WXDTKZRLXjWqG;yb%jM>QVj% zvEq@e52=~GG(U;l>V+Udm&b}}I2Fx9` F{{`gvpfLad delta 673 zcmZ`%&ubGw6n<}iWq)K-o3%RohkrtAq0X|ky32Vx`=XZ68lgCs${1D zs@ab<#|sr=kix!BHD1CBYP^P5n|c7$5WCP^oNz#>6H^xnvBuse&c5Qoz1sjo!J51| z=L*ddkYZ>NS9X?QPd(=j4gL+63X>XtCm1dM6RS7u=H(faJ?$rURlEeXg`x}p6a_#Q zAK;@Ci5ws)?kswNG{6Cl){Jm9)JTr z9K+@kKUBY6EZmtelFE=CFN#ZUYq=cSY#WTVB6& zy%nYrOIs)XCpBTat-J9HDhJcnL6;rIN6!wDgvHO>J)Y^?b|4@mV*2p&SA89M+3>hq zSbwbNW~V)f2Hk$dmL=ngbnWCgUC9a`R?C?hJcTo$ZNKevtH%aDP-pJcEVt Oa?ZdSX)Cxop8E@BxO9gA diff --git a/utils/__pycache__/getdeviceevents.cpython-313.pyc b/utils/__pycache__/getdeviceevents.cpython-313.pyc index a7fc47120640b6378923c88b1fc28fff7e1a299f..6613a363b1b63ffab7b2c78c13d534acd02b3ebd 100644 GIT binary patch delta 789 zcmYjPO-vI(6rS0g>24Rg1{K;=D_g0QibW++dc&`Ju473;+6$HMGGDu+ z7=Xus02AhU>PQoC&jC!S`K7(Nz651m(D&)7JDdZ`#Q!Y%AN0}11DFqTp5)MaXcYf3BznJ>^0yZ_Dt@LMaD5f zBw{A|WJh7&N=4ls(I2(4Pr+l&^#4(%!emh2Czkxh8kN# zscZ{rF+2J6z%&FN1H(SQfY!sBW}38`rX@u-*|^T2*+4nS%z)wwUU8J_Enkej0JLo)~J{|P;Fh*)!O#jZ!h@)p02spycgrT@qYw$t5_zUO}+B{iZx%WIQDe84KDnf=M;hhl7giffam?V4&!ERC473e|!h#DK$Kp#h0$wWjHA*)@99 zvloejVg>Qy#e)Ya-t;DT6-AIxyz4awuYOb7v@gs%&%58wd^60)%$IbcACKDv#dhDW z|1`RZ3`})hcW#6P>@F1PA62{F1U2o;!kOaeU(yMAP6XjFjnRYdi*3+k3FavkRC+L) zr9$I&b(xR`BScV-U4fc~-=cCsYnm}0ufVh|*I|;?J_}7&HD7K(fz<*G-wuL{;SMbq z*ox}9Cq7)>KaodQ24~|bIRwM$^q{8SWP%EvXJ)8p$iFn7HU>5GaGfya7^{FK>#PvX z2$P@SPDS@3@)gTNM1Eq9YYUs7#Oo41sys=q-p3n95BK0X5#{-3x}%RF6cmgjOemN{ za21?FC@PpjIE^5`>M1z0^IH!=-Y_4*ko<0rLstGXZyB*3?F4Pvu#%9I9c$J|V&fns z-&^SmF~r;v^_DJI>mpnW!g_1-b_sR1zT`jj+J0j-tS{aRuKCT4#jUNtf6!>lnMlzt z;|>OnaCxT@`2fk?#IdKXC#{#6H_o>6BjG+C`6Xwgujln3tJ=EC3d$ywsnzdDa8B_Y fTF+Y8^jACWwTr=djOs-~e2my}yU$9H*!%H6-`IRq diff --git a/utils/__pycache__/hashfunctions.cpython-313.pyc b/utils/__pycache__/hashfunctions.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dd4bdff7a59ff6dc076b50e24578250b8db318d4 GIT binary patch literal 4826 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 K|I2{r%;^7v$7Kir literal 0 HcmV?d00001 diff --git a/utils/allowlist.py b/utils/allowlist.py index c8bbbdb..2279917 100644 --- a/utils/allowlist.py +++ b/utils/allowlist.py @@ -3,7 +3,7 @@ import requests import json import os -def allowlistexechistories(url): +def allowlistexechistories(url, outputjson: bool): endpoint = url + '/v1/group' print("[+] Grabbing All Policies") payload = {} @@ -23,11 +23,14 @@ def allowlistexechistories(url): endpoint = url + '/v1/logging/exechistories' payload_dict = { "type":[1,2,6,7], + "checkpoint":"000000000000000000000" "policy": [policiesnames[choice]] } payload = json.dumps(payload_dict) print(payload) response = requests.request("POST", endpoint, headers=headers, data=payload, verify=False) + if outputjson == True: + return response parse_text = json.loads(response.text) for item in parse_text['response']['exechistories']: print(item['checkpoint']) \ No newline at end of file diff --git a/utils/getdeviceevents.py b/utils/getdeviceevents.py index d9261ae..fb86053 100644 --- a/utils/getdeviceevents.py +++ b/utils/getdeviceevents.py @@ -3,7 +3,7 @@ import requests import json import os -def devicehistory(url): +def devicehistory(url, outputjson: bool): endpoint = url + '/v1/getexechistory' print("\n") print("1. Today") @@ -43,7 +43,12 @@ def devicehistory(url): } response = requests.request("POST", endpoint, headers=headers, data=payload, verify=False) + + if outputjson == True: + return response + parse_text = json.loads(response.text) + for block in parse_text['response']['exechistory']: print(f"Command: {block['commandline']}") print(f"Date: {block['datetime']}") diff --git a/utils/hashfunctions.py b/utils/hashfunctions.py index ff57f43..550cb22 100644 --- a/utils/hashfunctions.py +++ b/utils/hashfunctions.py @@ -1,22 +1,45 @@ import pandas as pd import requests import os +import json -def aggregateHashes(executions_json: dict) -> pd.DataFrame: + +def aggregateHashes(executions_json) -> pd.DataFrame: """ Takes the executions, aggregates all the data with sha256 as primary, then returns aggregated dataframe """ + """ + old version + data = executions_json.json() - exechistories = executions_json.get("response", {}).get("exechistories", []) - df = pd.DataFrame(exechistories) - + df = pd.DataFrame(data["response"]["exechistories"]) + print(df) if df.empty: return df - # Aggregate by sha256 - keep all entries in lists + #Aggregate by sha256 - keep all entries in lists agg_df = df.groupby("sha256").agg(lambda x: list(x)).reset_index() return agg_df + """ + + + data = executions_json.json() + df = pd.DataFrame(data["response"]["exechistories"]) + + if df.empty: + return df + + # Aggregate by sha256, deduplicate lists, and preserve order + agg_df = df.groupby("sha256").agg(lambda x: list(dict.fromkeys(x))).reset_index() + + # Add a column for the number of unique hostnames + agg_df["num_devices"] = agg_df["hostname"].apply(len) + + # Sort by num_devices in descending order + agg_df = agg_df.sort_values("num_devices", ascending=False) + + return agg_df def augmentAggregatedHashes(url, agg_df: pd.DataFrame) -> pd.DataFrame: """ @@ -66,7 +89,7 @@ def categorize_hashes(aug_df: pd.DataFrame, threat_tolerance: int, untrusted_pub untrusted_publishers = [] # Flatten threatlevel from nested reputation dict - df = df.copy() + df = aug_df.copy() df["threatlevel"] = df["reputation"].apply(lambda x: x.get("threatlevel") if pd.notnull(x) else None) # Masks for each category