Reversing Code Research Labs

You are here: Home

Search

Latest News

  • Apple QuickTime Player H.264 issues
  • About...
  • SSD-1012211 - IBM Lotus Domino 8.5.2 Nnotes.dll!NSFComputeEvaluateExt Stack-Based Buffer Overflow
  • (0-Day) ZDI-11-112 - HP Data Protector Media Operations DBServer.exe Integer Overflow
  • 0-day

This Site

  • Home
  • Advisories
  • Papers
  • Contact
  • About

Apple QuickTime Player H.264 issues

Details
Category: Advisories
Published on Thursday, 01 September 2011 20:26
Written by rmallof

Some months ago, analyzing module in charge to parse H.264 compressed data in QuickTime Player, were found exactly two vulnerabilities in the way it do it.

First we need document this codec. The basic from http://en.wikipedia.org/wiki/H.264/MPEG-4_AVC :

“H.264/MPEG-4 Part 10 or AVC (Advanced Video Coding) is a standard for video compression, and is currently one of the most commonly used formats for the recording, compression, and distribution of high definition video.”

Looking for more info, could be found that the coded video data is organized into NAL Units, which contains besides that a header with information about data (like type of the structure contained), and the size of each variable:

 

 

This pseudo-code structure and the other that we need can be found at ITU-T H.264 with terms, algorithms to encode / decode data, and so on; speaking regarding algorithms and according to documentation, we should find three parsers:

- to Exponential-Golomb coding;

- to CAVLC for transform coefficients levels;

- to CABAC for slice data;

Exponential-Golomb is responsible of decoding the syntax elements of the corresponding structures, and necessary for us on this case.

The process to decode unsigned integers begins looking for the MSB in stream setted to 1 and counting the leading bits equals to zero. Some like this:

 

zeroBits = -1;

for(b = 0; !b; zeroBits++) {

b = read_bits(1);

}

 

Then, zeroBits acts like exponent in base two and like the number of bits to read this time:

 

codeNum = (2**zeroBits) - 1 + read_bits(zeroBits);


Like you can see, this algorithm allows us generate values from a base ((2 ** zeroBits) - 1) and then add it to an offset (read_bits(zeroBits)), our selected value.

Since we have the exponent value equals to number of bits to read, when we need to read a large offset the base value will grow too, losing precision to generate all values. This issue will bring us problems in the exploitation process, as we shall see later.

Here is code example about implementation of last algorithm from QuickTimeH264.qtx:

 

.text:681D4A39      loc_681D4A39:

.text:681D4A39 bsr eax, [esp+84h+SliceHeader]

.text:681D4A3E mov ecx, 3Fh

.text:681D4A43 cmovz eax, ecx

.text:681D4A46 xor eax, 1Fh

.text:681D4A49 mov [esp+84h+var_48], eax

.text:681D4A4D mov edx, [esp+84h+var_48]

.text:681D4A51 mov eax, [esp+84h+SliceHeader]

.text:681D4A55 lea ecx, [edx+1]

.text:681D4A58 shl eax, cl

.text:681D4A5A mov ecx, 20h

.text:681D4A5F sub ecx, edx

.text:681D4A61 mov ebx, 1

.text:681D4A66 shr eax, cl

.text:681D4A68 mov ecx, edx

.text:681D4A6A neg ecx

.text:681D4A6C sbb ecx, ecx

.text:681D4A6E and eax, ecx

.text:681D4A70  mov ecx, edx

.text:681D4A72 shl ebx, cl

.text:681D4A74  lea edx, [ebp+edx*2+1]

.text:681D4A78  mov [esp+84h+SliceHeader], eax

.text:681D4A7C  lea eax, [ebx+eax-1]

.text:681D4A80 mov ebx, edx

.text:681D4A82  shr edx, 3

.text:681D4A85 add esi, edx

Decoding unsigned integers with Exponential - Golomb

 

