扩展现有程序的function我没有来源

我正在研究一个第三方程序,它汇总了大量不同的现有Windows程序的数据。 每个程序都有一个通过GUI导出数据的机制。 最死脑筋的方法会让我通过使用AutoIt或其他一些GUI操作程序生成提取通过GUI生成提取。 问题在于,当突然间,一些自动程序接pipe时,人们可能正在与计算机进行交互。 这不好。 我真正想要做的是每天有一个程序运行一次,并默默地(即不popup任何GUI)导出每个程序的数据。

我的研究告诉我,我需要挂钩每个应用程序(假设这些应用程序总是运行),并注入一个自定义的DLL来触发每个导出。 我是否远离正确的轨道? 我是一个相当有经验的软件开发人员,但是我不太了解逆向工程或钩子。 任何意见或方向将不胜感激。

编辑:我试图pipe理某种types的专业人员的可用性。 他们的时间表存储在专有系统中。 在他们的许可下,我想在他们的系统上安装一个应用程序,从他们正在使用的系统中提取他们的时间表,并将这些信息上传到中央服务器,以便我可以向潜在客户展示这些信息。

我知道有四种方法来提取你想要的信息,既有它们的优点也有缺点。 在你做任何事情之前,你需要知道你创建的任何解决方案都是不能保证的,而且事实上,如果目标应用程序不断更新,那么就不太可能继续工作。 原因在于,在每种情况下,您都依赖于实现细节,而不是通过其导出数据的预定义接口。

钩住GUI

第一种方法是按照您的建议挂接GUI。 你在这种情况下做什么只是从实际用户会看到什么。 这通常更容易,因为你正在钩住明确定义的WinAPI。 一个危险是程序显示的内容与它应该表示的内部数据相比是不一致的或不完整的。

通常,有两种常见的方法来执行WinAPI挂钩:

  • DLL注入。 你创建一个你加载到另一个程序的虚拟地址空间的DLL。 这意味着您具有对目标的整个内存的读/写访问权限(通过VirtualProtect可以获得可写权限)。 从这里你可以蹦跳被调用来设置UI信息的功能。 例如,要检查一个窗口是否改变了它的文本,你可以蹦一下SetWindowText函数。 注意每个控件都有不同的界面来设置他们正在显示的内容。 在这种情况下,您正在挂钩代码调用的函数来设置显示。
  • SetWindowsHookEx 。 在封面下,这与DLL注入类似,在这种情况下,实际上只是另一种方法来扩展/颠覆由控件接收的消息的控制流。 在这种情况下你要做的是钩住每个子控件的窗口过程。 例如,当一个项目被添加到组合框时 ,它会收到一个CB_ADDSTRING消息。 在这种情况下,您正在挂接显示更改时收到的消息。

这种方法的一个警告是,它只会在目标使用或扩展WinAPI控件时才起作用。

从GUI读取

可以使用WinAPI直接从目标窗口中读取,而不是挂钩GUI。 但是,在某些情况下,这可能是不允许的。 在这种情况下没有太多的事情要做,而是试着去看看是否有效。 这实际上可能是最简单的方法。 通常情况下,您将发送诸如WM_GETTEXT之类的消息来查询目标窗口的当前显示内容。 为此,您需要获得包含您感兴趣的控件的确切窗口层次结构。例如,假设您想要读取编辑控件,您需要查看窗口层次结构中的父窗口。为了获得它的窗口句柄。

从内存中读取(高级)

这种方法到目前为止是最复杂的,但如果你能够完全逆向工程目标程序,那么最有可能获得一致的数据。 这种方法通过从目标进程中读取内存来工作。 这种技术是非常常用的游戏黑客添加“功能”,并观察游戏的内部状态。

考虑到以及在GUI中存储信息,程序经常保持其自己的所有数据的内部模型。 当使用的控件是虚拟的并且简单地查询要显示的数据的子集时,情况尤其如此。 这是前两种方法用处不大的情况的一个例子。 这些数据经常被保存在某种抽象数据类型中,比如列表或甚至数组。 诀窍是在内存中找到这个列表,并直接读取值。 这可以通过ReadProcessMemory在外部完成,也可以在内部通过DLL注入来完成。 困难主要在于两个先决条件:

  • 首先,您必须能够可靠地定位这些数据结构。 这个问题是代码不能保证在同一个地方,尤其是像ASLR这样的特性。 通俗地说,这有时被称为代码转换。 ASLR可以通过使用来自模块库的偏移量来抵消,并通过诸如GetmoduleeHandle之类的函数动态获取模块基址。 和ASLR一样,发生这种情况的原因是动态内存分配(例如通过malloc )。 在这种情况下,你将需要找到一个存储指针的堆地址(例如malloc的返回值),解除引用并找到你的列表。 那个指针很容易出现ASLR,而不是一个指针,它可能是一个双指针,三指针等等。
  • 你面对的第二个问题是,每个列表项都是一个基本类型是很少见的。 例如,而不是一个字符数组(字符串)的列表,你可能会面对一个对象列表。 您需要进一步对每个对象类型进行逆向工程,并了解内部布局(至少能够根据与对象库的偏移量来确定您感兴趣的原始值的偏移量)。 更高级的方法实际上是逆向工程对象的虚表 ,并调用其“API”。

您可能会注意到,我无法在此处提供具体的信息。 原因在于,从本质上讲,使用这种方法需要对目标内部进行深入的了解,因此,具体细节只能由目标的编程方式来确定。 除非你有逆向工程方面的知识和经验,否则你不可能想要走这条路。

挂钩目标的内部API(高级)

与上面的解决方案一样,不是挖掘数据结构,而是挖掘内部API。 我在早些时候讨论vtables时简单地介绍了这一点。 而不是这样做,你会试图找到GUI修改时调用的内部API。 通常情况下,当一个视图/用户界面被修改,而不是直接调用WinAPI来更新它,程序将有它自己的包装功能,它调用哪个又调用WinAPI。 你只需要找到这个函数并挂钩它。 这也是可能的,但需要逆向工程技能。 你可能会发现你发现了自己想要调用的函数。 在这种情况下,除了能够定位函数的位置之外,还必须对其所需的参数进行反向工程,调用约定,并且需要确保调用函数没有副作用。

我会认为这种方法是先进的。 这当然是可以做到的,而且是游戏黑客中用来观察内部状态和操纵目标行为的另一种常用技术,但是很难!


前两种方法非常适合从WinAPI程序读取数据,而且要容易得多。 后两种方法允许更大的灵活性。 有了足够的工作,你可以阅读目标封装的任何东西,但需要很多技能。

另一个值得关注的问题可能与您的案例相关,也可能与您的案例无关,那就是更新您的解决方案以便更新目标。 使用前两种方法,更有可能不需要做任何改变或者做小的改动。 使用第二种方法,即使是源代码的小改动也会导致您所依赖的偏移量的重新定位。 处理这个问题的一个方法是使用字节签名来动态生成偏移量。 我前一段时间写了另外一个答案 ,解决了这个问题。

我写的只是可以用来实现你想要的各种技术的简要总结。 我可能已经错过了方法,但是这些是我所知道并且有经验的最常见的方法。 既然这些都是大问题,我建议你问一个新的问题,如果你想获得更多的细节。 请注意,在我所讨论过的所有方法中,没有一个会受到外界可见的任何交互的影响,所以你不会有任何问题出现。 正如你所描述的那样,将是“沉默的”。


这是我从之前的回答中解脱出来的有关迂回/蹦床的信息,我写道:

如果您正在寻找程序绕开其他进程的执行方式,通常通过以下两种方式之一:

  • 动态(运行时)迂回 – 这是更常见的方法,是库如Microsoft Detours使用的 。 这里是一个相关的论文,其中一个函数的前几个字节被覆盖,无条件分支到仪器。
  • (静态)二进制重写 – 对于rootkit而言,这是一种不太常见的方法,但是被研究项目所使用。 它允许通过静态分析和覆盖二进制来执行绕行。 用于Windows的旧版(不公开的)软件包是Etch。 本文从概念上提供了一个高层次的概念。

尽管Detours展示了一种动态绕行的方法,但业界还是有无数的方法,特别是在逆向工程和黑客领域。 这些包括上面提到的IAT和断点方法。 为了“为您指出正确的方向”,您应该看看在研究项目和逆向工程领域进行的“研究”。