root:/path_to_libming/build/bin# ./listswf poc
==26225==WARNING: AddressSanitizer failed to allocate 0xfffffffffffffff9 bytes
==26225==AddressSanitizer's allocator is terminating the process instead of returning 0
==26225==If you don't like this behavior set allocator_may_return_null=1
==26225==AddressSanitizer CHECK failed: /mnt/d/CLib/llvm-6.0.1/projects/compiler-rt/lib/sanitizer_common/sanitizer_allocator.cc:225 "((0)) != (0)" (0x0, 0x0)
#0 0x4e3385 in __asan::AsanCheckFailed(char const*, int, char const*, unsigned long long, unsigned long long) /mnt/d/CLib/llvm-6.0.1/projects/compiler-rt/lib/asan/asan_rtl.cc:69
#1 0x500c45 in __sanitizer::CheckFailed(char const*, int, char const*, unsigned long long, unsigned long long) /mnt/d/CLib/llvm-6.0.1/projects/compiler-rt/lib/sanitizer_common/sanitizer_termination.cc:79
#2 0x4e9786 in __sanitizer::ReportAllocatorCannotReturnNull() /mnt/d/CLib/llvm-6.0.1/projects/compiler-rt/lib/sanitizer_common/sanitizer_allocator.cc:225
#3 0x4e97c6 in __sanitizer::ReturnNullOrDieOnFailure::OnBadRequest() /mnt/d/CLib/llvm-6.0.1/projects/compiler-rt/lib/sanitizer_common/sanitizer_allocator.cc:241
#4 0x41f676 in __asan::asan_malloc(unsigned long, __sanitizer::BufferedStackTrace*) /mnt/d/CLib/llvm-6.0.1/projects/compiler-rt/lib/asan/asan_allocator.cc:856
#5 0x4da20b in malloc /mnt/d/CLib/llvm-6.0.1/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:89
#6 0x5b7e7e in readBytes /path_to_libming/util/read.c:252:17
#7 0x59b963 in parseSWF_DEFINELOSSLESS2 /path_to_libming/util/parser.c:2168:38
#8 0x546cf9 in blockParse /path_to_libming/util/blocktypes.c:145:14
#9 0x53bc13 in readMovie /path_to_libming/util/main.c:269:11
#10 0x53a0d6 in main /path_to_libming/util/main.c:354:2
#11 0x7fce52d93bf6 in __libc_start_main /build/glibc-S9d2JN/glibc-2.27/csu/../csu/libc-start.c:310
#12 0x41a2f9 in _start (/path_to_libming/build/bin/listswf+0x41a2f9)
The cause of this bug is the lack of boundary checks. Specifically, in the parseSWF_DEFINELOSSLESS2 function, the size of end and fileOffset is not compared when readBytes is called. As a result, end-fileOffset may be a negative integer, which eventually leads to allocation failure.
The detailed call chain analysis is as follows.
Download poc
staticvoidreadMovie(FILE *f)
{
int block, type, length, nextFrame=0;
SWF_Parserstruct *blockp;
for (;;)
{
if(filelen_check_fails(2))
break;
// Read 16 bits from the input file, the block is controlled by the attacker
block = readUInt16 (f);
type = block >> 6;
// length = block & 0x3f, which means length<=3f
length = block & ((1 << 6) - 1);
if (length == 63) /* it's a long block. */
{
if(filelen_check_fails(4))
break;
unsignedlong real_length = readUInt32 (f);
if (real_length > INT_MAX) {
SWF_warn(" Could not process long block with length %lu:"" blocks with length > %d not supported on this system\n",
real_length, INT_MAX);
continue;
} else {
length = (int) real_length;
}
}
nextFrame = fileOffset+length;
if(filelen_check_fails(length))
break;
blockp= blockParse(f, length, type);
......
}
......
}
SWF_Parserstruct *
blockParse (FILE *f, int length, SWFBlocktype header)
{
int i;
for (i = 0; i < numBlocks; i++)
{
// Select the corresponding parser to parseif (blocks[i].type == header)
{
return blocks[i].parser(f,length);
}
}
returnparseSWF_UNKNOWNBLOCK(f, length);
}
SWF_Parserstruct *
parseSWF_DEFINELOSSLESS2 (FILE * f, int length)
{
int end = fileOffset + length;
PAR_BEGIN (SWF_DEFINELOSSLESS2);
parserrec->CharacterID = readUInt16 (f); // Read 16 bits from the input file, and fileOffset = fileOffset+2
parserrec->BitmapFormat = readUInt8 (f); // Read 8 bits from the input file, and fileOffset = fileOffset+1
parserrec->BitmapWidth = readUInt16 (f); // Read 16 bits from the input file, and fileOffset = fileOffset+2
parserrec->BitmapHeight = readUInt16 (f); Read 16 bits from the input file, and fileOffset = fileOffset+2if( parserrec->BitmapFormat == 3/* 8-bit */ ) {
parserrec->BitmapColorTableSize = readUInt8 (f);
}
// When length=0, at this moment end=Old_fileOffset, fileOffset=Old_fileOffset+7, then end-fileOffset will be equal to -7 which is a negative integer
parserrec->ZlibBitmapData = (UI8 *)readBytes (f,end-fileOffset);
PAR_END;
}
char *readBytes(FILE *f, unsignedlong size)
{
if (size < 1) {
#if DEBUG
SWF_warn("readBytes: want to read %lu < 1 bytes: Handling a 0\n", size);
#endif
size = 0;
}
unsignedlong i;
char *buf;
// The parameter size's type is unsigned long. Given a negative integer as input, it will be treated as a large unsigned integer and passed to malloc, causing allocation failures.
buf = (char *)malloc(sizeof(char)*size);
if (buf == NULL) {
fprintf(stderr, "readBytes: Failed to allocate %lu bytes", sizeof(char) * size);
exit(-1);
}
for(i=0;i<size;i++)
{
buf[i]=(char)readUInt8(f);
}
return buf;
}
The text was updated successfully, but these errors were encountered:
version: master(commit 04aee52 )
command: listswf $FILE
The cause of this bug is the lack of boundary checks. Specifically, in the
parseSWF_DEFINELOSSLESS2function, the size ofendandfileOffsetis not compared whenreadBytesis called. As a result,end-fileOffsetmay be a negative integer, which eventually leads to allocation failure.The detailed call chain analysis is as follows.
Download poc
The text was updated successfully, but these errors were encountered: