飘云阁

 找回密码
 加入我们

QQ登录

只需一步,快速开始

查看: 1425|回复: 0

[C/C++] SetTcpEntry6 - 一个针对IPv6的自定义SetTcpEntry实现

[复制链接]
  • TA的每日心情
    开心
    2019-3-15 11:00
  • 签到天数: 262 天

    [LV.8]以坛为家I

    发表于 2022-2-15 15:09:11 | 显示全部楼层 |阅读模式
    翻译
    原文地址: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)函数如下:
    1. 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 };

    2. struct KillTcpSocketData_V4
    3. {
    4.         WORD wLocalAddressFamily;
    5.         WORD wLocalPort;
    6.         DWORD dwLocalAddr;
    7.         BYTE bReserved1[20];

    8.         WORD wRemoteAddressFamily;
    9.         WORD wRemotePort;
    10.         DWORD dwRemoteAddr;
    11.         BYTE bReserved2[20];
    12. };

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

    19.         // load nsi.dll module (vista onwards)
    20.         hNsiModule = LoadLibrary("nsi.dll");
    21.         if(hNsiModule != NULL)
    22.         {
    23.                 // find NsiSetAllParameters function
    24.                 pNsiSetAllParameters = (unsigned long (__stdcall *)(unsigned long,unsigned long,void *,unsigned long,void *,unsigned long,void *,unsigned long))GetProcAddress(hNsiModule, "NsiSetAllParameters");
    25.                 if(pNsiSetAllParameters == NULL)
    26.                 {
    27.                         return 1;
    28.                 }
    29.         }

    30.         if(pNsiSetAllParameters == NULL)
    31.         {
    32.                 // NsiSetAllParameters not found - call original SetTcpEntry function
    33.                 memcpy((void*)&SetTcpEntryTcpRow, (void*)pTcpRow, sizeof(SetTcpEntryTcpRow));
    34.                 SetTcpEntryTcpRow.dwState = MIB_TCP_STATE_DELETE_TCB;
    35.                 if(SetTcpEntry(&SetTcpEntryTcpRow) != 0)
    36.                 {
    37.                         return 1;
    38.                 }
    39.         }
    40.         else
    41.         {
    42.                 // set socket data
    43.                 memset((void*)&KillTcpSocketData, 0, sizeof(KillTcpSocketData));
    44.                 KillTcpSocketData.wLocalAddressFamily = AF_INET;
    45.                 KillTcpSocketData.wLocalPort = (WORD)pTcpRow->dwLocalPort;
    46.                 KillTcpSocketData.dwLocalAddr = pTcpRow->dwLocalAddr;
    47.                 KillTcpSocketData.wRemoteAddressFamily = AF_INET;
    48.                 KillTcpSocketData.wRemotePort = (WORD)pTcpRow->dwRemotePort;
    49.                 KillTcpSocketData.dwRemoteAddr = pTcpRow->dwRemoteAddr;

    50.                 // kill socket
    51.                 if(pNsiSetAllParameters(1, 2, (LPVOID)bGlobal_NPI_MS_TCP_MODULEID, 16, (LPVOID)&KillTcpSocketData, sizeof(KillTcpSocketData), 0, 0) != 0)
    52.                 {
    53.                         return 1;
    54.                 }
    55.         }

    56.         return 0;
    57. }
    复制代码


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

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

    1. 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 };

    2. struct KillTcpSocketData_V6
    3. {
    4.         WORD wLocalAddressFamily;
    5.         WORD wLocalPort;
    6.         BYTE bReserved1[4];
    7.         BYTE bLocalAddr[16];
    8.         DWORD dwLocalScopeID;

    9.         WORD wRemoteAddressFamily;
    10.         WORD wRemotePort;
    11.         BYTE bReserved2[4];
    12.         BYTE bRemoteAddr[16];
    13.         DWORD dwRemoteScopeID;
    14. };

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

    20.         // load nsi.dll module (vista onwards)
    21.         hNsiModule = LoadLibrary("nsi.dll");
    22.         if(hNsiModule != NULL)
    23.         {
    24.                 // find NsiSetAllParameters function
    25.                 pNsiSetAllParameters = (unsigned long (__stdcall *)(unsigned long,unsigned long,void *,unsigned long,void *,unsigned long,void *,unsigned long))GetProcAddress(hNsiModule, "NsiSetAllParameters");
    26.                 if(pNsiSetAllParameters == NULL)
    27.                 {
    28.                         return 1;
    29.                 }
    30.         }

    31.         if(pNsiSetAllParameters == NULL)
    32.         {
    33.                 // NsiSetAllParameters not found (win XP or earlier - ipv6 not supported)
    34.                 return 1;
    35.         }

    36.         // set socket data
    37.         memset((void*)&KillTcpSocketData, 0, sizeof(KillTcpSocketData));
    38.         KillTcpSocketData.wLocalAddressFamily = AF_INET6;
    39.         KillTcpSocketData.wLocalPort = (WORD)pTcpRow->dwLocalPort;
    40.         memcpy((void*)KillTcpSocketData.bLocalAddr, (void*)pTcpRow->ucLocalAddr, sizeof(KillTcpSocketData.bLocalAddr));
    41.         KillTcpSocketData.dwLocalScopeID = pTcpRow->dwLocalScopeId;
    42.         KillTcpSocketData.wRemoteAddressFamily = AF_INET6;
    43.         KillTcpSocketData.wRemotePort = (WORD)pTcpRow->dwRemotePort;
    44.         memcpy((void*)KillTcpSocketData.bRemoteAddr, (void*)pTcpRow->ucRemoteAddr, sizeof(KillTcpSocketData.bRemoteAddr));
    45.         KillTcpSocketData.dwRemoteScopeID = pTcpRow->dwRemoteScopeId;

    46.         // kill socket
    47.         if(pNsiSetAllParameters(1, 2, (LPVOID)bGlobal_NPI_MS_TCP_MODULEID, 16, (LPVOID)&KillTcpSocketData, sizeof(KillTcpSocketData), 0, 0) != 0)
    48.         {
    49.                 return 1;
    50.         }

    51.         return 0;
    52. }
    复制代码

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

    PYG19周年生日快乐!
    您需要登录后才可以回帖 登录 | 加入我们

    本版积分规则

    快速回复 返回顶部 返回列表