0k, as I said, this is the process to decode unsigned integers for structures, so what about this structures? His names are Sequence Parameter Set (SPS), Picture Parameter Set (PPS), and Slice Header, and here are their definitions:

  • Sequence parameter set: A syntax structure containing syntax elements that apply to zero or more entire coded video sequences as determined by the content of a seq_parameter_set_id syntax element found in the picture parameter set referred to by the pic_parameter_set_id syntax element found in each slice header:

 

 

  • Picture parameter set: A syntax structure containing syntax elements that apply to zero or more entire codedpictures as determined by the pic_parameter_set_id syntax element found in each slice header:

 

 

  • Slice header: A part of a coded slice containing the data elements pertaining to the first or all macroblocks represented in the slice (this is an integer number of macroblocks or macroblock pairs ordered consecutively in the raster scan within a particular slice group):

 

 

Knowing QuickTime movie container format (“.mov” extension) are organized by Atoms, we could situate the H.264 bit stream containing last three structs on MDAT atom .

 

Thus QuickTime starts looking for Nal Units on stream with nal_unit_type indicating SPS or PPS structures on 6810F040 and checks if any. If yes, first decodes SPS on QuickTimeH264.qtx!68192FB0 and then PPS on QuickTimeH264.qtx!68190100; the algorithm need decode last two structs to parse Slice Header.

After at QuickTimeH264.qtx!68194810, while decoding Slice Header, application checks either Slice_Header.Num_Ref_IDX_Active_Override_Flag is setted or not, a flag indicating if our Slice Header has been created with Num_Ref_IDX_l0_Active_Minus1 and Num_Ref_IDX_l1_Active_Minus1 fields.

What says specification about this values?:

num_ref_idx_l0_active_minus1 specifies the maximum reference index for reference picture list 0 that shall be used to decode each slice of the picture in which list 0 is used when num_ref_idx_active_override_flag is equal to 0 for the slice. […]The value of num_ref_idx_l0_active_minus1 shall be in the range of 0 to 31, inclusive.

A new structure is present, Slice_Header.ref_pic_list_reordering, and last fields are indicating size of data contained on here:

Looking for members on spec, we can see:

 

'ref_pic_list_reordering_flag_l0 equal to 1 specifies that the syntax element

 

reordering_of_pic_nums_idc is present for specifying reference picture list 0. ref_pic_list_reordering_flag_l0 equal to 0 specifies that this syntax element is not present.

 

When ref_pic_list_reordering_flag_l0 is equal to 1, the number of times that reordering_of_pic_nums_idc is not equal to 3 following ref_pic_list_reordering_flag_l0 shall not exceed

num_ref_idx_l0_active_minus1 + 1.

 

When RefPicList0[ num_ref_idx_l0_active_minus1 ] in the initial reference picture list produced as specified in subclause 8.2.4.2 is equal to "no reference picture", ref_pic_list_reordering_flag_l0 shall be equal to 1 and reordering_of_pic_nums_idc shall not be equal to 3 until RefPicList0[num_ref_idx_l0_active_minus1 ] in the reordered list produced as specified in subclause 8.2.4.3 is not equal to "no reference picture".'

 

And:

'reordering_of_pic_nums_idc together with abs_diff_pic_num_minus1 or long_term_pic_num specifies which of the reference pictures are re-mapped. The values of  reordering_of_pic_nums_idc are specified below. The value of the first reordering_of_pic_nums_idc that follows immediately after ref_pic_list_reordering_flag_l0 or  ref_pic_list_reordering_flag_l1 shall not be equal to 3.

 

reordering_of_pic_nums_idc Reordering specified

0 abs_diff_pic_num_minus1 is present and corresponds to a difference to subtract from a picture number prediction value

1 abs_diff_pic_num_minus1 is present and corresponds to a difference to add to a picture number prediction value

2 long_term_pic_num is present and specifies the long-term picture number for a reference picture

3 End loop for reordering of the initial reference picture list”

 

This number is result of decoding our crafted data, and as you can see, his value indicates type of reference pictures, but value 3 indicates end of stream being decoded.

