因为已从原单位离职,复现的环境也已经丢失,再加上也没怎么提交过漏洞,导致上传cnvd失败,故发在此处,万一有用的话,有缘人可自行提交漏洞库。
(一) 环境
组态软件IP地址:192.168.0.189
PLC IP:192.168.0.70
(二) 原理
组态软件MaView中有一个进程windowsRTE.exe,它在udp端口20181(也有可能是20281端口,忘记了)监听,并与plc通信和交互数据:
通过调试,发现该端口的数据包头格式可以定义如下:
typedef struct
{
USHORT Version; //0
UCHAR CmdType; //2
UCHAR PkgSeq; //3
DWORD unused; //4
ULONGLONG CycleID; //8
UINT BeatCount; //16
USHORT PkgID; //20
USHORT PkgCount; //22
UINT PkgBodyLen; //24
}UDPPRESLAYERHEAD;
通过跟踪WindowsRTE.exe模块中的函数0x0048C27B(UdpRecv),发现数据包字段的处理存在逻辑漏洞,拷贝时有可能导致缓冲区溢出。
0x0048C27B函数详细代码如下:
INT __cdecl UdpRecv(INT servSocket, char *recvBuff)
{
INT result; // eax@2
char *v3; // eax@11
char *v4; // eax@11
INT v5; // ebx@11
char *v6; // eax@11
INT v7; // ebx@11
char *v8; // eax@11
int v9; // edx@19
int v10; // edx@28
int v11; // edx@37
int v12; // edx@48
int v13; // edx@57
int v14; // edx@66
int v15; // edx@75
CHAR cfgIP[16]; // [sp+3Bh] [bp-11Dh]@11
CHAR recvIP[16]; // [sp+4Bh] [bp-10Dh]@11
UCHAR iosrIPCount; // [sp+5Bh] [bp-FDh]@6
SOCKADDR_IN cfgClntSocketAddr; // [sp+5Ch] [bp-FCh]@11
INT recvClntSockAddrSize; // [sp+6Ch] [bp-ECh]@1
SOCKADDR_IN recvClntSocketAddr; // [sp+70h] [bp-E8h]@3
INT err; // [sp+80h] [bp-D8h]@99
UINT pkgBodyLen; // [sp+84h] [bp-D4h]@19
_DWORD cycleID[3]; // [sp+88h] [bp-D0h]@19
UCHAR pkgSeq; // [sp+95h] [bp-C3h]@19
USHORT pkgID; // [sp+96h] [bp-C2h]@19
USHORT pkgCount; // [sp+98h] [bp-C0h]@19
USHORT version; // [sp+9Ah] [bp-BEh]@19
UINT pkgBodyLen_0; // [sp+9Ch] [bp-BCh]@28
_DWORD cycleID_0[3]; // [sp+A0h] [bp-B8h]@28
UCHAR pkgSeq_0; // [sp+ADh] [bp-ABh]@28
USHORT pkgID_0; // [sp+AEh] [bp-AAh]@28
USHORT pkgCount_0; // [sp+B0h] [bp-A8h]@28
USHORT version_0; // [sp+B2h] [bp-A6h]@28
UINT pkgBodyLen_1; // [sp+B4h] [bp-A4h]@37
_DWORD cycleID_1[3]; // [sp+B8h] [bp-A0h]@37
UCHAR pkgSeq_1; // [sp+C5h] [bp-93h]@37
USHORT pkgID_1; // [sp+C6h] [bp-92h]@37
USHORT pkgCount_1; // [sp+C8h] [bp-90h]@37
USHORT version_1; // [sp+CAh] [bp-8Eh]@37
UINT pkgBodyLen_2; // [sp+CCh] [bp-8Ch]@48
_DWORD cycleID_2[3]; // [sp+D0h] [bp-88h]@48
UCHAR pkgSeq_2; // [sp+DDh] [bp-7Bh]@48
USHORT pkgID_2; // [sp+DEh] [bp-7Ah]@48
USHORT pkgCount_2; // [sp+E0h] [bp-78h]@48
USHORT version_2; // [sp+E2h] [bp-76h]@48
UINT pkgBodyLen_3; // [sp+E4h] [bp-74h]@57
_DWORD cycleID_3[3]; // [sp+E8h] [bp-70h]@57
UCHAR pkgSeq_3; // [sp+F5h] [bp-63h]@57
USHORT pkgID_3; // [sp+F6h] [bp-62h]@57
USHORT pkgCount_3; // [sp+F8h] [bp-60h]@57
USHORT version_3; // [sp+FAh] [bp-5Eh]@57
UINT pkgBodyLen_4; // [sp+FCh] [bp-5Ch]@66
_DWORD cycleID_4[3]; // [sp+100h] [bp-58h]@66
UCHAR pkgSeq_4; // [sp+10Dh] [bp-4Bh]@66
USHORT pkgID_4; // [sp+10Eh] [bp-4Ah]@66
USHORT pkgCount_4; // [sp+110h] [bp-48h]@66
USHORT version_4; // [sp+112h] [bp-46h]@66
UINT pkgBodyLen_5; // [sp+114h] [bp-44h]@75
_DWORD cycleID_5[3]; // [sp+118h] [bp-40h]@75
UCHAR pkgSeq_5; // [sp+127h] [bp-31h]@75
USHORT pkgID_5; // [sp+128h] [bp-30h]@75
USHORT pkgCount_5; // [sp+12Ah] [bp-2Eh]@75
USHORT version_5; // [sp+12Ch] [bp-2Ch]@75
UCHAR cmdType; // [sp+12Fh] [bp-29h]@18
UDP_PRESLAYER_HEAD *udpPresLayerHead; // [sp+130h] [bp-28h]@18
INT recvIpLen; // [sp+134h] [bp-24h]@10
INT cfgIpLen; // [sp+138h] [bp-20h]@10
INT clntIP; // [sp+13Ch] [bp-1Ch]@10
INT i; // [sp+140h] [bp-18h]@1
INT iRead; // [sp+144h] [bp-14h]@1
INT isIPExist; // [sp+148h] [bp-10h]@10
INT ii; // [sp+14Ch] [bp-Ch]@10
iRead = -1;
i = 0;
recvClntSockAddrSize = 16;
if ( iosrvServSock == -1 )
{
KyldLog(1, 3, "UdpRecv:servSocket is not ctreated.\n");
result = 2;
}
else
{
memset(iosrvRecvBuff, 0, 0x514u);
iRead = recvfrom(
iosrvServSock,
iosrvRecvBuff,
1300,
0,
(struct sockaddr *)&recvClntSocketAddr,
&recvClntSockAddrSize);
if ( iRead <= 0 )
{
LABEL_98:
if ( iRead >= 0 )
{
if ( iRead )
{
result = 1;
}
else
{
KyldLog(1, 3, "UdpRecv:ERROR!!! ioser disconnect ,or network disconnect\n");
IosrComVarInit();
SetIosrComStatus(-1);
result = 1;
}
}
else
{
err = GetLastError();
if ( err != 4 && err != 140 && err != 10035 )
{
if ( err == 10054 )
KyldLog(
1,
3,
"UdpRecv: ERROR!!! ioserver disconnect abnormally,remote close forcibly .:iRead=%d,errno=%d\n",
iRead,
10054);
else
KyldLog(1, 3, "UdpRecv: read ERROR!!!:iRead=%d,errno=%d\n", iRead, err);
IosrComVarInit();
SetIosrComStatus(-1);
result = 2;
}
else
{
result = 1;
}
}
}
else
{
iosrvClntAddr = recvClntSocketAddr;
iosrvClntAddrSize = recvClntSockAddrSize;
isRecvTimerActived = 1;
recvTimeOut = 10000;
SetIosrComStatus(0);
if ( recvBuff )
{
iosrIPCount = 0;
memset(gIosrIpSets, 0, 0x190u);
if ( IO_GetIOSvrNetIp(gIosrIpSets, &iosrIPCount) )
{
KyldLog(1, 3, "UdpRecv:IO_GetIOSvrNetIp fail,ioser can not communicate.\n");
result = 2;
}
else if ( iosrIPCount )
{
isIPExist = 0;
clntIP = 0;
cfgIpLen = 0;
recvIpLen = 0;
for ( ii = 0; ii < iosrIPCount; ++ii )
{
memset(recvIP, 0, 0x10u);
memset(cfgIP, 0, 0x10u);
cfgClntSocketAddr.sin_addr.S_un.S_addr = gIosrIpSets[ii];
v3 = inet_ntoa(cfgClntSocketAddr.sin_addr);
cfgIpLen = strlen(v3);
v4 = inet_ntoa(recvClntSocketAddr.sin_addr);
recvIpLen = strlen(v4);
v5 = recvIpLen;
v6 = inet_ntoa(recvClntSocketAddr.sin_addr);
memcpy(recvIP, v6, v5);
v7 = cfgIpLen;
v8 = inet_ntoa(cfgClntSocketAddr.sin_addr);
memcpy(cfgIP, v8, v7);
KyldLog(
1,
1,
"UdpRecv:IO_GetIOSvrNetIp success,iosrIPCount=%d,i=%d,recvIP=%s,cfgIP=%s,cfgIpLen=%d,recvIPLen=%d.\n",
iosrIPCount,
ii,
recvIP,
cfgIP,
cfgIpLen,
recvIpLen);
if ( !strncmp(recvIP, cfgIP, cfgIpLen) && cfgIpLen == recvIpLen )
{
isIPExist = 1;
break;
}
}
if ( isIPExist == 1 )
{
KyldLog(1, 1, "UdpRecv:IO_GetIOSvrNetIp,ip(%s) is legal,communication normal.\n", recvIP);
udpPresLayerHead = (UDP_PRESLAYER_HEAD *)iosrvRecvBuff;
cmdType = iosrvRecvBuff[2];
switch ( cmdType )
{
case 1u:
version = udpPresLayerHead->Version;
pkgCount = udpPresLayerHead->PkgCount;
pkgID = udpPresLayerHead->PkgID;
pkgSeq = udpPresLayerHead->PkgSeq;
v9 = HIDWORD(udpPresLayerHead->CycleID);
cycleID[0] = udpPresLayerHead->CycleID;
cycleID[1] = v9;
pkgBodyLen = udpPresLayerHead->PkgBodyLen;
if ( pkgBodyLen <= 0x400 )
{
if ( pkgCount )
{
memcpy(&iosrvDiagRequestTable + 1024 * (pkgID - 1), &iosrvRecvBuff[32], pkgBodyLen);
if ( ++diagRequestPkgCount == 1 )
{
isDiagRequestTimerActived = 1;
diagRequestTimeOut = 100;
}
if ( pkgCount != diagRequestPkgCount )
goto LABEL_84;
KyldLog(1, 1, "UdpRecv:ioserver recv diag request.\n");
diagRequestPkgCount = 0;
isDiagRequestTimerActived = 0;
diagRequestTimeOut = 100;
result = 32;
}
else
{
KyldLog(1, 3, "UdpRecv:CmdIosrDiagRequest,ERROR!!!pkgCount<=0,pkgCount=%d\n", 0);
result = 2;
}
}
else
{
KyldLog(
1,
3,
"UdpRecv:CmdIosrDiagRequest,ERROR!!!pkgBodyLen > SUB_PKG_SIZE_MAX,pkgBodyLen=%d\n",
pkgBodyLen);
result = 2;
}
break;
case 3u:
if ( GetStateMorS() != 1 )
goto LABEL_84;
KyldLog(1, 1, "UdpRecv:CmdIosrDataRequest,line=%d\n", 1591);
version_0 = udpPresLayerHead->Version;
pkgCount_0 = udpPresLayerHead->PkgCount;
pkgID_0 = udpPresLayerHead->PkgID;
pkgSeq_0 = udpPresLayerHead->PkgSeq;
v10 = HIDWORD(udpPresLayerHead->CycleID);
cycleID_0[0] = udpPresLayerHead->CycleID;
cycleID_0[1] = v10;
pkgBodyLen_0 = udpPresLayerHead->PkgBodyLen;
if ( pkgBodyLen_0 <= 0x400 )
{
if ( pkgCount_0 )
{
memcpy(&iosrvDataRequestTable + 1024 * (pkgID_0 - 1), &iosrvRecvBuff[32], pkgBodyLen_0);
if ( ++dataRequestPkgCount == 1 )
{
isDataRequestTimerActived = 1;
dataRequestTimeOut = 100;
}
if ( pkgCount_0 != dataRequestPkgCount )
goto LABEL_84;
KyldLog(1, 1, "UdpRecv:ioserver recv data request.\n");
dataRequestPkgCount = 0;
isDataRequestTimerActived = 0;
dataRequestTimeOut = 100;
result = 33;
}
else
{
KyldLog(1, 3, "UdpRecv:CmdIosrDataRequest,ERROR!!!pkgCount<=0,pkgCount=%d\n", 0);
result = 2;
}
}
else
{
KyldLog(
1,
3,
"UdpRecv:CmdIosrDataRequest,ERROR!!!pkgBodyLen > SUB_PKG_SIZE_MAX,pkgBodyLen=%d\n",
pkgBodyLen_0);
result = 2;
}
break;
case 5u:
if ( GetStateMorS() != 1 )
goto LABEL_84;
KyldLog(1, 1, "UdpRecv:CmdIosrDataResend,line=%d\n", 1640);
version_1 = udpPresLayerHead->Version;
pkgCount_1 = udpPresLayerHead->PkgCount;
pkgID_1 = udpPresLayerHead->PkgID;
pkgSeq_1 = udpPresLayerHead->PkgSeq;
v11 = HIDWORD(udpPresLayerHead->CycleID);
cycleID_1[0] = udpPresLayerHead->CycleID;
cycleID_1[1] = v11;
pkgBodyLen_1 = udpPresLayerHead->PkgBodyLen;
if ( pkgBodyLen_1 <= 0x400 )
{
if ( pkgCount_1 )
{
memcpy(&iosrvDataResendTable + 1024 * (pkgID_1 - 1), &iosrvRecvBuff[32], pkgBodyLen_1);
if ( ++dataResendPkgCount == 1 )
{
isDataResendTimerActived = 1;
dataResendTimeOut = 100;
}
if ( pkgCount_1 != dataResendPkgCount )
goto LABEL_84;
dataResendPkgCount = 0;
isDataResendTimerActived = 0;
dataResendTimeOut = 100;
result = 34;
}
else
{
KyldLog(1, 3, "UdpRecv:CmdIosrDataResend,ERROR!!!pkgCount<=0,pkgCount=%d\n", 0);
result = 2;
}
}
else
{
KyldLog(
1,
3,
"UdpRecv:CmdIosrDataResend,ERROR!!!pkgBodyLen > SUB_PKG_SIZE_MAX,pkgBodyLen=%d\n",
pkgBodyLen_1);
result = 2;
}
break;
case 4u:
if ( GetStateMorS() != 1 )
goto LABEL_84;
result = 39;
break;
case 6u:
if ( GetStateMorS() != 1 )
goto LABEL_84;
KyldLog(1, 1, "UdpRecv:CmdIosrItemRead,line=%d\n", 1702);
version_2 = udpPresLayerHead->Version;
pkgCount_2 = udpPresLayerHead->PkgCount;
pkgID_2 = udpPresLayerHead->PkgID;
pkgSeq_2 = udpPresLayerHead->PkgSeq;
v12 = HIDWORD(udpPresLayerHead->CycleID);
cycleID_2[0] = udpPresLayerHead->CycleID;
cycleID_2[1] = v12;
pkgBodyLen_2 = udpPresLayerHead->PkgBodyLen;
if ( pkgBodyLen_2 <= 0x400 )
{
if ( pkgCount_2 )
{
memcpy(&iosrvItemReadTable + 1024 * (pkgID_2 - 1), &iosrvRecvBuff[32], pkgBodyLen_2);
if ( ++itemReadPkgCount == 1 )
{
isItemReadTimerActived = 1;
itemReadTimeOut = 100;
}
if ( pkgCount_2 != itemReadPkgCount )
goto LABEL_84;
itemReadPkgCount = 0;
isItemReadTimerActived = 0;
itemReadTimeOut = 100;
result = 35;
}
else
{
KyldLog(1, 3, "UdpRecv:CmdIosrItemRead,ERROR!!!pkgCount<=0,pkgCount=%d\n", 0);
result = 2;
}
}
else
{
KyldLog(
1,
3,
"UdpRecv:CmdIosrItemRead,ERROR!!!pkgBodyLen > SUB_PKG_SIZE_MAX,pkgBodyLen=%d\n",
pkgBodyLen_2);
result = 2;
}
break;
case 7u:
if ( GetStateMorS() != 1 )
goto LABEL_84;
KyldLog(1, 1, "UdpRecv:CmdIosrItemWrite,line=%d\n", 1750);
version_3 = udpPresLayerHead->Version;
pkgCount_3 = udpPresLayerHead->PkgCount;
pkgID_3 = udpPresLayerHead->PkgID;
pkgSeq_3 = udpPresLayerHead->PkgSeq;
v13 = HIDWORD(udpPresLayerHead->CycleID);
cycleID_3[0] = udpPresLayerHead->CycleID;
cycleID_3[1] = v13;
pkgBodyLen_3 = udpPresLayerHead->PkgBodyLen;
if ( pkgBodyLen_3 <= 0x400 )
{
if ( pkgCount_3 )
{
memcpy(&iosrvItemWriteTable + 1024 * (pkgID_3 - 1), &iosrvRecvBuff[32], pkgBodyLen_3);
if ( ++itemWritePkgCount == 1 )
{
isItemWriteTimerActived = 1;
itemWriteTimeOut = 100;
}
if ( pkgCount_3 != itemWritePkgCount )
goto LABEL_84;
itemWritePkgCount = 0;
isItemWriteTimerActived = 0;
itemWriteTimeOut = 100;
result = 36;
}
else
{
KyldLog(1, 3, "UdpRecv:CmdIosrItemWrite,ERROR!!!pkgCount<=0,pkgCount=%d\n", 0);
result = 2;
}
}
else
{
KyldLog(
1,
3,
"UdpRecv:CmdIosrItemWrite,ERROR!!!pkgBodyLen > SUB_PKG_SIZE_MAX,pkgBodyLen=%d\n",
pkgBodyLen_3);
result = 2;
}
break;
case 8u:
if ( GetStateMorS() != 1 )
goto LABEL_84;
KyldLog(1, 1, "UdpRecv:CmdIosrItemForce,line=%d\n", 1798);
version_4 = udpPresLayerHead->Version;
pkgCount_4 = udpPresLayerHead->PkgCount;
pkgID_4 = udpPresLayerHead->PkgID;
pkgSeq_4 = udpPresLayerHead->PkgSeq;
v14 = HIDWORD(udpPresLayerHead->CycleID);
cycleID_4[0] = udpPresLayerHead->CycleID;
cycleID_4[1] = v14;
pkgBodyLen_4 = udpPresLayerHead->PkgBodyLen;
if ( pkgBodyLen_4 <= 0x400 )
{
if ( pkgCount_4 )
{
memcpy(&iosrvItemForceTable + 1024 * (pkgID_4 - 1), &iosrvRecvBuff[32], pkgBodyLen_4);
if ( ++itemForcePkgCount == 1 )
{
isItemForceTimerActived = 1;
itemForceTimeOut = 100;
}
if ( pkgCount_4 != itemForcePkgCount )
goto LABEL_84;
itemForcePkgCount = 0;
isItemForceTimerActived = 0;
itemForceTimeOut = 100;
result = 37;
}
else
{
KyldLog(1, 3, "UdpRecv:CmdIosrItemForce,ERROR!!!pkgCount<=0,pkgCount=%d\n", 0);
result = 1;
}
}
else
{
KyldLog(
1,
3,
"UdpRecv:CmdIosrItemForce,ERROR!!!pkgBodyLen > SUB_PKG_SIZE_MAX,pkgBodyLen=%d\n",
pkgBodyLen_4);
result = 2;
}
break;
case 9u:
if ( GetStateMorS() != 1 )
goto LABEL_84;
KyldLog(1, 1, "UdpRecv:CmdIosrItemForceCancel,line=%d\n", 1846);
version_5 = udpPresLayerHead->Version;
pkgCount_5 = udpPresLayerHead->PkgCount;
pkgID_5 = udpPresLayerHead->PkgID;
pkgSeq_5 = udpPresLayerHead->PkgSeq;
v15 = HIDWORD(udpPresLayerHead->CycleID);
cycleID_5[0] = udpPresLayerHead->CycleID;
cycleID_5[1] = v15;
pkgBodyLen_5 = udpPresLayerHead->PkgBodyLen;
if ( pkgBodyLen_5 <= 0x400 )
{
if ( pkgCount_5 )
{
memcpy(&iosrvItemForceCancelTable + 1024 * (pkgID_5 - 1), &iosrvRecvBuff[32], pkgBodyLen_5);
if ( ++itemForceCancelPkgCount == 1 )
{
isItemForceCancelTimerActived = 1;
itemForceCancelTimeOut = 100;
}
if ( pkgCount_5 != itemForceCancelPkgCount )
goto LABEL_84;
itemForceCancelPkgCount = 0;
isItemForceCancelTimerActived = 0;
itemForceCancelTimeOut = 100;
result = 38;
}
else
{
KyldLog(1, 3, "UdpRecv:CmdIosrItemForceCancel,ERROR!!!pkgCount<=0,pkgCount=%d\n", 0);
result = 2;
}
}
else
{
KyldLog(
1,
3,
"UdpRecv:CmdIosrItemForceCancel,ERROR!!!pkgBodyLen > SUB_PKG_SIZE_MAX,pkgBodyLen=%d\n",
pkgBodyLen_5);
result = 2;
}
break;
default:
KyldLog(1, 3, "UdpRecv:recv invalid cmd type.\n");
LABEL_84:
if ( diagRequestTimeOut > 0 )
{
if ( dataRequestTimeOut > 0 )
{
if ( dataResendTimeOut > 0 )
{
if ( itemReadTimeOut > 0 )
{
if ( itemWriteTimeOut > 0 )
{
if ( itemForceTimeOut > 0 )
{
if ( itemForceCancelTimeOut > 0 )
goto LABEL_98;
KyldLog(1, 3, "UdpRecv:item force cancel recv time out.\n");
itemForceCancelPkgCount = 0;
isItemForceCancelTimerActived = 0;
itemForceCancelTimeOut = 100;
result = 70;
}
else
{
KyldLog(1, 3, "UdpRecv:item force recv time out.\n");
itemForcePkgCount = 0;
isItemForceTimerActived = 0;
itemForceTimeOut = 100;
result = 69;
}
}
else
{
KyldLog(1, 3, "UdpRecv:item write recv time out.\n");
itemWritePkgCount = 0;
isItemWriteTimerActived = 0;
itemWriteTimeOut = 100;
result = 68;
}
}
else
{
KyldLog(1, 3, "UdpRecv:item read recv time out.\n");
itemReadPkgCount = 0;
isItemReadTimerActived = 0;
itemReadTimeOut = 100;
result = 67;
}
}
else
{
KyldLog(1, 3, "UdpRecv:data resend recv time out.\n");
dataResendPkgCount = 0;
isDataResendTimerActived = 0;
dataResendTimeOut = 100;
result = 66;
}
}
else
{
KyldLog(1, 3, "UdpRecv:data Request recv time out.\n");
dataRequestPkgCount = 0;
isDataRequestTimerActived = 0;
dataRequestTimeOut = 100;
result = 65;
}
}
else
{
KyldLog(1, 3, "UdpRecv:diag Request recv time out.\n");
diagRequestPkgCount = 0;
isDiagRequestTimerActived = 0;
diagRequestTimeOut = 100;
result = 64;
}
break;
}
}
else
{
KyldLog(1, 3, "UdpRecv:IO_GetIOSvrNetIp,ip(%s) is illegal,ioser can not communicate.\n", recvIP);
result = 2;
}
}
else
{
KyldLog(1, 3, "UdpRecv:IO_GetIOSvrNetIp,iosrIPCount<=0,ioser can not communicate.\n");
result = 2;
}
}
else
{
KyldLog(1, 3, "UdpRecv:recvBuff is null.\n");
result = 2;
}
}
}
return result;
}
执行时的触发逻辑:
程序调用recvfrom函数接收数据包,在182行中判断发送方的ip地址,如果为192.168.0.2或者192.168.0.3,那么进入188行,可以看出这两个地址是特殊的ip地址,可能用于内部测试。在189行中取出数据包中的命令字段,判断pkgBodyLen<=0x400,pkgCount不为0,那么拷贝iosrvRecvBuff[32]地址处的长度为pkgBodyLen字节的值到地址iosrvDiagRequestTable + 1024 * (pkgID - 1)的地址中,此时如果pkgID为0xffff那么拷贝的目的地址在iosrvDiagRequestTable加偏移0x3fff800的地址,即 0x0241CE80+0x3fff800=641C680。但是该模块内存中的最大地址为0x400000+0x4030000=0x4430000,该地址超出模块在内存中加载后的有效地址空间,访问此地址空间一定造成越界访问异常。
从代码中得知,所有命令(1-9)的处理都存在上述漏洞。
(三) 攻击实现
上述漏洞的触发需要条件是源ip必须是192.168.0.2。没有api可以实现此功能,因此通过安装第三方开发包来实现,这里选用winpcap。
攻击代码主要有以下步骤:
- 获取本机网卡和目标网卡的ip和mac,adapter name等信息。
- 根据攻击目标的ip地址,找到本机上跟目标ip同一网段下的所有网卡,同时获取目标机器的mac地址,并调用winpcap打开本机上的所有网卡接口。
- 将目标网卡的ip,mac,源ip 192.169.0.2等几个参数作为数据包构造的必要参数,调用发包函数,构造造成目标程序溢出的数据包,调用winpcap函数发送。
攻击成功后,目标进程windowsRTE.exe和MaVIEW.exe的cpu利用率从0都上升到30%-40%,说明进程指令空转,右下角的控制台输出大量的异常提示,停止和启动按钮失效,只有重启程序才能恢复正常:
这时如果用ida挂载则程序发生崩溃。这种现象的解释是,因为异常处理顺序中最优先的是调试器,所以ida挂载后马上接收到异常,选择传递给程序后程序崩溃,选择忽略后则会在ida中继续收到异常。源程序的异常处理程序无法处理这种异常因而造成某些指令的死循环导致cpu使用率异常。
Poc代码在附件中。由于无法上传附件,附件和攻击脚本可点击:点击下载攻击脚本
该软件开发商好像叫做kyland,算是国内该行业的知名厂商。
注意:为了成功编译源码,需要:
- 安装winpcap开发包
- 本工程若不能编译,右击工程,点击属性-> c/c++ ->预处理器 中添加如下几条宏定义:
WIN32_LEAN_AND_MEAN
_WINSOCK_DEPRECATED_NO_WARNINGS
_XKEYCHECK_H