tag:blogger.com,1999:blog-73563496639799685772024-03-14T16:05:01.453+08:00Reversing on WindowsCoding, Reversing, and Security Testing by <a href="https://twitter.com/reon_wi">@reon_wi</a>Attila Suszterhttp://www.blogger.com/profile/16838249167428995033noreply@blogger.comBlogger83125tag:blogger.com,1999:blog-7356349663979968577.post-5195928959961464002016-01-30T15:34:00.000+08:002016-01-31T13:55:34.836+08:00Managed out-of-bound access in DeflateStream (.NET)Recently I made a test to see the robustness of the Deflate algorithm in .NET Framework. It was written in Visual Studio 2013 using C# and DeflateStream class.<br />
<br />
The test came back with one issue worth mentioning in this blog.<br />
<br />
<b>Background</b><br />
<br />
IndexOutOfRangeException exception is thrown when the program tries to access out of the buffer boundaries. When this exception is thrown it indicates a missing or insufficient sanity check. When the sanity check works as expected it should prevent the exception from being thrown.<br />
<br />
Microsoft explains like this.<br />
<blockquote class="tr_bq">
Typically, an IndexOutOfRangeException exception is thrown as a result of developer error. Instead of handling the exception, you should diagnose the cause of the error and correct your code.</blockquote>
DeflateStream performs sanity check on the stream during the decompression and when a corrupted stream is detected InvalidDataException is being thrown.<br />
<br />
<b>The Issue</b><br />
<br />
The issue the test hit is like this. During the decompression a specially crafted stream can bypass the sanity check and so the code doesn't throw InvalidDataException. Instead it tries to access out of boundaries and IndexOutOfRangeException is thrown.<br />
<br />
The isolated testcase to reproduce the issue is like this.<br />
<br />
<span style="font-family: monospace;">using System;</span><br />
<span style="font-family: monospace;">using System.IO.Compression;</span><br />
<span style="font-family: monospace;">using System.IO;</span><br />
<span style="font-family: monospace;"><br /></span>
<span style="font-family: monospace;">namespace DeflateTestCase</span><br />
<span style="font-family: monospace;">{</span><br />
<span style="font-family: monospace;"> class Program</span><br />
<span style="font-family: monospace;"> {</span><br />
<span style="font-family: monospace;"> static Byte[] compressedData = {</span><br />
<span style="font-family: monospace;"> 0x04, 0xDF, 0x03, 0x20, 0xFC, 0xA1, 0x6F, 0x85, 0xF2, 0x2B, 0xC5, 0xA4, 0xAA, 0x8A, 0xC8, 0xB4,</span><br />
<span style="font-family: monospace;"> 0xDE, 0x3A, 0x5C, 0x06, 0xA2, 0x8C, 0xD9, 0x39, 0x41, 0xCB, 0xA6, 0x34, 0xDD, 0xCA, 0xC4, 0x2C,</span><br />
<span style="font-family: monospace;"> 0x80, 0x7C, 0xCC</span><br />
<span style="font-family: monospace;"> };</span><br />
<span style="font-family: monospace;"><br /></span>
<span style="font-family: monospace;"> static void Main(string[] args)</span><br />
<span style="font-family: monospace;"> {</span><br />
<span style="font-family: monospace;"> using (MemoryStream compressedStream = new MemoryStream(compressedData))</span><br />
<span style="font-family: monospace;"> {</span><br />
<span style="font-family: monospace;"> MemoryStream resultStream = new MemoryStream();</span><br />
<span style="font-family: monospace;"> using (DeflateStream decompressionStream = new DeflateStream(compressedStream, CompressionMode.Decompress))</span><br />
<span style="font-family: monospace;"> {</span><br />
<span style="font-family: monospace;"> try</span><br />
<span style="font-family: monospace;"> {</span><br />
<span style="font-family: monospace;"> decompressionStream.CopyTo(resultStream);</span><br />
<span style="font-family: monospace;"> }</span><br />
<span style="font-family: monospace;"> catch (System.IO.InvalidDataException e)</span><br />
<span style="font-family: monospace;"> {</span><br />
<span style="font-family: monospace;"> System.Console.WriteLine("{0}", e.Message);</span><br />
<span style="font-family: monospace;"> }</span><br />
<span style="font-family: monospace;"> catch (System.IndexOutOfRangeException e)</span><br />
<span style="font-family: monospace;"> {</span><br />
<span style="font-family: monospace;"> System.Console.WriteLine("{0}", e.Message);</span><br />
<span style="font-family: monospace;"> System.Console.WriteLine("{0}", e.StackTrace);</span><br />
<span style="font-family: monospace;"> }</span><br />
<span style="font-family: monospace;"> }</span><br />
<span style="font-family: monospace;"> }</span><br />
<span style="font-family: monospace;"> }</span><br />
<span style="font-family: monospace;"> }</span><br />
<span style="font-family: monospace;">}</span><br />
<br />
Stack trace.<br />
<br />
<span style="font-family: monospace;">c:\Dev\DeflateTestCase\bin\Release>DeflateTestCase.exe</span><br />
<span style="font-family: monospace;">Index was outside the bounds of the array.</span><br />
<span style="font-family: monospace;"> at System.IO.Compression.HuffmanTree.CreateTable()</span><br />
<span style="font-family: monospace;"> at System.IO.Compression.HuffmanTree..ctor(Byte[] codeLengths)</span><br />
<span style="font-family: monospace;"> at System.IO.Compression.Inflater.DecodeDynamicBlockHeader()</span><br />
<span style="font-family: monospace;"> at System.IO.Compression.Inflater.Decode()</span><br />
<span style="font-family: monospace;"> at System.IO.Compression.Inflater.Inflate(Byte[] bytes, Int32 offset, Int32 length)</span><br />
<span style="font-family: monospace;"> at System.IO.Compression.DeflateStream.Read(Byte[] array, Int32 offset, Int32 count)</span><br />
<span style="font-family: monospace;"> at System.IO.Stream.InternalCopyTo(Stream destination, Int32 bufferSize)</span><br />
<span style="font-family: monospace;"> at System.IO.Stream.CopyTo(Stream destination)</span><br />
<span style="font-family: monospace;"> at DeflateTestCase.Program.Main(String[] args) in c:\Dev\DeflateTestCase\Program.cs:line 24</span><br />
<br />
<b>Consequence</b><br />
<br />
If DeflateStream is used (either implicitly or expicitly) to decompress data and the data can come from untrusted source IndexOutOfRangeException is expected to happen and it should be handled in order to prevent the program from abrupt termination (DoS).<br />
<br />
The testcase can be downloaded from <a href="https://onedrive.live.com/redir?resid=3CF97A8AA9AC4799%21198374">here</a>.<br />
<br />
<b>UPDATE 31/January/2016</b> Further test confirm the same issue can be reached via a different code path from GZipStream.<br />
<br />
Stack trace.<br />
<br />
<span style="font-family: monospace;">c:\Dev\GZipTestCase\bin\Release>GZipTestCase.exe</span><br />
<span style="font-family: monospace;">Index was outside the bounds of the array.</span><br />
<span style="font-family: monospace;"> at System.IO.Compression.HuffmanTree.CreateTable()</span><br />
<span style="font-family: monospace;"> at System.IO.Compression.HuffmanTree..ctor(Byte[] codeLengths)</span><br />
<span style="font-family: monospace;"> at System.IO.Compression.Inflater.DecodeDynamicBlockHeader()</span><br />
<span style="font-family: monospace;"> at System.IO.Compression.Inflater.Decode()</span><br />
<span style="font-family: monospace;"> at System.IO.Compression.Inflater.Inflate(Byte[] bytes, Int32 offset, Int32 length)</span><br />
<span style="font-family: monospace;"> at System.IO.Compression.DeflateStream.Read(Byte[] array, Int32 offset, Int32 count)</span><br />
<span style="font-family: monospace;"> at System.IO.Compression.GZipStream.Read(Byte[] array, Int32 offset, Int32 count)</span><br />
<span style="font-family: monospace;"> at System.IO.Stream.InternalCopyTo(Stream destination, Int32 bufferSize)</span><br />
<span style="font-family: monospace;"> at System.IO.Stream.CopyTo(Stream destination)</span><br />
<span style="font-family: monospace;"> at GZipTestCase.Program.Main(String[] args) in c:\Dev\GZipTestCase\Program.cs:line 26</span><br />
<br />
The gzip testcase can be downloaded from <a href="https://onedrive.live.com/redir?resid=3CF97A8AA9AC4799%21198376">here</a> and the gzip file from <a href="https://onedrive.live.com/redir?resid=3CF97A8AA9AC4799%21198375">here</a>.Attila Suszterhttp://www.blogger.com/profile/16838249167428995033noreply@blogger.comtag:blogger.com,1999:blog-7356349663979968577.post-59911313229926802862015-08-23T12:20:00.000+08:002015-08-23T22:42:36.617+08:00Fully Managed C# Can Corrupt MemoryIn this post I'm writing about memory corruption in fully managed C# code. On the internet, many people advocate that managed C# should be immune against memory corruption. Even reputable organizations mention the same but provide no reference so people can't check the source of the information for themselves.<br />
<br />
The fact is, Microsoft don't explicitly claim whether or not managed C# should introduce memory corruption in your app.<br />
<br />
<b>Input Sanitization</b><br />
<br />
The materials made by Microsoft mentions the importance of sanitizing input values in managed code. This also means that things can go wrong if you just pass untrusted values to framework APIs.<br />
<br />
<b>AccessViolationException</b><br />
<br />
.NET Framework has the AccessViolationException exception class for accessing protected memory. The description says:<br />
<blockquote class="tr_bq">
An access violation occurs in unmanaged or unsafe code when it attempts to read or write to memory that has not been allocated, or to which it does not have access.</blockquote>
This is quite true, however, AccessViolationException can be originated from fully managed code, too.<br />
<br />
In the past months, I was doing some C# development, and during the testing, I experienced several times that my app had terminated with the sign of memory corruption:<br />
<blockquote class="tr_bq">
Attempted to read or write protected memory. This is often an indication that other memory is corrupt.</blockquote>
It looks this error is commonly seen in the search result.<br />
<br />
<b>Memory Corruption</b><br />
<br />
I did a bit of research on this topic, and wrote a simplified testcase for one of such corruption. I sent it to the people at MSRC. When they finished their investigation I received a reply from them:<br />
<blockquote class="tr_bq">
We have successfully reproduced the issue and can confirm that the memory corruption is happening within the application itself and not the system. As such, this does not appear to be a security issue and I will be closing this case.</blockquote>
The statement above is a bit vague but this is my understanding of what it means.<br />
<br />
If there is a C# API that's designed to handle untrusted data (such as a decompression API) and there is a memory corruption bug in the way the API handles the data the bug may be a security issue, and so it has to be fixed by Microsoft.<br />
<br />
However, if the bug is triggered due to an erroneous use of the C# API, such as a non-sanitized parameter is supplied, then the bug is considered to be fixed in the application.<br />
<br />
Whether the bug is in the system or application you can end up corrupting the memory in the process so it can affect the security of your app. Despite this the bug may not be qualified for a fix in the .NET framework.<br />
<br />
.NET framework manages the memory to eliminate the memory problems but this doesn't guarantee that it eliminates all the memory problems. Memory corruption in fully managed C# is possible.<br />
<br />
<b>Testcase</b><br />
<br />
<a href="https://onedrive.live.com/redir?resid=3CF97A8AA9AC4799!115402&authkey=!AAezyF6SrdZsBRY&ithint=file%2czip">The testcase</a> is a Visual Studio 2013 project that reproduces the memory corruption on Windows Phone 8.1 device and Windows Phone 8.1 Emulator.<br />
<br />
The testcase creates an array of pixels with the use of IRandomAccessStream, BitmapEncoder and Stream. When checksumming the bytes in the array the checksum changes every time the vulnerability is triggered.<br />
<br />
Checksumming is simple like this (the idea is borrowed from one of the public Flash infoleak made by Chris Evans).<br />
<br />
<code>
int checksum = 0;<br />
foreach (byte i in arr)<br />
{<br />
checksum += arr[i];<br />
}<br />
</code><br />
Sometimes the testcase crashes with AccessViolationException but most of the time it's observed that the app continues to run after the memory corruption.<br />
<div>
<br /></div>
Attila Suszterhttp://www.blogger.com/profile/16838249167428995033noreply@blogger.comtag:blogger.com,1999:blog-7356349663979968577.post-43316907108113425852015-02-24T21:00:00.000+08:002015-02-24T23:14:27.025+08:00Simple Code Coverage Analyzer<span style="font-family: Courier New, Courier, monospace;">coco.cpp</span> is a simple pintool for code coverage analysis. It comes with the Pin Framework.<br />
<br />
The reason I write a post about it is because it's really a simple but well-designed tool. The code coverage information for an executable section is stored in a vector of booleans. Each boolean represents a byte in the executable section. If the boolean is set true it means the corresponding byte has been executed. If the boolean is set false the corresponding byte is untouched.<br />
<br />
If you want the tool to produce the code coverage hash just add yourself a call that calculates the hash of the vector of booleans. This works well when the pintool is executed on small programs.<br />
<br />
However when working with more complex programs it's possible you notice that different code coverage hashes produced for seemingly similar executions. This is not an error. The code coverage can be different between the executions in the finest graduality sense. One example is when the application exits via different path between the executions.<br />
<br />
To filter these differences above you can virtually split the vector into many regions and produce the hash of each region. Now you may see that most of the hashes are the same between the executions.<br />
<br />
<b>UPDATE 24/February/2015</b> No official PIN repository to see <span style="font-family: Courier New, Courier, monospace;">coco.cpp</span> but Gunther was kind to share it via Twitter for those want to <a href="https://twitter.com/Gunther_AR/status/570233097943265280">take a look at</a> without the need to download the framework. Thx!Attila Suszterhttp://www.blogger.com/profile/16838249167428995033noreply@blogger.comtag:blogger.com,1999:blog-7356349663979968577.post-64229502719137927742015-01-18T14:13:00.000+08:002015-01-18T17:22:19.589+08:00Even Calculator Has BugsWindows Calculator (calc.exe) has a functional bug that is associated with the clipboard and the integers below.<br />
<br />
<code>
INT8_MIN -128<br />
INT16_MIN -32768<br />
INT32_MIN -2147483648<br />
INT64_MIN -9223372036854775808</code><br /><br />
In Programmer mode (View -> Programmer) when <i>Dec</i> and <i>Byte</i> are selected the minimum value the calculator can accept is -128. It's tricky to enter that value but you can do by the following four key-presses: (1) (+/-) (2) (8). I said it's tricky as you can't type (1) (2) (8) (+/-) because 128 is greater than the maximum value of INT8 that is 127. While it's a bit inconvenience it can be worked around.<br />
<br />
To reproduce the bug select <i>Dec</i> and <i>Byte</i> and type -128. Copy it to the clipboard via Edit -> Copy or Ctrl+C. Then paste it via Edit->Paste or Ctrl+V. What happens is -12 is pasted rather than -128, discarding the last digit.<br />
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; text-align: left;"><tbody>
<tr><td style="text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEZM_ASFo1N7820Sup1oGzI9O8C3oM6dD20XuHoOMAFZXtEzmayDz-vcsG0vKmn7RMKohhAzNyvBcaoxabH9b0cwzEBBuPCTK68fLLH3l-BrWVgkewH0P5J5ePgYSwRsliHxtXUhMnLuY/s1600/Calc.PNG" height="297" width="320" /></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Last digit is discarded when -128 (INT8_MIN) is pasted.</td></tr>
</tbody></table>
<br />
The effect is the same if you copy -128 in Notepad then paste it in Calculator.<br />
<br />
While a beeping sound may be heard when pasting, nothing else warns you about the error. Those who muted the speaker may not notice the error. This is especially possible when the value is long in digits (INT64_MIN) and can be easily overlooked.<br />
<br />
It's plausible that programmers use INT_MIN values in their calculations as these are commonly used when developing software.<br />
<br />
Windows 8.1 is affected by this issue. Other versions are not verified but likely affected.<br />
<br />
While this issue is most likely the limitation of the design some may find it embarrassing as a calculator has nothing else to do than to work with numbers without failure.<br />
<br />
The issue found when I was recently working on my own calculator for Windows Phone. I realized I had to deal with many corner cases and I checked how these corner cases affect Windows Calculator.Attila Suszterhttp://www.blogger.com/profile/16838249167428995033noreply@blogger.comtag:blogger.com,1999:blog-7356349663979968577.post-57599082496315705742015-01-11T15:22:00.000+08:002015-01-11T15:22:05.593+08:00Arrangement Of The Variables In Data StructuresLet's assume that an extensive code review had identified the direct security issues and the developers eliminated all. Now the code is free from bugs. How nice to write that. :-)<br />
<br />
That would not be the reason to stop code review though. There may be still things to be done to reduce the severity of potential future bugs.<br />
<br />
Newly added code can introduce and/or expose issues. The idea is to make changes in the existing code that make the exploitation of a future bug more challenging. This is good to do without introducing new issues like performance degradation, etc.<br />
<br />
Given a heap based buffer overflow, one of the common attack scenario is to overwrite a function pointer in any structure. If, however, the function pointer is at the end of the structure, the overflow may:<br />
<ul>
<li>Not be long enough to overwrite the function pointer</li>
<li>Overwrite the variables preceding the function pointer and so destroy the internal state of the application. This could lead the application to bail out early before the function gets called.</li>
</ul>
So putting the function pointer as a last item in the structure can make exploitation more challenging.<br />
<br />
A more generic suggestion in security point of view is like this. If possible, arrange the variables to have<br />
<ul>
<li>the sensitive ones at the end of the structure</li>
<li>the ones that can bail the execution out early at the beginning of the structure</li>
</ul>
Attila Suszterhttp://www.blogger.com/profile/16838249167428995033noreply@blogger.comtag:blogger.com,1999:blog-7356349663979968577.post-12919918317399740192015-01-06T21:49:00.000+08:002015-01-06T21:49:00.034+08:00EMET Can Interfere With PinSometimes no matter how simple your pintool is when it's run against the target it crashes. Recently I investigated such crash. One of my pintool was randomly crashed/hung/terminated as well as displayed memory errors.<br />
<br />
My target was added to EMET (Enhanced Mitigation Experience Toolkit). Also, EMET was running at the time of experiment. I was thinking... what if I stop EMET? I disabled all the mitigations in EMET and stopped its service. Re-launched my pintool and checked if EMET.dll and EMET64.dll are not loaded in the target's process. This time my pintool was running without any obstacle.<br />
<br />
Third party programs can make a pintool to crash. Of course, it's not a surprise but it's something to be aware of when working with a pintool.<br />
<br />
If your pintool is still crashing you may want to take look at <a href="http://reversingonwindows.blogspot.sg/2014/07/practical-suggestions-for-writing.html">one</a> of my earlier post.Attila Suszterhttp://www.blogger.com/profile/16838249167428995033noreply@blogger.comtag:blogger.com,1999:blog-7356349663979968577.post-10116005730912004862014-12-22T00:28:00.000+08:002014-12-22T00:28:12.874+08:00Use of refactor can make Visual C# 2013 to crashFor the change I'm working on a C# project not much to do with security. I was happy to re-discover and use the refactor feature in Visual C# 2013 until the point it crashed. Here are the simplified steps to reproduce the crash.<br />
<ul>
<li>Create an empty Visual C# project, or open any C# project.</li>
<li>Add a class like below.</li>
<li>Do right-click on <span style="font-family: Courier New, Courier, monospace;">hello</span> in <span style="font-family: Courier New, Courier, monospace;">hello = true</span>, select <span style="font-family: Courier New, Courier, monospace;">Refactor</span>, then select <span style="font-family: Courier New, Courier, monospace;">Remove Parameters...</span></li>
</ul>
<div class="separator" style="clear: both; text-align: left;">
<img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTnhTrIDo_d1nBEAT8Xt-_8iXMKktLSt1JjOIvg7Kbkx6ECkiPbY4hE9qsIxh00MwKBdv-8XJdgbzo1F83ljeouyX2rYtmz0PG2X4MgxUE0xmlat2Tq_-jRIp_pdG5hMlHa1pZg6b2OIw/s1600/refactor.png" /></div>
<br />
<ul>
<li>Visual C# crashes.</li>
</ul>
<div class="separator" style="clear: both; text-align: left;">
<img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcVqq_3cN946yniY-0v6gl2vOTTBojyGq5JQp-nVADVLVFD1o_RT4t9oT8E2jWVK7i4dhfpxbpo4uCm2s2kYaop7NF55HWF-Jl2Hp3-Cm7-kOlWRqoJF8MvgM5gdWZD0h1-AP-H3ckYxg/s1600/crash.png" /></div>
Note, I was able to trigger the crash by an alternate way by simply using the hotkey Ctrl+R, Ctrl+V when the cursor is within <span style="font-family: Courier New, Courier, monospace;">hello</span> in <span style="font-family: Courier New, Courier, monospace;">hello = true</span>.<br />
<br />
The bug reproduces with the up-to-date version of Visual C# 2013 Community Edition.Attila Suszterhttp://www.blogger.com/profile/16838249167428995033noreply@blogger.comtag:blogger.com,1999:blog-7356349663979968577.post-34838665078233076932014-12-19T20:53:00.000+08:002014-12-19T20:53:28.591+08:00Variable-length permutation with repetition using backtrackingRecently, I needed the implementation of the search algorithm that qualifies for the followings.<br />
<ol>
<li>It must be able to produce the variable-length permutation with repetition of the given set.</li>
<li>It must be based on backtracking.</li>
<li>It must be a state machine.</li>
<li>It must have basic programming elements only.</li>
<li>It must be clean without irrelevant part.</li>
</ol>
Even I needed the final implementation in ActionScript, I was searching for the algorithm in C that I would convert later. Thought my odds would be better if I did so. Unluckily I didn't find anything useful, and so I wrote the code myself. Here is the sample implementation in C.<br />
<br />
<span style="font-family: monospace;">// Features:</span><br />
<span style="font-family: monospace;">// - Variable-length permutation with repetition</span><br />
<span style="font-family: monospace;">// - Backtracking</span><br />
<span style="font-family: monospace;">// - State machine</span><br />
<span style="font-family: monospace;"><br /></span>
<span style="font-family: monospace;">#include <stdio.h></span><br />
<span style="font-family: monospace;"><br /></span>
<span style="font-family: monospace;">#define ITEMS 3 // number of items</span><br />
<span style="font-family: monospace;">#define LASTITEM_IDX (ITEMS-1) // index of the last item</span><br />
<span style="font-family: monospace;">#define INIT -1 // initial value</span><br />
<span style="font-family: monospace;">#define EMPTY 0 // empty</span><br />
<span style="font-family: monospace;"><br /></span>
<span style="font-family: monospace;">static char set[ITEMS] = {1,2,3}; // set</span><br />
<span style="font-family: monospace;"><br /></span>
<span style="font-family: monospace;">// State</span><br />
<span style="font-family: monospace;">static char idx[ITEMS] = {INIT,INIT,INIT}; // indices into set</span><br />
<span style="font-family: monospace;">static char out[ITEMS] = {EMPTY,EMPTY,EMPTY}; // output</span><br />
<span style="font-family: monospace;"><br /></span>
<span style="font-family: monospace;">static int index = INIT;</span><br />
<span style="font-family: monospace;">static bool dir = 1; // direction: deep(1) / wide(0)</span><br />
<span style="font-family: monospace;">// State - END</span><br />
<span style="font-family: monospace;"><br /></span>
<span style="font-family: monospace;">bool backtrack();</span><br />
<span style="font-family: monospace;"><br /></span>
<span style="font-family: monospace;">// item to try</span><br />
<span style="font-family: monospace;">void add_item() {</span><br />
<span style="font-family: monospace;"> idx[index]++;</span><br />
<span style="font-family: monospace;"> out[index] = set[idx[index]];</span><br />
<span style="font-family: monospace;">}</span><br />
<span style="font-family: monospace;"><br /></span>
<span style="font-family: monospace;">bool step_wide() {</span><br />
<span style="font-family: monospace;"> if (index == INIT) {</span><br />
<span style="font-family: monospace;"> // reached initial level</span><br />
<span style="font-family: monospace;"> // no more items to take</span><br />
<span style="font-family: monospace;"> return false;</span><br />
<span style="font-family: monospace;"> }</span><br />
<span style="font-family: monospace;"> // way to go wider?</span><br />
<span style="font-family: monospace;"> if (idx[index] < LASTITEM_IDX) {</span><br />
<span style="font-family: monospace;"> add_item(); // take item</span><br />
<span style="font-family: monospace;"> return true;</span><br />
<span style="font-family: monospace;"> }</span><br />
<span style="font-family: monospace;"> else {</span><br />
<span style="font-family: monospace;"> return backtrack(); // backtrack a level higher</span><br />
<span style="font-family: monospace;"> }</span><br />
<span style="font-family: monospace;">}</span><br />
<span style="font-family: monospace;"><br /></span>
<span style="font-family: monospace;">bool backtrack() {</span><br />
<span style="font-family: monospace;"> // backtrack a level higher</span><br />
<span style="font-family: monospace;"> idx[index] = INIT;</span><br />
<span style="font-family: monospace;"> out[index] = EMPTY;</span><br />
<span style="font-family: monospace;"> index--;</span><br />
<span style="font-family: monospace;"><br /></span>
<span style="font-family: monospace;"> return step_wide();</span><br />
<span style="font-family: monospace;">}</span><br />
<span style="font-family: monospace;"><br /></span>
<span style="font-family: monospace;">bool step_deep() {</span><br />
<span style="font-family: monospace;"> // way to go deeper?</span><br />
<span style="font-family: monospace;"> if (index < LASTITEM_IDX) {</span><br />
<span style="font-family: monospace;"> index++; // step a level deeper</span><br />
<span style="font-family: monospace;"> add_item(); // take item</span><br />
<span style="font-family: monospace;"> return true;</span><br />
<span style="font-family: monospace;"> }</span><br />
<span style="font-family: monospace;"> else {</span><br />
<span style="font-family: monospace;"> return step_wide(); // step wide</span><br />
<span style="font-family: monospace;"> }</span><br />
<span style="font-family: monospace;">}</span><br />
<span style="font-family: monospace;"><br /></span>
<span style="font-family: monospace;">// returns true if step is successful</span><br />
<span style="font-family: monospace;">// returns false if no more items to take</span><br />
<span style="font-family: monospace;">bool step() {</span><br />
<span style="font-family: monospace;"> if (dir) {</span><br />
<span style="font-family: monospace;"> return step_deep();</span><br />
<span style="font-family: monospace;"> } else {</span><br />
<span style="font-family: monospace;"> return step_wide();</span><br />
<span style="font-family: monospace;"> }</span><br />
<span style="font-family: monospace;">}</span><br />
<span style="font-family: monospace;"><br /></span>
<span style="font-family: monospace;">int main(int argc, char* argv[])</span><br />
<span style="font-family: monospace;">{</span><br />
<span style="font-family: monospace;"> while (step()) {</span><br />
<span style="font-family: monospace;"> for (int i=0; i<ITEMS && out[i]!=EMPTY; i++) {</span><br />
<span style="font-family: monospace;"> printf("%02x ", out[i]);</span><br />
<span style="font-family: monospace;"> }</span><br />
<span style="font-family: monospace;"> printf("\n");</span><br />
<span style="font-family: monospace;"> }</span><br />
<span style="font-family: monospace;"><br /></span>
<span style="font-family: monospace;"> return 0;</span><br />
<span style="font-family: monospace;">}</span><br />
<div>
<br /></div>
The source can be downloaded from <a href="https://onedrive.live.com/redir?resid=3CF97A8AA9AC4799%2129666">here</a>.<br />
<br />
The output of the run looks like this.<br />
<br />
<span style="font-family: monospace;">01</span><br />
<span style="font-family: monospace;">01 01</span><br />
<span style="font-family: monospace;">01 01 01</span><br />
<span style="font-family: monospace;">01 01 02</span><br />
<span style="font-family: monospace;">01 01 03</span><br />
<span style="font-family: monospace;">01 02</span><br />
<span style="font-family: monospace;">01 02 01</span><br />
<span style="font-family: monospace;">01 02 02</span><br />
<span style="font-family: monospace;">01 02 03</span><br />
<span style="font-family: monospace;">01 03</span><br />
<span style="font-family: monospace;">01 03 01</span><br />
<span style="font-family: monospace;">01 03 02</span><br />
<span style="font-family: monospace;">01 03 03</span><br />
<span style="font-family: monospace;">02</span><br />
<span style="font-family: monospace;">02 01</span><br />
<span style="font-family: monospace;">02 01 01</span><br />
<span style="font-family: monospace;">02 01 02</span><br />
<span style="font-family: monospace;">02 01 03</span><br />
<span style="font-family: monospace;">02 02</span><br />
<span style="font-family: monospace;">02 02 01</span><br />
<span style="font-family: monospace;">02 02 02</span><br />
<span style="font-family: monospace;">02 02 03</span><br />
<span style="font-family: monospace;">02 03</span><br />
<span style="font-family: monospace;">02 03 01</span><br />
<span style="font-family: monospace;">02 03 02</span><br />
<span style="font-family: monospace;">02 03 03</span><br />
<span style="font-family: monospace;">03</span><br />
<span style="font-family: monospace;">03 01</span><br />
<span style="font-family: monospace;">03 01 01</span><br />
<span style="font-family: monospace;">03 01 02</span><br />
<span style="font-family: monospace;">03 01 03</span><br />
<span style="font-family: monospace;">03 02</span><br />
<span style="font-family: monospace;">03 02 01</span><br />
<span style="font-family: monospace;">03 02 02</span><br />
<span style="font-family: monospace;">03 02 03</span><br />
<span style="font-family: monospace;">03 03</span><br />
<span style="font-family: monospace;">03 03 01</span><br />
<span style="font-family: monospace;">03 03 02</span><br />
<span style="font-family: monospace;">03 03 03</span>Attila Suszterhttp://www.blogger.com/profile/16838249167428995033noreply@blogger.comtag:blogger.com,1999:blog-7356349663979968577.post-33927082142931005852014-08-09T18:51:00.003+08:002014-08-09T18:57:42.553+08:00Instrumenting Flash Player to Inspect JITted Pages for Integer ErrorsIn this blog post I'm writing about the method I experiment with to discover potential areas, that may or may not be prone to integer errors, in Flash Player.<br />
<br />
I have 26k flash files that are used as a corpus to generate the test samples for Flash Player. The test samples have an element of 0x41424241 in the integer pool. I have a total of 344k files generated to test Flash Player with.<br />
<br />
During the test, I use a pintool to instrument the JITted code. The pintool is based on <a href="https://traceandwatch.codeplex.com/">this</a> implementation. Since the elements in the integer pool being dereferenced by action script it makes sense to restrict the instrumentation to JITted code.<br />
<br />
I use instruction-level instrumentation that allows to check the register values at every single instruction being executed. If any of the general registers have the value of 0x41424241 and the instruction is referencing to that register, the instruction information along with general registers are logged.<br />
<br />
The pintool pre-allocates the address of 0x41424241 so Flash Player won't use that memory address and so reducing the irrelevant lines in the log.<br />
<br />
There is no need to wait for the test to finish to get partial results. A log file is generated for each test file rendered by Flash Player.<br />
<br />
The size of log files are vary. Some are close to size 0 specially if the value above makes the code to fail early. There are many log files with size 4k. When the execution keeps going long the size is about 16k. If the value has to do something with a loop the log can reach 100k but that's rare.<br />
<br />
Logs can be grouped and many can be thrown away as they don't contain instructions associated with vulnerabilities.<br />
<br />
What I look for is like <a href="http://reversingonwindows.blogspot.com/2014/07/inspection-of-sar-instructions.html">signed shift</a>, addition, subtraction, or <a href="http://reversingonwindows.blogspot.com/2014/04/inspection-of-division-multiplication.html">multiplication</a> instructions. If the value is used in displacement with lea instruction that counts suspicious too.<br />
<br />
Once an address in the log is chosen for closer inspection, I reproduce the log on isolation with an option to dump the JITted pages so I can manually analyze the surrounding area of that address in disassembler. Knowing the state information it's also possible to debug the code.<br />
<br />
If results positive, certain level of automation can be added.Attila Suszterhttp://www.blogger.com/profile/16838249167428995033noreply@blogger.comtag:blogger.com,1999:blog-7356349663979968577.post-24046847803792680472014-07-30T19:48:00.000+08:002014-07-30T19:48:13.391+08:00Practical Suggestions for Writing a PintoolThis is my list of practical suggestions to people developing a pintool. Since I dealt with these previously I thought to jot them down to help others. By applying this you should be somewhat closer to avoid your pintool from unexpected termination.<br />
<br />
<b>Start from scratch.</b> So you use a sample pintool to develop your own. Rather than to modify the sample, start with an empty project and gradually build it up by taking elements from the sample.<br />
<br />
<b>Simplicity.</b> Keep the code-base small and easy to understand.<br />
<br />
<b>Testing.</b> As a part of development, aim to test if all blocks have been exercised. Refrain from adding unreachable blocks.<br />
<br />
<b>Errors.</b> Check for errors as early as possible, specially when returning from a Pin API.<br />
<br />
<b>Safe memory dereference.</b> Whenever you have to dereference the target's memory use PIN_SafeCopy. If you want to read an integer you should use this function, too, rather than the dereference "*" operator.<br />
<br />
<b>Thread safety.</b> Be aware the target may be running with multiple threads. Possibly, you want your pintool to be thread safe.<br />
<br />
<b>Multi-threading.</b> Sometimes you want your variables to be stored in the thread context to have the ability to distinguish the analysis between threads. In that case looking at the sample inscount_tls.cpp is a good start.<br />
<br />
<b>Probe mode.</b> Use of probe mode is always preferred as it gives better performance. However, only limited Pin facilities available in probe mode.<br />
<br />
<b>Limit instrumentation.</b> Consider restricting the instrumentation to routines or libraries and even can avoid the instrumentation of shared libraries to get better performance.<br />
<br />
<b>Standard library.</b> It's good idea to use C++ standard library in a pintool as it provides the most frequently needed data structures.<br />
<br />
<b>Visual Studio.</b> Visual C++ project file is available with Pin framework in MyPinTool folder. Alternatively, you can create one for yourself after looking at an <a href="http://reversingonwindows.blogspot.com/2013/06/sample-pintools-for-visual-studio.html">earlier post</a>.<br />
<br />
<b>Trace vs Ins. </b>Instruction instrumentation is practically the same as trace instrumentation. You can do instruction analysis from the trace by iterating through the instructions.<br />
<br />
<b>Output.</b> Having output routines in Fini makes the application to run faster than having them in analysis functions. However if the application terminates unexpectedly and so Fini is not called there will be no results shown. By having output routines in analysis functions makes the application to run slower but if the application terminates unexpectedly partial results may be shown.Attila Suszterhttp://www.blogger.com/profile/16838249167428995033noreply@blogger.comtag:blogger.com,1999:blog-7356349663979968577.post-41318266142408619862014-07-26T18:05:00.000+08:002014-07-26T18:05:24.340+08:00Inspection of SAR InstructionsSAR stands for Shift Arithmetic Right and the instruction performs arithmetic shift. The instruction preserves the sign of the value to be shifted and so the vacant bits are filled according to the sign-bit.<br />
<br />
Compilers generate SAR instruction when right shift operator ">>" is used on a signed integer.<br />
<br />
The use of SAR instruction can potentially lead to create a signedness bug if it's assumed the shift is unsigned.<br />
<br />
Given the following simplified example.<br />
<br />
<span style="font-family: monospace;">char retItem(char* arr, int value)</span><br />
<span style="font-family: monospace;">{</span><br />
<span style="font-family: monospace;"> return arr[value>>24];</span><br />
<span style="font-family: monospace;">}</span><br />
<br />
If <code>value</code> is positive the code is working as expected. However if <code>value</code> is negative the program can read out of the bounds of <code>arr</code>.<br />
<br />
Other example would be to compare the signed value after the shift to an unsigned value leading to implicit conversion that may lead to trigger bug.<br />
<br />
In my experiment, in several cases, it is seen that memory is being dereferenced involving SAR instruction. These places may be worthy to look for bugs, specially if the value to be shifted is a user input or is a controlled one.<br />
<br />
If an unsigned jump is followed by a signed shift that could be a potential to look for bugs as well.<br />
<br />
Regular expressions or scripts can be used to search for patterns of occurrences of SAR instructions. When it's not feasible to review all occurrences of SAR, a pintool may be used to highlight what SAR instructions have been executed, and only focus on those executed.Attila Suszterhttp://www.blogger.com/profile/16838249167428995033noreply@blogger.comtag:blogger.com,1999:blog-7356349663979968577.post-32876610314060105642014-07-22T18:01:00.001+08:002014-07-22T18:01:14.906+08:00Examining Native Code by Looking for PatternsEarlier this year a post was published of <a href="http://reversingonwindows.blogspot.com/2014/04/examining-unknown-binary-formats.html">examining data format</a> without using the program that reads the format. That post discusses patterns to look for, in order to identify certain constructs. This post focuses on static methods of examining code that can be either the complete code section of the file, memory dump, or just fragment. It also describes selected ideas what patterns to look for when examining a given code.<br />
<br />
The reason one may look for patterns in code is to locate certain functionalities or to get high-level understanding of what the code does. Others may look for certain construct that may be the key part of the program in security point of view.<br />
<br />
It's true to say one can expect this to be a rapid method compared to other methods such as line-by-line instruction analysis.<br />
<br />
But, it's always good to read documentation, if possible at all, to get an overview of the expectations.<br />
<br />
There are methods that more effective if performed on small region. Therefore to narrow the scope of the search wherein to look for pattern is something good to do at the beginning of analysis albeit it's not always feasible to do with enough certainty. Anyway, one can always widen the search region if required at a later stage.<br />
<br />
Compilers tend to produce executable files with particular layout. Some have the library code at the beginning of the code section, while others have it at the end of the code section.<br />
<br />
If there is no information about the compiler or no information about the layout there are other ways to locate the library in the code.<br />
<br />
You may look for library function calls that can be visible in disassembler. Library code may have distinct color in disassembler.<br />
<br />
Library/runtime code often have many implementations of functions to use the advantage of latest hardware. An example is MSVC. And so SSE instructions/functions may indicate the presence of library/runtime code.<br />
<br />
Library code can be spotted by looking for strings can be associated with particular libraries.<br />
<br />
Library/runtime code can be spotted by looking for constant values that can be associated with particular libraries such as cryptographic libraries that tend to have many constants.<br />
<br />
To guess the compiler that was used to generate the code is possible by analyzing the library/runtime code.<br />
<br />
In case the code is just a fragment of user code you may consider examining the instructions how they are encoded. Intel encodings are redundant and one instruction can have multiple encodings. This is something to make guess on what compiler was used.<br />
<br />
If multiple encodings of an instruction is found in a binary the code that could be generated with a polymorphic encoder.<br />
<br />
Also, code has other characteristics that may differ between compilers such as padding and stack allocation.<br />
<br />
Imports and exports as well as strings can tell a lot. You may check where they are referenced in the code.<br />
<br />
Debugging symbols can help awfully lot if the disassembler can handle that. Sometimes it's available sometimes it's not.<br />
<br />
No matter what code you're looking at it most likely deals with input data. That case it may get the data from file, from network, via standard API calls. These are valuable areas to audit for security problems, and it's possible to follow how the data returned by these APIs. It may require to analyze caller functions as usually these APIs are wrapped around many calls before using the input.<br />
<br />
Just like when reading the data the code may write data, or send data via standard API calls. These areas may be security-sensitive.<br />
<br />
Programs have centralized, well-established functions. These functions, for example, read dword values, read data into structures and propagate any other internal storage. Discovery of these functions not considered hard, they are normally small, and have instructions of memory read and write. By looking where they referenced from we can find good attack surfaces.<br />
<br />
Good to keep in mind that code sections can contain data besides code. But normally data is stored in data section. In the disassembler it's convenient to see how the data is referenced, and may decide if there is an attack surface nearby.<br />
<br />
CRC and hash constants may indicate there is some data which is being CRC'd or hashed. You may figure out where is that data from and how can you perform security testing around.<br />
<br />
When a library is using a parameter hardcoded it's often encoded as a part of the instruction rather than stored in data section of the executable. Example encoding looks like mov eax, <param> or mov al, <param>.<br />
<br />
When a data format is parsed often a magic value is tested. Looking for instructions like cmp reg, <magic> or cmp dword ptr [addr], <magic> or similar instructions can help to locate attack surfaces.<br />
<br />
Longer strings may be broken into immediate values and compared with multiple cmp instructions.<br />
<br />
Looking for strcmp function calls is good idea to look for if you want to find code that test for data format as often strcmp functions are used for this purpose.<br />
<br />
If the code is optimized for speed there are many ways to confirm. Normally the readability of code bad, for example when the code performs division or use the same memory address for multiple variables. If EBP register is used in arithmetic or other than to store stack base address that could indicate the code is optimized.<br />
<br />
Perhaps there are circumstances when looking at the frequency of instructions, looking for undocumented instructions, or rare instruction, or instructions that not present can give us valuable clues that help the examination.<br />
<br />
Intuitively going through the code and looking for undefined patterns can be good idea if the scientific ways have been exhausted.Attila Suszterhttp://www.blogger.com/profile/16838249167428995033noreply@blogger.comtag:blogger.com,1999:blog-7356349663979968577.post-64423246019027643302014-07-16T18:03:00.000+08:002014-07-16T18:03:14.897+08:00251 Potential NULL Pointer Dereferences in Flash Player251 potential NULL pointer dereference issues have been identified in Flash Player 14 by pattern matching approach. The file examined is NPSWF32_14_0_0_145.dll (17,029,808 bytes).<br />
<br />
The issues are classified as <a href="http://cwe.mitre.org/data/definitions/690.html">CWE-690: Unchecked Return Value to NULL Pointer Dereference</a>.<br />
<br />
I don't copy&paste all the issues in this blog post but bringing up few examples.<br />
<h4>
First Example</h4>
<span style="font-family: monospace;">0:012> uf 5438a1d0</span><br />
<span style="font-family: monospace;">NPSWF32_14_0_0_145!BrokerMainW+0xf6f6b:</span><br />
<span style="font-family: monospace;">5438a1d0 f6410810 test byte ptr [ecx+8],10h</span><br />
<span style="font-family: monospace;">5438a1d4 8b4104 mov eax,dword ptr [ecx+4]</span><br />
<span style="font-family: monospace;">5438a1d7 7411 je NPSWF32_14_0_0_145!BrokerMainW+0xf6f85 (5438a1ea)</span><br />
<span style="font-family: monospace;"><br /></span>
<span style="font-family: monospace;">NPSWF32_14_0_0_145!BrokerMainW+0xf6f74:</span><br />
<span style="font-family: monospace;">5438a1d9 85c0 test eax,eax</span><br />
<span style="font-family: monospace;">5438a1db 740b je NPSWF32_14_0_0_145!BrokerMainW+0xf6f83 (5438a1e8)</span><br />
<span style="font-family: monospace;"><br /></span>
<span style="font-family: monospace;">NPSWF32_14_0_0_145!BrokerMainW+0xf6f78:</span><br />
<span style="font-family: monospace;">5438a1dd 8b4c2404 mov ecx,dword ptr [esp+4]</span><br />
<span style="font-family: monospace;">5438a1e1 8b448808 mov eax,dword ptr [eax+ecx*4+8]</span><br />
<span style="font-family: monospace;">5438a1e5 c20400 ret 4</span><br />
<span style="font-family: monospace;"><br /></span>
<span style="font-family: monospace;">NPSWF32_14_0_0_145!BrokerMainW+0xf6f83:</span><br />
<span style="background-color: yellow; font-family: monospace;">5438a1e8 33c0 xor eax,eax <--Set return value to NULL</span><br />
<span style="font-family: monospace;"><br /></span>
<span style="font-family: monospace;">NPSWF32_14_0_0_145!BrokerMainW+0xf6f85:</span><br />
<span style="background-color: yellow; font-family: monospace;">5438a1ea c20400 ret 4 <--Return with NULL</span><br />
<span style="font-family: monospace;">0:012> u 5438a47b L2</span><br />
<span style="font-family: monospace;">NPSWF32_14_0_0_145!BrokerMainW+0xf7216:</span><br />
<span style="font-family: monospace;">5438a47b e850fdffff call NPSWF32_14_0_0_145!BrokerMainW+0xf6f6b (5438a1d0)</span><br />
<span style="background-color: yellow;"><span style="font-family: monospace;">5438a480 8a580c mov bl,byte ptr [eax+0Ch] <--Dereference NULL</span> </span><br />
<h4>
Second Example</h4>
<span style="font-family: monospace;">0:012> uf 54362e60</span><br />
<span style="font-family: monospace;">NPSWF32_14_0_0_145!BrokerMainW+0xcfbfb:</span><br />
<span style="font-family: monospace;">54362e60 8b4128 mov eax,dword ptr [ecx+28h]</span><br />
<span style="font-family: monospace;">54362e63 8b4c2404 mov ecx,dword ptr [esp+4]</span><br />
<span style="font-family: monospace;">54362e67 3b4804 cmp ecx,dword ptr [eax+4]</span><br />
<span style="font-family: monospace;">54362e6a 7205 jb NPSWF32_14_0_0_145!BrokerMainW+0xcfc0c (54362e71)</span><br />
<span style="font-family: monospace;"><br /></span>
<span style="font-family: monospace;">NPSWF32_14_0_0_145!BrokerMainW+0xcfc07:</span><br />
<span style="background-color: yellow; font-family: monospace;">54362e6c 33c0 xor eax,eax <--Set return value to NULL</span><br />
<span style="background-color: yellow; font-family: monospace;">54362e6e c20400 ret 4 <--Return with NULL</span><br />
<span style="font-family: monospace;"><br /></span>
<span style="font-family: monospace;">NPSWF32_14_0_0_145!BrokerMainW+0xcfc0c:</span><br />
<span style="font-family: monospace;">54362e71 56 push esi</span><br />
<span style="font-family: monospace;">54362e72 8b748808 mov esi,dword ptr [eax+ecx*4+8]</span><br />
<span style="font-family: monospace;">54362e76 56 push esi</span><br />
<span style="font-family: monospace;">54362e77 e8e4b0faff call NPSWF32_14_0_0_145!BrokerMainW+0x7acfb (5430df60)</span><br />
<span style="font-family: monospace;">54362e7c 83c404 add esp,4</span><br />
<span style="font-family: monospace;">54362e7f 85c0 test eax,eax</span><br />
<span style="font-family: monospace;">54362e81 7407 je NPSWF32_14_0_0_145!BrokerMainW+0xcfc25 (54362e8a)</span><br />
<span style="font-family: monospace;"><br /></span>
<span style="font-family: monospace;">NPSWF32_14_0_0_145!BrokerMainW+0xcfc1e:</span><br />
<span style="font-family: monospace;">54362e83 8b4010 mov eax,dword ptr [eax+10h]</span><br />
<span style="font-family: monospace;">54362e86 5e pop esi</span><br />
<span style="font-family: monospace;">54362e87 c20400 ret 4</span><br />
<span style="font-family: monospace;"><br /></span>
<span style="font-family: monospace;">NPSWF32_14_0_0_145!BrokerMainW+0xcfc25:</span><br />
<span style="font-family: monospace;">54362e8a 8bc6 mov eax,esi</span><br />
<span style="font-family: monospace;">54362e8c 83e0f8 and eax,0FFFFFFF8h</span><br />
<span style="font-family: monospace;">54362e8f 5e pop esi</span><br />
<span style="font-family: monospace;">54362e90 c20400 ret 4</span><br />
<span style="font-family: monospace;">0:012> u NPSWF32_14_0_0_145+006b4eb2 L2</span><br />
<span style="font-family: monospace;">NPSWF32_14_0_0_145!BrokerMainW+0xd1c4d:</span><br />
<span style="font-family: monospace;">54364eb2 e8a9dfffff call NPSWF32_14_0_0_145!BrokerMainW+0xcfbfb (54362e60)</span><br />
<span style="background-color: yellow; font-family: monospace;">54364eb7 8b7004 mov esi,dword ptr [eax+4] <--Dereference NULL</span><br />
<h4>
Third Example</h4>
<span style="font-family: monospace;">0:012> uf 5429979a</span><br />
<span style="font-family: monospace;">NPSWF32_14_0_0_145!BrokerMainW+0x6535:</span><br />
<span style="font-family: monospace;">5429979a 0fb74108 movzx eax,word ptr [ecx+8]</span><br />
<span style="font-family: monospace;">5429979e 48 dec eax</span><br />
<span style="font-family: monospace;">5429979f 48 dec eax</span><br />
<span style="font-family: monospace;">542997a0 740c je NPSWF32_14_0_0_145!BrokerMainW+0x6549 (542997ae)</span><br />
<span style="font-family: monospace;"><br /></span>
<span style="font-family: monospace;">NPSWF32_14_0_0_145!BrokerMainW+0x653d:</span><br />
<span style="font-family: monospace;">542997a2 83e815 sub eax,15h</span><br />
<span style="font-family: monospace;">542997a5 7403 je NPSWF32_14_0_0_145!BrokerMainW+0x6545 (542997aa)</span><br />
<span style="font-family: monospace;"><br /></span>
<span style="font-family: monospace;">NPSWF32_14_0_0_145!BrokerMainW+0x6542:</span><br />
<span style="background-color: yellow; font-family: monospace;">542997a7 33c0 xor eax,eax <--Set return value to NULL</span><br />
<span style="background-color: yellow; font-family: monospace;">542997a9 c3 ret <--Return with NULL</span><br />
<span style="font-family: monospace;"><br /></span>
<span style="font-family: monospace;">NPSWF32_14_0_0_145!BrokerMainW+0x6545:</span><br />
<span style="font-family: monospace;">542997aa 8d4110 lea eax,[ecx+10h]</span><br />
<span style="font-family: monospace;">542997ad c3 ret</span><br />
<span style="font-family: monospace;"><br /></span>
<span style="font-family: monospace;">NPSWF32_14_0_0_145!BrokerMainW+0x6549:</span><br />
<span style="font-family: monospace;">542997ae 8d410c lea eax,[ecx+0Ch]</span><br />
<span style="font-family: monospace;">542997b1 c3 ret</span><br />
<span style="font-family: monospace;">0:012> u NPSWF32_14_0_0_145+005f3423 L2</span><br />
<span style="font-family: monospace;">NPSWF32_14_0_0_145!BrokerMainW+0x101be:</span><br />
<span style="font-family: monospace;">542a3423 e87263ffff call NPSWF32_14_0_0_145!BrokerMainW+0x6535 (5429979a)</span><br />
<span style="background-color: yellow; font-family: monospace;">542a3428 8038fe cmp byte ptr [eax],0FEh <--Dereference NULL</span><br />
<br />
You can find a list of 251 potential NULL pointer dereferences in Flash Player <a href="https://onedrive.live.com/redir?resid=3CF97A8AA9AC4799!29051&authkey=!AJ3WRTvAOj9J2WQ&ithint=file%2c.txt">here</a>.Attila Suszterhttp://www.blogger.com/profile/16838249167428995033noreply@blogger.comtag:blogger.com,1999:blog-7356349663979968577.post-25736811390106370302014-07-14T19:09:00.000+08:002014-07-14T19:10:18.038+08:00Issues with Flash Player & Firefox in Non-default ConfigurationsFew months ago I encountered a bug when a fuzzed flash file is being rendered by Flash Player in Firefox. This bug can be reached only in the non-default configuration described below so very unlikely you are affected by this bug.<br />
<br />
To trigger the bug the flash player module has to be loaded into Firefox's virtual address space. And this can be achieved if Flash Player protected mode is disabled and Firefox plugin container process is disabled too.<br />
<br />
The bug involves to dereference arbitrary memory address via a CALL instruction in the vtable dispatcher. Here you can see the bug in the exception state.<br />
<code><br /></code>
<span style="font-family: monospace;">0:048> g</span><br />
<span style="font-family: monospace;">Implementation limit exceeded: attempting to allocate too-large object</span><br />
<span style="font-family: monospace;">error: out of memory</span><br />
<span style="font-family: monospace;">(170fc.16998): Access violation - code c0000005 (first chance)</span><br />
<span style="font-family: monospace;">First chance exceptions are reported before any exception handling.</span><br />
<span style="font-family: monospace;">This exception may be expected and handled.</span><br />
<span style="font-family: monospace;">eax=00000001 ebx=00000000 ecx=0034f670 edx=00000000 esi=1600f2c8 edi=0000001c</span><br />
<span style="font-family: monospace;">eip=5996bd5f esp=0034f638 ebp=0034f668 iopl=0 nv up ei pl nz na po nc</span><br />
<span style="font-family: monospace;">cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010202</span><br />
<span style="font-family: monospace;">*** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\Windows\SysWOW64\Macromed\Flash\NPSWF32_14_0_0_145.dll - </span><br />
<span style="font-family: monospace;">NPSWF32_14_0_0_145!unuse_netscape_plugin_Plugin+0x5c2:</span><br />
<span style="font-family: monospace;">5996bd5f 8b461c mov eax,dword ptr [esi+1Ch] ds:002b:1600f2e4=????????</span><br />
<span style="font-family: monospace;">0:000> u eip L10</span><br />
<span style="font-family: monospace;">NPSWF32_14_0_0_145!unuse_netscape_plugin_Plugin+0x5c2:</span><br />
<span style="font-family: monospace;">5996bd5f 8b461c <span style="background-color: yellow;">mov eax,dword ptr [esi+1Ch]</span> <--Read unmapped address</span><br />
<span style="font-family: monospace;">5996bd62 a801 test al,1</span><br />
<span style="font-family: monospace;">5996bd64 7420 je NPSWF32_14_0_0_145!unuse_netscape_plugin_Plugin+0x5e9 (5996bd86)</span><br />
<span style="font-family: monospace;">5996bd66 33d2 xor edx,edx</span><br />
<span style="font-family: monospace;">5996bd68 39550c cmp dword ptr [ebp+0Ch],edx</span><br />
<span style="font-family: monospace;">5996bd6b 7519 jne NPSWF32_14_0_0_145!unuse_netscape_plugin_Plugin+0x5e9 (5996bd86)</span><br />
<span style="font-family: monospace;">5996bd6d 8b4e04 mov ecx,dword ptr [esi+4]</span><br />
<span style="font-family: monospace;">5996bd70 83e0fe and eax,0FFFFFFFEh</span><br />
<span style="font-family: monospace;">5996bd73 89461c mov dword ptr [esi+1Ch],eax</span><br />
<span style="font-family: monospace;">5996bd76 8b06 <span style="background-color: yellow;">mov eax,dword ptr [esi]</span> <--Read unmapped address</span><br />
<span style="font-family: monospace;">5996bd78 51 push ecx</span><br />
<span style="font-family: monospace;">5996bd79 8bce mov ecx,esi</span><br />
<span style="font-family: monospace;">5996bd7b 895604 mov dword ptr [esi+4],edx</span><br />
<span style="font-family: monospace;">5996bd7e 895618 mov dword ptr [esi+18h],edx</span><br />
<span style="font-family: monospace;">5996bd81 ff500c <span style="background-color: yellow;">call dword ptr [eax+0Ch]</span> <--Dereference arbitrary memory content</span><br />
<span style="font-family: monospace;">5996bd84 eb06 jmp NPSWF32_14_0_0_145!unuse_netscape_plugin_Plugin+0x5ef (5996bd8c)</span><br />
<br />
I had reported this bug to Adobe and they opened a case PSIRT-2707 on 14/April/2014 but so far Adobe didn't confirm whether or not it was able to reproduce the bug or the exception state reported.<br />
<br />
Again, the bug doesn't affect the default configuration, and so very unlikely you're affected by this. However, users using Firefox with plugin-container disabled as well as Flash Player plugin with protected mode disabled are affected by this issue.<br />
<br />
The original report is about Flash Player 13_0_0_182 and Firefox 28.0 but the testcase fails with Flash Player 14_0_0_145 and Firefox 30.0 (latest available till today).<br />
<br />
These are the steps to reproduce the bug.<br />
<ul>
<li>Edit mms.cfg to have ProtectedMode=0 to disable protected mode in Flash Player</li>
<li>Start cmd.exe and type "set MOZ_DISABLE_OOP_PLUGINS=1" to disable plugin-container in Firefox</li>
</ul>
These settings above required to get Flash Player plugin loaded in firefox.exe's address space.<br />
<ul>
<li>Start Firefox from command prompt opened previously</li>
<li>Open fuzzed.swf in Firefox (drag n drop should work)</li>
<li>Attach firefox.exe process to Windbg when you notice that Firefox is hanging</li>
<li>Exception should occur in few second. If you see the out-of-memory error in the debugger log without exception you may restart the browser and try again.</li>
</ul>
The fuzzed flash file has the following changes compared to the template file. The value of the first item in the integer pool has been changed to a large value. TagLength of DoAbc tag and FileSize of the main header have been therefore updated to maintain the integrity of the flash file.<br />
<br />
Drop me an email if you think you need the testcase.Attila Suszterhttp://www.blogger.com/profile/16838249167428995033noreply@blogger.comtag:blogger.com,1999:blog-7356349663979968577.post-9257514314552685702014-05-13T17:03:00.000+08:002014-05-16T13:59:54.542+08:00Security Implications of IsBad*Ptr Calls in BinariesIsBad*Ptr [1] functions are to test whether the memory range specified in the argument list is accessible. Despite the fact they have been banned, they are still being referenced in many binaries shipped with popular applications.<br />
<div>
<br />
In this post I'm describing the inner working of IsBad*Ptr, the steps the attacker may follow to abuse them, and mention few examples of binaries that have a reference to these banned functions.<br />
<h4>
Inner Working</h4>
When IsBad*Ptr is executed it first registers an exception handler. Then, it attempts to access to the memory specified in the argument list.<br />
<br />
For example, IsBadReadPtr has the following instruction to read memory. ECX is the memory address specified in the argument list.
<br />
<br />
<code>
mov al,byte ptr [ecx]<br />
</code><br />
If the instruction raises an exception, the execution is transferred to the exception-handler code. And IsBad*Ptr returns TRUE, meaning, it is a "bad" pointer because the data pointed by is inaccessible.<br />
<br />
If the instruction executes without an exception being raised IsBad*Ptr returns FALSE.<br />
<h4>
Steps of Attacking</h4>
The attack against IsBad*Ptr looks like this.<br />
<ol>
<li>The attacker attempts to supply an invalid pointer parameter to IsBad*Ptr that returns TRUE.</li>
<li><strike>The attacker refines step #1 in a way that the supplied invalid pointer becomes valid due to a forced allocation for the location pointed by the invalid pointer.</strike> The attacker refines step #1 in a way that the supplied invalid pointer will point to valid memory location allocated by heap spray. And so, IsBad*Ptr returns FALSE leading to enter in an inconsistent state; that may or may not be an exploitable state.</li>
<li>If the attacker can perform step #2 with IsBadWritePtr, when the call returns, it's expected to reach code that writes the location pointed by the pointer -- and that has attacker controlled data. And so, he reaches a presumably exploitable condition.</li>
</ol>
Referencing IsBad*Ptr can be easily checked during binary analysis and it is worthy to do.<br />
<h4>
Examples</h4>
</div>
This code snippet below can be found in msvbvm60.dll in Windows folder.<br />
<br />
<span style="font-family: monospace;">.text:72A0FEE5 push 38h ; ucb</span><br />
<span style="font-family: monospace;">.text:72A0FEE7 push edi ; attacker supplies pointer was invalid before</span><br />
<span style="font-family: monospace;">.text:72A0FEE8 call ds:IsBadReadPtr ; and now it's valid because he's filled memory up</span><br />
<span style="font-family: monospace;">.text:72A0FEEE test eax, eax</span><br />
<span style="font-family: monospace;">.text:72A0FEF0 jnz loc_72A0FF80 ; fall through</span><br />
<span style="font-family: monospace;">.text:72A0FEF6 mov eax, [edi+4]</span><br />
<span style="font-family: monospace;">.text:72A0FEF9 mov eax, [eax+4]</span><br />
<span style="font-family: monospace;">.text:72A0FEFC mov esi, [eax+8] ; ESI is attacker controlled</span><br />
<span style="font-family: monospace;">.text:72A0FEFF and [ebp+arg_0], 0</span><br />
<span style="font-family: monospace;">.text:72A0FF03 mov ax, [edi+2]</span><br />
<span style="font-family: monospace;">.text:72A0FF07 test esi, esi</span><br />
<span style="font-family: monospace;">.text:72A0FF09 jz short loc_72A0FF42 ; fall through</span><br />
<span style="font-family: monospace;">.text:72A0FF0B movzx ebx, ax</span><br />
<span style="font-family: monospace;">.text:72A0FF0E mov eax, [esi] ; EAX is attacker controlled</span><br />
<span style="font-family: monospace;">.text:72A0FF10 push esi</span><br />
<span style="font-family: monospace;">.text:72A0FF11 call dword ptr [eax+0Ch] ; EIP is attacker controlled</span><br />
<span style="font-family: monospace;"><br /></span>
<br />
This one below can be found in dxtrans.dll in Windows folder.<br />
<br />
<span style="font-family: monospace;">.text:35C6142C push 4 ; ucb</span><br />
<span style="font-family: monospace;">.text:35C6142E push esi ; attacker supplies pointer was invalid before</span><br />
<span style="font-family: monospace;">.text:35C6142F call ds:__imp__IsBadWritePtr@8 ; and now it's valid because he's filled memory up</span><br />
<span style="font-family: monospace;">.text:35C61435 test eax, eax</span><br />
<span style="font-family: monospace;">.text:35C61437 jz short loc_35C61440 ; jump is taken</span><br />
<span style="font-family: monospace;">.text:35C61439 mov eax, 80004003h</span><br />
<span style="font-family: monospace;">.text:35C6143E jmp short loc_35C6144A</span><br />
<span style="font-family: monospace;">.text:35C61440 loc_35C61440: ; CODE XREF: CDXBaseSurface::GetAppData(ulong *)+14</span><br />
<span style="font-family: monospace;">.text:35C61440 mov eax, [ebp+this]</span><br />
<span style="font-family: monospace;">.text:35C61443 mov eax, [eax+24h]</span><br />
<span style="font-family: monospace;">.text:35C61446 mov [esi], eax ; ESI is attacker controlled</span><br />
<div>
<br /></div>
The next code snippet is taken from v2.0.50727\mscorwks.dll in Windows folder. IsBadReadPtr is used to test the pointer that is passed to MultiByteToWideChar.<br />
<br />
<span style="font-family: monospace;">.text:7A0D17FB push eax ; ucb</span><br />
<span style="font-family: monospace;">.text:7A0D17FC push ebx ; attacker supplies pointer was invalid before</span><br />
<span style="font-family: monospace;">.text:7A0D17FD call ds:__imp__IsBadReadPtr@8 ; and now it's valid because he's filled memory up</span><br />
<span style="font-family: monospace;">.text:7A0D1803 test eax, eax</span><br />
<span style="font-family: monospace;">.text:7A0D1805 jz short loc_7A0D17A7 ; jump is taken</span><br />
<span style="font-family: monospace;">[...]</span><br />
<span style="font-family: monospace;">.text:7A0D17A7 cmp edi, esi</span><br />
<span style="font-family: monospace;">.text:7A0D17A9 jle short loc_7A0D17BF</span><br />
<span style="font-family: monospace;">.text:7A0D17AB push esi ; cchWideChar</span><br />
<span style="font-family: monospace;">.text:7A0D17AC push esi ; lpWideCharStr</span><br />
<span style="font-family: monospace;">.text:7A0D17AD push edi ; cbMultiByte</span><br />
<span style="font-family: monospace;">.text:7A0D17AE push ebx ; lpMultiByteStr - attacker's data</span><br />
<span style="font-family: monospace;">.text:7A0D17AF push 1 ; dwFlags</span><br />
<span style="font-family: monospace;">.text:7A0D17B1 push esi ; CodePage</span><br />
<span style="font-family: monospace;">.text:7A0D17B2 call ?WszMultiByteToWideChar@@YGHIKPBDHPAGH@Z ; WszMultiByteToWideChar(uint,ulong,char const *,int,ushort *,int)</span><br />
<div>
<br /></div>
I was collecting files with IsBad*Ptr in them, and have found plenty others including but not exclusively MSCOMCTL.OCX, EXCEL.EXE, Lenovo's, Corel's, Nokia's, AVerMedia's products...<br />
<br />
<b>UPDATE</b> 13/May/2014 To add IsBad*Ptr to the program doesn't automatically mean to create bugs. However if IsBad*Ptr is present we have reason to believe that the function is expecting a pointer that might be invalid in certain circumstances. In that case IsBad*Ptr may be used to attack the program. And that's why it's important to conduct the audit according to this.<br />
<br />
<b>UPDATE</b> 16/May/2014 The term "valid pointer" had an ambiguous meaning in the part Steps of Attacking. This is now reworded. <a href="http://www.reddit.com/r/ReverseEngineering/comments/25n3xe/security_implications_of_isbadptr_calls_in/chiw7wh" target="_blank">Reference</a>.<br />
<br />
<span style="font-size: x-small;">[1] IsBad*Ptr functions are IsBadReadPtr, IsBadCodePtr, IsBadWritePtr, and IsBadStringPtr. All of them are exports of kernel32.dll.</span>Attila Suszterhttp://www.blogger.com/profile/16838249167428995033noreply@blogger.comtag:blogger.com,1999:blog-7356349663979968577.post-30718332367959553702014-04-28T19:38:00.001+08:002014-04-30T02:00:18.017+08:00Order of Memory Reads of Intel's String InstructionsNeither the Intel Manual nor Kip R. Irvine's assembly book discusses the behavior I'm describing about x86 string instructions in this post.<br />
<br />
Given the following instruction that compares the byte at ESI to the byte at EDI.<br />
<br />
<code>
cmps byte ptr [esi],byte ptr es:[edi]</code><br />
<br />
To perform comparison the instruction must read the bytes first. The question is whether byte at ESI <i>or</i> byte at EDI is read first?<br />
<br />
Intel Manual says:<br />
<blockquote class="tr_bq">
Compares the byte, word, doubleword, or quadword specified with the first source operand with the byte, word, doubleword, or quadword specified with the second source operand</blockquote>
Kip R. Irvine's book titled Assembly Language for Intel-Based Computers (5th edition) says:<br />
<blockquote class="tr_bq">
The CMPSB, CMPSW, and CMPSD instructions each compare a memory operand pointed to by ESI to a memory operand pointed to by EDI</blockquote>
Both of the descriptions explain what the instructions do but none of them says <i>how</i>. So I needed to do some experiments in Windbg to find the answer to the question.<br />
<br />
The first experiment was not a good one. Initially, I thought I'd put processor breakpoint (aka memory breakpoint) at ESI and another one at EDI. I also thought to execute CMPS and let the debugger to break-in on either of the processor breakpoints. And here it goes why it was a bad idea. The execution of CMPS has to complete for debugger break-in. And, by the time the CMPS completes it hits both of the breakpoints.<br />
<br />
The other experiment I came up with is like this. Set both ESI and EDI to point two distinct memory addresses that are unmapped. The assumption is when CMPS is executed it raises an exception when trying to read memory. By looking at the exception record we can tell the address the instruction tries to read from. Given that, we can tell if that value was assigned to ESI, or to EDI, and so we can tell whether byte at ESI or byte at EDI is read first.<br />
<br />
Here is how I did the experiment in Windbg.<br />
<br />
I opened an executable test file in Windbg. I assembled CMPS to be placed in the memory at EIP.<br />
<br />
<span style="font-family: monospace;">0:000> a</span><br />
<span style="font-family: monospace;">011113be cmpsb</span><br />
<code>cmpsb</code><br />
<br />
I changed ESI to point to invalid memory. And I did the same with EDI.<br />
<br />
<span style="font-family: monospace;">0:000> resi=51515151</span><br />
<code>0:000> redi=d1d1d1d1</code><br />
<br />
Here is the disassembly of CMPS. Also, you know from the highlighted text that both ESI and EDI point to unmapped memory addresses.<br />
<br />
<span style="font-family: monospace;">0:000> r</span><br />
<span style="font-family: monospace;">eax=cccccccc ebx=7efde000 ecx=00000000 edx=00000001 esi=51515151 edi=d1d1d1d1</span><br />
<span style="font-family: monospace;">eip=011113be esp=0022fb70 ebp=0022fc3c iopl=0 nv up ei pl nz na po nc</span><br />
<span style="font-family: monospace;">cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000202</span><br />
<span style="font-family: monospace;">test!wmain+0x1e:</span><br />
<code>011113be a6 cmps byte ptr [esi],byte ptr es:[edi] ds:002b:<span style="background-color: yellow;">51515151=??</span> es:002b:<span style="background-color: yellow;">d1d1d1d1=??</span></code><br />
<br />
I executed the process leading to an expected access violation triggered by CMPS instruction.<br />
<br />
<span style="font-family: monospace;">0:000> g</span><br />
<span style="font-family: monospace;">(5468.1eec8): Access violation - code c0000005 (first chance)</span><br />
<span style="font-family: monospace;">First chance exceptions are reported before any exception handling.</span><br />
<span style="font-family: monospace;">This exception may be expected and handled.</span><br />
<span style="font-family: monospace;">eax=cccccccc ebx=7efde000 ecx=00000000 edx=00000001 esi=51515151 edi=d1d1d1d1</span><br />
<span style="font-family: monospace;">eip=011113be esp=0022fb70 ebp=0022fc3c iopl=0 nv up ei pl nz na po nc</span><br />
<span style="font-family: monospace;">cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010202</span><br />
<span style="font-family: monospace;">test!wmain+0x1e:</span><br />
<code>011113be a6 cmps byte ptr [esi],byte ptr es:[edi] ds:002b:51515151=?? es:002b:d1d1d1d1=?? </code><br />
<br />
I got the details of the exception like below.<br />
<br />
<span style="font-family: monospace;">0:000> .exr -1</span><br />
<span style="font-family: monospace;">ExceptionAddress: 011113be (test!wmain+0x0000001e)</span><br />
<span style="font-family: monospace;"> ExceptionCode: c0000005 (Access violation)</span><br />
<span style="font-family: monospace;"> ExceptionFlags: 00000000</span><br />
<span style="font-family: monospace;">NumberParameters: 2</span><br />
<span style="font-family: monospace;"> Parameter[0]: 00000000</span><br />
<span style="font-family: monospace;"> Parameter[1]: d1d1d1d1</span><br />
<span style="background-color: yellow; font-family: monospace;">Attempt to read from address d1d1d1d1</span><br />
<br />
As you can see the access violation was occurred due to an attempt to read from d1d1d1d1 that is the value of EDI. Therefore, to answer the question at the beginning of the article, the byte at EDI is read first.<br />
<br />
To give more to the fun, you may try how emulators handle this - that is the order of memory reads of CMPS instructions.<br />
<br />
If you like this you may click to read more <a href="http://reversingonwindows.blogspot.com/search/label/Debugging">debugging</a> <a href="http://reversingonwindows.blogspot.com/search/label/Windbg">posts</a>.<br />
<br />
<b>UPDATE</b> 28/April/2014 Of course I don't encourage people to rely on undocumented behavior when developing software. Stephen Canon <a href="https://twitter.com/stephentyrone/status/460788908025192448">says</a> Intel may optimize the microcode for operands from time to time, and so we don't have a good reason to believe this behavior to be stable.<br />
<br />
<b>UPDATE</b> 29/April/2014 Here is a Windows C++ program to test this behavior on your architecture: <a href="https://onedrive.live.com/redir?resid=3CF97A8AA9AC4799!13068&authkey=!ACoALzdthxIxb7o&ithint=file%2c.cpp">cmps-probe.cpp</a><br />
<div class="separator" style="clear: both; text-align: center;">
<img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1SAu6qKzJf02KBtP91_yl8Popj9XfWI2cM7eJolCm0dEqbUoEXT7eQastFE6NTVZ6AB08x8DV16XTbKYe6mC35RuLtRvCkvBI74c5jkrJN2bCoZxBnPDF3IiD4C7qMT3rnR65g8V7T1c/s1600/cmps-probe.png" /></div>
<br />Attila Suszterhttp://www.blogger.com/profile/16838249167428995033noreply@blogger.comtag:blogger.com,1999:blog-7356349663979968577.post-89567598395545555672014-04-23T19:51:00.001+08:002014-04-27T18:57:39.411+08:00Inspection of Division & MultiplicationDivision and multiplication calculations can lead to trigger bugs, and potentially pose as security risks. Here are few things that I believe to be helpful for those who do binary inspection.<br />
<h4>
Division</h4>
Production quality binaries are normally built with optimization enabled which makes the binary to run fast. One of the optimizations technique for the compiler is to emit a series of fast instructions instead of a single slow instruction.<br />
<br />
DIV and IDIV instructions are known to be slow. As a part of optimization the compiler emits a series of fast instructions that are functionally equivalent to DIVs. The fast instructions are shift, multiplication, and addition instructions that take magic (constant) values depending on the divisor. Therefore the divisor has to be known at compile-time to apply optimization.<br />
<br />
If the optimized binary has any DIVs, that means, the divisor was not known at compile time. Thus it's known at run-time, and so it could be a user-controlled value or a user input taken as it is.<br />
<br />
Division can cause exception if the divisor is 0, or if the result is to large to store.<br />
<h4>
Division by Zero in CLR's Native Code</h4>
As an interesting experiment I looked at what happens when an integer is divided by zero in C#.<br />
<br />
CLR generates native code with division instruction in it. When the instruction of division by zero is executed, an exception is raised that is handled by CLR's exception handler.<br />
<br />
So the generated code with division in it doesn't have a test for the divisor. It's left for the exception handler to handle division by zero situations.<br />
<h4>
Multiplication</h4>
Like division, multiplication can be optimized, too, by using a sequence of fast instructions (sometimes one instruction). Whether or not it's worth optimizing depends on the value of multiplier (or multiplicand).<br />
<br />
The multiplication you can see in binary might not be seen on source-code level. And some multiplication cannot be easily spotted in binary code due to optimization. And, multiplications can lead to trigger bugs.<br />
<h4>
Overflow in Multiplication</h4>
Multiplication can lead to integer overflow. Multiplication of two values are more likely to lead to integer overflow than addition of the two values. Multiplication of two word length integers can overflow on 32-bit but addition can't.<br />
<br />
Few instances of the IMUL instruction can take immediate value, that is the multiplier. It's easily possible to calculate what multiplicand overflows the multiplication. The challenging part is to determine how the value could be assigned to the multiplicand to trigger overflow.<br />
<br />
It's worth searching for MUL and IMUL instructions in the binary using the <b>#</b> (hash mark) Windbg command.<br />
<h4>
Overflow in Multiplication by Scale Factor</h4>
Scale factor is a constant value by which the register in the instruction is multiplied. The scale factor is either 1, 2, 4 or 8.<br />
<br />
Use of scale factor could be the result of optimization of multiplication. The example below demonstrates to multiply a value by 4.<br />
<br />
<code>
lea eax,[edi*4]<br />
</code><br />
Other common use case involves to dereference an element of the array. In the below example the array consists of elements of size 8. On source-level there is no multiplication but on low-level there is.<br />
<br />
<code>
mov [edi+edx*8],eax<br />
</code><br />
If the value of the register by which the scale factor is multiplied is large enough an integer overflow can occur.<br />
<br />
Look at the below instruction. Even the multiplication might not overflow the result can, due to base (esp) and displacement (8000).<br />
<br />
<code>
mov [esp+ebx*4+8000],eax<br />
</code><br />
<h4>
Method of Inspection</h4>
Generally, it's not feasible to review all the occurrences of certain instructions but on critical areas it might be reasonable to do. Instruction tracing, and tracing like <a href="http://reversingonwindows.blogspot.com/2014/03/trace-and-watch.html">this</a> can be a good start to narrow the area that can be inspected closer.Attila Suszterhttp://www.blogger.com/profile/16838249167428995033noreply@blogger.comtag:blogger.com,1999:blog-7356349663979968577.post-70564187673045339262014-04-16T20:31:00.000+08:002014-04-27T18:59:20.288+08:00You May Not Need to Debug SSE InstructionsThere are binaries that contain implementation of an algorithm in two ways. The first one is optimized to run on all architectures and so it consists of i386 instructions only. The second one is optimized to run fast and therefore it has SSE instructions. When the application runs it checks the architecture to decide which implementation of the algorithm to be executed.<br />
<br />
It is common thing that binaries can contain various implementations of the same algorithm. One example is the Microsoft Visual C++ runtime.<br />
<br />
You may not need to debug SSE instructions though. What you need to do is to tell your application that SSE support is not available - which is most likely a lie in 2014.<br />
<br />
Recently, when I debugged a Windows application I noticed it executes SSE instructions. Here is how I got my application to believe that there is no SSE support available.<br />
<br />
I knew about CPUID instruction. It can come back with plenty information about the processor. If CPUID is used with input EAX set to 1 feature information is returned in ECX and EDX.<br />
<br />
We only need the SSE-related bits of the feature information. Here are they (source: Intel Developer Manual).<br />
<br />
In ECX:<br />
<code>
Bit 0 SSE3 Extensions<br />
Bit 9 SSSE3 Extensions<br />
Bit 19 SSE4.1<br />
Bit 20 SSE4.2<br />
</code>
<br />
In EDX:<br />
<code>
Bit 25 SSE Extensions<br />
Bit 26 SSE2 Extensions<br />
</code>
<br />
The idea is when CPUID is executed with EAX set to 1 we need to clear SSE bits in ECX and EDX. To clear SSE bits we have to mask the registers like below.<br />
<br />
<code>
ECX<-ECX&FFE7FDFE<br />
EDX<-EDX&F9FFFFFF</code><br />
<br />
I used the following Windbg command to search for CPUID instructions in the code section of the virtual image.<br />
<br />
<code># cpuid <span style="color: #999999;"><address></span> L?<span style="color: #999999;"><size></span></code><br />
<br />
I saw CPUID at few places. I checked all of them to find the ones that have EAX set to 1 input. I found few fragments like these.<br />
<br />
<code>xor eax,eax<br />
inc eax<br />
cpuid<br />
</code>
<br />
I put breakpoints just after each of the right CPUID instructions. When the breakpoint hit the SSE flags are cleared and the execution resumes.<br />
<br />
<code>bp <span style="color: #999999;"><address></span> "reip; recx=ecx&0ffe7fdfe; redx=edx&0f9ffffff; gc"</code><br />
<br />
And it worked as expected in my experiment. The application took the alternate, but slower, code path of i386 instructions.<br />
<br />
A final note, this technique may be used to avoid debugging SSE instructions but it can also be useful to increase code coverage during security testing.Attila Suszterhttp://www.blogger.com/profile/16838249167428995033noreply@blogger.comtag:blogger.com,1999:blog-7356349663979968577.post-53351747591804541982014-04-08T17:35:00.000+08:002014-04-28T00:53:38.336+08:00Examining Unknown Binary FormatsThis post is about to discuss the methods for examining unknown binary formats that can be either a file, file fragment, or memory dump.<br />
<br />
Before discussing the methods I'm describing few scenarios when examination of an unknown format is appropriate.<br />
<br />
Imagine you deal with an application that handles a certain file type that you want to fuzz. You think to carry out some dumb fuzzing with a bit of improvement. Before doing so, you may be examining the format to create an approximate map of the layout. So you'll get an idea what parts of the files are worth fuzzing, and what fuzzing method is reasonable to apply for each part.<br />
<br />
In other scenario you might have the binary file but don't have the program that parses it. You want to know as much as possible of the format of the binary file to understand it's layout.<br />
<br />
If the application that reads the file format is available you can use debugger to watch how the data is parsed. This scenario is not discussed here.<br />
<br />
If the application that writes the format is available you can try the following idea. You may produce output file using the application. This can be done by save, export, convert options available in the application. Next time when producing output you change something minor in the settings that may produce a similar output file. Comparing the two output files you may see what changed.<br />
<br />
Entropy analysis is very useful to locate compressed, encrypted, and other way encoded data. Higher entropy can indicate encoding of some kind. Lower entropy is likely anything else including text, code, header, data structures. Redundancy analysis is analogue to entropy analysis; the lower the redundancy the most likely the data is encoded.<br />
<br />
Encoded data could be anything, even multimedia data. The compressed streams can have headers and/or magic bytes identify the compression type.<br />
<br />
Character distribution of the file can tell us a lot. Creating a byte frequency map is very straightforward by using modern programming languages. That can tell us what are the most and less frequent bytes. We can easily know what are the bytes that are not present at all.<br />
<br />
Strings can be discovered even with popular tools like a hex-editor. Most common encodings are ASCII and Unicode. If there is no terminating zero the length of the string is likely stored somewhere in the binary. It's often the preceding byte(s) of the first letter of the string.<br />
<br />
Consecutive patterns, byte sequences are seen to be used for padding, for alignment, or to fill slack space.<br />
<br />
Random-looking printable characters can indicate some kind of encoding of any data in plain text.<br />
<br />
Scattered bytes, scattered zeros, scattered 0FFh bytes can indicate sequence of encoded integers. Integers can be offsets and lengths. Scattered zeros might indicate text in Unicode format.<br />
<br />
It could be useful to analyze the density of zeros, printable characters, or of other patterns. This could be applied on the whole file or on a particular region of the file.<br />
<div>
<br /></div>
Consecutive values, integers might indicate an array of pointers. It might be useful to know if the values increasing, decreasing, or random values.<br />
<br />
Also, good to know in what endianness the integers stored.<br />
<br />
x86 code can be be detected by running disassembler on the binary. If you see a sequence of meaningful instructions that might be code-area.<br />
<br />
There is a simpler way to look for x86 code though. You write a small program in some high level language that searchers for E8 (CALL) / E9 (JMP) patterns and calculates the absolute offset where the instruction jumps. If there is an absolute offset referenced from different places that might be an entry point of a real function. The more functions are identified the better the chance you have found code.<br />
<br />
If you know what native code to look for you can search for a sequence of common instructions, like bytes at function entry point.<br />
<br />
Meaningful text fragment in high-entropy area might indicate run-length encoding which is also known as RLE compression.<br />
<br />
There is data format that looks like this. It consists of a sequence of structures, or chunks. The size of each structure is encoded sometimes as a first value in the structure. It's commonly seen that a sequence of compressed data is stored like that.<br />
<br />
If it's known the binary is associated with certain time stamp or version number those constants might worth searching for.<br />
<br />
Some methods described here can be combined with xor-search, and with other simple decoding techniques to discover the structure of the file.Attila Suszterhttp://www.blogger.com/profile/16838249167428995033noreply@blogger.comtag:blogger.com,1999:blog-7356349663979968577.post-13256907441036685252014-04-05T21:03:00.000+08:002014-04-28T04:41:56.756+08:00Thoughts About Finding Race Condition BugsRace condition bugs can exist in multi-threaded applications. Improper synchronization can be the root cause of race condition bugs.<br />
<br />
Executing stress testing is a good start to find bugs. It might not be an ideal black-box testing method though as it is mostly for developers to test their proprietary software. Injecting delays at various points into the target could help finding bugs but we need to know the right locations to inject the delays. <a href="http://research.microsoft.com/en-us/projects/cuzz/" target="_blank">Cuzz</a> is a Microsoft tool for finding concurrency bugs by injecting random delays - it looks promising.<br />
<br />
Using DBI (Dynamic Binary Instrumentation) it's possible to tell if an EIP is executed, and if so by what thread(s). Therefore it's possible to tell what code is executed by what thread(s).<br />
<br />
Using DBI it is also possible to tell where (value of EIP) the thread context switch happens.<br />
<br />
By having the above information we can make educated guesses where to inject the delays.<br />
<br />
If a bug is found it might not be reachable from outside. That's always a possibility. However it's good to see if you can provide input that makes the application to run longer near the location of the intended delay. There might be a <code>ReadFile</code> that can take longer to complete if the file is large enough. Or there might be a loop where the iteration count can be controlled by user...Attila Suszterhttp://www.blogger.com/profile/16838249167428995033noreply@blogger.comtag:blogger.com,1999:blog-7356349663979968577.post-87955439503231952552014-04-03T01:13:00.000+08:002014-04-28T04:43:38.055+08:00Change of Execution Flow in DebuggerWhen debugging sometimes we need to force the execution to either take or not take the conditional jump.<br />
<br />
There are several ways to achieve this. One possibility is to overwrite the conditional jump with either JMP or NOP instruction to force the execution into the desired path.<br />
<br />
The next trick is to simply change the instruction pointer. The below example demonstrates to increment the instruction pointer by 2 in Windbg.<br />
<br />
<code>
reip=eip+2</code><br />
<br />
Another idea involves to see what are the conditions of taking or not taking the conditional jump. Knowing the conditions you can change the register or data at the right memory location to influence the execution flow.<br />
<br />
My favorite is to change the x86 flags when the instruction pointer points to the conditional jump. Below is how to set the zero flag in Windbg.<br />
<br />
<code>
rzf=1</code><br />
<br />
To see more info about flags check out <a href="http://msdn.microsoft.com/en-us/library/windows/hardware/ff561502%28v=vs.85%29.aspx">msdn</a> or Windbg's help.Attila Suszterhttp://www.blogger.com/profile/16838249167428995033noreply@blogger.comtag:blogger.com,1999:blog-7356349663979968577.post-70674464123356791772014-04-01T18:30:00.000+08:002014-04-28T04:45:37.147+08:00Tracking Down by PinRecently, there was a challenging situation I had faced. At first sight it looked like a common debugging problem that can be solved with some experiment but the more time I spent on it the more difficult the situation looked like.<br />
<br />
The situation was the following. The below instruction reads memory.<br />
<br />
<code>00400000+006026de mov eax,dword ptr [ebp+4]</code><br />
<br />
What is the <code>EIP</code> of the instruction that writes <code>[ebp+4]</code>? This is all I wanted to know that stage.<br />
<br />
<i>Note, while looking at the instruction it looks like ebp+4 reads a stack address -- it reads actually a heap address.</i><br />
<br />
First I was looking at the function if I can find the instruction in it that writes <code>[ebp+4]</code>. It wasn't there so I investigated the caller functions, and their callers, and so on. Again, it wasn't there but noticed something. The functions passed a pointer to a context as a parameter containing many variables including <code>[ebp+4]</code>.<br />
<br />
At this point I had a good reason to believe the situation looked difficult because the context is likely to set by an initializer that may be on a completely different code path to the one I was investigating.<br />
<br />
You may ask why I didn't use processor breakpoint too see what instruction writes <code>[ebp+4]</code>. It was a heap address kept changing on every execution and the address was not known to put breakpoint on.<br />
<br />
I could have gone back to the point when the structure is allocated, and I could have set a breakpoint relative to the base address and see what code writes <code>[ebp+4]</code>. That sounded good and I would have gone to that direction if I hadn't had a better idea.<br />
<br />
I thought I could write a PinTool that tracks write and read memory accesses. It adds all instructions writing memory to the list. When the instruction that reads memory is reached the program searches the list for instructions wrote that address. Of course this has to be thread safe.<br />
<br />
It took me a day to develop the PinTool and find the <code>EIP</code> that writes <code>[ebp+4]</code>.<br />
<br />
This is how I executed the PinTool from command line.<br />
<br />
<code>pin.exe -t TrackDownWrite.dll -ip 0x6026de -s 4 -- c:\work\<redacted>.exe</code><br />
<br />
<code>-ip</code> is the instruction pointer where <code>[ebp+4]</code> is read<br />
<code>-s</code> is the size of read/write to track<br />
<br />
The result looked like this.<br />
<br />
<code>
0bab05dc is read by 006026de<br />
0bab05dc was written by <span style="background-color: yellow;">005ee358</span> before read</code><br />
<br />
The wanted instruction is below.<br />
<br />
<code>
00400000+005ee358 mov dword ptr [eax+4],edx</code><br />
<br />
The prototype is available for <a href="https://onedrive.live.com/redir?resid=3CF97A8AA9AC4799!13010&authkey=!AEn01ZHgCvteV0Q&ithint=file%2c.cpp">download</a>. After finished my debugging task I also tested it a bit on Windows x86 and I think it looks useful for similar problems might arise in the future.Attila Suszterhttp://www.blogger.com/profile/16838249167428995033noreply@blogger.comtag:blogger.com,1999:blog-7356349663979968577.post-73166468954645693192014-03-10T17:39:00.000+08:002014-04-28T04:46:52.693+08:00On-the-fly Switching Between DebuggersSometimes it's useful to switch between debuggers without restarting the target application. An example for doing so is when you want to use another debugger's capability that the one doesn't have. Here is how to do by using the well-known EB FE trick.<br />
<ul>
<li>Instruct the debugger to break-in, and memorize the two bytes at EIP.</li>
<li>Replace the two bytes at EIP with EB FE that is JMP EIP.</li>
<li>Detach the debugger leaving the application in an endless loop.</li>
<li>Attach the other debugger to the running process.</li>
<li>Locate the thread of the endless loop by switching between threads, and when found, restore the two bytes you memorized.</li>
<li>Carry-on with the debugging using the other debugger.</li>
</ul>
<div>
Note, the patched thread could interfere with watchdog thread if any, however I haven't experienced it yet.</div>
Attila Suszterhttp://www.blogger.com/profile/16838249167428995033noreply@blogger.comtag:blogger.com,1999:blog-7356349663979968577.post-36182795086776501252014-03-05T18:41:00.001+08:002014-04-28T04:53:22.601+08:00Trace And WatchThis is how I recently performed dynamic integer analysis on a 32-bit binary application that reads DWORD values from the file.<br />
<ul>
<li>The file format contains many fields of type DWORD. There was given a sample file. I made as many copies of the sample file as many DWORD fields it had. I crafted each sample to have <code>0x41414141</code> in a DWORD field. Only one DWORD field was changed per sample so all DWORD fields were covered by the change.</li>
<li>I wrote a PinTool, called <i>TraceAndWatch</i>, for this occassion that checks the value of the general registers before every instruction is executed. It shows memory state including disassembly of the instruction when a register value matches <code>0x41414141</code>.</li>
<li>I executed the application using <i>TraceAndWatch </i>and let the application to parse the first sample containing <code>0x41414141</code>. <i>TraceAndWatch </i>produced a log and I saw what instructions using <code>0x41414141</code>.</li>
<li>In static disassembly code, I located the instructions using <code>0x41414141</code> and saw arithmetic and comparison operations with that value.</li>
<li>In some cases I realized I can enter to other code path by changing <code>0x41414141</code> in the sample to other value e.g. to signed value like <code>0x88888888</code>. And re-run the test with <i>TraceAndWatch </i>specifying to trace and watch instructions using <code>0x88888888</code>.</li>
<li>I executed this manual test on all the samples produced earlier.</li>
</ul>
<br />
The following weaknesses can be audited by this approach.<br />
<br />
CWE-839: Numeric Range Comparison Without Minimum Check<br />
CWE-195: Signed to Unsigned Conversion Error<br />
CWE-682: Incorrect Calculation<br />
CWE-190: Integer Overflow or Wraparound<br />
CWE-680: Integer Overflow to Buffer Overflow<br />
CWE-191: Integer Underflow (Wrap or Wraparound)<br />
<h4>
Final Notes</h4>
This is a generic, and quick way to locate comparison and arithmetic of integers.<br />
<br />
<i>TraceAndWatch </i>doesn't track other than general registers so you can loose track of integers when value copied to, like, SSE register.<br />
<br />
When arithmetic is performed on the value e.g. <code>0x41414141</code> is multiplied by 2, you need to set <i>TraceAndWatch </i>to look for <code>0x82828282</code> not to loose the tracking.<br />
<br />
<i>TraceAndWatch </i>is available for <a href="https://onedrive.live.com/redir?resid=3CF97A8AA9AC4799!12625&authkey=!AJGkXsoF1DR1bqY&ithint=file%2c.cpp">download</a> on my OneDrive space. If you use it you may contact me with your experience.Attila Suszterhttp://www.blogger.com/profile/16838249167428995033noreply@blogger.comtag:blogger.com,1999:blog-7356349663979968577.post-37347802951531953702014-02-19T06:19:00.000+08:002014-04-30T21:13:37.814+08:00Bug in Flash Player when processing PNG format<h4>
The Bug</h4>
The PNG file consists of a sequence of data structures called chunks. A chunk has a <code>Length</code> field that is a <code>DWORD </code> value. A specially crafted <code>Length</code> field can cause integer overflow in Flash Player leading to read out of the designated buffer. Here is the disassembly code snippet explaining the bug.
<br />
<br />
<span style="font-family: monospace; font-size: x-small;">015344a0 e8f7feffff call FlashPlayer!WinMainSandboxed+0x1f1122 (0153439c) ;Read CHUNK.Length from attacker controlled buffer</span><br />
<span style="font-family: monospace; font-size: x-small;">015344a5 8bd8 mov ebx,eax ;CHUNK.Length = 0ffffffd3h</span><br />
<span style="font-family: monospace; font-size: x-small;">015344a7 6a04 push 4</span><br />
<span style="font-family: monospace; font-size: x-small;">015344a9 8d45fc lea eax,[ebp-4]</span><br />
<span style="font-family: monospace; font-size: x-small;">015344ac 50 push eax</span><br />
<span style="font-family: monospace; font-size: x-small;">015344ad 8bce mov ecx,esi</span><br />
<span style="font-family: monospace; font-size: x-small;">015344bb e8dcfeffff call FlashPlayer!WinMainSandboxed+0x1f1122 (0153439c)</span><br />
<span style="font-family: monospace; font-size: x-small;">015344c0 8b4d08 mov ecx,dword ptr [ebp+8]</span><br />
<span style="font-family: monospace; font-size: x-small;">015344c3 8901 mov dword ptr [ecx],eax</span><br />
<span style="font-family: monospace; font-size: x-small;">015344c5 8b560c mov edx,dword ptr [esi+0Ch] ;Current Position in buffer = 29h</span><br />
<span style="font-family: monospace; font-size: x-small;">015344c8 8945fc mov dword ptr [ebp-4],eax</span><br />
<span style="font-family: monospace; font-size: x-small;">015344cb 8d441a04 lea eax,[edx+ebx+4] ;<-First integer overflow</span><br />
<span style="font-family: monospace; font-size: x-small;"> ;TotalValue = Position + CHUNK.Length + 4</span><br />
<span style="font-family: monospace; font-size: x-small;"> ;TotalValue = 29h + 0ffffffd3h + 4 = 0</span><br />
<span style="font-family: monospace; font-size: x-small;">015344cf 3b4610 cmp eax,dword ptr [esi+10h] ;Compare TotalValue (0) to FileSize (3d0h)</span><br />
<span style="font-family: monospace; font-size: x-small;">015344d2 7351 jae FlashPlayer!WinMainSandboxed+0x1f12ab (01534525) ;Unsigned evaluation. Jump is not taken</span><br />
<span style="font-family: monospace; font-size: x-small;">015344d4 57 push edi</span><br />
<span style="font-family: monospace; font-size: x-small;">015344d5 6afc push 0FFFFFFFCh</span><br />
<span style="font-family: monospace; font-size: x-small;">015344d7 58 pop eax</span><br />
<span style="font-family: monospace; font-size: x-small;">015344d8 83cfff or edi,0FFFFFFFFh</span><br />
<span style="font-family: monospace; font-size: x-small;">015344db 3bd8 cmp ebx,eax ;Compare CHUNK.Length (0ffffffd3h) to hardcoded 0FFFFFFFCh</span><br />
<span style="font-family: monospace; font-size: x-small;">015344dd 7e26 jle FlashPlayer!WinMainSandboxed+0x1f128b (01534505) ;Signed evaluation. Jump is taken.</span><br />
<span style="font-family: monospace; font-size: x-small;">[...]</span><br />
<span style="font-family: monospace; font-size: x-small;">01534505 8b4e14 mov ecx,dword ptr [esi+14h] ;Set pointer to Buffer</span><br />
<span style="font-family: monospace; font-size: x-small;">01534508 03ca add ecx,edx ;Set Current Position in Buffer</span><br />
<span style="font-family: monospace; font-size: x-small;">0153450a 03cb add ecx,ebx ;<-Second integer overflow</span><br />
<span style="font-family: monospace; font-size: x-small;"> ;Increment by CHUNK.Length leading to position out of the buffer backward</span><br />
<span style="font-family: monospace; font-size: x-small;">0153450c e88bfeffff call FlashPlayer!WinMainSandboxed+0x1f1122 (0153439c)</span><br />
<span style="font-family: monospace; font-size: x-small;">[...]</span><br />
<span style="font-family: monospace; font-size: x-small;">0153439c 0fb601 movzx eax,byte ptr [ecx] ;<-Can read out of designated buffer</span><br />
<span style="font-family: monospace; font-size: x-small;">0153439f 0fb65101 movzx edx,byte ptr [ecx+1] ;<-Can read out of designated buffer</span><br />
<span style="font-family: monospace; font-size: x-small;">015343a3 c1e008 shl eax,8</span><br />
<span style="font-family: monospace; font-size: x-small;">015343a6 0bc2 or eax,edx</span><br />
<span style="font-family: monospace; font-size: x-small;">015343a8 0fb65102 movzx edx,byte ptr [ecx+2] ;<-Can read out of designated buffer</span><br />
<span style="font-family: monospace; font-size: x-small;">015343ac 0fb64903 movzx ecx,byte ptr [ecx+3] ;<-Can read out of designated buffer</span><br />
<span style="font-family: monospace; font-size: x-small;">015343b0 c1e008 shl eax,8</span><br />
<span style="font-family: monospace; font-size: x-small;">015343b3 0bc2 or eax,edx</span><br />
<span style="font-family: monospace; font-size: x-small;">015343b5 c1e008 shl eax,8</span><br />
<span style="font-family: monospace; font-size: x-small;">015343b8 0bc1 or eax,ecx</span><br />
<span style="font-family: monospace; font-size: x-small;">015343ba c3 ret</span><br />
<br />
State in the erroneous code path looks like below. The designated buffer containing the content of PNG file starts at <code>00e4c810</code> where the PNG signature is seen. Due to the bug the instruction reads the memory at <code>4</code> bytes minus the pointer to the buffer, at <code>00e4c80c</code>. Note, the instruction doesn't cause access violation because the illegally accessed memory address is mapped.<br />
<br />
<span style="font-family: monospace;">0:000> t</span><br />
<span style="font-family: monospace;">eax=fffffffc ebx=ffffffd3 ecx=00e4c80c edx=00000029 esi=0019e134 edi=ffffffff</span><br />
<span style="font-family: monospace;">eip=0153439c esp=0019dbf4 ebp=0019dc08 iopl=0 nv up ei pl nz na pe cy</span><br />
<span style="font-family: monospace;">cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000207</span><br />
<span style="font-family: monospace;">FlashPlayer!WinMainSandboxed+0x1f1122:</span><br />
<span style="font-family: monospace;">0153439c 0fb601 movzx eax,byte ptr [ecx] ds:002b:00e4c80c=00</span><br />
<span style="font-family: monospace;">0:000> db ecx</span><br />
<span style="font-family: monospace;">00e4c80c 00 00 00 00 89 50 4e 47-0d 0a 1a 0a 00 00 00 0d .....PNG........</span><br />
<span style="font-family: monospace;">00e4c81c 49 48 44 52 00 00 01 2c-00 00 01 2c 08 02 00 00 IHDR...,...,....</span><br />
<span style="font-family: monospace;">00e4c82c 00 f6 1f 19 22 ff ff ff-d3 49 44 41 54 78 9c ed ...."....IDATx..</span><br />
<span style="font-family: monospace;">00e4c83c d9 31 8a c3 40 14 44 c1-1e e3 fb 5f 59 8a 9d 09 .1..@.D...._Y...</span><br />
<span style="font-family: monospace;">00e4c84c 1c bc 40 55 6c b4 20 70-f2 68 98 7f b6 6b bb ce ..@Ul. p.h...k..</span><br />
<span style="font-family: monospace;">00e4c85c ef df b6 f3 e8 9f f3 ad-6f 7d fb e7 b7 9f 01 a9 ........o}......</span><br />
<span style="font-family: monospace;">00e4c86c ef 4e fd 13 e0 dd 44 08-31 11 42 4c 84 10 13 21 .N....D.1.BL...!</span><br />
<span style="font-family: monospace;">00e4c87c c4 bc 8e 42 cc 12 42 4c-84 10 13 21 c4 44 08 31 ...B..BL...!.D.1</span><br />
<h4>
Root Cause</h4>
Two incorrect sanity checks were identified.<br />
<br />
Incorrect sanity check (<code>015344cf</code>) because it happens after the overflow (<code>015344cb</code>).<br />
Incorrect sanity check (<code>015344db</code>) because signed comparison is performed on <code>CHUNK.Length</code> that is unsigned.<br />
<h4>
Severity</h4>
The technical severity of this bug is low because diverting execution flow is not possible. Further analysis suggests that address disclosure is not possible because the memory region can be accessed out of the designated buffer doesn't contain address.<br />
<h4>
Reproduction</h4>
Open Flash Player 12.0.0.38 (flashplayer_12_sa.exe has a size of 10,339,208) in Windbg. Then execute the following command.<br />
<span style="font-family: monospace;">0:006> bp flashplayer + 001f44a0 2</span><br />
<span style="font-family: monospace;">0:006> g</span><br />
Open the PoC in Flash Player (send me an e-mail for a copy). Debugger breaks-in so you can step through the disassembly code and see the data-flow as explained above.<br />
<br />
I'm aware there is a new version of Flash Player 12.0.0.44. I verified and it's affected by this bug, too.<br />
<br />
<b>UPDATE</b> On 26th February an Adobe engineer confirmed via e-mail that he could reproduce the bug.Attila Suszterhttp://www.blogger.com/profile/16838249167428995033noreply@blogger.com