首页
社区
课程
招聘
[翻译]SetTcpEntry6 - 一个针对IPv6的自定义SetTcpEntry实现
发表于: 2022-2-15 15:06 12845

[翻译]SetTcpEntry6 - 一个针对IPv6的自定义SetTcpEntry实现

2022-2-15 15:06
12845

翻译

原文地址:https://www.x86matthew.com/view_post?id=settcpentry6

功能:一个针对IPv6的自定义SetTcpEntry实现


Windows有一个名为SetTcpEntry的函数,可以用来终止TCP表中的一个活动连接。这个函数只支持IPv4连接,目前还没有针对IPv6的对应函数。甚至微软自己的TCPView工具也不允许关闭IPv6连接。

我对原始的SetTcpEntry函数进行了逆向工程,并成功创建了一个自定义的SetTcpEntry6函数。这段代码可以在所有带有 "下一代TCP/IP栈"(Vista以上)的Windows版本上使用。Windows XP从一开始就不完全支持IPv6,所以这些函数在所有现实情况下都能按预期工作。

SetTcpEntry函数调用NsiSetAllParameters时使用了一个未记录的数据结构。我对这个结构进行了逆向工程,并将其标记为KillTcpSocketData_V4。我逆向工程的SetTcpEntry(IPv4)函数如下:

BYTE bGlobal_NPI_MS_TCP_MODULEID[] = { 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x4A, 0x00, 0xEB, 0x1A, 0x9B, 0xD4, 0x11, 0x91, 0x23, 0x00, 0x50, 0x04, 0x77, 0x59, 0xBC };

struct KillTcpSocketData_V4
{
	WORD wLocalAddressFamily;
	WORD wLocalPort;
	DWORD dwLocalAddr;
	BYTE bReserved1[20];

	WORD wRemoteAddressFamily;
	WORD wRemotePort;
	DWORD dwRemoteAddr;
	BYTE bReserved2[20];
};

DWORD KillTcpSocket_V4(MIB_TCPROW_OWNER_PID *pTcpRow)
{
	HMODULE hNsiModule = NULL;
	DWORD (WINAPI *pNsiSetAllParameters)(DWORD dwStatic, DWORD dwActionCode, LPVOID NPI_MS_MODULEID, DWORD dwIoMainCode, LPVOID lpNetInfoBuffer, DWORD SizeofNetInfoBuffer, LPVOID lpMetricBuffer, DWORD SizeofMetricBuffer) = NULL;
	KillTcpSocketData_V4 KillTcpSocketData;
	MIB_TCPROW_OWNER_PID SetTcpEntryTcpRow;

	// load nsi.dll module (vista onwards)
	hNsiModule = LoadLibrary("nsi.dll");
	if(hNsiModule != NULL)
	{
		// find NsiSetAllParameters function
		pNsiSetAllParameters = (unsigned long (__stdcall *)(unsigned long,unsigned long,void *,unsigned long,void *,unsigned long,void *,unsigned long))GetProcAddress(hNsiModule, "NsiSetAllParameters");
		if(pNsiSetAllParameters == NULL)
		{
			return 1;
		}
	}

	if(pNsiSetAllParameters == NULL)
	{
		// NsiSetAllParameters not found - call original SetTcpEntry function
		memcpy((void*)&SetTcpEntryTcpRow, (void*)pTcpRow, sizeof(SetTcpEntryTcpRow));
		SetTcpEntryTcpRow.dwState = MIB_TCP_STATE_DELETE_TCB;
		if(SetTcpEntry(&SetTcpEntryTcpRow) != 0)
		{
			return 1;
		}
	}
	else
	{
		// set socket data
		memset((void*)&KillTcpSocketData, 0, sizeof(KillTcpSocketData));
		KillTcpSocketData.wLocalAddressFamily = AF_INET;
		KillTcpSocketData.wLocalPort = (WORD)pTcpRow->dwLocalPort;
		KillTcpSocketData.dwLocalAddr = pTcpRow->dwLocalAddr;
		KillTcpSocketData.wRemoteAddressFamily = AF_INET;
		KillTcpSocketData.wRemotePort = (WORD)pTcpRow->dwRemotePort;
		KillTcpSocketData.dwRemoteAddr = pTcpRow->dwRemoteAddr;

		// kill socket
		if(pNsiSetAllParameters(1, 2, (LPVOID)bGlobal_NPI_MS_TCP_MODULEID, 16, (LPVOID)&KillTcpSocketData, sizeof(KillTcpSocketData), 0, 0) != 0)
		{
			return 1;
		}
	}

	return 0;
}


上面的函数实际上并不是必需的,因为现有的 SetTcpEntry 函数适用于所有版本的 Windows 上的 IPv4 sockets ,但它可以作为创建 IPv6 实现的起点。

在花了一些时间看了nsi.dll中其他与IPv6有关的函数后,我想出了以下代码:

BYTE bGlobal_NPI_MS_TCP_MODULEID[] = { 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x4A, 0x00, 0xEB, 0x1A, 0x9B, 0xD4, 0x11, 0x91, 0x23, 0x00, 0x50, 0x04, 0x77, 0x59, 0xBC };

struct KillTcpSocketData_V6
{
	WORD wLocalAddressFamily;
	WORD wLocalPort;
	BYTE bReserved1[4];
	BYTE bLocalAddr[16];
	DWORD dwLocalScopeID;

	WORD wRemoteAddressFamily;
	WORD wRemotePort;
	BYTE bReserved2[4];
	BYTE bRemoteAddr[16];
	DWORD dwRemoteScopeID;
};

DWORD KillTcpSocket_V6(MIB_TCP6ROW_OWNER_PID *pTcpRow)
{
	HMODULE hNsiModule = NULL;
	DWORD (WINAPI *pNsiSetAllParameters)(DWORD dwStatic, DWORD dwActionCode, LPVOID NPI_MS_MODULEID, DWORD dwIoMainCode, LPVOID lpNetInfoBuffer, DWORD SizeofNetInfoBuffer, LPVOID lpMetricBuffer, DWORD SizeofMetricBuffer) = NULL;
	KillTcpSocketData_V6 KillTcpSocketData;

	// load nsi.dll module (vista onwards)
	hNsiModule = LoadLibrary("nsi.dll");
	if(hNsiModule != NULL)
	{
		// find NsiSetAllParameters function
		pNsiSetAllParameters = (unsigned long (__stdcall *)(unsigned long,unsigned long,void *,unsigned long,void *,unsigned long,void *,unsigned long))GetProcAddress(hNsiModule, "NsiSetAllParameters");
		if(pNsiSetAllParameters == NULL)
		{
			return 1;
		}
	}

	if(pNsiSetAllParameters == NULL)
	{
		// NsiSetAllParameters not found (win XP or earlier - ipv6 not supported)
		return 1;
	}

	// set socket data
	memset((void*)&KillTcpSocketData, 0, sizeof(KillTcpSocketData));
	KillTcpSocketData.wLocalAddressFamily = AF_INET6;
	KillTcpSocketData.wLocalPort = (WORD)pTcpRow->dwLocalPort;
	memcpy((void*)KillTcpSocketData.bLocalAddr, (void*)pTcpRow->ucLocalAddr, sizeof(KillTcpSocketData.bLocalAddr));
	KillTcpSocketData.dwLocalScopeID = pTcpRow->dwLocalScopeId;
	KillTcpSocketData.wRemoteAddressFamily = AF_INET6;
	KillTcpSocketData.wRemotePort = (WORD)pTcpRow->dwRemotePort;
	memcpy((void*)KillTcpSocketData.bRemoteAddr, (void*)pTcpRow->ucRemoteAddr, sizeof(KillTcpSocketData.bRemoteAddr));
	KillTcpSocketData.dwRemoteScopeID = pTcpRow->dwRemoteScopeId;

	// kill socket
	if(pNsiSetAllParameters(1, 2, (LPVOID)bGlobal_NPI_MS_TCP_MODULEID, 16, (LPVOID)&KillTcpSocketData, sizeof(KillTcpSocketData), 0, 0) != 0)
	{
		return 1;
	}

	return 0;
}



我已经在从Vista到最新版本的Windows 10的所有版本上测试了我的KillTcpSocket_V6功能,结果是成功的。



[课程]Android-CTF解题方法汇总!

收藏
免费 2
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//