@@ -30,79 +30,80 @@ def on_admin_login(self, context, connection):
3030 context .log .debug (f"Error connecting to RemoteRegistry { e } on host { connection .host } " )
3131 finally :
3232 remote_ops .finish ()
33-
34- for sid_directory in connection .conn .listPath ("C$" , "$Recycle.Bin\\ *" ):
35- if sid_directory .get_longname () and sid_directory .get_longname () not in self .false_positive :
36-
37- # Extracts the username from the SID
38- if remote_ops ._RemoteOperations__rrp :
39- ans = rrp .hOpenLocalMachine (remote_ops ._RemoteOperations__rrp )
40- reg_handle = ans ["phKey" ]
41- ans = rrp .hBaseRegOpenKey (
42- remote_ops ._RemoteOperations__rrp ,
43- reg_handle ,
44- f"SOFTWARE\\ Microsoft\\ Windows NT\\ CurrentVersion\\ ProfileList\\ { sid_directory .get_longname ()} "
45- )
46- key_handle = ans ["phkResult" ]
47- _ = username = profileimagepath = None
48- try :
49- _ , profileimagepath = rrp .hBaseRegQueryValue (
50- remote_ops ._RemoteOperations__rrp ,
51- key_handle ,
52- "ProfileImagePath\x00 "
33+
34+ if remote_ops ._RemoteOperations__rrp :
35+ for sid_directory in connection .conn .listPath ("C$" , "$Recycle.Bin\\ *" ):
36+ if sid_directory .get_longname () and sid_directory .get_longname () not in self .false_positive :
37+
38+ # Extracts the username from the SID
39+ if remote_ops ._RemoteOperations__rrp :
40+ ans = rrp .hOpenLocalMachine (remote_ops ._RemoteOperations__rrp )
41+ reg_handle = ans ["phKey" ]
42+ ans = rrp .hBaseRegOpenKey (
43+ remote_ops ._RemoteOperations__rrp ,
44+ reg_handle ,
45+ f"SOFTWARE\\ Microsoft\\ Windows NT\\ CurrentVersion\\ ProfileList\\ { sid_directory .get_longname ()} "
5346 )
54- # Get username and remove embedded null byte
55- username = profileimagepath .split ("\\ " )[- 1 ].replace ("\x00 " , "" )
56- except rrp .DCERPCSessionError as e :
57- context .log .debug (f"Couldn't get username from SID { e } on host { connection .host } " )
47+ key_handle = ans ["phkResult" ]
48+ _ = username = profileimagepath = None
49+ try :
50+ _ , profileimagepath = rrp .hBaseRegQueryValue (
51+ remote_ops ._RemoteOperations__rrp ,
52+ key_handle ,
53+ "ProfileImagePath\x00 "
54+ )
55+ # Get username and remove embedded null byte
56+ username = profileimagepath .split ("\\ " )[- 1 ].replace ("\x00 " , "" )
57+ except rrp .DCERPCSessionError as e :
58+ context .log .debug (f"Couldn't get username from SID { e } on host { connection .host } " )
5859
59- # Lists for any file or directory in the recycle bin
60- spider_folder = f"$Recycle.Bin\\ { sid_directory .get_longname ()} \\ "
61- paths = connection .spider (
62- "C$" ,
63- folder = spider_folder ,
64- regex = [r"(.*)" ],
65- no_print_results = True
66- )
60+ # Lists for any file or directory in the recycle bin
61+ spider_folder = f"$Recycle.Bin\\ { sid_directory .get_longname ()} \\ "
62+ paths = connection .spider (
63+ "C$" ,
64+ folder = spider_folder ,
65+ regex = [r"(.*)" ],
66+ no_print_results = True
67+ )
6768
68- false_positiv = ["." , ".." , "desktop.ini" ]
69- filtered_file_paths = [path for path in paths if not path .endswith (tuple (false_positiv ))]
70- if filtered_file_paths :
71- if username is not None :
72- context .log .highlight (f"CONTENT FOUND { sid_directory .get_longname ()} ({ username } )" )
73- else :
74- context .log .highlight (f"CONTENT FOUND { sid_directory .get_longname ()} " )
69+ false_positiv = ["." , ".." , "desktop.ini" ]
70+ filtered_file_paths = [path for path in paths if not path .endswith (tuple (false_positiv ))]
71+ if filtered_file_paths :
72+ if username is not None :
73+ context .log .highlight (f"CONTENT FOUND { sid_directory .get_longname ()} ({ username } )" )
74+ else :
75+ context .log .highlight (f"CONTENT FOUND { sid_directory .get_longname ()} " )
7576
76- for path in filtered_file_paths :
77- # Returned path look like:
78- # $Recycle.Bin\S-1-5-21-4140170355-2927207985-2497279808-500\/$I87021Q.txt
79- # Or
80- # $Recycle.Bin\S-1-5-21-4140170355-2927207985-2497279808-500\/$R87021Q.txt
81- # $I files are metadata while $R are actual files so we split the path from the SID
82- # And check that the filename contains $R only to prevent downloading useless stuff
83-
84- if "$R" in path .split (sid_directory .get_longname ())[1 ] and not path .endswith (tuple (["." , ".." , "desktop.ini" ])):
85- try :
86- buf = BytesIO ()
87- connection .conn .getFile ("C$" , path , buf .write )
88- context .log .highlight (f"\t { path } " )
89- found += 1
90- buf .seek (0 )
91- file_path = path .split ('$' )[- 1 ].replace ("/" , "_" )
92- if username :
93- filename = f"{ connection .host } _{ username } _recyclebin_{ file_path } "
94- else :
95- filename = f"{ connection .host } _{ sid_directory .get_longname ()} _recyclebin_{ file_path } "
96- export_path = join (NXC_PATH , "modules" , "recyclebin" )
97- path = abspath (join (export_path , filename ))
98- makedirs (export_path , exist_ok = True )
77+ for path in filtered_file_paths :
78+ # Returned path look like:
79+ # $Recycle.Bin\S-1-5-21-4140170355-2927207985-2497279808-500\/$I87021Q.txt
80+ # Or
81+ # $Recycle.Bin\S-1-5-21-4140170355-2927207985-2497279808-500\/$R87021Q.txt
82+ # $I files are metadata while $R are actual files so we split the path from the SID
83+ # And check that the filename contains $R only to prevent downloading useless stuff
84+
85+ if "$R" in path .split (sid_directory .get_longname ())[1 ] and not path .endswith (tuple (["." , ".." , "desktop.ini" ])):
9986 try :
100- with open (path , "w+" ) as file :
101- file .write (buf .read ().decode ("utf-8" , errors = "ignore" ))
87+ buf = BytesIO ()
88+ connection .conn .getFile ("C$" , path , buf .write )
89+ context .log .highlight (f"\t { path } " )
90+ found += 1
91+ buf .seek (0 )
92+ file_path = path .split ('$' )[- 1 ].replace ("/" , "_" )
93+ if username :
94+ filename = f"{ connection .host } _{ username } _recyclebin_{ file_path } "
95+ else :
96+ filename = f"{ connection .host } _{ sid_directory .get_longname ()} _recyclebin_{ file_path } "
97+ export_path = join (NXC_PATH , "modules" , "recyclebin" )
98+ path = abspath (join (export_path , filename ))
99+ makedirs (export_path , exist_ok = True )
100+ try :
101+ with open (path , "w+" ) as file :
102+ file .write (buf .read ().decode ("utf-8" , errors = "ignore" ))
103+ except Exception as e :
104+ context .log .fail (f"Failed to write recyclebin file to { filename } : { e } " )
102105 except Exception as e :
103- context .log .fail (f"Failed to write recyclebin file to { filename } : { e } " )
104- except Exception as e :
105- # Probably trying to getFile a directory which won't work
106- context .log .debug (f"Couldn't open { path } because of { e } " )
107- if found > 0 :
108- context .log .highlight (f"Recycle bin's content downloaded to { export_path } " )
106+ # Probably trying to getFile a directory which won't work
107+ context .log .debug (f"Couldn't open { path } because of { e } " )
108+ if found > 0 :
109+ context .log .highlight (f"Recycle bin's content downloaded to { export_path } " )
0 commit comments