본문 바로가기

Programming

linux/windows SSL client example

OpenSSL 리눅스 클라이언트 예제.

https 웹서버에서 인덱스페이지를 받아옴.



#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 



#include 

#include 

#include 



// Simple structure to keep track of the handle, and

// of what needs to be freed later.

typedef struct {

    int socket;

    SSL *sslHandle;

    SSL_CTX *sslContext;

} connection;



// For this example, we'll be testing on openssl.org

#define SERVER  "www.openssl.org"

#define PORT 443



// Establish a regular tcp connection

int tcpConnect ()

{

  int error, handle;

  struct hostent *host;

  struct sockaddr_in server;



  host = gethostbyname (SERVER);

  handle = socket (AF_INET, SOCK_STREAM, 0);

  if (handle == -1)

    {

      perror ("Socket");

      handle = 0;

    }

  else

    {

      server.sin_family = AF_INET;

      server.sin_port = htons (PORT);

      server.sin_addr = *((struct in_addr *) host->h_addr);

      bzero (&(server.sin_zero), 8);



      error = connect (handle, (struct sockaddr *) &server,

                       sizeof (struct sockaddr));

      if (error == -1)

        {

          perror ("Connect");

          handle = 0;

        }

    }



  return handle;

}



// Establish a connection using an SSL layer

connection *sslConnect (void)

{

  connection *c;



  c = malloc (sizeof (connection));

  c->sslHandle = NULL;

  c->sslContext = NULL;



  c->socket = tcpConnect ();

  if (c->socket)

    {

      // Register the error strings for libcrypto & libssl

      SSL_load_error_strings ();

      // Register the available ciphers and digests

      SSL_library_init ();



      // New context saying we are a client, and using SSL 2 or 3

      c->sslContext = SSL_CTX_new (SSLv23_client_method ());

      if (c->sslContext == NULL)

        ERR_print_errors_fp (stderr);



      // Create an SSL struct for the connection

      c->sslHandle = SSL_new (c->sslContext);

      if (c->sslHandle == NULL)

        ERR_print_errors_fp (stderr);



      // Connect the SSL struct to our connection

      if (!SSL_set_fd (c->sslHandle, c->socket))

        ERR_print_errors_fp (stderr);



      // Initiate SSL handshake

      if (SSL_connect (c->sslHandle) != 1)

        ERR_print_errors_fp (stderr);

    }

  else

    {

      perror ("Connect failed");

    }



  return c;

}



// Disconnect & free connection struct

void sslDisconnect (connection *c)

{

  if (c->socket)

    close (c->socket);

  if (c->sslHandle)

    {

      SSL_shutdown (c->sslHandle);

      SSL_free (c->sslHandle);

    }

  if (c->sslContext)

    SSL_CTX_free (c->sslContext);



  free (c);

}



// Read all available text from the connection

char *sslRead (connection *c)

{

  const int readSize = 1024;

  char *rc = NULL;

  int received, count = 0;

  char buffer[1024];



  if (c)

    {

      while (1)

        {

          if (!rc)

            rc = malloc (readSize * sizeof (char) + 1);

          else

            rc = realloc (rc, (count + 1) *

                          readSize * sizeof (char) + 1);



          received = SSL_read (c->sslHandle, buffer, readSize);

          buffer[received] = '\0';



          if (received > 0)

            strcat (rc, buffer);



          if (received < readSize)

            break;

          count++;

        }

    }



  return rc;

}



// Write text to the connection

void sslWrite (connection *c, char *text)

{

  if (c)

    SSL_write (c->sslHandle, text, strlen (text));

}



// Very basic main: we send GET / and print the response.

int main (int argc, char **argv)

{

  connection *c;

  char *response;



  c = sslConnect ();



  sslWrite (c, "GET /\r\n\r\n");

  response = sslRead (c);



  printf ("%s\n", response);



  sslDisconnect (c);

  free (response);



  return 0;

}





Windows 클라이언트 예제.

Window 의 경우 ssleay32.lib, libeay32.lib 이 두개의 파일과

header 파일들이 필요한데, perl, nmake, ml 이렇게 3가지 툴로

윈도우용 makefile 을 가지고 컴파일 하면 생성됨.

자세한건 구글링 참조



// openssl.cpp : 콘솔 응용 프로그램에 대한 진입점을 정의합니다.
//

#include "stdafx.h"

#include  // To prevent crashing (see the OpenSSL FAQ)
#include  // BIO objects for I/O
#include  // SSL and SSL_CTX for SSL connections
#include  // Error reporting

