PROPagate:一种新的代码注入技巧介绍

桂林seo半杯酒博客

通常在不同的进程空间中执行代码会有很多种方法,最常见的方法有以下几种:

1.注入的DLL或系统级的钩子;

2.sideload模式;

3.执行远程线程;

4.APCs;

5.拦截和修改远程线程的线程上下文。

然后再通过Gapz/Powerloader代码注入(又名EWMI),AtomBombing或映射/不映射方法来利用NtClose补丁。

不过今天,我会在本文介绍一个一种新的代码注入技巧——PROPagate。

还记得2002左右发生的“粉碎”(shatter)攻击吗?UIPI是一种强制机制,它阻止向高级进程发送特定的windows事件消息。保护模式依靠UIPI来防止低级进程向更高级权限的进程发送潜在的恶意消息,这也就是所谓的“粉碎攻击”的原理。

在我看来,实施粉碎攻击不止有一种方法,下面我要描述的技巧更简单甚至不需要任何ROP。

在使用窗口子类化的系统上总是存在一类窗口,因为在子类化过程中,旧窗口过程被保留,而新窗口被显示在当前的窗口中。不过旧窗口并不会停止运行,而是把所有的显示信息都拦截下来隐藏在后台运行 。

“native”窗口子类化是使用SetWindowSubclass API完成的,当一个窗口被子类化时,它会获得一个存储在其内部结构中的新属性,并根据comctl32.dll的版本来命名名称:

版本6.x对应的名称是UxSubclassInfo;

版本5.x对应的名称是CC32SubclassInfo。

查看Windows资源管理器子窗口的属性,你可以看到其中很多都使用了这个特殊的子类属性:

可以这么说,几乎所有的Windows应用程序都是如此,包括OllyDbg:

当SetWindowSubclass被调用时,它使用SetProp API将这两个属性(UxSubclassInfo或CC32SubclassInfo)中的一个指向内存中的一个区域,其中旧的函数指针就被存储在该区域。当调用新的通信进程时,它将为给定的窗口调用GetProp API,一旦它被检索到,它就会被执行。

回想一下上述的粉碎攻击,我可以不使用SetWindowLong或SetClassLong来设置windows属于其他进程(通过GWL_WNDPROC或GCL_WNDPROC)的窗口地址。但是,SetProp函数不受此限制的影响。当涉及到低级进程时,窗口就会发出以下提示信息:

SetProp受 UIPI的限制,进程只能调用属于较低或相同级别的进程窗口上函数。当UIPI阻止属性更改时,GetLastError将返回5。

因此,如果你要在同一会话中讨论其他用户应用程序,就可以自由地修改其windows的属性,比如:

1.你可以自由地修改属于另一个进程的窗口的属性;

2.我们还知道一些属性指向内存区域,该区域存储的是子类窗口进程的旧地址;

3.地址指向的进程将在某个阶段执行。

应该说,这都是UxSubclassInfo/CC32SubclassInfo属性正在使用的结构。在检查SetProp在这些子类窗口的运行过程后,你会很快发现,旧的过程存储在该内存区域开头的偏移量0×18处。这个结构有点复杂,虽然它包含多个回调,但第一个回调出现在0×18处。

因此,将一个小的缓冲区注入到目标进程中,可以确保预期的结构被正确地填充并且指向有效载荷,然后改变相应的窗口属性以确保下一次窗口接收到消息时会执行有效载荷(这个过程可以通过发送消息来强制执行)。

当我发现这个技巧后,迅速编写了POC,该POC会用前面提到的属性枚举所有的窗口。对于发现的每个子类属性,我都会将其更改为随机值—,这样Windows资源管理器,Total Commander,Process Hacker,Ollydbg和其他一些应用程序就会立即崩溃。这代表所发现的技巧是正确的,然后我创建了一个非常小的shellcode,它会在桌面窗口上显示一个消息框,并在Windows 10(在正常帐户下)进行测试。

在第一个随机目标(这里是Total Commander)中调用shellcode的截图:

当然,它也适用于Windows资源管理器,这是它在执行时的截图:

如果我检查进程浏览器,就可以看到窗口属于explorer.exe:

在Windows XP系统上测试它,并向Windows资源管理器中注入shellcode,就会让每个窗口暴露出子类化属性的执行过程。

还有许多其他的通用属性可以以相同的方式来使用:

1.microsoftfoundation类库(MFC)使用“AfxOldWndProc423”属性来对其窗口进行子类化,

2.ControlOfs[HEX]属性与Delphi应用程序引用的内存可视化组件库(VCL)对象,

3.新的windows框架,例如Microsoft.Windows.WindowFactory.ViewId都需要更多的研究,

4.一些自定义控件使用“子类”时,我推断它们也可以以类似的方式进行修改,

5.一些公开了COM/OLE接口的属性,例如OleDropTargetInterface。