def symtask(cls, jobitem, symserver, symdest, symlocal): ''' perform symbol search for symbols of jobfile. If there are no symbols or symbols found are already in db, discard results. Else, return found symbols ''' symlogger = logging.getLogger("BAM.Pools.SymWkr") jobfile = jobitem[0] hashes = (jobfile[1], jobfile[2]) result = None logmsg = "[SYMMGR].. Getting SYM for (" + str(jobfile) + ")" symlogger.log(logging.DEBUG, logmsg) servers = "" if symlocal: servers = " \""+ symdest + "\"" else: servers = "u \"srv*" + symdest + "*" + symserver +"\"" args = (".\\tools\\x64\\symchk.exe /v \"" + str(jobfile) + "\" /s" + servers + " /od") try: with subprocess.Popen(args, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE) \ as psymchk: # communicate used as symchk's output is for one file and # is not "large or unlimited" pstdout, pstderr = psymchk.communicate() stdoutsplit = str(pstdout.decode("ascii")).split("\r\n") stderrsplit = str(pstderr.decode("ascii")).split("\r\n") logmsg = "[SYMMGR] Attempt to obtain symbols for " + str(jobfile) + " complete" symlogger.log(logging.DEBUG, logmsg) infolist = {} try: unpefile = pefile.PE(jobfile) except pefile.PEFormatError as peerror: logmsg = "[WSUS_DB] Caught: PE error " + str(peerror) + ". File: " + jobfile symlogger.log(logging.ERROR, logmsg) return result infolist['signature'] = getpesigwoage(unpefile) infolist['arch'] = getpearch(unpefile) unpefile.close() stderrsplit.append(symserver) result = ((str(jobfile), stderrsplit, stdoutsplit), hashes[0], hashes[1], infolist) except subprocess.CalledProcessError as error: logmsg = "[SYMMGR] {-} symchk failed with error: " + str(error) + ". File: " + jobfile symlogger.log(logging.ERROR, logmsg) result = None except FileNotFoundError as error: logmsg = ("[SYMMGR] {-} symchk.exe not found") symlogger.log(logging.ERROR, logmsg) result = None logmsg = "[SYMMGR] completed symtask for " + str(jobfile) symlogger.log(logging.DEBUG, logmsg) return result
def cleantask(cls, jobfile, updateid): ''' task to clean up folder before submitting jobs for symbol search if item is removed in cleaning, None is returned, else return item ''' clnlogger = logging.getLogger("BAM.Pools.ClnWkr") results = None logmsg = "[CLNMGR] Starting on " + str(jobfile) clnlogger.log(logging.DEBUG, logmsg) if ispe(jobfile): # check db to see if job already exists: hashes = getfilehashes(jobfile) if hashes is None: return hashes if wsuse_db.dbentryexistwithsymbols(globs.DBCONN.cursor(), \ globs.PATCHEDFILESDBNAME, hashes[0], hashes[1]): # if PE is already in db with symbols obtained, # do not retask job to symbol manager, return None instead return results else: pass logmsg = "[CLNMGR] continuing forward with " + str(jobfile) clnlogger.log(logging.DEBUG, logmsg) # getting to this point means item is not in db, may need to come up # with case where db needs to update item though infolist = { 'OriginalFilename': '', 'FileDescription': '', 'ProductName': '', 'Comments': '', 'CompanyName': '', 'FileVersion': '', 'ProductVersion': '', 'IsDebug': '', 'IsPatched': '', 'IsPreReleased': '', 'IsPrivateBuild': '', 'IsSpecialBuild': '', 'Language': '', 'PrivateBuild': '', 'SpecialBuild': '' } try: unpefile = pefile.PE(jobfile, fast_load=True) except pefile.PEFormatError as peerror: logmsg = "[WSUS_DB] skipping " + str(jobfile) + " due to exception: " + peerror.value clnlogger.log(logging.ERROR, logmsg) return results infolist['fileext'], infolist['stype'] = pebinarytype(unpefile) infolist['arch'] = getpearch(unpefile) infolist['age'] = getpeage(unpefile) infolist['strippedpe'] = ispedbgstripped(unpefile) infolist['builtwithdbginfo'] = ispebuiltwithdebug(unpefile) direntires=[ pefile.DIRECTORY_ENTRY['IMAGE_DIRECTORY_ENTRY_DEBUG'], \ pefile.DIRECTORY_ENTRY['IMAGE_DIRECTORY_ENTRY_RESOURCE'] ] unpefile.parse_data_directories(directories=direntires) infolist['pdbfilename'] = getpepdbfilename(unpefile) infolist['signature'] = getpesigwoage(unpefile) # a PE only have 1 VERSIONINFO, but multiple language strings # More information on different properites can be found at # https://msdn.microsoft.com/en-us/library/windows/desktop/aa381058 # https://msdn.microsoft.com/en-us/library/windows/desktop/aa381049 if getattr(unpefile, "VS_VERSIONINFO", None) is not None and \ getattr(unpefile, "FileInfo", None) is not None: for fileinfoentries in unpefile.FileInfo: for fileinfoentry in fileinfoentries: if getattr(fileinfoentry, "StringTable", None) is not None: for strtable in fileinfoentry.StringTable: # Currently only handling unicode en-us if strtable.LangID[:4] == b'0409' or \ (strtable.LangID[:4] == b'0000' and (strtable.LangID[4:] == b'04b0' or strtable.LangID[4:] == b'04B0')): infolist["Language"] \ = strtable.LangID.decode("utf-8") for field, value in strtable.entries.items(): dfield = field.decode('utf-8') dvalue = value.decode('utf-8') if dfield == "OriginalFilename": infolist["OriginalFilename"] \ = dvalue if dfield == "FileDescription": infolist["FileDescription"] \ = dvalue if dfield == "ProductName": infolist["ProductName"] \ = dvalue if dfield == "Comments": infolist["Comments"] \ = dvalue if dfield == "CompanyName": infolist["CompanyName"] \ = dvalue if dfield == "FileVersion": infolist["FileVersion"] \ = dvalue if dfield == "ProductVersion": infolist["ProductVersion"] \ = dvalue if dfield == "IsDebug": infolist["IsDebug"] \ = dvalue if dfield == "IsPatched": infolist["IsPatched"] \ = dvalue if dfield == "IsPreReleased": infolist["IsPreReleased"] \ = dvalue if dfield == "IsPrivateBuild": infolist["IsPrivateBuild"] \ = dvalue if dfield == "IsSpecialBuild": infolist["IsSpecialBuild"] \ = dvalue if dfield == "PrivateBuild": infolist["PrivateBuild"] \ = dvalue if dfield == "SpecialBuild": infolist["SpecialBuild"] \ = dvalue # Get the OS this PE is designed towards. # Microsoft PE files distributed via Microsoft's Updates typically # use the ProductVersion file properties to indicate the OS a specific # PE file is built towards. # If this is a Microsoft binary, the Product version is typically # the OS version it was built towards, but other products this is not # necessarily true if infolist['ProductName'].find("Operating System") != -1: infolist['osver'] = "NT" + infolist['ProductVersion'] else: infolist['osver'] = "UNKNOWN" unpefile.close() results = ((str(jobfile), updateid), hashes[0], hashes[1], infolist) else: # if jobfile is not a PE, then check if it's a cab. If not a cab, remove it. if not validatecab(str(jobfile)): logmsg = "[CLNMGR] cleantask: Removing " + str(jobfile) clnlogger.log(logging.DEBUG, logmsg) rmfile(jobfile) logmsg = "[CLNMGR] " + str(jobfile) + " removed, not PE or cab file" clnlogger.log(logging.DEBUG, logmsg) else: pass logmsg = "[CLNMGR] " + str(jobfile) + " is nested cab, skipping" clnlogger.log(logging.DEBUG, logmsg) return results logmsg = "[CLNMGR] completed one cleantask for " + str(jobfile) clnlogger.log(logging.DEBUG, logmsg) return results