ShadowMove复现与思考

简介

前段时间有几位老哥联名发了一篇论文,这篇论文描述了一种复制套接字劫持网络连接的技术,本文旨在于简单分析复现这种技术,如有错误欢迎指正。

作者给出的理论图如下,通过创建两个基于原套接字复制的套接字,定期挂起原套接字接收和响应特殊的数据包。

复现过程

尽管windows本身提供了WSADuplicateSocket函数,但是这个函数需要本地进程的socks句柄,而句柄只在本地进程才有意义,这篇文章的作者提出了一种从远程复制句柄技术的变体。

作者发现套接字的句柄等同于的名为\Device\Afd文件句柄,这个句柄可以直接视为socks使用(虽然就是同一个,但说还是这么说),我们可以通过常规的句柄枚举技术从远程进程得到它,然后使用NtDuplicateObject函数将它复制到本地进程,本地进程再通过WSADuplicateSocket获取克隆套接字需要的参数,然后我们可以像使用自己的socket一样使用这个克隆过来的socket了。

在github有0xcpu师傅分享了一份ShadowMove的代码,这里我做了一点简化。

首先师傅获取了系统的所有句柄。

获取句柄之后将所有句柄克隆到了当前进程(句柄只有在本地进程才有意义),对这个句柄的类型做了一个判断。(这里我简单的做了一个优化,作者的源代码是判断所有句柄类型不等于0x28的句柄,其实所有\drivice\开头的文件句柄都是OB_TYPE_DEVICE, // 25,设备类型)。

随后比较简单的通过NtQueryObject函数查询句柄描述对象的部分属性,我们知道windows系统是对象驱动的,而在三环描述对象的是句柄,我们可以通过句柄查询一下句柄所描述对象的属性,这里查询了对象的设备描述符。

最后这个师傅就直接开始复制套接字。

完整代码

复现和思考

这种技术理论上只能应用于明文传输的协议,如Telnet、ftp,劫持连接后我们通常能直接掠过身份认证的过程,这里我们起一个nc的bash控制口做一个测试。

我们先在kali上起一个服务端,然后使用nc去连接。

之后运行我们的poc,由于套接字的处理是异步的,我们需要另起一个线程去发送命令,然后使用主线程接收。

可以看到主副socket都接收到了命令的结果,如果我们不想要主套接字接收到,我们可以直接挂起或者干掉它来接管这个网络连接。

原文如下:

最后更新于

这有帮助吗?