In other words, it break loop.

 

 

Also, if we look PPS structure we will see it has fields with same name, num_ref_idx_l0_active_minusX, cause this will be used as values to Slice Header fields if Slice_Header.Num_Ref_IDX_Active_Override_Flag == 0:

 

 

.text:681950BB check_reordering_flag:  ; CODE XREF: parseSliceHeader+88Cj

.text:681950BB                         ; parseSliceHeader+891j

.text:681950BB                         ; parseSliceHeader+896j

.text:681950BB                         ; parseSliceHeader+89Bj

.text:681950BB                         ; parseSliceHeader+8A0j

.text:681950BB             shr eax, 1Fh ; Bit - stream

.text:681950BE             mov [edi+Slice_Header.Num_Ref_IDX_Active_Override_Flag], al

.text:681950C1             mov eax, [esp+84h+var_68]

.text:681950C5             add eax, 1

.text:681950C8             mov edx, eax

.text:681950CA             and edx, 7

.text:681950CD             shr eax, 3

.text:681950D0             mov ebp, edx

.text:681950D2             add esi, eax

.text:681950D4             mov [esp+84h+var_68], ebp

.text:681950D8             mov [esp+84h+counter], esi

.text:681950DC             mov ecx, [esp+84h+counter]

.text:681950E0             mov edx, ecx

.text:681950E2             and edx, 0FFFFFFFCh

.text:681950E5             neg ecx

.text:681950E7             mov ebx, [edx]

.text:681950E9             lea ecx, [edx+ecx+4]

.text:681950ED             mov edx, [edx+4]

.text:681950F0             bswap ebx

.text:681950F2             shl ecx, 3

.text:681950F5             bswap edx

.text:681950F7             shrd edx, ebx, cl

.text:681950FA             cmp ecx, 20h ; ' '

.text:681950FD             cmovz edx, ebx

.text:68195100             mov [esp+84h+SliceHeader], edx

.text:68195104             mov eax, [esp+84h+SliceHeader]

.text:68195108             mov ecx, ebp

.text:6819510A             shl eax, cl

.text:6819510C             cmp [edi+Slice_Header.Num_Ref_IDX_Active_Override_Flag], 0

.text:68195110             mov [esp+84h+SliceHeader], eax

.text:68195114             jz  default

...

.text:681951F3 default:                ; CODE XREF: parseSliceHeader+904j

.text:681951F3             mov ecx, [esp+84h+PPS]

.text:681951F7             mov edx, [ecx+PPS.Num_Ref_IDX_l0_Active_Minus1]

.text:681951FA             mov [edi+Slice_Header.Num_Ref_IDX_l0_Active_Minus1], edx

.text:681951FD             mov ecx, [ecx+PPS.Num_Ref_IDX_l1_active_minus1]

.text:68195200             mov [edi+Slice_Header.Num_Ref_IDX_l1_active_minus1], ecx

 

But if flag is setted, Slice_Header.Num_Ref_IDX_l0_Active_Minus1 and/or Slice_Header.Num_Ref_IDX_l1_Active_Minus1 are decoded again from input stream on fields within the same name on Slice_Header:

 

.text:68195114             jz  default

.text:6819511A             bsr eax, [esp+84+SliceHeader] ; decode our value

.text:6819511F             mov ecx, 3Fh ; '?'

.text:68195124             cmovz eax, ecx

.text:68195127             xor eax, 1Fh

.text:6819512A             mov [esp+84h+var_34], eax

.text:6819512E             mov edx, [esp+84h+var_34]

.text:68195132             mov eax, [esp+84h+SliceHeader]

.text:68195136             lea ecx, [edx+1]

.text:68195139             shl eax, cl

.text:6819513B             mov ecx, 20h

.text:68195140             sub ecx, edx

.text:68195142             mov ebx, 1

.text:68195147             shr eax, cl

.text:68195149             mov ecx, edx

.text:6819514B             neg ecx

.text:6819514D             sbb ecx, ecx

.text:6819514F             and eax, ecx

