diff --git a/pypykatz/commons/readers/local/common/live_reader_ctypes.py b/pypykatz/commons/readers/local/common/live_reader_ctypes.py index 669c5f3..05287f6 100644 --- a/pypykatz/commons/readers/local/common/live_reader_ctypes.py +++ b/pypykatz/commons/readers/local/common/live_reader_ctypes.py @@ -74,6 +74,14 @@ def get_device_prefixes(): device_prefixes[QueryDosDevice(drive)] = drive return device_prefixes +def convert_ntpath(exepath): + image_filename = str(exepath) + for win_path in DEVICE_PREFIXES: + if image_filename.startswith(win_path): + image_filename = DEVICE_PREFIXES[win_path] + image_filename[len(win_path):] + return image_filename + + DEVICE_PREFIXES = get_device_prefixes() WINDOWS_BUILD_NUMBER = getWindowsBuild() @@ -89,33 +97,40 @@ def get_device_prefixes(): def get_process_full_imagename(pid): _NtQuerySystemInformation = windll.ntdll.NtQuerySystemInformation image_filename = '' - buf = ctypes.create_unicode_buffer(0x1000) + buf = ctypes.create_unicode_buffer(0x100) process_info = SYSTEM_PROCESS_ID_INFORMATION() process_info.ProcessId = ctypes.c_void_p(pid) process_info.ImageName.MaximumLength = len(buf) process_info.ImageName.Buffer = addressof(buf) status = _NtQuerySystemInformation( SystemProcessIdInformation, - process_info, + byref(process_info), sizeof(process_info), None) if status == STATUS_INFO_LENGTH_MISMATCH: - buf = ctypes.create_unicode_buffer(MAX_PATH_UNICODE) + buf = ctypes.create_unicode_buffer(process_info.ImageName.MaximumLength) process_info.ImageName.MaximumLength = len(buf) process_info.ImageName.Buffer = addressof(buf) status = _NtQuerySystemInformation( SystemProcessIdInformation, - process_info, + byref(process_info), sizeof(process_info), None) if status == 0: image_filename = str(process_info.ImageName.Buffer) if image_filename.startswith('\\Device\\'): - for win_path in DEVICE_PREFIXES: - if image_filename.startswith(win_path): - image_filename = DEVICE_PREFIXES[win_path] + image_filename[len(win_path):] + image_filename = convert_ntpath(image_filename) else: - image_filename = 'N/A' + # Another method Just in case + # We only need PROCESS_QUERY_LIMITED_INFORMATION + try: + process_handle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, False, pid) + image_filename = QueryFullProcessImageNameW(process_handle) + except Exception as e: + image_filename = 'N/A' + finally: + if process_handle: + CloseHandle(process_handle) return image_filename PS_PROTECTED_TYPE_STRINGS = [None,"Light","Full"] @@ -124,30 +139,30 @@ def get_process_full_imagename(pid): PS_PROTECTED_TYPE_OLD_OS_STRINGS = [None,"System protected process"] #https://msdn.microsoft.com/en-us/library/windows/desktop/ms683217(v=vs.85).aspx -#def enum_process_names(): -# pid_to_fullname = {} -# -# for pid in EnumProcesses(): -# if pid == 0: -# continue -# -# pid_to_fullname[pid] = get_process_full_imagename(pid) -# return pid_to_fullname - def enum_process_names(): - pid_to_name = {} + pid_to_fullname = {} for pid in EnumProcesses(): if pid == 0: continue - pid_to_name[pid] = 'Not found' - try: - process_handle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, False, pid) - except Exception as e: - continue - - pid_to_name[pid] = QueryFullProcessImageNameW(process_handle) - return pid_to_name + + pid_to_fullname[pid] = get_process_full_imagename(pid) + return pid_to_fullname + +#def enum_process_names(): +# pid_to_name = {} +# +# for pid in EnumProcesses(): +# if pid == 0: +# continue +# pid_to_name[pid] = 'Not found' +# try: +# process_handle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, False, pid) +# except Exception as e: +# continue +# +# pid_to_name[pid] = QueryFullProcessImageNameW(process_handle) +# return pid_to_name def get_process_extended_basic_information(pid,process_handle=None): process_basic_info = PROCESS_EXTENDED_BASIC_INFORMATION() @@ -196,7 +211,7 @@ def get_protected_process_infos(pid,process_handle=None): def get_lsass_pid(): pid_to_name = enum_process_names() for pid in pid_to_name: - if pid_to_name[pid].lower().endswith('lsass.exe'): + if pid_to_name[pid].lower().endswith(':\\windows\\system32\\lsass.exe'): return pid raise Exception('Failed to find lsass.exe') diff --git a/pypykatz/commons/readers/local/live_reader.py b/pypykatz/commons/readers/local/live_reader.py index 5466289..18388b2 100644 --- a/pypykatz/commons/readers/local/live_reader.py +++ b/pypykatz/commons/readers/local/live_reader.py @@ -344,14 +344,14 @@ def setup(self): pid = get_lsass_pid() logging.log(1, 'Lsass.exe found at PID %d' % pid) logging.log(1, 'Checking Lsass.exe protection status') - #proc_protection_info = get_protected_process_infos(pid) - #protection_msg = "Protection Status: No protection" - #if proc_protection_info: - # protection_msg = f"Protection Status: {proc_protection_info['type']}" - # if 'signer' in proc_protection_info: - # protection_msg += f" ({proc_protection_info['signer']})" - # raise Exception('Failed to open lsass.exe Reason: %s' % protection_msg) - #logging.log(1, protection_msg) + proc_protection_info = get_protected_process_infos(pid) + protection_msg = "Protection Status: No protection" + if proc_protection_info: + protection_msg = f"Protection Status: {proc_protection_info['type']}" + if 'signer' in proc_protection_info: + protection_msg += f" ({proc_protection_info['signer']})" + raise Exception('Failed to open lsass.exe Reason: %s' % protection_msg) + logging.log(1, protection_msg) logging.log(1, 'Opening lsass.exe') self.lsass_process_handle = OpenProcess(PROCESS_ALL_ACCESS, False, pid) if self.lsass_process_handle is None: