I have recently been doing some fuzzing on the Adobe Flash Player. I started by implementing a simple format fuzzer for Flash based on a homegrown framework that I have been developing for awhile. I implemented and executed tests and progressively covered more and more of the format. After a few days, I noticed one of the SWF files causing strange crashes, the “Just in time” debugger gets triggered but the process is terminated.
Note: The debugging process has taken place under a Windows XP SP2 machine with Adobe Flash 10.1.85.3 installed. During the debugging process we debugged Internet Explorer while it was rebased to the address 03281000.
I started debugging it for awhile and saw that there was an off-by-one vulnerability in one of the functions responsible for parsing the “DefineFont2” tag’s data. The vulnerability is not as straight-forward as it may seem, however. The main function that parses “DefineFont2” is parsing the entire tag correctly, as the data propagate and the font we defined is rendered for use, the vulnerability occurs. The tag “DefineFont2” allows us to specify a font-name with the size of up-to 0xFF bytes. The “DefineFont2” tag’s format is as follows:
After the initial processing of the “DefintFont2” tag, the function at 032ACB45 “CopyFontName” allocates a new buffer to store the font-name parameter it received. The buffer is allocated by calling the function “AllocateBuffer” at the address 032CA7FE.
Note: The function “AllocateBuffer” is wrapped by another function. The call is indirect but for the sake of simplicity, we modified the listing to show a direct call.
.text:032ACB68 push [esp+0Ch+FontName]
.text:032ACB6C jge short loc_32ACB79
.text:032ACB79 lea esi, [edi+10h]
.text:032ACB7C mov ecx, esi
.text:032ACB7E call AllocateBuffer ; // AllocateBuffer(Buf, FontName);
.text:032ACB83 mov ecx, esi
.text:032ACB85 push 80h
.text:032ACB8A call NullTerminate ; // NullTerminate(Buf, 0x80);
.text:032ACB8F mov ecx, edi
.text:032ACB91 call sub_32ACA47
.text:032ACB96 pop edi
.text:032ACB97 pop esi
.text:032ACB98 pop ebx
.text:032ACB99 retn 8
“AllocateBuffer” allocates a new buffer at the size of the given string. (This buffer will be used to overflow the stack with an off-by-one vulnerability later-on)
.text:032CA61C lea edx, [eax+1]
.text:032CA61F mov cl, [eax]
.text:032CA621 inc eax
.text:032CA622 test cl, cl
.text:032CA624 jnz short loc_32CA61F
.text:032CA626 sub eax, edx
.text:032CA628 jmp short loc_32CA62C
This part of the function calculates the length of the given string; it is equivalent to the following code:
After the length of the string is calculated, the function allocates a buffer at the proper size and copies the contents of the string onto the buffer. When “AllocateBuffer” returns, “CopyFontName” calls “NullTerminate” with the constant parameter of 0x80 to limit the buffer size to no more than 0x80.
Later on, the buffer that we allocated gets copied to a stack buffer during the execution of the function “Overwrite” (03426283). This function has a stack buffer with the size 0x80 to copy the string into. The problem is that the string size is 0x80 + a null terminator (which is actually 0x81). The function copies the string using the following compiler-generated code:
.text:03426372 mov cl, [eax]
.text:03426374 mov [edx+eax], cl
.text:03426377 inc eax
.text:03426378 test cl, cl
.text:0342637A jnz short StringCopy
This code fragment first copies a character and only then checks if that character is a null (as most string copy functions do). The result is a classic off-by-one vulnerability that results in the overwrite of a single byte of the stack cookie with null. This condition is not exploitable under the windows platform and it causes the browser to crash while failing the stack-cookie test.
(Btw, this vulnerability is currently a zero-day as far as i know)
About the Author
Tal Zeltzer (zelik) is a security researcher from Israel, focusing on reverse engineering both software and hardware. He spends most of his free time developing private security tools and exploits for fun.