thc-hydra/hydra-pcanywhere.c
2020-02-01 11:47:13 +01:00

294 lines
6.8 KiB
C

// This plugin was written by <david dot maciejak at kyxar dot fr>
//
// PC-Anywhere authentication protocol test on Symantec PC-Anywhere 10.5
//
// no memleaks found on 110425
#include "hydra-mod.h"
extern char *HYDRA_EXIT;
int32_t pcadebug = 0;
int32_t send_cstring(int32_t s, char *crypted_string) {
char buffer2[100], *bptr = buffer2;
char clientcryptheader[] = "\x06";
memset(buffer2, 0, sizeof(clientcryptheader));
bptr = buffer2;
buffer2[0] = 6;
bptr++;
buffer2[1] = strlen(crypted_string);
bptr++;
strcpy(bptr, crypted_string);
return hydra_send(s, buffer2, 2 + strlen(crypted_string), 0);
}
void show_buffer(char *buffer, int32_t size) {
int32_t i;
printf("size: %d, buffer:\n", size);
for (i = 0; i < size; i++) {
printf("%c", buffer[i]);
}
printf("\n");
}
void clean_buffer(char *buf, int32_t size) {
int32_t i;
for (i = 0; i < size; i++) {
int32_t pos = buf[i];
if (pos < 32 || pos > 126) {
// . char
buf[i] = 46;
}
}
}
void print_encrypted_str(char *str) {
int32_t i;
printf("encode string: ");
for (i = 0; i < strlen(str); i++) {
printf("%x ", str[i]);
}
printf("\n");
}
void pca_encrypt(char *cleartxt) {
char passwd[128];
int32_t i;
strncpy(passwd, cleartxt, sizeof(passwd) - 1);
passwd[sizeof(passwd) - 1] = 0;
if (strlen(cleartxt) > 0) {
passwd[0] = (passwd[0] ^ 0xab);
for (i = 1; i < strlen(passwd); i++)
passwd[i] = passwd[i - 1] ^ passwd[i] ^ (i - 1);
passwd[strlen(passwd)] = '\0';
strcpy(cleartxt, passwd);
}
}
void pca_decrypt(char *password) {
char cleartext[128];
int32_t i;
if (strlen(password) > 0) {
cleartext[0] = password[0] ^ 0xab;
for (i = 1; i < strlen(password); i++)
cleartext[i] = password[i - 1] ^ password[i] ^ (i - 1);
cleartext[strlen(password)] = '\0';
strcpy(password, cleartext);
}
}
void debugprintf(char *msg) {
if (pcadebug)
printf("debug: %s\n", msg);
}
int32_t start_pcanywhere(int32_t s, char *ip, int32_t port, unsigned char options, char *miscptr, FILE *fp) {
char *empty = "";
char *login, *pass;
char buffer[2048] = "";
char clogin[128] = "";
char cpass[128] = "";
int32_t ret, i;
char *client[4];
char *server[5];
int32_t clientsize[4];
client[0] = "\x00\x00\x00\x00";
clientsize[0] = 4;
client[1] = "\x6F\x06\xff";
clientsize[1] = 3;
client[2] = "\x6f\x61\x00\x09\x00\xfe\x00\x00\xff\xff\x00\x00\x00\x00";
clientsize[2] = 14;
client[3] = "\x6f\x62\x01\x02\x00\x00\x00";
clientsize[3] = 7;
server[0] = "nter";
server[1] = "\x1B\x61";
server[2] = "\0x1B\0x62";
server[3] = "Enter login name";
server[4] = "denying connection";
if (strlen(login = hydra_get_next_login()) == 0)
login = empty;
if (strlen(pass = hydra_get_next_password()) == 0)
pass = empty;
debugprintf("dans pcanywhere start");
/*printf("testing %s:%s\n",login,pass); */
strcpy(clogin, login);
strcpy(cpass, pass);
pca_encrypt(clogin);
pca_encrypt(cpass);
for (i = 0; i < 4; i++) {
if (hydra_send(s, client[i], clientsize[i], 0) < 0) {
return 1;
}
ret = hydra_recv(s, buffer, sizeof(buffer) - 1);
if (ret == -1) {
return 1;
}
if (i == 3) {
if (ret == 3) {
/*one more to get the login prompt */
ret = hydra_recv(s, buffer, sizeof(buffer) - 1);
}
}
if (ret >= 0)
buffer[ret] = 0;
if (i == 0 || i == 3)
clean_buffer(buffer, ret);
if (debug)
show_buffer(buffer, ret);
if (i == 2) {
clean_buffer(buffer, ret);
buffer[sizeof(buffer) - 1] = 0;
if (strstr(buffer, server[i + 2]) != NULL) {
fprintf(stderr, "[ERROR] PC Anywhere host denying connection because "
"you have requested a lower encrypt level\n");
return 3;
}
}
if (strstr(buffer, server[i]) == NULL) {
if (i == 3) {
debugprintf("problem receiving login banner");
}
return 1;
}
}
if (send_cstring(s, clogin) < 0) {
return 1;
}
ret = hydra_recv(s, buffer, sizeof(buffer) - 1);
if (ret < 0) {
return 1;
}
buffer[ret] = 0;
clean_buffer(buffer, ret);
/*show_buffer(buffer,ret); */
if (strstr(buffer, "Enter password:") == NULL) {
debugprintf("problem receiving password banner");
return 1;
}
if (send_cstring(s, cpass) < 0) {
return 1;
}
ret = hydra_recv(s, buffer, sizeof(buffer));
if (ret < 0)
return 1;
else
buffer[ret] = 0;
clean_buffer(buffer, ret);
/*show_buffer(buffer,ret); */
if ((strstr(buffer, "Invalid login") != NULL) || (strstr(buffer, "Enter password") != NULL)) {
debugprintf("login/passwd wrong");
hydra_completed_pair();
if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
return 3;
return 2;
} else {
debugprintf("cool find login/passwd");
hydra_report_found_host(port, ip, "pcanywhere", fp);
hydra_completed_pair_found();
if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
return 3;
return 2;
}
return 1;
}
void service_pcanywhere(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname) {
int32_t run = 1, next_run = 1, sock = -1;
int32_t myport = PORT_PCANYWHERE, mysslport = PORT_PCANYWHERE_SSL;
hydra_register_socket(sp);
if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
return;
while (1) {
switch (run) {
case 1: /* connect and service init function */
if (sock >= 0)
sock = hydra_disconnect(sock);
usleepn(275);
if ((options & OPTION_SSL) == 0) {
if (port != 0)
myport = port;
sock = hydra_connect_tcp(ip, myport);
port = myport;
} else {
if (port != 0)
mysslport = port;
sock = hydra_connect_ssl(ip, mysslport, hostname);
port = mysslport;
}
if (sock < 0) {
if (quiet != 1)
fprintf(stderr, "[ERROR] Child with pid %d terminating, can not connect\n", (int32_t)getpid());
hydra_child_exit(1);
}
next_run = 2;
break;
case 2:
next_run = start_pcanywhere(sock, ip, port, options, miscptr, fp);
break;
case 3:
if (sock >= 0)
sock = hydra_disconnect(sock);
hydra_child_exit(0);
return;
default:
fprintf(stderr, "[ERROR] Caught unknown return code, exiting!\n");
hydra_child_exit(0);
}
run = next_run;
}
}
int32_t service_pcanywhere_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname) {
// called before the childrens are forked off, so this is the function
// which should be filled if initial connections and service setup has to be
// performed once only.
//
// fill if needed.
//
// return codes:
// 0 all OK
// -1 error, hydra will exit, so print a good error message here
return 0;
}