dlldiag/subcommands/trace.py
def performTrace(debugger, helper, module, architecture, cwd, args=[]):
		'''
		Performs a `LoadLibrary()` trace with loader snaps enabled
		'''
		
		# Load NTDLL.DLL so we can use the RtlNtStatusToDosError() function to map NTSTATUS codes to Windows API error codes
		ntdll = cdll.LoadLibrary('ntdll')
		
		# Run our library loader helper through the debugger with loader snaps enabled
		result = debugger.debugWithLoaderSnaps(architecture, helper.executable, [module], cwd=cwd)
		
		# Locate the start and end markers in the debugger stdout so we avoid parts of the trace that relate
		# purely to loading the helper executable rather than loading the module we are interested in
		startMarker = '[LOADLIBRARY][START]'
		endMarker = '[LOADLIBRARY][END]'
		start = result.stdout.index(startMarker) + len(startMarker)
		end = result.stdout.index(endMarker)
		subset = result.stdout[start:end]
		
		# Split each line into prefix, function name, and details
		lines = [line.split(' - ', 2) for line in subset.replace('\r\n', '\n').split('\n')]
		
		# Isolate the lines related to the functions we are interested in
		lines = [line for line in lines if len(line) == 3 and line[1] in TraceHelpers.getFunctionWhitelist()]
		
		# Parse the details of each line
		parsedLines = [TraceHelpers.parseLine(line[0], line[1], line[2]) for line in lines]
		
		# Pair the ENTER and RETURN lines to determine the return values for each function call
		calls = []
		pending = []
		while len(parsedLines) > 0:
			
			# Determine if this is an ENTER line or a RETURN line
			parsed = parsedLines.pop(0)
			if parsed['operation'] == 'ENTER':
				
				# Create a CallTrace object for the function call
				trace = CallTrace(parsed['prefix'], parsed['function'], parsed['dll'], parsed['result'])
				calls.append(trace)
				pending.append(trace)
				
			else:
				
				# Attempt to match the RETURN line to its corresponding ENTER line
				matches = [c for c in reversed(pending) if parsed['prefix'] == c.prefix and parsed['function'] == c.function]
				if len(matches) > 0:
					
					# Match found, update the result value
					match = matches[0]
					match.result = ntdll.RtlNtStatusToDosError(int(parsed['result'], 16))
					pending.remove(match)
					
				elif len(parsedLines) > 1:
					
					# Match not found but there are other lines remaining, so push this one back in the queue
					OutputFormatting.printWarning('encountered a RETURN trace line before its corresponding ENTER line')
					parsedLines.insert(2, parsed)
					
				else:
					
					# Match not found and no other lines left, so we have no choice but to simply drop the line
					OutputFormatting.printWarning('dropped a RETURN trace line because no corresponding ENTER line could be found')
		
		# Report any function calls for which we did not find a return value
		unresolved = [c for c in calls if c.result is None]
		calls = [c for c in calls if c.result is not None]
		if len(unresolved) > 0:
			OutputFormatting.printWarning('return values could not be found for the following function calls:')
			print(colored('- ' + '\n- '.join([str(c) for c in unresolved]) + '\n', color='yellow'), flush=True)
		
		# Return the raw trace output and the list of calls for which a return value was found
		return (subset + result.stderr, calls)

		Performs a `LoadLibrary()` trace with loader snaps enabled
		
Performs a `LoadLibrary()` trace with loader snaps enabled
Performs a ` LoadLibrary () ` trace with loader snaps enabled
def performTrace(debugger, helper, module, architecture, cwd, args=[]):
		ntdll = cdll.LoadLibrary('ntdll')
		result = debugger.debugWithLoaderSnaps(architecture, helper.executable, [module], cwd=cwd)
		startMarker = '[LOADLIBRARY][START]'
		endMarker = '[LOADLIBRARY][END]'
		start = result.stdout.index(startMarker) + len(startMarker)
		end = result.stdout.index(endMarker)
		subset = result.stdout[start:end]
		lines = [line.split(' - ', 2) for line in subset.replace('\r\n', '\n').split('\n')]
		lines = [line for line in lines if len(line) == 3 and line[1] in TraceHelpers.getFunctionWhitelist()]
		parsedLines = [TraceHelpers.parseLine(line[0], line[1], line[2]) for line in lines]
		calls = []
		pending = []
		while len(parsedLines) > 0:
			parsed = parsedLines.pop(0)
			if parsed['operation'] == 'ENTER':
				trace = CallTrace(parsed['prefix'], parsed['function'], parsed['dll'], parsed['result'])
				calls.append(trace)
				pending.append(trace)
			else:
				matches = [c for c in reversed(pending) if parsed['prefix'] == c.prefix and parsed['function'] == c.function]
				if len(matches) > 0:
					match = matches[0]
					match.result = ntdll.RtlNtStatusToDosError(int(parsed['result'], 16))
					pending.remove(match)
				elif len(parsedLines) > 1:
					OutputFormatting.printWarning('encountered a RETURN trace line before its corresponding ENTER line')
					parsedLines.insert(2, parsed)
				else:
					OutputFormatting.printWarning('dropped a RETURN trace line because no corresponding ENTER line could be found')
		unresolved = [c for c in calls if c.result is None]
		calls = [c for c in calls if c.result is not None]
		if len(unresolved) > 0:
			OutputFormatting.printWarning('return values could not be found for the following function calls:')
			print(colored('- ' + '\n- '.join([str(c) for c in unresolved]) + '\n', color='yellow'), flush=True)
		return (subset + result.stderr, calls)
