Exploit-DB #18777
Description: Microsoft .NET Framework EncoderParameter - Integer Overflow (MS12-025)
Type: dos
Platform: windows
Date: 2012-04-24
Author: Akita Software Security

Exploit:
------------------------------------------------------------------------
.NET Framework EncoderParameter integer overflow vulnerability
------------------------------------------------------------------------
Yorick Koster, September 2011

------------------------------------------------------------------------
Abstract
------------------------------------------------------------------------
An integer overflow vulnerability has been discovered in the
EncoderParameter class of the .NET Framework. Exploiting this
vulnerability results in an overflown integer that is used to allocate a
buffer on the heap. After the incorrect allocation, one or more
user-supplied buffers are copied in the new buffer, resulting in a
corruption of the heap.

By exploiting this vulnerability, it is possible for an application
running with Partial Trust permissions to to break from the CLR sandbox
and run arbitrary code with Full Trust permissions.

------------------------------------------------------------------------
Affected versions
------------------------------------------------------------------------
It has been verified that this vulnerability exists in the .NET
Framework versions 2.0, 3.0, 3.5 & 4. Earlier versions of the .NET
Framework may or may not be vulnerable as well as the affected class is
also available the .NET Framework versions 1.0 & 1.1.

------------------------------------------------------------------------
See also
------------------------------------------------------------------------
- MS12-025 [2]: Vulnerability in .NET Framework Could Allow Remote Code
Execution (2671605)
- KB2671605 [3] MS12-025: Vulnerabilities in the .NET Framework could
allow remote code execution: April 10, 2012
- SSD: [4] SecuriTeam Secure Disclosure program
- MS12-025 [5]: IKVM.NET Weblog

------------------------------------------------------------------------
Fix
------------------------------------------------------------------------
This issue was resolved with the release of MS12-025 [6]. It appears the
fix was part of a security push for System.Drawing.dll.

------------------------------------------------------------------------
Introduction
------------------------------------------------------------------------
The EncoderParameter class (System.Drawing.Imaging.EncoderParameter [7])
is used to pass a value, or an array of values, to an image encoder
(GDI+). An image encoder can be used to translate an Image or Bitmap
object to a particular file format, for example GIF, JPEG or PNG.

EncoderParameter is implemented in the System.Drawing.dll Assembly,
which is located in the Global Assembly Cache [8] (GAC). Consequently,
the Assembly is trusted by the .NET Framework and therefore this
Assembly will run with Full Trust permissions. In addition, the Assembly
is compiled with the AllowPartiallyTrustedCallers [9] attribute, which
allows it to be called from Assemblies running with Partial Trust
permissions.

------------------------------------------------------------------------
Integer overflow
------------------------------------------------------------------------
The EncoderParameter class contains various constructor methods. All of
these constructors allocate memory on the heap. The size of the
allocated buffer depends on the constructor's parameters. After
allocation, the values of these constructor parameters are copied into
the new buffer. For example the constructor EncoderParameter(Encoder,
Int64) accepts a 64-bit (8-byte) long value, thus 8 bytes are allocated
on the heap after which the value of the long parameter is copied into
this heap buffer. The heap buffer is freed by calling the Dispose()
method. This method is also called when the EncoderParameter object is
destroyed.

Some constructor methods accept one or more arrays. For these methods,
the number of allocated bytes is the size of one array member multiplied
by the number of members in the array. These methods do not check
whether the resulting integer value (used for heap allocation)
overflows. In some cases it is possible to trigger an integer overflow
resulting in the allocation of a buffer that is too small for the
supplied constructor parameters. Not all methods are exploitable as an
overly long array is required to trigger an integer overflow. The .NET
Framework limits the number of array members.

One constructor method (EncoderParameter(Encoder, Int32[], Int32[],
Int32[], Int32[])) appears to be very suitable for exploiting this
vulnerability. The implementation of this method is listed below.

public EncoderParameter(Encoder encoder,
                int[] numerator1, int[] denominator1,
                int[] numerator2, int[] denominator2)
{
        this.parameterGuid = encoder.Guid;
        if (numerator1.Length != denominator1.Length ||
                numerator1.Length != denominator2.Length ||
                denominator1.Length != denominator2.Length)
        {
                throw SafeNativeMethods.Gdip.StatusException(2);
        }
        else
        {
                this.parameterValueType = 8;
                this.numberOfValues = numerator1.Length;
                int num = Marshal.SizeOf(typeof (int));
                this.parameterValue = Marshal.AllocHGlobal(this.numberOfValues * 4 *
num);
                if (this.parameterValue == IntPtr.Zero)
                {
                        throw SafeNativeMethods.Gdip.StatusException(3);
                }
                else
                {
                        for (int index = 0; index < this.numberOfValues; ++index)
                        {
                                Marshal.WriteInt32(EncoderParameter.Add(this.parameterValue,
                                        4 * index * num), numerator1[index]);
                                Marshal.WriteInt32(EncoderParameter.Add(this.parameterValue,