diff --git a/hydra-radmin2.c b/hydra-radmin2.c index 74dd511..c816b5c 100644 --- a/hydra-radmin2.c +++ b/hydra-radmin2.c @@ -15,7 +15,7 @@ extern int blockDecrypt(cipherInstance *cipher, keyInstance *key,CONST BYTE *inp //RAdmin 2.x -struct rmessage{ +struct rmessage { char magic; //Indicates version, probably? unsigned int length; //Total message size of data. unsigned int checksum; //Checksum from type to end of data. @@ -24,12 +24,12 @@ struct rmessage{ }; /* -* Usage: sum = checksum(message); -* Function: Returns a 4 byte little endian sum of the messages typecode+data. This data is zero padded for alignment. -* Example message (big endian): -* [01][00000021][0f43d461] sum([1b6e779a f37189bb c1b22982 c80d1f4d 66678ff9 4b10f0ce eabff6e8 f4fb8338 3b] + zeropad(3)]) -* Sum: is 0f43d461 (big endian) -*/ + * Usage: sum = checksum(message); + * Function: Returns a 4 byte little endian sum of the messages typecode+data. This data is zero padded for alignment. + * Example message (big endian): + * [01][00000021][0f43d461] sum([1b6e779a f37189bb c1b22982 c80d1f4d 66678ff9 4b10f0ce eabff6e8 f4fb8338 3b] + zeropad(3)]) + * Sum: is 0f43d461 (big endian) + */ unsigned int checksum(struct rmessage *msg) { int blen; unsigned char *stream; @@ -55,10 +55,10 @@ unsigned int checksum(struct rmessage *msg) { } /* -* Usage: challenge_request(message); -* Function: Modifies message to reflect a request for a challenge. Updates the checksum as appropriate. -*/ -void challenge_request(struct rmessage *msg) { + * Usage: challenge_request(message); + * Function: Modifies message to reflect a request for a challenge. Updates the checksum as appropriate. + */ +void challenge_request(struct rmessage *msg) { msg->magic = 0x01; msg->length = 0x01; msg->type = 0x1b; @@ -66,9 +66,9 @@ void challenge_request(struct rmessage *msg) { } /* -* Usage: challenge_request(message); -* Function: Modifies message to reflect a response to a challenge. Updates the checksum as appropriate. -*/ + * Usage: challenge_request(message); + * Function: Modifies message to reflect a response to a challenge. Updates the checksum as appropriate. + */ void challenge_response(struct rmessage *msg, unsigned char *solution) { msg->magic = 0x01; msg->length = 0x21; @@ -78,9 +78,9 @@ void challenge_response(struct rmessage *msg, unsigned char *solution) { } /* -* Usage: buffer = message2buffer(message); send(buffer, message->length + 10); free(buffer) -* Function: Allocates a buffer for transmission and fills the buffer with message data such that it is ready to transmit. -*/ + * Usage: buffer = message2buffer(message); send(buffer, message->length + 10); free(buffer) + * Function: Allocates a buffer for transmission and fills the buffer with message data such that it is ready to transmit. + */ //TODO: conver to a sendMessage() function? char *message2buffer(struct rmessage *msg) { char *data; @@ -207,123 +207,133 @@ void service_radmin2(char *ip, int sp, unsigned char options, char *miscptr, FIL if( memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0) { return; } - - // Get a password to work with. - strncpy(password, hydra_get_next_password(), 101); - MD5_Init(&md5c); - MD5_Update(&md5c, password, 100); - MD5_Final(rawkey, &md5c); - //Copy raw md5 data into ASCIIZ string - for(index = 0; index < 16; index++) { - sprintf((pkey+index*2), "%02x", rawkey[index]); - } - /* Typical conversation goes as follows... - 0) connect to server - 1) request challenge - 2) receive 32 byte challenge response - 3) send 32 byte challenge solution - 4) receive 1 byte auth success/fail message - */ - // 0) Connect to the server - sock = hydra_connect_tcp(ip, myport); - if(sock < 0) { - hydra_report(stderr, "Error: Child with pid %d terminating, can not connect\n", (int)getpid()); - hydra_child_exit(1); - } + while(1) { + // Get a password to work with. + strncpy(password, hydra_get_next_password(), 101); + MD5_Init(&md5c); + MD5_Update(&md5c, password, 100); + MD5_Final(rawkey, &md5c); + //Copy raw md5 data into ASCIIZ string + for(index = 0; index < 16; index++) { + sprintf((pkey+index*2), "%02x", rawkey[index]); + } - // 1) request challenge (working) - msg = calloc(1, sizeof(struct rmessage)); - challenge_request(msg); - request = message2buffer(msg); - hydra_send(sock, request, 10, 0); - free(msg); - free(request); + /* Typical conversation goes as follows... + 0) connect to server + 1) request challenge + 2) receive 32 byte challenge response + 3) send 32 byte challenge solution + 4) receive 1 byte auth success/fail message + */ + // 0) Connect to the server + sock = hydra_connect_tcp(ip, myport); + if(sock < 0) { + hydra_report(stderr, "Error: Child with pid %d terminating, can not connect\n", (int)getpid()); + hydra_child_exit(1); + } - //2) receive response (working) - index = 0; - while(index < 42) { //We're always expecting back a 42 byte buffer from a challenge request. - switch(hydra_data_ready(sock)) { - case -1: - hydra_report(stderr, "Error: Child with pid %d terminating, receive error\nerror:\t%s\n", (int)getpid(), strerror(errno)); - hydra_child_exit(1); - break; - case 0: - //keep waiting... - break; - default: - bytecount = hydra_recv(sock, buffer+index, 42 - index); - if(bytecount < 0) { + // 1) request challenge (working) + msg = calloc(1, sizeof(struct rmessage)); + challenge_request(msg); + request = message2buffer(msg); + hydra_send(sock, request, 10, 0); + free(msg); + free(request); + + //2) receive response (working) + index = 0; + while(index < 42) { //We're always expecting back a 42 byte buffer from a challenge request. + switch(hydra_data_ready(sock)) { + case -1: hydra_report(stderr, "Error: Child with pid %d terminating, receive error\nerror:\t%s\n", (int)getpid(), strerror(errno)); hydra_child_exit(1); - } - index += bytecount; + break; + case 0: + //keep waiting... + break; + default: + bytecount = hydra_recv(sock, buffer+index, 42 - index); + if(bytecount < 0) { + hydra_report(stderr, "Error: Child with pid %d terminating, receive error\nerror:\t%s\n", (int)getpid(), strerror(errno)); + hydra_child_exit(1); + } + index += bytecount; + } } - } - - //3) Send challenge solution. - //3.a) generate a new message from the buffer - msg = buffer2message(buffer); + //3) Send challenge solution. - //3.b) encrypt data received using pkey & known IV - index = makeKey(&key, DIR_ENCRYPT, 128, pkey); - if(index != TRUE) { - hydra_report(stderr, "Error: Child with pid %d terminating, make key error (%08x)\n", (int)getpid(), index); - hydra_child_exit(1); - } + //3.a) generate a new message from the buffer + msg = buffer2message(buffer); - index = cipherInit(&cipher, MODE_CBC, IV); - if(index != TRUE) { - hydra_report(stderr, "Error: Child with pid %d terminating, cipher init error(%08x)\n", (int)getpid(), index); - hydra_child_exit(1); - } + //3.b) encrypt data received using pkey & known IV + index = makeKey(&key, DIR_ENCRYPT, 128, pkey); + if(index != TRUE) { + hydra_report(stderr, "Error: Child with pid %d terminating, make key error (%08x)\n", (int)getpid(), index); + hydra_child_exit(1); + } - index = blockEncrypt(&cipher, &key, msg->data, 32 * 8, encrypted); - if(index <= 0) { - hydra_report(stderr, "Error: Child with pid %d terminating, encrypt error(%08x)\n", (int)getpid(), index); - hydra_child_exit(1); - } - - //3.c) half sum - this is the solution to the challenge. - for(index=0; index < 16; index++) { - *(encrypted+index) += *(encrypted+index+16); - } - memset((encrypted+16), 0x00, 16); + index = cipherInit(&cipher, MODE_CBC, IV); + if(index != TRUE) { + hydra_report(stderr, "Error: Child with pid %d terminating, cipher init error(%08x)\n", (int)getpid(), index); + hydra_child_exit(1); + } - //3.d) send half sum - challenge_response(msg, encrypted); - request = message2buffer(msg); - hydra_send(sock, request, 42, 0); - free(msg); - free(request); + index = blockEncrypt(&cipher, &key, msg->data, 32 * 8, encrypted); + if(index <= 0) { + hydra_report(stderr, "Error: Child with pid %d terminating, encrypt error(%08x)\n", (int)getpid(), index); + hydra_child_exit(1); + } - //4) receive auth success/failure - index = 0; - while(index < 10) { //We're always expecting back a 42 byte buffer from a challenge request. - switch(hydra_data_ready(sock)) { - case -1: - hydra_report(stderr, "Error: Child with pid %d terminating, receive error\nerror:\t%s\n", (int)getpid(), strerror(errno)); - hydra_child_exit(1); - break; - case 0: - //keep waiting... - break; - default: - bytecount = hydra_recv(sock, buffer+index, 10 - index); - if(bytecount < 0) { + //3.c) half sum - this is the solution to the challenge. + for(index=0; index < 16; index++) { + *(encrypted+index) += *(encrypted+index+16); + } + memset((encrypted+16), 0x00, 16); + + //3.d) send half sum + challenge_response(msg, encrypted); + request = message2buffer(msg); + hydra_send(sock, request, 42, 0); + free(msg); + free(request); + + //4) receive auth success/failure + index = 0; + while(index < 10) { //We're always expecting back a 42 byte buffer from a challenge request. + switch(hydra_data_ready(sock)) { + case -1: hydra_report(stderr, "Error: Child with pid %d terminating, receive error\nerror:\t%s\n", (int)getpid(), strerror(errno)); hydra_child_exit(1); - } - index += bytecount; + break; + case 0: + //keep waiting... + break; + default: + bytecount = hydra_recv(sock, buffer+index, 10 - index); + if(bytecount < 0) { + hydra_report(stderr, "Error: Child with pid %d terminating, receive error\nerror:\t%s\n", (int)getpid(), strerror(errno)); + hydra_child_exit(1); + } + index += bytecount; + } } + msg = buffer2message(buffer); + switch(msg->type) { + case 0x0a: + hydra_completed_pair_found(); + break; + case 0x0b: + hydra_completed_pair(); + hydra_disconnect(sock); + break; + default: + hydra_report(stderr, "Error: Child with pid %d terminating, protocol error\n", (int)getpid()); + hydra_child_exit(2); + } + } - msg = buffer2message(buffer); - if(msg->type == 0x0a) { - hydra_completed_pair_found(); - } - //5) Disconnect - hydra_disconnect(sock); } int service_radmin2_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *hostname) { @@ -334,8 +344,8 @@ int service_radmin2_init(char *ip, int sp, unsigned char options, char *miscptr, // fill if needed. // // return codes: - // 0 all OK - // -1 error, hydra will exit, so print a good error message here + // 0 all OK + // -1 error, hydra will exit, so print a good error message here return 0; }