.text:68195151             mov ecx, edx

.text:68195153             shl ebx, cl

.text:68195155             mov [esp+84h+SliceHeader], eax

.text:68195159             mov ecx, ebp

.text:6819515B             lea eax, [ebx+eax-1] ; get size

.text:6819515F             mov [edi+Slice_Header.Num_Ref_IDX_l0_Active_Minus1], eax ; p0wned!

 

Num_Ref_IDX_lX_Active_Minus1 values has been checked on QuickTimeH264.qtx!68190100 (>= 0 && <= 31), but this time simply not.

Then this value is used to decode ref_pic_list_reordering, if any, to stack-based buffer present on QT Slice Header struct:

 

00000000 SliceHeader struct

...

00000150 ref_pic_list_reordering_buffer_l0 db 132 dup(?)

000001d4 ref_pic_list_reordering_buffer_l1  db 132 dup(?)

...

 

Like you can see on ref_pic_list_reordering definition we need set some fields more to the decoding :

  • ref_pic_list_reordering_flag_l0/1
  • reordering_of_pic_nums_idc

Remembering to set reordering_of_pic_nums_idc != 3 to not break loop and without checks against Num_Ref_IDX_lX_Active_Minus1, we can craft a stream (..F8025b80..) to overflow Slice_Header.ref_pic_list_reordering_buffer_l0 or Slice_Header.ref_pic_list_reordering_buffer_l1 in this loop (QuickTimeH264!681952A0):

 

 

Exactly:

 

.text:68195289 mov     [esp+84h+counter], 0

.text:68195291 lea     ebp, [edi+Slice_Header.ref_pic_list_reordering_buffer_l0]

.text:68195297 jmp     short get_reordering_of_pic_nums_idc

...

.text:681952A0 get_reordering_of_pic_nums_idc:

.text:6819531D  bsr     eax, [esp+84h+SliceHeader]

...

.text:68195360  mov     [ebp+0], eax    ; stack overflow!

.text:68195363  jmp     short check_limit

.text:681953B4  check_limit:            ; CODE XREF: parseSliceHeader+B53j

.text:681953B4  mov     ecx, [esp+84h+var_68]

.text:681953B8  lea     eax, [ecx+edx*2+1]

...

.text:681953D2  mov     ecx, [esp+84h+counter]

.text:681953D6  cmp     ecx, [edi+Slice_Header.Num_Ref_IDX_l0_Active_Minus1]

.text:681953D9  mov     [esp+84h+SliceHeader], eax

.text:681953DD ja      out

.text:681953E3  add     [esp+84h+counter], 1

.text:681953E8  add     ebp, 4

.text:681953EB  jmp     get_reordering_of_pic_nums_idc

 


 

+ Exploitation:

 

We already know Exponential-Golomb coding and it losses precission when we set a high base value, as shown in the following chart (x = offset, y = base):

 

 

limiting our data generation; but looking for a nice address we could hit one decodable: QuickTimePlayerLauncher.exe!0x00441FFF jmp esp, or encoded: 0x00000221.

Overwritting RET address with data resulting of decode 0x221, we can redirect flow while ESP register are pointing to our decoded data, but to make the job easier we will insert in stream a trampoline to our uncoded ShellCode executing minimum coded opcodes.

For this, we going to follow next steps:

1) Adding, ORing and Shifting values we will get relative distance value of pointer (saved in the stack) pointing to our mapped file from our position.

2) Substract last value to ESP.

3) POPing from stack a pointer to our buffer to EDI.

4) Add value from 1st step to EDI 4 times, just to point to our ShellCode.

5) CALL EDI.

 

Here are two images terminating this process:

 

 

Zooming:

 

 

A file sample is avaible cliking here.

Advisories: ZDI-11-255 & ZDI-11-257.

SSD-1012211 - IBM Lotus Domino 8.5.2 Nnotes.dll!NSFComputeEvaluateExt Stack-Based Buffer Overflow