// plain text connection
void openssltest() {
   // First, set up a BIO object. BIO objects abstract away the socket IO operations so we don't have to deal with it. 
   // We're connecting to google.com on port 80.
   BIO* bio = BIO_new_connect("google.com:80");
   // Was the BIO successfully created?
   if (bio == NULL) {
      printf("Error creating BIO!\n");
      // This function prints out error messages. Use Google and the OpenSSL documentation to find out what the problem is.
      ERR_print_errors_fp(stderr);
      return;
   }

   // BIO_do_connect() tells our BIO object to connect to the server.
   if (BIO_do_connect(bio) <= 0) {
      printf("Failed to connect!");
      return;
   }
   // Create a buffer for grabbing information from the page.
   char buf[1024];
   memset(buf, 0, sizeof(buf));
   // Create a buffer for the request we'll send to the server
   char send[1024];
   memset(send, 0, sizeof(send));
   // Create our GET request.
   strcat(send, "GET / HTTP/1.1\nHost:google.com\nUser Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)\nConnection: Close\n\n");
   // BIO_puts sends a null-terminated string to the server. In this case it's our GET request.
   BIO_puts(bio, send);
   // Loop while there's information to be read.
   while (1) {
      // BIO_read() reads data from the server into a buffer. It returns the number of characters read in.
      int x = BIO_read(bio, buf, sizeof(buf) - 1);
      // If we haven't read in anything, assume there's nothing more to be sent since we used Connection: Close.
      if (x == 0) {
         break;
      }
      // If BIO_read() returns a negative number, there was an error
      else if (x < 0) {
         // BIO_should_retry lets us know if we should keep trying to read data or not.
         if (!BIO_should_retry(bio)) {
            printf("\nRead Failed!\n");
            BIO_free_all(bio);
            return;
         }
      }
      // We actually got some data, without errors!
      else {
         // Null-terminate our buffer, just in case
         buf[x] = 0;
         // Echo what the server sent to the screen
         printf("%s", buf);
      }
   }
   // Free up that BIO object we created.
   BIO_free_all(bio);
   // Return.
   return;
}

// use encryption
void openssltest2() {
   // Set up a SSL_CTX object, which will tell our BIO object how to do its work
   SSL_CTX* ctx = SSL_CTX_new(SSLv23_client_method());
   // Create a SSL object pointer, which our BIO object will provide.
   SSL* ssl;
   // Create our BIO object for SSL connections.
   BIO* bio = BIO_new_ssl_connect(ctx);
   // Failure?
   if (bio == NULL) {
      printf("Error creating BIO!\n");
           ERR_print_errors_fp(stderr);
      // We need to free up the SSL_CTX before we leave.
           SSL_CTX_free(ctx);
           return;
   }
   // Makes ssl point to bio's SSL object.
   BIO_get_ssl(bio, &ssl);
   // Set the SSL to automatically retry on failure.
   SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
   // We're connection to google.com on port 443.
   BIO_set_conn_hostname(bio, "www.google.com:https");

   // Same as before, try to connect.
   if (BIO_do_connect(bio) <= 0) {
      printf("Failed to connect!");
      BIO_free_all(bio);
      SSL_CTX_free(ctx);
      return;
   }

   // Now we need to do the SSL handshake, so we can communicate.
   if (BIO_do_handshake(bio) <= 0) {
      printf("Failed to do SSL handshake!");
      BIO_free_all(bio);
      SSL_CTX_free(ctx);
      return;
   }
   // Create a buffer for grabbing information from the page.
   char buf[1024];
   memset(buf, 0, sizeof(buf));
   // Create a buffer for the reqest we'll send to the server
   char send[1024];
   memset(send, 0, sizeof(send));
   // Create our GET request.
   strcat(send, "GET / HTTP/1.1\nHost:google.com\nUser Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)\nConnection: Close\n\n");
   // BIO_puts sends a null-terminated string to the server. In this case it's our GET request.
   BIO_puts(bio, send);
   // Loop while there's information to be read.
   while (1) {
      // BIO_read() reads data from the server into a buffer. It returns the number of characters read in.
      int x = BIO_read(bio, buf, sizeof(buf) - 1);
      // If we haven't read in anything, assume there's nothing more to be sent since we used Connection: Close.
      if (x == 0) {
         break;
      }
      // If BIO_read() returns a negative number, there was an error
      else if (x < 0) {
         // BIO_should_retry lets us know if we should keep trying to read data or not.
         if (!BIO_should_retry(bio)) {
            printf("\nRead Failed!\n");
            BIO_free_all(bio);
            SSL_CTX_free(ctx);         
            return;
         }
      }
      // We actually got some data, without errors!
      else {
         // Null-terminate our buffer, just in case
         buf[x] = 0;
         // Echo what the server sent to the screen
         printf("%s", buf);
      }
   }
   // Free up that BIO object we created.
   BIO_free_all(bio);
   // Remember, we also need to free up that SSL_CTX object!
   SSL_CTX_free(ctx);
   // Return.
   return;
}

int _tmain(int argc, _TCHAR* argv[])
{
	printf("hello world\n");

	CRYPTO_malloc_init(); // Initialize malloc, free, etc for OpenSSL's use
	SSL_library_init(); // Initialize OpenSSL's SSL libraries
	SSL_load_error_strings(); // Load SSL error strings
	ERR_load_BIO_strings(); // Load BIO error strings
	OpenSSL_add_all_algorithms(); // Load all available encryption algorithms
   
	openssltest2();
   
	return 0;
}




'Programming' 카테고리의 다른 글

x86 privilege level  (0) 2013.02.21
OpenSSL Server Example  (0) 2013.02.05
QEMU Detection  (0) 2013.01.28
Anti Debugging with POP SS  (0) 2013.01.28
x86 linux idt hooking  (0) 2013.01.24