def Main(): cgiEnv = lib_common.CgiEnv() grph = cgiEnv.GetGraph() try: procid = int(cgiEnv.GetId()) except Exception: lib_common.ErrorMessageHtml("Must provide a pid") objProc = CIM_Process.PsutilGetProcObj(procid) envProp = lib_common.MakeProp("environment") try: # Psutil version after 4.0.0 envsDict = objProc.environ() except: exc = sys.exc_info()[1] lib_common.ErrorMessageHtml("Error:" + str(exc)) node_process = lib_common.gUriGen.PidUri(procid) for envKey in envsDict: envVal = envsDict[envKey] DEBUG("envKey=%s envVal=%s", envKey, envVal) nodeEnvNam = lib_util.NodeLiteral(envKey) # When a file or a directory displayed with a node, # its name is shortened so it can fit into the table., # so it is less visible. # Some are probably for Windows only. if envKey in ["PATH", "PSMODULEPATH", "PYPATH"]: valSplit = envVal.split(os.pathsep) nodFilArr = [ lib_common.gUriGen.DirectoryUri(filNam) for filNam in valSplit ] nodFilArrNod = lib_util.NodeLiteral(nodFilArr) #for filNam in valSplit: # nodFil = lib_common.gUriGen.DirectoryUri(filNam) grph.add((nodeEnvNam, pc.property_rdf_data_nolist2, nodFilArrNod)) elif os.path.isdir(envVal): nodFil = lib_common.gUriGen.DirectoryUri(envVal) #grph.add((nodeEnvNam,pc.property_directory,nodFil)) grph.add((nodeEnvNam, pc.property_rdf_data_nolist2, nodFil)) elif os.path.exists(envVal): nodFil = lib_common.gUriGen.FileUri(envVal) grph.add((nodeEnvNam, pc.property_rdf_data_nolist2, nodFil)) #grph.add((nodeEnvNam,pc.property_directory,nodFil)) else: # TODO: Beware that "\L" is transformed into "<TABLE>" by Graphviz !!! envValClean = envVal.replace(">", "_").replace("<", "_").replace( "&", "_").replace("\\", "_") nodeEnvValue = lib_util.NodeLiteral(envValClean) grph.add((nodeEnvNam, pc.property_rdf_data_nolist2, nodeEnvValue)) grph.add((node_process, envProp, nodeEnvNam)) # cgiEnv.OutCgiRdf("LAYOUT_RECT", [pc.property_directory,envProp]) cgiEnv.OutCgiRdf("LAYOUT_RECT", [envProp])
def FunctionProcess(mapToProc, proc): # The process might have left in the meantime. pid = proc.pid if lib_common.is_useless_process(proc): return try: all_maps = CIM_Process.PsutilProcMemmaps(proc) except: exc = sys.exc_info()[1] WARNING("get_memory_maps Pid=%d. Caught %s", pid, str(exc)) return # This takes into account only maps accessed by several processes. # TODO: What about files on a shared drive? # To make things simple, for the moment mapped memory is processed like files. # sys.stderr.write("NbMaps=%d\n" % len(all_maps) ) for map in all_maps: cleanPath = GoodMap(map.path) if cleanPath == "": continue # sys.stderr.write( "Adding cleanPath=%s\n" % cleanPath ) try: theList = mapToProc[cleanPath] theList.append(pid) except KeyError: mapToProc[cleanPath] = [pid]
def tree_parent_process(grph, proc_obj, pids_seen_set): try: the_pid = proc_obj.pid if the_pid == 0 or the_pid == 1: return # A circular processes hierarchy can happen on Windows. if the_pid in pids_seen_set: logging.warning("Circular pids tree:%d", the_pid) return pids_seen_set.add(the_pid) # Strange, but apparently it can happen. the_ppid = proc_obj.ppid() if the_ppid == 0: return node_process = lib_uris.gUriGen.PidUri(the_pid) node_pprocess = lib_uris.gUriGen.PidUri(the_ppid) grph.add((node_pprocess, pc.property_ppid, node_process)) CIM_Process.AddInfo(grph, node_pprocess, [str(the_ppid)]) AddExtraInformationtoProcess(grph, node_process, proc_obj) parent_proc_obj = psutil.Process(int(the_ppid)) tree_parent_process(grph, parent_proc_obj, pids_seen_set) # This exception depends on the version of psutil. except CIM_Process.NoSuchProcess: # Maybe a process has suddenly disappeared. It does not matter. return
def Main(): cgiEnv = lib_common.ScriptEnvironment() pid = int(cgiEnv.GetId()) grph = cgiEnv.GetGraph() proc_obj = CIM_Process.PsutilGetProcObj(pid) node_process = lib_uris.gUriGen.PidUri(pid) try: all_maps = proc_obj.memory_maps() except Exception as exc: lib_common.ErrorMessageHtml("get_memory_maps Pid=%d. Caught %s\n" % (pid, str(exc))) propMemoryRSS = lib_common.MakeProp("Resident Set Size") for map_obj in all_maps: # This, because all Windows paths are "standardized" by us. # TODO: clean_map_path = lib_util.standardized_file_path(map_obj.path) clean_map_path = map_obj.path.replace("\\", "/") uri_mem_map = lib_uris.gUriGen.MemMapUri(clean_map_path) grph.add((uri_mem_map, propMemoryRSS, rdflib.Literal(map_obj.rss))) grph.add((node_process, pc.property_memmap, uri_mem_map)) cgiEnv.OutCgiRdf( "LAYOUT_SPLINE")
def Main(): cgiEnv = lib_common.ScriptEnvironment() user_name_with_host = cgiEnv.GetId() # Usernames have the syntax user@host # Example: [email protected] user_split = user_name_with_host.split('@') user_name = user_split[0] # TODO: Should factorize this code. if len(user_split) > 1: user_host = user_split[1] if user_host != lib_util.currentHostname: # TODO: Should interrogate other host with "finger" protocol. lib_common.ErrorMessageHtml("Cannot get user properties on different host:" + user_host) grph = cgiEnv.GetGraph() # It will be possible to transform this into a Json tree by # selecting only the RDF predicate property_ppid. # This will be done in a gui cgi script which takes as input # parameter a CGI script, visible by SLP, stored in a bookmark page # or anything else. # See http://stackoverflow.com/questions/17967686/retrieving-specific-rdf-graph-triples-based-on-predicate-nodes # on how to select triples on a given predicate only. # But in the general case, we cannot know if the RDF graph will be a tree, # something similar to a CSV file (That is, flat) or a general graph. # So we might have to process the resulting graph on the fly, to see # which visualising methods are applicable. # Also, in the case of a tree, we must find ourselves what is its root. for proc in psutil.process_iter(): proc_username = CIM_Process.PsutilProcToUser(proc) # proc_username=EURO\\UK936025 user_name=UK936025 # proc_username=NT AUTHORITY\\NETWORK SERVICE # proc_username=NT AUTHORITY\\SYSTEM # proc_username=EURO\\UK936025 # proc_username=NT AUTHORITY\\SYSTEM if proc_username != user_name: continue pid = proc.pid parent_pid = proc.ppid() # Built the same way in other RDF documents. node_process = lib_uris.gUriGen.PidUri(pid) parent_node_process = lib_uris.gUriGen.PidUri(parent_pid) # We avoid duplicating the edges. Why would the RFD merge do? grph.add((node_process, pc.property_ppid, parent_node_process)) grph.add((node_process, pc.property_pid, lib_util.NodeLiteral(pid))) # grph.add((node_process, pc.property_information, lib_util.NodeLiteral(proc_username))) cgiEnv.OutCgiRdf()
def Main(): cgiEnv = lib_common.ScriptEnvironment() grph = cgiEnv.GetGraph() try: procid = int(cgiEnv.GetId()) except Exception: lib_common.ErrorMessageHtml("Must provide a pid") obj_proc = CIM_Process.PsutilGetProcObj(procid) node_process = lib_uris.gUriGen.PidUri(procid) CIM_Process.add_command_line_arguments(grph, node_process, obj_proc) cgiEnv.OutCgiRdf("LAYOUT_RECT")
def Usable(entity_type, entity_ids_arr): """Python and Linux processes""" is_linux = lib_util.UsableLinux(entity_type, entity_ids_arr) if not is_linux: return False # This tells if it is a Python process. return CIM_Process.Usable(entity_type, entity_ids_arr)
def Main(): cgiEnv = lib_common.CgiEnv() pidProc = int(cgiEnv.GetId()) grph = cgiEnv.GetGraph() node_process = lib_common.gUriGen.PidUri(pidProc) proc_obj = CIM_Process.PsutilGetProcObj(pidProc) # Python 2 # cmd_arr=['C:\\Python27\\python.exe', 'test_survol_client_library.py', '--debug', 'SurvolLocalTest.test_msdos_current_batch'] # Python 3 # cmd_arr=['C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\Python36_64\\python.exe', 'test_survol_client_library.py', '--debug', 'SurvolLocalTest.test_msdos_current_batch'] argvArray = CIM_Process.PsutilProcToCmdlineArray(proc_obj) DEBUG("argvArray=%s", str(argvArray)) # This extracts the command file name and creates a node for it. for theArg in argvArray[1:]: if theArg[0] == "/": continue # Check if the file exists in the current directory. currPwd, errMsg = CIM_Process.PsutilProcCwd(proc_obj) if not currPwd: break allDirsToSearch = [currPwd] envPath = CIM_Process.GetEnvVarProcess("PATH", proc_obj.pid) if envPath: allDirsToSearch += envPath.split(";") # Now tries all possible dirs, starting with current directory. for aDir in allDirsToSearch: fullScriptPath = os.path.join(aDir, theArg) DEBUG("fullScriptPath=%s", fullScriptPath) if os.path.isfile(fullScriptPath): DEBUG("fullScriptPath=%s", fullScriptPath) scriptNode = lib_common.gUriGen.FileUri(fullScriptPath) grph.add((node_process, pc.property_runs, scriptNode)) break break cgiEnv.OutCgiRdf()
def Usable(entity_type, entity_ids_arr): """Python processes""" pidProc = entity_ids_arr[0] try: # Any error, no display. proc_obj = CIM_Process.PsutilGetProcObjNoThrow(int(pidProc)) except: return False cmd_line = CIM_Process.PsutilProcToCmdline(proc_obj) cmdlinSplit = cmd_line.split(" ") execNam = cmdlinSplit[0] basNam = os.path.basename(execNam) # This is a python process because of the executable. return basNam.startswith("python")
def MakeProcDictWindows(): procDict = dict() for proc in psutil.process_iter(): procName = CIM_Process.PsutilProcToName(proc) # procName = proc.name # OK pour le process creer par httpd, sous Windows. # C:\Python\3.2.3-0.3\pythonw.exe -u D:/Projects/Divers/Reverse/PythonStyle/survol/task_control.py #if procName != "pythonw.exe": # continue # Might be different depending on the Python interpreter. if procName != "python.exe": continue # With a real subtask: # python.exe 18980 24656 C:\Python\3.2.3-0.3\python.exe C:\Python\3.2.3-0.3\python.exe -c from multiprocessing.forking import main; main() --multiprocessing-fork 788 # python.exe 24656 14680 C:\Python\3.2.3-0.3\python.exe python D:/Projects/Divers/Reverse/PythonStyle/survol/sources_top/psutil_processes_perf.py run procCmd = CIM_Process.PsutilProcToCmdline(proc) pid = proc.pid parent_pid = CIM_Process.PsutilProcToPPid(proc) # This differentiates between the feeder and the sub-server. # This test but get better, but it is OK for the moment. mtch_task = re.match(".*/survol/(.*) run", procCmd) if mtch_task: subDct = {'parentPid': parent_pid, 'script': mtch_task.group(1)} try: procDict[pid].update(subDct.items()) except KeyError: procDict[pid] = subDct continue if re.match(".*multiprocessing.forking.*", procCmd): subDct = {'subPid': pid, 'subScript': procCmd} try: procDict[parent_pid].update(subDct.items()) except KeyError: procDict[parent_pid] = subDct continue return procDict
def Main(): cgiEnv = lib_common.ScriptEnvironment() pid_proc = int(cgiEnv.GetId()) grph = cgiEnv.GetGraph() node_process = lib_uris.gUriGen.PidUri(pid_proc) proc_obj = CIM_Process.PsutilGetProcObj(int(pid_proc)) # Now we are parsing the command line. argv_array = CIM_Process.PsutilProcToCmdlineArray(proc_obj) logging.debug("argv_array=%s", str(argv_array)) # The difficulty is that filenames with spaces are split. # Therefore, entire filenames must be rebuilt from pieces. _add_nodes_from_command_line(argv_array, grph, node_process, proc_obj) cgiEnv.OutCgiRdf()
def GetMemMaps(pidint): # TODO: Replace this by scanning /proc/<pid>/mmaps p = CIM_Process.PsutilGetProcObj(pidint) # Depending on psutil version. try: return p.get_memory_maps(grouped=False) except AttributeError: # New version. return p.memory_maps(grouped=False)
def Main(): paramkeyShowSharedLib = "Show shared libraries" paramkeyShowFontFiles = "Show font files" cgiEnv = lib_common.CgiEnv(parameters={ paramkeyShowSharedLib: False, paramkeyShowFontFiles: False }) top_pid = int(cgiEnv.GetId()) flagShowSharedLib = bool(cgiEnv.get_parameters(paramkeyShowSharedLib)) flagShowFontFiles = bool(cgiEnv.get_parameters(paramkeyShowFontFiles)) grph = cgiEnv.GetGraph() proc_obj = CIM_Process.PsutilGetProcObj(top_pid) # sys.stderr.write("top_pid=%d\n" % top_pid) node_process = lib_common.gUriGen.PidUri(top_pid) CIM_Process.AddInfo(grph, node_process, [str(top_pid)]) ################################################################################ try: fillist = CIM_Process.PsutilProcOpenFiles(proc_obj) except Exception: exc = sys.exc_info()[1] lib_common.ErrorMessageHtml("Caught:" + str(exc) + ":" + str(proc_obj)) for fil in fillist: # TODO: Resolve symbolic links. Do not do that if shared memory. # TODO: AVOIDS THESE TESTS FOR SHARED MEMORY !!!! if lib_common.is_meaningless_file(fil.path, not flagShowSharedLib, not flagShowFontFiles): continue fileNode = lib_common.gUriGen.FileUri(fil.path) grph.add((node_process, pc.property_open_file, fileNode)) # This works but not really necessary because there are not so many files. # cgiEnv.OutCgiRdf( "", [pc.property_open_file] ) cgiEnv.OutCgiRdf("LAYOUT_SPLINE")
def Main(): cgiEnv = lib_common.CgiEnv() pidInt = int( cgiEnv.GetId() ) grph = cgiEnv.GetGraph() node_process = lib_common.gUriGen.PidUri(pidInt) proc_obj = CIM_Process.PsutilGetProcObj(pidInt) cgiEnv.OutCgiRdf()
def MakeProcDictLinux(): procDict = dict() for proc in psutil.process_iter(): procName = proc.name # BEWARE: It depends on the interpreter. if procName != "python": continue # With a real subtask: # apache 8423 1 0 12:36 ? 00:00:00 python /home/rchateau/public_html/RevPython/survol/sources_top/tcpdump.py run # apache 8426 8423 0 12:36 ? 00:00:00 python /home/rchateau/public_html/RevPython/survol/sources_top/tcpdump.py run procCmd = CIM_Process.PsutilProcToCmdline(proc) pid = proc.pid parent_pid = CIM_Process.PsutilProcToPPid(proc) # This differentiates between the feeder and the sub-server. # This test but get better, but it is OK for the moment. mtch_task = re.match(".*/survol/(.*) run", procCmd) if mtch_task: if parent_pid == 1: subDct = { 'parentPid': parent_pid, 'script': mtch_task.group(1) } try: procDict[pid].update(subDct.items()) except KeyError: procDict[pid] = subDct else: subDct = {'subPid': pid, 'subScript': procCmd} try: procDict[parent_pid].update(subDct.items()) except KeyError: procDict[parent_pid] = subDct continue return procDict
def Main(): cgiEnv = lib_common.CgiEnv() pid = int(cgiEnv.GetId()) # TODO: These are probably in win32com or a similar module. PROCESS_QUERY_INFORMATION = 0x0400 PROCESS_VM_READ = 0x0010 grph = cgiEnv.GetGraph() node_process = lib_common.gUriGen.PidUri(pid) exec_node = CIM_Process.AddInfo(grph, node_process, [pid]) #Get handle to the process based on PID hProcess = kernel.OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, False, pid) if hProcess: ModuType = c_ulong * 512 hModuleArr = ModuType() rawCntModules = c_ulong() psapi.EnumProcessModules(hProcess, byref(hModuleArr), sizeof(hModuleArr), byref(rawCntModules)) nbModules = int(rawCntModules.value / sizeof(c_ulong())) if nbModules >= 512: raise Exception("Disaster overrun") modname = c_buffer(256) for idx in range(0, nbModules): retLen = psapi.GetModuleFileNameExA(hProcess, hModuleArr[idx], modname, sizeof(modname)) if retLen == 0: # Maybe the string is empty. continue raw_filename_bytes = modname[:retLen] raw_filename_as_str = raw_filename_bytes.decode() filnam = lib_util.standardized_file_path(raw_filename_as_str) #if lib_util.is_py3: # # Truncation because "b'C:/xxx/yyy.zzz'", on Python 3 # # Backslashes are duplicated. # filnam = str(tab).replace('\\','/')[2:-1].replace("//","/") #else: # # Windows "\\" must be replaced by "/", so the URLs are the same for all tools. # filnam = str(tab).replace('\\','/') # The same filename might appear several times. DEBUG("idx=%d retLen=%d filnam=%s", idx, retLen, filnam) libNode = lib_common.gUriGen.SharedLibUri(filnam) grph.add((node_process, pc.property_library_depends, libNode)) kernel.CloseHandle(hProcess) cgiEnv.OutCgiRdf()
def Main(): cgiEnv = lib_common.CgiEnv() grph = cgiEnv.GetGraph() # Not really useful. grph.add((lib_common.nodeMachine, pc.property_hostname, lib_common.NodeLiteral(lib_util.currentHostname))) mapToProc = {} for proc in CIM_Process.ProcessIter(): # TODO: Instead, should test psutil version !!! try: FunctionProcess(mapToProc, proc) except CIM_Process.AccessDenied: pass except Exception: lib_common.ErrorMessageHtml("Unexpected error:" + str(sys.exc_info()[0])) # sys.stderr.write( "Leaving processes enumeration\n" ) addedProcs = {} # Now display only memory maps with more than one process linked to it. for mapPath, procLst in lib_util.six_iteritems(mapToProc): if len(procLst) <= 0: continue uriMemMap = lib_common.gUriGen.MemMapUri(mapPath) for pid in procLst: try: nodeProcess = addedProcs[pid] except KeyError: nodeProcess = lib_common.gUriGen.PidUri(pid) addedProcs[pid] = nodeProcess grph.add((nodeProcess, pc.property_memmap, uriMemMap)) # sys.stderr.write( "Leaving second maps enumeration\n" ) # TODO: They could also be displayed based on the hierarchy of their # associated file in the directory tree. for pid, nodeProcess in lib_util.six_iteritems(addedProcs): grph.add((nodeProcess, pc.property_pid, lib_common.NodeLiteral(pid))) # TODO: Petit bug: Ca duplique les memmap. Forcement, l'affichage en tables # suppose que c'est un arbre. Mais c'est plus rapide et plus clair. # cgiEnv.OutCgiRdf("",[pc.property_memmap]) cgiEnv.OutCgiRdf("LAYOUT_SPLINE")
def Main(): cgiEnv = lib_common.CgiEnv() pidProc = int(cgiEnv.GetId()) grph = cgiEnv.GetGraph() node_process = lib_common.gUriGen.PidUri(pidProc) proc_obj = CIM_Process.PsutilGetProcObj(int(pidProc)) # Now we are parsing the command line. cmd_line = CIM_Process.PsutilProcToCmdline(proc_obj) sys.stderr.write("cmd_line=%s\n" % str(cmd_line)) # Similar to split, but ignores white spaces in double quotes. argvArray = re.findall(r'(?:[^\s "]|"(?:\\.|[^"])*")+', cmd_line) sys.stderr.write("argvArray=%s\n" % str(argvArray)) argvArgs = " ".join(argvArray[1:]) sys.stderr.write("argvArgs=%s\n" % argvArgs) opts, otherArgs = getopt.getopt(argvArgs, "Bc:dEhim:ORQ:sStuvVW:x3") ignoreEnvs = False for opt, arg in opts: if opt == '-E': ignoreEnvs = True if otherArgs: filNam = otherArgs filNode = PyFilNode(proc_obj, filNam, ignoreEnvs) if filNode: grph.add((node_process, pc.property_runs, filNode)) sys.stderr.write("filNam=%s\n" % filNam) cgiEnv.OutCgiRdf()
def Main(): cgiEnv = lib_common.ScriptEnvironment() pid_proc = int(cgiEnv.GetId()) grph = cgiEnv.GetGraph() node_process = lib_uris.gUriGen.PidUri(pid_proc) proc_obj = CIM_Process.PsutilGetProcObj(pid_proc) argv_array = CIM_Process.PsutilProcToCmdlineArray(proc_obj) logging.debug("argv_array=%s", str(argv_array)) # This extracts the command file name and creates a node for it. for the_arg in argv_array[1:]: if the_arg[0] == "/": continue # Check if the file exists in the current directory. curr_pwd, err_msg = CIM_Process.PsutilProcCwd(proc_obj) if not curr_pwd: break all_dirs_to_search = [curr_pwd] env_path = CIM_Process.GetEnvVarProcess("PATH", proc_obj.pid) if env_path: all_dirs_to_search += env_path.split(";") # Now tries all possible dirs, starting with current directory. for a_dir in all_dirs_to_search: full_script_path = os.path.join(a_dir, the_arg) logging.debug("full_script_path=%s", full_script_path) if os.path.isfile(full_script_path): script_node = lib_uris.gUriGen.FileUri(full_script_path) grph.add((node_process, pc.property_runs, script_node)) break break cgiEnv.OutCgiRdf()
def Main(): cgiEnv = lib_common.ScriptEnvironment() grph = cgiEnv.GetGraph() try: procid = int(cgiEnv.GetId()) except Exception: lib_common.ErrorMessageHtml("Must provide a pid") obj_proc = CIM_Process.PsutilGetProcObj(procid) env_prop = lib_common.MakeProp("environment") try: envs_dict = obj_proc.environ() except Exception as exc: lib_common.ErrorMessageHtml("Caught:%s" % exc) node_process = lib_uris.gUriGen.PidUri(procid) for env_key in envs_dict : env_val = envs_dict[env_key] logging.debug("env_key=%s env_val=%s", env_key, env_val) node_env_nam = lib_util.NodeLiteral(env_key) # When a file or a directory displayed with a node, # its name is shortened so it can fit into the table., # so it is less visible. # Some are probably for Windows only. if env_key in ["PATH", "PSMODULEPATH", "PYPATH"]: val_split = env_val.split(os.pathsep) nod_fil_arr = [lib_uris.gUriGen.DirectoryUri(fil_nam) for fil_nam in val_split] nod_fil_arr_nod = lib_util.NodeLiteral(nod_fil_arr) grph.add((node_env_nam, pc.property_rdf_data_nolist2, nod_fil_arr_nod)) elif os.path.isdir(env_val): nod_fil = lib_uris.gUriGen.DirectoryUri(env_val) grph.add((node_env_nam, pc.property_rdf_data_nolist2, nod_fil)) elif os.path.exists(env_val): nod_fil = lib_uris.gUriGen.FileUri(env_val) grph.add((node_env_nam, pc.property_rdf_data_nolist2, nod_fil)) else: # TODO: Beware that "\L" is transformed into "<TABLE>" by Graphviz !!! env_val_clean = env_val.replace(">", "_").replace("<", "_").replace("&", "_").replace("\\", "_") node_env_value = lib_util.NodeLiteral(env_val_clean) grph.add((node_env_nam, pc.property_rdf_data_nolist2, node_env_value)) grph.add((node_process, env_prop, node_env_nam)) cgiEnv.OutCgiRdf("LAYOUT_RECT", [env_prop])
def Main(): cgiEnv = lib_common.CgiEnv() pid = int(cgiEnv.GetId()) # TODO: These are probably in win32com or a similar module. PROCESS_QUERY_INFORMATION = 0x0400 PROCESS_VM_READ = 0x0010 grph = cgiEnv.GetGraph() node_process = lib_common.gUriGen.PidUri(pid) exec_node = CIM_Process.AddInfo(grph, node_process, [pid]) #Get handle to the process based on PID hProcess = kernel.OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, False, pid) if hProcess: ModuType = c_ulong * 512 hModuleArr = ModuType() rawCntModules = c_ulong() psapi.EnumProcessModules(hProcess, byref(hModuleArr), sizeof(hModuleArr), byref(rawCntModules)) nbModules = int(rawCntModules.value / sizeof(c_ulong())) if nbModules >= 512: raise Exception("Disaster overrun") modname = c_buffer(256) for idx in range(0, nbModules): retLen = psapi.GetModuleFileNameExA(hProcess, hModuleArr[idx], modname, sizeof(modname)) tab = modname[:retLen] if sys.version_info >= (3, ): # Truncation because "b'C:/xxx/yyy.zzz'", on Python 3 filnam = str(tab).replace('\\', '/')[2:-1] else: filnam = tab # The same filename might appear several times. sys.stderr.write("idx=%d retLen=%d filnam=%s\n" % (idx, retLen, filnam)) if idx > 0: libNode = lib_common.gUriGen.SharedLibUri(filnam) grph.add((node_process, pc.property_library_depends, libNode)) kernel.CloseHandle(hProcess) cgiEnv.OutCgiRdf()
def Main(): cgiEnv = lib_common.CgiEnv() hostname = cgiEnv.GetId() cgiEnv = lib_common.CgiEnv() grph = cgiEnv.GetGraph() hostAddr = lib_util.GlobalGetHostByName(hostname) hostNode = lib_common.gUriGen.HostnameUri(hostname) for proc in CIM_Process.ProcessIter(): pid = proc.pid cgiEnv.OutCgiRdf()
def Main(): cgiEnv = lib_common.CgiEnv() try: root_pid = int(cgiEnv.GetId()) except KeyError: lib_common.ErrorMessageHtml("Process id should be provided") grph = cgiEnv.GetGraph() proc_obj = CIM_Process.PsutilGetProcObj(root_pid) # Sub-processes, recursion. tree_subprocesses(grph, proc_obj) # Now display the parent processes. # It could be done in a loop instead of recursive calls. tree_parent_process(grph, proc_obj, set()) # This layout style, because the nodes are quite big. cgiEnv.OutCgiRdf("LAYOUT_RECT")
def DoAll(lstStructs, verbose=True): print("Starting") if len(sys.argv) > 1: maxDisplay = int(sys.argv[2]) else: maxDisplay = 10 # python -m cProfile mmapregex.py if len(sys.argv) > 2: pidint = int(sys.argv[1]) ProcessMemoryScan(pidint, lstStructs, maxDisplay, verbose) else: for i in CIM_Process.ProcessIter(): print("Pid=%d name=%s" % (i.pid, i.name())) try: ProcessMemoryScan(i.pid, lstStructs, maxDisplay, verbose) print("") except Exception: t, e = sys.exc_info()[:2] print(" Caught:" + str(e).replace("\n", " ")) print("")
def Main(): cgiEnv = lib_common.ScriptEnvironment() pid = int(cgiEnv.GetId()) # TODO: These are probably in win32com or a similar module. PROCESS_QUERY_INFORMATION = 0x0400 PROCESS_VM_READ = 0x0010 grph = cgiEnv.GetGraph() node_process = lib_uris.gUriGen.PidUri(pid) exec_node = CIM_Process.AddInfo(grph, node_process, [pid]) #Get handle to the process based on PID hProcess = kernel.OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, False, pid) if hProcess: ModuType = c_ulong * 512 hModuleArr = ModuType() raw_cnt_modules = c_ulong() psapi.EnumProcessModules(hProcess, byref(hModuleArr), sizeof(hModuleArr), byref(raw_cnt_modules)) nb_modules = int(raw_cnt_modules.value/sizeof(c_ulong())) if nb_modules >= 512: raise Exception("Disaster overrun") modname = c_buffer(256) for idx in range(0, nb_modules): ret_len = psapi.GetModuleFileNameExA(hProcess, hModuleArr[idx], modname, sizeof(modname)) if ret_len == 0: # Maybe the string is empty. continue raw_filename_bytes = modname[:ret_len] raw_filename_as_str = raw_filename_bytes.decode() filnam = lib_util.standardized_file_path(raw_filename_as_str) lib_node = lib_uris.gUriGen.SharedLibUri(filnam) grph.add((node_process, pc.property_library_depends, lib_node)) kernel.CloseHandle(hProcess) cgiEnv.OutCgiRdf()
def Main(): paramkey_show_unconnected = "Show unconnected sockets" # TODO: At the moment, only uses false default values for boolean parameters, # TODO: because CGI and the CGI lib do not send empty strings. cgiEnv = lib_common.ScriptEnvironment( parameters={paramkey_show_unconnected: False}) flag_show_unconnected = bool( cgiEnv.get_parameters(paramkey_show_unconnected)) grph = cgiEnv.GetGraph() for proc in psutil.process_iter(): try: pid = proc.pid # TCP sockets only. all_connect = CIM_Process.PsutilProcConnections(proc) if all_connect: node_process = lib_uris.gUriGen.PidUri(pid) # Not sure this is the best plmace to add this edge. grph.add( (node_process, pc.property_host, lib_common.nodeMachine)) grph.add( (node_process, pc.property_pid, lib_util.NodeLiteral(pid))) # TODO: MAYBE CREATES ALL THE PROCESSES AND RUN THE THREADS ON THE COMPLETE LIST ??? survol_addr.PsutilAddSocketToGraphAsync( node_process, all_connect, grph, flag_show_unconnected) except Exception as exc: # This is for psutil.AccessDenied and psutil.NoSuchProcess but we do not want to import the module exc_str = str(exc) if (exc_str.find("AccessDenied") < 0) and (exc_str.find("NoSuchProcess") < 0): lib_common.ErrorMessageHtml("Caught:" + exc_str) cgiEnv.OutCgiRdf("LAYOUT_SPLINE")
def Main(): cgiEnv = lib_common.ScriptEnvironment() try: the_pid = int(cgiEnv.GetId()) except Exception: lib_common.ErrorMessageHtml("Must provide a pid") # If cannot be the current pid, otherwise it will block. if the_pid == os.getpid(): lib_common.ErrorMessageHtml("Cannot debug current process") if not lib_util.isPlatformWindows: lib_common.ErrorMessageHtml("This works only on Windows platforms") grph = cgiEnv.GetGraph() # Starts a second session cdb_fil = lib_util.TmpFile("CdbCommand", "cdb") cdb_fd = open(cdb_fil.Name, "w") cdb_fd.write("lm\n") # List loaded modules cdb_fd.write("k\n") # Display stack backtrace. cdb_fd.write("qd\n") # Quit and detach. cdb_fd.close() cdb_cmd = "cdb -p " + str(the_pid) + " -cf " + cdb_fil.Name proc_node = lib_uris.gUriGen.PidUri(the_pid) call_node_prev = None modules_map = {} logging.debug("Starting cdb_cmd=%s", cdb_cmd) try: cdb_pipe = lib_common.SubProcPOpen(cdb_cmd) except WindowsError as exc: lib_common.ErrorMessageHtml("cdb not available: Caught:%s" % str(exc)) logging.debug("Started cdb_cmd=%s", cdb_cmd) cdb_output, cdb_err = cdb_pipe.communicate() # Without decode, "TypeError: Type str does not support the buffer API" cdb_str = cdb_output.decode("utf-8") call_depth = 0 for dot_line in cdb_str.split('\n'): err_match = re.match(".*parameter is incorrect.*", dot_line) if err_match: lib_common.ErrorMessageHtml("CDB:"+dot_line) # 76590000 766a0000 kernel32 (export symbols) C:\Windows\syswow64\kernel32.dll match_lm = re.match(r"[0-9a-fA-F]+ [0-9a-fA-F]+ +([^ ]*) +\(export symbols\) +(.*)", dot_line ) if match_lm: module_name = match_lm.group(1) dll_name_raw = match_lm.group(2).strip() dll_name = lib_util.standardized_file_path(dll_name_raw) logging.debug("module_name=%s dll_name=%s", module_name, dll_name) modules_map[module_name] = dll_name continue # 295cfb0c 00000000 ntdll!RtlInitializeExceptionChain+0x36 # Another format, maybe because of a 64 bits machine. # 00000000`02edff90 00000000`00000000 ntdll!RtlUserThreadStart+0x21 match_k = re.match("[`0-9a-fA-F]+ [`0-9a-fA-F]+ ([^!]*)!([^+]*)", dot_line) if match_k: module_name = match_k.group(1) try: dll_name = modules_map[module_name] except KeyError: dll_name = module_name func_name = match_k.group(2).strip() logging.debug("module_name=%s dll_name=%s func_name=%s", module_name, dll_name, func_name) dll_name = CDB.TestIfKnownDll(dll_name) call_node_prev = survol_symbol.AddFunctionCall(grph, call_node_prev, proc_node, func_name, dll_name) grph.add((call_node_prev, lib_properties.MakeProp("Call_depth"), lib_util.NodeLiteral(call_depth))) call_depth += 1 continue logging.debug("dot_line=%s", dot_line) logging.debug("Parsed cdb result") call_node_prev = survol_symbol.AddFunctionCall(grph, call_node_prev, proc_node, None, None) CIM_Process.AddInfo(grph, proc_node, [the_pid]) # http://msdn.microsoft.com/en-us/library/windows/hardware/ff539058(v=vs.85).aspx # # This section describes how to perform basic debugging tasks using # the Microsoft Console Debugger (CDB) and Microsoft NT Symbolic Debugger (NTSD). # CDB and NTSD are identical in every way, except that NTSD spawns # a new text window when it is started, whereas CDB inherits # the Command Prompt window from which it was invoked. # The instructions in this section are given for CDB, # but they work equally well for NTSD. For a discussion # of when to use CDB or NTSD, see Debugging Environments. cgiEnv.OutCgiRdf("LAYOUT_SPLINE")
def Main(): cgiEnv = lib_common.ScriptEnvironment() try: the_pid = int(cgiEnv.GetId()) except Exception: lib_common.ErrorMessageHtml("Must provide a pid") if not lib_util.isPlatformWindows: lib_common.ErrorMessageHtml("This works only on Windows platforms") # If cannot be the current pid, otherwise it will block. if the_pid == os.getpid(): lib_common.ErrorMessageHtml("Cannot debug current process") grph = cgiEnv.GetGraph() # Starts a second session cdb_fil = lib_util.TmpFile("CdbCommand", "cdb") cdb_fd = open(cdb_fil.Name, "w") cdb_fd.write("lmv\n") # List loaded modules, verbose mode. cdb_fd.write("qd\n") # Quit and detach. cdb_fd.close() cdb_cmd = "cdb -p " + str(the_pid) + " -cf " + cdb_fil.Name proc_node = lib_uris.gUriGen.PidUri(the_pid) logging.debug("Starting cdb_cmd=%s", cdb_cmd) try: cdb_pipe = lib_common.SubProcPOpen(cdb_cmd) except WindowsError as exc: lib_common.ErrorMessageHtml("cdb not available: Caught:%s" % str(exc)) logging.debug("Started cdb_cmd=%s", cdb_cmd) cdb_output, cdb_err = cdb_pipe.communicate() # Without decode, "TypeError: Type str does not support the buffer API" cdb_str = cdb_output.decode("utf-8", "ignore") prop_loaded_module = lib_common.MakeProp("Loaded module") for dot_line in cdb_str.split('\n'): # moduleName=uDWM moduleStatus=deferred file_name= # dot_line= Image path: C:\windows\system32\uDWM.dll # dot_line= Image name: uDWM.dll # dot_line= Timestamp: Tue Jul 14 02:33:35 2009 (4A5BE06F) # dot_line= CheckSum: 0005E9A4 # dot_line= ImageSize: 00057000 # dot_line= File version: 6.1.7600.16385 # dot_line= Product version: 6.1.7600.16385 # dot_line= File flags: 0 (Mask 3F) # dot_line= File OS: 40004 NT Win32 # dot_line= File type: 2.0 Dll # dot_line= File date: 00000000.00000000 # dot_line= Translations: 0409.04b0 # dot_line= CompanyName: Microsoft Corporation # dot_line= ProductName: Microsoft Windows Operating System # dot_line= InternalName: udwm.dll # dot_line= OriginalFilename: udwm.dll # dot_line= ProductVersion: 6.1.7600.16385 # dot_line= FileVersion: 6.1.7600.16385 (win7_rtm.090713-1255) # dot_line= FileDescription: Microsoft Desktop Window Manager # dot_line= LegalCopyright: Microsoft Corporation. All rights reserved. match_lin = re.match(" *Image path: *(.*)", dot_line) if match_lin: file_name = match_lin.group(1) file_name = CDB.TestIfKnownDll(file_name) file_name = file_name.strip() file_name = lib_util.standardized_file_path(file_name) file_node = lib_uris.gUriGen.FileUri(file_name) grph.add((proc_node, prop_loaded_module, file_node)) continue match_lin = re.match(" *CompanyName: *(.*)", dot_line) if match_lin: company_name = match_lin.group(1) grph.add((file_node, lib_common.MakeProp("Company Name"), lib_util.NodeLiteral(company_name))) continue match_lin = re.match(" *File OS: *(.*)", dot_line) if match_lin: file_os = match_lin.group(1) grph.add((file_node, lib_common.MakeProp("File OS"), lib_util.NodeLiteral(file_os))) continue match_lin = re.match(" *FileDescription: *(.*)", dot_line) if match_lin: file_description = match_lin.group(1) grph.add((file_node, lib_common.MakeProp("Description"), lib_util.NodeLiteral(file_description))) continue logging.debug("Parsed cdb result") CIM_Process.AddInfo(grph, proc_node, [the_pid]) cgiEnv.OutCgiRdf("LAYOUT_RECT", [prop_loaded_module])
def Main(): cgiEnv = lib_common.CgiEnv() # userNameWithHost = cgiEnv.GetId() # Usernames have the syntax user@host # Example: [email protected] # userSplit = userNameWithHost.split('@') # userName = userSplit[0] userName = cgiEnv.m_entity_id_dict["Name"] try: # Exception if local machine. userHost = cgiEnv.m_entity_id_dict["Domain"] except KeyError: userHost = lib_util.currentHostname if userHost: # if userHost != lib_util.currentHostname: if not lib_util.IsLocalAddress(userHost): # TODO: Should interrogate other host with "finger" protocol. # Cannot get user properties on different host:rchateau-HP than rchateau-HP.home lib_common.ErrorMessageHtml( "Cannot get user properties on different host:%s than %s" % (userHost, lib_util.currentHostname)) grph = cgiEnv.GetGraph() # It will be possible to transform this into a Json tree by # selecting only the RDF predicate property_ppid. # This will be done in a gui cgi script which takes as input # parameter a CGI script, visible by SLP, stored in a bookmark page # or anything else. # See http://stackoverflow.com/questions/17967686/retrieving-specific-rdf-graph-triples-based-on-predicate-nodes # on how to select triples on a given predicate only. # But in the general case, we cannot know if the RDF graph will be a tree, # something similar to a CSV file (That is, flat) or a general graph. # So we might have to process the resulting graph on the fly, to see # which visualising methods are applicable. # Also, in the case of a tree, we must find ourselves what is its root. for proc in CIM_Process.ProcessIter(): procUsername = CIM_Process.PsutilProcToUser(proc) # sys.stderr.write("procUsername=%s userName=%s\n" % ( procUsername, userName ) ) # procUsername=EURO\\UK936025 userName=UK936025 # procUsername=NT AUTHORITY\\NETWORK SERVICE # procUsername=NT AUTHORITY\\SYSTEM # procUsername=EURO\\UK936025 # procUsername=NT AUTHORITY\\SYSTEM if procUsername != userName: # On Windows, second chance with only the second part of the user. try: userShort = procUsername.split('\\')[1] except IndexError: userShort = procUsername if userShort != userName: continue if lib_common.is_useless_process(proc): continue procName = proc.name pid = proc.pid parent_pid = CIM_Process.PsutilProcToPPid(proc) # Built the same way in other RDF documents. node_process = lib_common.gUriGen.PidUri(pid) parent_node_process = lib_common.gUriGen.PidUri(parent_pid) # We avoid duplicating the edges. Why would the RFD merge do? grph.add((node_process, pc.property_ppid, parent_node_process)) grph.add((node_process, pc.property_pid, lib_common.NodeLiteral(pid))) # grph.add( ( node_process, pc.property_information, lib_common.NodeLiteral(procUsername) ) ) # We avoid duplicating the edges. Why would the RFD merge do? ############ grph.add( ( node_process, pc.property_ppid, parent_node_process ) ) cgiEnv.OutCgiRdf()
def Main(): paramkeyShowSharedLib = "Show shared libraries" paramkeyShowFontFiles = "Show font files" paramkeyShowNonShared = "Show non shared files" # TODO: At the moment, only uses false default values for boolean parameters, # TODO: because CGI and the CGI lib do not send empty strings. cgiEnv = lib_common.CgiEnv( parameters={ paramkeyShowSharedLib: False, paramkeyShowFontFiles: False, paramkeyShowNonShared: False }) flagShowSharedLib = bool(cgiEnv.GetParameters(paramkeyShowSharedLib)) flagShowFontFiles = bool(cgiEnv.GetParameters(paramkeyShowFontFiles)) flagShowNonShared = bool(cgiEnv.GetParameters(paramkeyShowNonShared)) grph = cgiEnv.GetGraph() ################################################################################ Main.dictPathToNod = {} AddPidFileLink.dictFiles = {} # Maybe this is done in another CGI. What happens when merging ? grph.add((lib_common.nodeMachine, pc.property_hostname, lib_common.NodeLiteral(lib_util.currentHostname))) # https://code.google.com/p/psutil/issues/detail?id=340 # This might hang. for proc in CIM_Process.ProcessIter(): try: if lib_common.UselessProc(proc): continue pid = proc.pid node_process = None # http://code.google.com/p/psutil/issues/detail?id=340 # https://github.com/giampaolo/psutil/issues/340 for fil in CIM_Process.PsutilProcOpenFiles(proc): # Some files are not interesting even if accessed by many processes. if lib_common.MeaninglessFile(fil.path, not flagShowSharedLib, not flagShowFontFiles): continue # Adds the process node only if it has at least one open file. if node_process == None: node_process = lib_common.gUriGen.PidUri(pid) grph.add((node_process, pc.property_pid, lib_common.NodeLiteral(pid))) # TODO: What about files on a shared drive? if flagShowNonShared: fileNode = PathToNod(fil.path) grph.add((node_process, pc.property_open_file, fileNode)) else: # This takes into account only files accessed by several processes. AddPidFileLink(grph, node_process, fil.path) # except psutil.AccessDenied: # pass except: exc = sys.exc_info()[1] sys.stderr.write("Exception:%s\n" % str(exc)) pass cgiEnv.OutCgiRdf("LAYOUT_SPLINE")