Details
Category: Advisories
Published on Monday, 07 March 2011 01:12
Written by rmallof

Hi,

some months ago, we contacted with SecuriTeam Secure Disclosure to tramit IBM vulnerability, and finally, today customer published advisory regarding IBM Lotus Domino 8.5.2 issue: here.

As his name suggest, WebAdmin.nsf module is administration tool to configure nHTTP.exe server. On this control panel, after login, server allows us configurate multiple options, ie open ports on server.

For this functionality, user sends next POST request to server:

 

__Click=0

&tHPRAgentName=wqsToolConfig$UserL2  <- 0wnd

&tHPRXml1=<?xml version='1.0' encoding='UTF-8' ?><tool id='portConfig'><port

name='LAN3' newname='LAN3' driver='NETBIOS' new='0' modified='1' deleted='0'

renamed='0' enabled='0' encrypted='0' compressed='0' manual='0' unit='3' />

</tool>

thpragentname=op

 

tHPRAgentName POST variable is processed on Ninotes.dll!InotesHTTPProcessRequest → Nnotes.dll!NSFComputeEvaluateExt → Nnotes.dll!strncpy, where without checks, our buffer is copied to fixed-size buffer of 444 bytes.

 

 

This issue allows to attackers overwrite SEH pointer stored on stack and redirect execution flow, executing arbitrary code on remote IBM LD installations, but wait!

To exploit this bug, we must send alphanumeric payload and looking for valid address writable as alphanumeric characters: nnotes.dll has perfect address to POP-POP-RET on 0x60404672 (on Windows XP SP3 Spanish).

Therefore, this POST request is only attainable when user is authenticated on webadmin.nsf, since we need set "Authorization: Basic" Header to:

 

"Authorization: Basic  "+Base64((usr:pwd))+"\r\n"

 

Ok, then we can achieve this information injecting code through Cross-Site Scripting residing on administration tool :) :

 

http://localhost/webadmin.nsf/fmpgPanelHeader

?ReadForm

&PanelIcon="><script>alert("XSS");</script><img src="

 

Once we have all information, we could exploit this post-auth vulnerability. Here is the PoC.

0-day

Details
Category: Articles
Published on Sunday, 06 March 2011 20:04
Written by rmallof

Hi,

 

this website will contain advisories regarding software security issues uncovereds by Roi (@rmallof) and Sherab (@shaddycls).

Details about vulnerabilities will be posted when this ones has been fixed and patched.

 

Regards.

(0-Day) ZDI-11-112 - HP Data Protector Media Operations DBServer.exe Integer Overflow

Details
Category: Advisories
Published on Monday, 07 March 2011 00:02
Written by rmallof

Hi there,

today ZDI has published our first advisory regarding Hewlett-Packard Data Protector Media Operations Server version 6.11, which provides automated backup and recovery of physical and virtual servers from disk through net.

 

From Zero Day Initiative advisory :

"This vulnerability allows remote attackers to execute arbitrary code on vulnerable installations of HP Data Protector. Authentication is not required to exploit this vulnerability.

The specific flaw exists within the DBServer.exe process which listens by default on TCP port 19813. While parsing a request, the process trusts a user-supplied 32-bit length value and uses it within a memory operation. By specifying large enough values in a packet sent to the service, a remote attacker can execute arbitrary code under the context of the SYSTEM user."

 

Before server calculates total allocation size, classical integer overflow can be triggered when attackers send crafted packet, sure.

First, process allocate heap block with this, then this value is used too like size argument in memcpy() wrapper, where it execute insufficient checks, writting out of bounds of assigned block:

 

 

This bug is caused by non-existent security checks against this Size value before memory operations, and as said ZDI this allows executing arbitrary code remotely on HP Data Protector Media Operations Server installations like SYSTEM user.

 

(0 day) Hewlett-Packard Data Protector Media Operations DBServer.exe Remote Code Execution Vulnerability Advisory here.

 

Bye!

 

Reversing Code Research Labs, Powered by Joomla! Joomla 1.6 Templates by SiteGround