def performTrace ( debugger , helper , module , architecture , cwd , args = [ ] ) : ntdll = cdll . LoadLibrary ( 'ntdll' ) result = debugger . debugWithLoaderSnaps ( architecture , helper . executable , [ module ] , cwd = cwd ) startMarker = '[LOADLIBRARY][START]' endMarker = '[LOADLIBRARY][END]' start = result . stdout . index ( startMarker ) + len ( startMarker ) end = result . stdout . index ( endMarker ) subset = result . stdout [ start : end ] lines = [ line . split ( ' - ' , 2 ) for line in subset . replace ( '\r\n' , '\n' ) . split ( '\n' ) ] lines = [ line for line in lines if len ( line ) == 3 and line [ 1 ] in TraceHelpers . getFunctionWhitelist ( ) ] parsedLines = [ TraceHelpers . parseLine ( line [ 0 ] , line [ 1 ] , line [ 2 ] ) for line in lines ] calls = [ ] pending = [ ] while len ( parsedLines ) > 0 : parsed = parsedLines . pop ( 0 ) if parsed [ 'operation' ] == 'ENTER' : trace = CallTrace ( parsed [ 'prefix' ] , parsed [ 'function' ] , parsed [ 'dll' ] , parsed [ 'result' ] ) calls . append ( trace ) pending . append ( trace ) else : matches = [ c for c in reversed ( pending ) if parsed [ 'prefix' ] == c . prefix and parsed [ 'function' ] == c . function ] if len ( matches ) > 0 : match = matches [ 0 ] match . result = ntdll . RtlNtStatusToDosError ( int ( parsed [ 'result' ] , 16 ) ) pending . remove ( match ) elif len ( parsedLines ) > 1 : OutputFormatting . printWarning ( 'encountered a RETURN trace line before its corresponding ENTER line' ) parsedLines . insert ( 2 , parsed ) else : OutputFormatting . printWarning ( 'dropped a RETURN trace line because no corresponding ENTER line could be found' ) unresolved = [ c for c in calls if c . result is None ] calls = [ c for c in calls if c . result is not None ] if len ( unresolved ) > 0 : OutputFormatting . printWarning ( 'return values could not be found for the following function calls:' ) print ( colored ( '- ' + '\n- ' . join ( [ str ( c ) for c in unresolved ] ) + '\n' , color = 'yellow' ) , flush = True ) return ( subset + result . stderr , calls )
Performs a `LoadLibrary()` trace with loader snaps enabled
Performs a ` LoadLibrary () ` trace with loader snaps enabled
'''
		Performs a `LoadLibrary()` trace with loader snaps enabled
		''' # Load NTDLL.DLL so we can use the RtlNtStatusToDosError() function to map NTSTATUS codes to Windows API error codes # Run our library loader helper through the debugger with loader snaps enabled # Locate the start and end markers in the debugger stdout so we avoid parts of the trace that relate # purely to loading the helper executable rather than loading the module we are interested in # Split each line into prefix, function name, and details # Isolate the lines related to the functions we are interested in # Parse the details of each line # Pair the ENTER and RETURN lines to determine the return values for each function call # Determine if this is an ENTER line or a RETURN line # Create a CallTrace object for the function call # Attempt to match the RETURN line to its corresponding ENTER line # Match found, update the result value # Match not found but there are other lines remaining, so push this one back in the queue # Match not found and no other lines left, so we have no choice but to simply drop the line # Report any function calls for which we did not find a return value # Return the raw trace output and the list of calls for which a return value was found
debugger
helper
module
architecture
cwd
args