https://blog.youkuaiyun.com/qq_38493448/article/details/104007711?utm_medium=distribute.pc_feed_404.none-task-blog-searchFromBaidu-8.nonecase&depth_1-utm_source=distribute.pc_feed_404.none-task-blog-searchFromBaidu-8.nonecas
Windows Ring3层注入——LSP劫持注入(SPI网络过滤器注入)(八)
LSP劫持注入知识背景
LSP劫持注入注入原理
LSP劫持注入实现步骤
LSP劫持注入相关代码
LSP劫持注入知识背景
LSP(Layered Service Provider ,分层服务提供者):
LSP是一个安装在winsock目录中的DLL程序。
应用程序通过winsock2进行网络通信时,会调用ws2_32.dll的导出函数(如connect、accept等)。而后端通过LSP实现这些函数的底层,简单来说就是调用winsock2提供的函数时会调用对应的LSP提供的SPI函数.
SPI(Service Provider Interface,服务器提供者接口):
SPI是由分层服务提供者(LSP)导出的供ws2_32.dll调用的系列函数。
SPI是Winsock2提供的一项新特性,通过它可以借助实现一个LSP对现有的传输服务提供者进行扩展。
Winsock2 SPI支持用户提供传输者和名称空间两种类型的服务提供者。
在这里插入图片描述
LSP劫持注入注入原理
1.因为Winsock服务体系符合Windows开放服务体系,所以它支持第三方服务提供者插入到其中。
2.只要上层和下层的边缘支持Winsock2 SPI,即可向他们中间安装第三方提供者程序。
3.普通开发者一般都是开发SPI的LSP(分层服务提供者),即第三方提供者,可用于监控Winsock API执行,
HOOK Winsock API,甚至利用LSP技术注入DLL。
4.基础协议(TCP、UDP、原始)的提供者其实就是DLL,编写分层协议提供者就是在编写DLL,然后安装在Winsock目录上,让系统上的所有使用基础协议的网络程序调用。
LSP注入的原理大概可以概括为只要将我们编写的LSP DLL安装到系统网络协议链中,那么所有基于Winsock实现的程序都会主动加载我们的LSP DLL。我们可以利用这个特点实现对网络功能的进程的注入。
在这里插入图片描述
LSP劫持注入实现步骤
系统有一个默认的LSP,就是mswsock.dll,在自己的LSP的WSPStartup中,只要找到上层接口 (如果没有其他LSP,那么实际上就是mswsock.dll接口)并调用即可。
我们根据LSP的原理分析可知,要实现LSP的注入,大概是如下两个步骤:
1.编写一个导出WSPStartup()函数的LSP DLL。
2.编写一个安装程序,把我们编写好的LSP安装到上图体系结构中。
LIBRARY MinWinsockSpi
DESCRIPTION “Implements a layered service provider for TCP”
EXPORTS WSPStartup
**LSP安装方法:**把安装的SPI模块信息写到注册表如下位置
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\WinSock2\Parameters\Protocol_Catalog9\Catalog_Entries\000000000001
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\WinSock2\Parameters\Protocol_Catalog9\Catalog_Entries\000000000002
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\WinSock2\Parameters\Protocol_Catalog9\Catalog_Entries\000000000003
安装完毕,每个需要加载网络模块的进程都会加载我们的SPI模块,这样就成功实现了注入。进一步完善SPI DLL接口,就可以直接对网络数据进行控制了。
// 要安装的LSP的硬编码,在移除的时候还要使用它
GUID ProviderGuid = {
0xd3c21122, 0x85e1, 0x48f3, {
0x9a,0xb6,0x23,0xd9,0x0c,0x73,0x07,0xef}};
LPWSAPROTOCOL_INFOW GetProvider(LPINT lpnTotalProtocols)
{
DWORD dwSize = 0;
int nError;
LPWSAPROTOCOL_INFOW pProtoInfo = NULL;
// 取得需要的长度
if(::WSCEnumProtocols(NULL, pProtoInfo, &dwSize, &nError) == SOCKET_ERROR)
{
if(nError != WSAENOBUFS)
return NULL;
}
pProtoInfo = (LPWSAPROTOCOL_INFOW)::GlobalAlloc(GPTR, dwSize);
*lpnTotalProtocols = ::WSCEnumProtocols(NULL, pProtoInfo, &dwSize, &nError);
return pProtoInfo;
}
void FreeProvider(LPWSAPROTOCOL_INFOW pProtoInfo)
{
::GlobalFree(pProtoInfo);
}
// 将LSP安装到UDP协议提供者之上
int InstallProvider(WCHAR *wszDllPath)
{