我正在编写一个 Python 脚本,它主要是一个用于在 Windows 主机上收集实时取证数据的 GUI 框架。到目前为止,我还没有遇到很多我无法解决的问题。但是这个让我难住了。这可能是涉及不正确的变量范围的问题,但对于我的生活,我找不到问题。脚本本身有两千多行,所以除非另有说明,否则我将复制相关部分。
我在破坏功能的地方对我的代码进行了更改。它曾经按预期完美地工作,现在我不知道为什么它没有。这肯定会导致我将来在项目中使用版本控制软件,这是肯定的。
奇怪的是,根本没有抛出异常。
我想要做的是让用户选择与他们想要执行的可选功能相对应的 Tkinter Checkbutton 小部件。我已经为每个 Checkbutton 小部件设置了 Tkinter IntVars,并将这些 IntVars 放入一个数组中以便于枚举。GUI 有一个“开始”按钮,按下该按钮会启动 start() 函数。如果 IntVar 设置为 1(表示选择),此函数应枚举数组中的 Checkbutton IntVars 并执行相关功能。
我的代码的所有其他部分都按预期运行。我在填充数组方面度过了一段可怕的时光。似乎我无法修改数组,即使在函数中声明为全局。如果我手动设置数组中的值,它会按预期工作。我无法遍历 IntVars 并将“全局”数组设置为正确的值。似乎这两个数组永远不会被修改,就好像没有一个 Checkbutton IntVars 通过被选中而设置为“1”。
#this is an array of integers corresponding to the checked
#state of desired filetypes for collection
filetypes = [0]*34
#this is an array of integers corresponding to optional collection items
optionalitems = [0]*10
#... snipped ...
#This function performs just fine if the filetypes array is set manually...
#extensions[] is an array containing file extension strings corresponding
# to the Checkbuttons on the fileSelector Toplevel widget.
#outputdirs[] is an array containing strings with a desired output directory.
def collectFiles():
global filetypes
n = 0
print("Parsing checkboxes for file collection...\r\n")
for item in filetypes:
if item:
print(extensions[n] + " selected...")
#make output dir corresponding to the desired extension
outputdest = cwd + "/output/" + computername + outputdirs[n]
if not os.path.exists(outputdest):
print(outputdest + " does not exist, creating...")
os.makedirs(outputdest)
print("Collection for " + outputdirs[n] + " beginning...")
for drive in drives:
print("Searching drive " + drive + "...")
for filename in search(drive, extensions[n]):
try:
i = 2
#outpath = cwd + "/output/" + username + outputdirs[n]
tempbasename = os.path.basename(filename)
testpath = os.path.join(outputdest, tempbasename)
tempbasename2 = ""
while os.path.exists(testpath):
print(testpath + " exists in output directory.")
tempbasename2 = str(i) + "_" + tempbasename
i += 1
testpath = os.path.join(outputdest, tempbasename2)
shutil.copy2(filename,testpath)
print("Copied:\n\t" + filename + "\n to:\n\t" + testpath + "\n")
logfile.write(str(datetime.datetime.now()) + "- Copied:\r\n\t" + filename
+ "\r\n to:\r\n\t" + testpath + "\r\n\r\n")
except:
print("****Problem copying: " + filename + "\n")
logfile.write(str(datetime.datetime.now()) + "****Problem copying: " + filename
+ "\r\n\r\n")
pass
n += 1
#... snipped ...
#here's where the oddness begins.
#The optionalitems array SHOULD be set outside of this
# function, before it is called.
def doOptionalCollection():
x = 0
for item in optionalitems:
if item:
optionfunctions[x]()
x = x + 1
collectFiles()
#this is the routine called when the "Start" button is pressed.
# The goal here is to enumerate the checkboxes on the GUI, and
# fill filetypes[] and optionalitems[] with values corresponding to
# whether or not the Checkbuttons are selected.
def start():
global filetypes
global optionalitems
#... snipped ...
#code here performs baseline forensic data collection,
# and performs exactly as intended.
#... snipped ...
#get status of checkboxes and update optionalitems array.
# optionArray is the Array of IntVars associated with Tkinter Checkbuttons
# obj.get() --> 0 = unchecked, 1 = checked
i = 0
for obj in optionArray:
optionalitems[i] = obj.get()
i = i + 1
doOptionalCollection()
#this is for a dialog-style window that pops up when a button is pressed.
# The dialog contains 34 checkboxes, each with a variable to hold the state.
def showFileSelector():
global filetypes
fs = Toplevel(master=root)
fs.title("Collect files by extension...")
#set up a grid based on the extensions dictionary keys.
# have the grid wrap on the 6th element.
#... snipped, setup of Checkbutton tkinter windgets ...
buttonArray = [txtButton, pdfButton, logButton, docButton, docxButton,
rarButton, zipButton, isoButton, jarButton, jpgButton,
jpegButton, bmpButton, pngButton, gifButton, exeButton,
pptButton, pptxButton, aviButton, mp4Button, movButton,
flvButton, mpgButton, wmvButton, mp3Button, flacButton,
wmaButton, m4aButton, wavButton, psdButton, rawButton,
apkButton, szipButton, indexdatButton, thumbsdbButton]
#using filetypes array, set the status of the checkbox.
#this is helpful if the dialog is re-opened, it will
# re-populate the dialog with previous selections.
x = 0
for item in buttonArray:
if filetypes[x]:
item.select()
x = x + 1
varArray = [txtvar, pdfvar, logvar, docvar, docxvar,
rarvar, zipvar, isovar, jarvar, jpgvar,
jpegvar, bmpvar, pngvar, gifvar, exevar,
pptvar, pptxvar, avivar, mp4var, movvar,
flvvar, mpgvar, wmvvar, mp3var, flacvar,
wmavar, m4avar, wavvar, psdvar, rawvar,
apkvar, szipvar, indexdatvar, thumbsdbvar]
def accept():
global filetypes
#user has possibly chosen files to collect by extension.
# iterate varArray to determine what files to collect,
# and store the result in filetypes[].
#This assignment also does not work.
x = 0
for var in varArray:
#var.get() to get the values of checkboxes
# 0 = unchecked
# 1 = checked
filetypes[x] = var.get()
x = x + 1
fs.destroy()
def cancel():
#user has decided to discard selections and close
# the window.
fs.destroy()
#... snipped, GUI placement ...
#back to the base-level indentation (no indents... not inside any functions)
#... snipped, optional item GUI Checkbutton setup ....
optionArray = [productkeyvar, outlookvar,
recyclebinvar, skypevar,
prefetchvar, installlogvar,
allmediavar, win7jumplistvar,
win7thumbcachevar, recentfilesvar]
optionfunctions = [collectProductKeys, collectOutlookAttachments,
collectRecycleBin, collectSkypeHistory,
collectPrefetchFolder, collectDeviceInstallationLogs,
collectMediaFiles, collectWin7JumpList,
collectWin7ThumbnailCache, collectShortcutRecentFiles]
#... snipped, more GUI setup ...
#and then, the obligatory...
root.mainloop()
要尝试简化流程:
用户在 GUI 上设置选项,也可以选择文件类型进行收集。如果用户选择了要收集的任何文件类型,则 filetypes[] 应该已经填充了所需的选择。修改这个数组似乎没有发生。
用户按下开始按钮,开始按钮命令是 start() 函数。定义了全局变量 - 即 filetypes[] 和 optionalitems[]。
在 start() 内部,发生基线取证收集,并按预期运行。
仍在 start() 中,获取可选集合的复选框状态,并填充可选项 []。修改这个数组似乎没有发生。
start() 然后调用 doOptionalCollection()。
doOptionalCollection() 还定义了全局变量 - filetypes[] 和 optionalitems[]。当数组被枚举时,它们被读取为它们的初始值——全为零。这意味着没有执行任何所需的收集功能。
doOptionalCollection() 调用 collectFiles()。
collectFiles() 有一个全局定义 - 这主要是我在函数本身中解析 filetypes[] 时的一个工件。由于 filetypes 数组始终全为零,因此除非在代码中手动设置,否则不会收集任何内容。
这是一个很长的帖子......第一次在这里发帖,所以我提前为巨大的文字墙道歉。我不希望从我的任何代码中获利,所以如果您想查看完整的预期功能,我可以分享我的代码库。我可以将整个软件包提供给感兴趣的人。提前致谢!