【问题标题】:How to know that the application has finished processing file?如何知道应用程序已经处理完文件?
【发布时间】:2016-10-21 09:05:13
【问题描述】:

我正在尝试自动化我在应用程序中执行的检测,但问题是我正在处理处理后不会自行退出的应用程序。例如,使用任何 pdfviewer/reader,如果我打开文件,则会显示该文件,并且我可以看到该应用程序已处理该文件。

通过应用程序处理文件,我的意思是该文件已被应用程序成功显示。

应用程序可以是任何用于 ex adobe reader、xpdf、foxitreader 的 GUI pdf 查看器或任何用于 ex gpicview 等的图像查看器。文件格式可以是任何类型,而不是任何特定的文件格式。

另外我没有应用程序的源代码,我正在处理应用程序的二进制文件。

但是在自动化过程时,我想知道应用程序何时处理了文件。我最初能想到的是会有一些基本块表示在执行后它已经完成了文件处理并在特定基本块执行后退出我的检测。

但这里的问题是如何识别那个基本块?

【问题讨论】:

  • 我认为对于大型 pdf 文件,显示仅使用部分文件读取,当用户向下滚动时根据需要在其余数据中流式传输......所以文件并没有完成,直到应用程序关闭。

标签: assembly binary reverse-engineering fuzzing


【解决方案1】:

对于黑盒可执行文件,您可以自动执行的最简单和最可靠的事情可能是查看它们的 CPU 使用率。当它们完成加载时,它们的所有线程应该(大部分)空闲,如果它们等待具有非无限超时的事件,可能会偶尔醒来。 (以及来自鼠标移动等其他 GUI 事件)。

确保等待足够长的时间来检测磁盘 I/O 上阻塞与等待用户输入阻塞之间的区别。 (在类 Unix 操作系统上,这是 Disk-sleep 和 Sleep 之间的区别,如 DS 在诸如 top 的进程列表之类的东西中所示。)

如果您不想依赖操作系统来检测磁盘睡眠与常规睡眠,只需等待比最大磁盘 I/O 请求服务时间长几倍(~= 几倍磁盘延迟,更低如果被测进程是唯一执行 I/O 的进程)。如果黑盒进程在该时间间隔内没有使用任何 CPU 时间,您可以假设它已完成加载并正在屏幕上显示文件。

当然,正如@Ped7g 指出的那样,它可能没有解析整个文件。例如,当用户滚动浏览大型 PDF 时,它可能会按需延迟加载。在以编程方式向进程发送向下翻页命令后,观察 CPU 时间应该是检测进程何时完成更新的合理方法。

我认为您应该能够从中获得良好可靠的结果。如果您想可靠地确定进程已完成加载,而无需等待最坏的情况,您可能需要考虑多个输入(如系统 I/O 性能或未完成的磁盘 IO 请求)的启发式方法。


正如 cmets 中所讨论的,在文件描述符上寻找到达 EOF 的进程对于此目的并不可靠(它可能会映射它)。我会把它留在这里,以防它对任何人都有趣或有用,但为了您的使用,您可能希望完全忽略它。充其量,您可以将其用作启发式方法的输入,以决定进程何时完成加载。

在大多数操作系统上,进程都有一些工具可以跟踪其他进程。在 Linux 上,主要的是 ptrace API。像strace 这样的命令使用它来跟踪系统调用。我相信 Windows 也有类似的东西,我认为 OS X 也有。

因此您可以在 PDF 上查找 open() 系统调用以找到正确的 fd,然后在其上查找 mmap、read() 和 close() 系统调用。如果 read() 返回 0,则它位于 EOF。如果它在没有 mmap 的情况下关闭,则该过程已完成(除非它再次打开它,或出于某种原因使用 dup() 或 dup2())。

您可以解析 strace 的文本输出,或者自己使用 ptrace API。


或者,在 Linux 上,您可以查看 /proc/<PID>/fdinfo/<FD> 中的文件位置。其他操作系统可能有类似的工具来查看打开的文件描述符/文件句柄的文件位置。

例如,我碰巧打开了evince 显示一个PDF。在`/proc/

$ ll /proc/4241/fd
...
lr-x------ 1 peter peter 64 Oct 21 06:43 14 -> /f/p/docs/agner_fog.microarchitecture.pdf    # is anyone really surprised this is the PDF I had open?  :P
...
$ ls -lL /proc/4241/fd/14       # follow the symlink to see the file size
-rw-rw-r-- 1 peter peter 2078709 Feb  4  2016 /proc/4241/fd/14

$ m /proc/4241/fdinfo/14        # alias for less
pos:    2078709
flags:  0100000
mnt_id: 49

这证实了我的猜测,当 evince 完成读取文件时,文件位置将位于 EOF。您可能应该等待几毫秒并再次检查,以防被测软件再次循环文件。

【讨论】:

  • 是否有必要关闭或 EOF 将指示应用程序已完成处理,假设我已读取缓冲区中的文件,然后显示我正在使用该缓冲区的数据。通过处理文件,我并不意味着该文件已被完全读取。我的意思是已经显示成功了。
  • @user2823667:是的,这是一个很好的观点。可能将其结合并等待它停止使用 CPU 时间是您最好的选择。只需等待它读取文件并且在大约 40 毫秒或其他时间内没有使用任何大量 CPU 时间,具体取决于您的磁盘 I/O 延迟。 (在等待 I/O 时避免误报)。
  • @user2823667:如果您可以跟踪它的任何线程是否用完它们的整个时间片,而不是它们是否刚刚醒来处理一个 GUI 事件并立即回到睡眠状态,那将是我认为要寻找的东西。
  • 如果应用程序映射文件,关闭它,然后才处理它怎么办?当应用程序只是其地址空间的一部分时,您无法(轻松地)检查对文件的访问。
  • @ShacharShemesh:好点,看文件描述符一般不可靠。等待进程的 CPU 使用率接近零的时间超过几次,您的磁盘 I/O 延迟应该始终有效。如果您想编写更多代码以在 some 情况下更确定地检测(因此不必等待很长时间以确保进程现在处于空闲状态),您可以使用 strace 来检测进程已关闭文件而不对其进行映射。但我认为查看进程的 CPU 使用率实际上是最好的选择。我将编辑我的答案,将其作为第一个建议。
猜你喜欢
  • 2017-01-08
  • 1970-01-01
  • 2010-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-16
  • 1970-01-01
相关资源
最近更新 更多