Talos Vulnerability Report

TALOS-2023-1908

Adobe Acrobat Reader Font CharStrings INDEX out-of-bounds read vulnerability

February 15, 2024
CVE Number

CVE-2024-20747

SUMMARY

An out-of-bounds read vulnerability exists in the font file processing functionality of Adobe Acrobat Reader 2023.006.20380. A specially crafted font file embedded into a PDF can trigger this vulnerability which can lead to disclosure of sensitive information. An attacker needs to trick the user into opening the malicious file to trigger this vulnerability.

CONFIRMED VULNERABLE VERSIONS

The versions below were either tested or verified to be vulnerable by Talos or confirmed to be vulnerable by the vendor.

Adobe Acrobat Reader 2023.006.20380

PRODUCT URLS

Acrobat Reader - https://acrobat.adobe.com/us/en/acrobat/pdf-reader.html

CVSSv3 SCORE

6.5 - CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N

CWE

CWE-125 - Out-of-bounds Read

DETAILS

Adobe Acrobat Reader is one of the most popular and feature-rich PDF readers on the market. It has a large user base and is usually a default PDF reader on systems. It also integrates into web browsers as a plugin for rendering PDFs.

Adobe Acrobat supports parsing of embedded font files in the PDF. This vulnerability is related to OpenType font format. An OpenType font file starts with a table directory (TableDirectory ) followed by one or more table record (TableRecord) entries. The structure of TableDirectory is as follows:

Offset Size   Name
------ ----- --------------------------------------
0x00    0x04  sfntVersion (0x00010000 or 0x4F54544F  )
0x04    0x02  numTables
0x06    0x02  searchRange
0x08    0x02  entrySelector
0x0c    0x02  rangeShift

If the value of the sfntVersion field is 0x00010000, the font contains TrueType data. The CFF data will be present if the value of sfntVersion is 0x4F54544F (‘OTTO). The numTables field specifies the number of TableRecord entries present in the font file. The structure of a TableRecord entry is as follows:

Offset Size   Name
------ ----- ----------------------------------
0x00    0x04  tableTag
0x04    0x04  tableChecksum
0x08    0x04  tableOffset
0x0C    0x04  tablelength

tableTag is the name of TableRecord. The tableOffset field specifies the offset of the table from the beginning of the file. The tablelength indicates the length of the table. The structure of each TableRecord depends on the type table, which is defined by the tableTag.

This vulnerability occurs when a font file contains CFF2 and maxp (Maximum Profile) tables. The values of the tableTag field are the strings maxp and CFF2 for maxp and CFF2 tables, respectively.

The maxp table provides information about the maximum values for various parameters in the font. The structure of a maxp table is as follows:

Offset Size         Name
------ --------    --------------------------------------
0x00    0x04        Version16Dot16                        
0x04    0x02        numGlyphs 
0x06    0x02        maxPoints
0x08    0x02        maxContours

This is not the complete structure of the maxp table, but for this vulnerability, the numGlyphs field is important. numGlyphs indicates the number of glyphs in the font.

CFF2 stands for Compact Font Format version 2 table. It is used to store and represent glyph outlines and other related data for OpenType fonts. A CFF2 table starts with a table header, followed by Top DICT, Global Subr INDEX, VariationStore and so on. The structure of the CFF2 table header is as follows:

Offset Size   Name
------ ----- --------------------------------------
0x00    0x01  cff2MajorVersion
0x01    0x01  cfff2MinorVersion
0x02    0x01  cff2HeaderSize
0x03    0x02  topDictLength

Here, the topDictLength field indicates the length of the Top DICT data in bytes. The Top DICT data is a dictionary data comprising key-value pairs, where the key is a 1- or 2-byte operator and the dictionary value is encoded as a variable-size numeric operand. The important thing to note here is that in Top DICT data, an operator is preceded by the operand(s) that specify its value. The following table indicates various types of operators Top DICT data may contain:

Operator Name   Operator Value    Operand type and meaning
----------------------------------------------------------------------------------------------------------
CharStrings    0x11               number and it gives CharStrings INDEX offset, from start of the CFF2 table.
vstore         0x18               number and it VariationStore structure offset, from start of the CFF2 table.
FDArray        0x0C 0x24          number and it Font DICT (FD) INDEX offset, from start of the CFF2 table.
FDSelect       0x0C 0x25          number and it CharStrings INDEX offset, from start of the CFF2 table. 
FontMatrix     0x0c 0x07          array and default value is (0.001 0 0 0.001 0 0)	

For this vulnerability, CharStrings operator is important. The value of CharStrings operator in byte is 0x11. The operand gives CharStrings INDEX offset, from the start of the CFF2 table. The operand value is encoded, and it can be decoded using the following pseudo python code:

 # usage: decode_integer(b"\x1d\x00\x00\x00\x8a")
 def decode_integer(data):
    first_byte = data[0]
    if 32 <= first_byte <= 246:
        return first_byte - 139
    elif 247 <= first_byte <= 250:
        return (first_byte - 247) * 256 + data[1] + 108
    elif 251 <= first_byte <= 254:
        return -(first_byte - 251) * 256 - data[1] - 108
    elif first_byte == 28:
        return data[1] * 256 + data[2]
    elif first_byte == 29:
        return (data[1] << 24) + (data[2] << 16) + (data[3] << 8) + data[4]

In our case, the Top DICT data contains three operators, and the content of the Top DICT data is as follows:

1D 00 00 00 7A 0C 24  ==>  (operator: FDArray, operand after encoding: 0x7A) 
1D 00 00 00 8A 11     ==>  (operator: CharStrings, operand after encoding: 0x8A)
1D 00 00 00 1C 18     ==>  (operator: vstore, operand after encoding: 0x1C)

The second entry of the Top DICT data shows that it contains CharStrings Index at offset 0x8A from the start of the CFF2 table. The CharStrings Index contains a header, followed by object data. The structure of CharStrings Index header is as follows:

 Offset Size                                     Name
-----------------------------------------------------------------------
0x00    0x04                                     CharStringsCount
0x04    0x01                                     CharStringsOffSize
0x05    CharStringsCount+1 * CharStringsOffSize  CharStringsOffset

CharStringsCount defines the number of object stored in INDEX . CharStringsOffset is an array, and the size of the array is the (CharStringsCount+1) * CharStringsOffSize bytes.

This vulnerability occurs when the value of the numGlyphs field in the maxp table is greater than CharStringsCount. We can observe the following in the debugger (with PageHeap enabled):

0:000> p
eax=a5d77ff8 ebx=00000000 ecx=6c6c6501 edx=00650070 esi=6c9df8e0 edi=6c6de3f0
eip=6c6de6b0 esp=050fd80c ebp=050fd840 iopl=0         nv up ei pl nz na po nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000202
CoolType!CTInit+0x2b050:
6c6de6b0 c645fc02        mov     byte ptr [ebp-4],2         ss:002b:050fd83c=01
0:000> p
eax=a5d77ff8 ebx=00000000 ecx=6c6c6501 edx=00650070 esi=6c9df8e0 edi=6c6de3f0
eip=6c6de6b4 esp=050fd80c ebp=050fd840 iopl=0         nv up ei pl nz na po nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000202
CoolType!CTInit+0x2b054:
6c6de6b4 395de0          cmp     dword ptr [ebp-20h],ebx ss:002b:050fd820=00000006
0:000> p
eax=a5d77ff8 ebx=00000000 ecx=6c6c6501 edx=00650070 esi=6c9df8e0 edi=6c6de3f0
eip=6c6de6b7 esp=050fd80c ebp=050fd840 iopl=0         nv up ei pl nz na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000206
CoolType!CTInit+0x2b057:
6c6de6b7 743f            je      CoolType!CTInit+0x2b098 (6c6de6f8)      [br=0]
0:000> p
eax=a5d77ff8 ebx=00000000 ecx=6c6c6501 edx=00650070 esi=6c9df8e0 edi=6c6de3f0
eip=6c6de6b9 esp=050fd80c ebp=050fd840 iopl=0         nv up ei pl nz na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000206
CoolType!CTInit+0x2b059:
6c6de6b9 837de006        cmp     dword ptr [ebp-20h],6 ss:002b:050fd820=00000006
0:000> p
eax=a5d77ff8 ebx=00000000 ecx=6c6c6501 edx=00650070 esi=6c9df8e0 edi=6c6de3f0
eip=6c6de6bd esp=050fd80c ebp=050fd840 iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
CoolType!CTInit+0x2b05d:
6c6de6bd 8b4ddc          mov     ecx,dword ptr [ebp-24h] ss:002b:050fd81c=a5d77ff8
0:000> p
eax=a5d77ff8 ebx=00000000 ecx=a5d77ff8 edx=00650070 esi=6c9df8e0 edi=6c6de3f0
eip=6c6de6c0 esp=050fd80c ebp=050fd840 iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
CoolType!CTInit+0x2b060:
6c6de6c0 720d            jb      CoolType!CTInit+0x2b06f (6c6de6cf)      [br=0]
0:000> p
eax=a5d77ff8 ebx=00000000 ecx=a5d77ff8 edx=00650070 esi=6c9df8e0 edi=6c6de3f0
eip=6c6de6c2 esp=050fd80c ebp=050fd840 iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
CoolType!CTInit+0x2b062:
6c6de6c2 0fb65904        movzx   ebx,byte ptr [ecx+4]       ds:002b:a5d77ffc=2d        ; <---------------- (1)
0:000> db ecx L10                                                                      ; <---------------  (2)
a5d77ff8  70 00 65 00 2d 00 d0 d0-?? ?? ?? ?? ?? ?? ?? ??  p.e.-...????????
0:000> p
eax=a5d77ff8 ebx=0000002d ecx=a5d77ff8 edx=00650070 esi=6c9df8e0 edi=6c6de3f0
eip=6c6de6c6 esp=050fd80c ebp=050fd840 iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
CoolType!CTInit+0x2b066:
6c6de6c6 0fb64105        movzx   eax,byte ptr [ecx+5]       ds:002b:a5d77ffd=00         ; <---------------- (3)
0:000> p
eax=00000000 ebx=0000002d ecx=a5d77ff8 edx=00650070 esi=6c9df8e0 edi=6c6de3f0
eip=6c6de6ca esp=050fd80c ebp=050fd840 iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
CoolType!CTInit+0x2b06a:
6c6de6ca c1e308          shl     ebx,8
0:000> p
eax=00000000 ebx=00002d00 ecx=a5d77ff8 edx=00650070 esi=6c9df8e0 edi=6c6de3f0
eip=6c6de6cd esp=050fd80c ebp=050fd840 iopl=0         nv up ei pl nz na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000206
CoolType!CTInit+0x2b06d:
6c6de6cd 03d8            add     ebx,eax                                                   ; <---------------- (4)
0:000> p
eax=00000000 ebx=00002d00 ecx=a5d77ff8 edx=00650070 esi=6c9df8e0 edi=6c6de3f0
eip=6c6de6cf esp=050fd80c ebp=050fd840 iopl=0         nv up ei pl nz na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000206
CoolType!CTInit+0x2b06f:
6c6de6cf 85c9            test    ecx,ecx
0:000> p
eax=00000000 ebx=00002d00 ecx=a5d77ff8 edx=00650070 esi=6c9df8e0 edi=6c6de3f0
eip=6c6de6d1 esp=050fd80c ebp=050fd840 iopl=0         nv up ei ng nz na po nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000282
CoolType!CTInit+0x2b071:
6c6de6d1 740d            je      CoolType!CTInit+0x2b080 (6c6de6e0)      [br=0]
0:000> p
eax=00000000 ebx=00002d00 ecx=a5d77ff8 edx=00650070 esi=6c9df8e0 edi=6c6de3f0
eip=6c6de6d3 esp=050fd80c ebp=050fd840 iopl=0         nv up ei ng nz na po nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000282
CoolType!CTInit+0x2b073:
6c6de6d3 807de400        cmp     byte ptr [ebp-1Ch],0       ss:002b:050fd824=01
0:000> p
eax=00000000 ebx=00002d00 ecx=a5d77ff8 edx=00650070 esi=6c9df8e0 edi=6c6de3f0
eip=6c6de6d7 esp=050fd80c ebp=050fd840 iopl=0         nv up ei pl nz na po nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000202
CoolType!CTInit+0x2b077:
6c6de6d7 7407            je      CoolType!CTInit+0x2b080 (6c6de6e0)      [br=0]

At (2), we show the content of maxp table. The numGlyphs field is read at (1) and (3). In our case, the value of the numGlyphs field is 0x2d00, and it can examined at (4).

eax=84407000 ebx=a6b63570 ecx=000001a6 edx=050fc2e4 esi=a6b635b4 edi=a6b63570
eip=6c6cc27c esp=050fc41c ebp=050fc430 iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
CoolType!CTInit+0x18c1c:
6c6cc27c 6a04            push    4
0:000> p
eax=84407000 ebx=a6b63570 ecx=000001a6 edx=050fc2e4 esi=a6b635b4 edi=a6b63570
eip=6c6cc27e esp=050fc418 ebp=050fc430 iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
CoolType!CTInit+0x18c1e:
6c6cc27e 57              push    edi
0:000> dd edi+2344 L4
a6b658b4  84406e00 00000000 00000000 00000000
0:000> db 84406e00                                                               ; <-------------------------------  (5)
84406e00  00 00 00 03 02 00 01 00-01 00 0b 01 3b 90 92 90  ............;...
84406e10  23 0a 8c 10 16 48 0a f9-e4 f8 fb 8b c1 87 8f 85  #....H..........
84406e20  ae 66 34 0a f2 9a 90 7b-3d 0a fb 78 32 0a 8b a2  .f4....{=..x2...
84406e30  3a 0a f4 7c 8c 7b 30 0a-9f 85 94 24 0a fb df 77  :..|.{0....$...w
84406e40  9f 8f 87 90 8c 10 16 f7-0e 9a 7e 8d 3d 0a fb a2  ..........~.=...
84406e50  32 0a b5 62 8b 8b 8c 9f-3b 0a f7 14 7c 74 83 87  2..b....;...|t..
84406e60  8f 85 93 2d 0a 9f 85 ba-8f 87 90 8c 10 06 fb f4  ...-............
84406e70  7a 59 8b 8b 8c 8c 10 16-f7 0c 9a 82 a1 3d 0a fb  zY...........=..
0:000> p
eax=84407000 ebx=a6b63570 ecx=000001a6 edx=050fc2e4 esi=a6b635b4 edi=a6b63570
eip=6c6cc27f esp=050fc414 ebp=050fc430 iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
CoolType!CTInit+0x18c1f:
6c6cc27f e8b9120000      call    CoolType!CTInit+0x19edd (6c6cd53d)              ; <------------------------------------(6)
0:000> p
eax=00000003 ebx=a6b63570 ecx=84406e04 edx=050fc2e4 esi=a6b635b4 edi=a6b63570
eip=6c6cc284 esp=050fc414 ebp=050fc430 iopl=0         nv up ei pl nz na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000206
CoolType!CTInit+0x18c24:
6c6cc284 59              pop     ecx                                             ;<--------------------------------------(7)
0:000> p
eax=00000003 ebx=a6b63570 ecx=a6b63570 edx=050fc2e4 esi=a6b635b4 edi=a6b63570
eip=6c6cc285 esp=050fc418 ebp=050fc430 iopl=0         nv up ei pl nz na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000206
CoolType!CTInit+0x18c25:
6c6cc285 8bd0            mov     edx,eax
0:000> p
eax=00000003 ebx=a6b63570 ecx=a6b63570 edx=00000003 esi=a6b635b4 edi=a6b63570
eip=6c6cc287 esp=050fc418 ebp=050fc430 iopl=0         nv up ei pl nz na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000206
CoolType!CTInit+0x18c27:
6c6cc287 eb09            jmp     CoolType!CTInit+0x18c32 (6c6cc292)
0:000> p
eax=00000003 ebx=a6b63570 ecx=a6b63570 edx=00000003 esi=a6b635b4 edi=a6b63570
eip=6c6cc292 esp=050fc418 ebp=050fc430 iopl=0         nv up ei pl nz na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000206
CoolType!CTInit+0x18c32:
6c6cc292 8b5d10          mov     ebx,dword ptr [ebp+10h] ss:002b:050fc440=050fc448

At (5), we can observe the content of CharStrings Index. The method called at (6) reads the CharStringsCount field. In this case the value of CharStringsCount is 0x03, and it can be observed at (7) .

eax=9344aff0 ebx=00000003 ecx=9344aff0 edx=00000000 esi=9344aff0 edi=00000003
eip=6c6b8342 esp=050fc044 ebp=050fc050 iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
CoolType!CTInit+0x4ce2:
6c6b8342 81ffffffff1f    cmp     edi,1FFFFFFFh
0:000> p
eax=9344aff0 ebx=00000003 ecx=9344aff0 edx=00000000 esi=9344aff0 edi=00000003
eip=6c6b8348 esp=050fc044 ebp=050fc050 iopl=0         nv up ei ng nz ac po cy
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000293
CoolType!CTInit+0x4ce8:
6c6b8348 0f87d9000000    ja      CoolType!CTInit+0x4dc7 (6c6b8427)       [br=0]
0:000> p
eax=9344aff0 ebx=00000003 ecx=9344aff0 edx=00000000 esi=9344aff0 edi=00000003
eip=6c6b834e esp=050fc044 ebp=050fc050 iopl=0         nv up ei ng nz ac po cy
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000293
CoolType!CTInit+0x4cee:
6c6b834e 8bc7            mov     eax,edi
0:000> p
eax=00000003 ebx=00000003 ecx=9344aff0 edx=00000000 esi=9344aff0 edi=00000003
eip=6c6b8350 esp=050fc044 ebp=050fc050 iopl=0         nv up ei ng nz ac po cy
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000293
CoolType!CTInit+0x4cf0:
6c6b8350 c1e003          shl     eax,3                                            ; <------------------------------- (8)
0:000> p
eax=00000018 ebx=00000003 ecx=9344aff0 edx=00000000 esi=9344aff0 edi=00000003
eip=6c6b8353 esp=050fc044 ebp=050fc050 iopl=0         nv up ei pl nz na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000206
CoolType!CTInit+0x4cf3:
6c6b8353 50              push    eax
0:000> p
eax=00000018 ebx=00000003 ecx=9344aff0 edx=00000000 esi=9344aff0 edi=00000003
eip=6c6b8354 esp=050fc040 ebp=050fc050 iopl=0         nv up ei pl nz na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000206
CoolType!CTInit+0x4cf4:
6c6b8354 e861d8ffff      call    CoolType!CTInit+0x255a (6c6b5bba)               ; <---------------------------- (9)
0:000> p
eax=97180fe8 ebx=00000003 ecx=6c6b5be2 edx=00000000 esi=9344aff0 edi=00000003
eip=6c6b8359 esp=050fc040 ebp=050fc050 iopl=0         nv up ei ng nz na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000286
CoolType!CTInit+0x4cf9:
6c6b8359 8906            mov     dword ptr [esi],eax  ds:002b:9344aff0=00000000
0:000> dd eax                                                                   ; <------------------------------- (10)
97180fe8  c0c0c0c0 c0c0c0c0 c0c0c0c0 c0c0c0c0
97180ff8  c0c0c0c0 c0c0c0c0 ???????? ????????
97181008  ???????? ???????? ???????? ????????
97181018  ???????? ???????? ???????? ????????
97181028  ???????? ???????? ???????? ????????
97181038  ???????? ???????? ???????? ????????
97181048  ???????? ???????? ???????? ????????
97181058  ???????? ???????? ???????? ????????
0:000> p
eax=97180fe8 ebx=00000003 ecx=6c6b5be2 edx=00000000 esi=9344aff0 edi=00000003
eip=6c6b835b esp=050fc040 ebp=050fc050 iopl=0         nv up ei ng nz na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000286
CoolType!CTInit+0x4cfb:
6c6b835b 59              pop     ecx

Later in the code, CharStringsCount is used to calculate the size of the vulnerable buffer at (8). The method called at (9) calls malloc to allocate the buffer. The buffer content can be examined at (10) after the call to malloc.

eax=00000000 ebx=00000080 ecx=31eda900 edx=00002d00 esi=00000000 edi=2366eff8
eip=6c6f7e0e esp=050fc3d0 ebp=050fc408 iopl=0         nv up ei pl nz na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000206
CoolType!CTInit+0x447ae:
6c6f7e0e 8b4dd8          mov     ecx,dword ptr [ebp-28h] ss:002b:050fc3e0=97180fe8
0:000> p
eax=00000000 ebx=00000080 ecx=97180fe8 edx=00002d00 esi=00000000 edi=2366eff8
eip=6c6f7e11 esp=050fc3d0 ebp=050fc408 iopl=0         nv up ei pl nz na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000206
CoolType!CTInit+0x447b1:
6c6f7e11 83c104          add     ecx,4
0:000> p                                                                                ;  <----------------------- (11)
eax=00000000 ebx=00000080 ecx=97180fec edx=00002d00 esi=00000000 edi=2366eff8
eip=6c6f7e14 esp=050fc3d0 ebp=050fc408 iopl=0         nv up ei ng nz na po nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000282
CoolType!CTInit+0x447b4:
6c6f7e14 3b39            cmp     edi,dword ptr [ecx]  ds:002b:97180fec=1f3beff8
0:000> dd 97180fe8                                                                      ; <------------------------(12)
97180fe8  1f3bcfe0 1f3beff8 1f3bcfe0 1f3beff8
97180ff8  1f3bcfe0 1f3beff8 ???????? ????????
97181008  ???????? ???????? ???????? ????????
97181018  ???????? ???????? ???????? ????????
97181028  ???????? ???????? ???????? ????????
97181038  ???????? ???????? ???????? ????????
97181048  ???????? ???????? ???????? ????????
97181058  ???????? ???????? ???????? ????????
0:000> p
eax=00000000 ebx=00000080 ecx=97180fec edx=00002d00 esi=00000000 edi=2366eff8
eip=6c6f7e16 esp=050fc3d0 ebp=050fc408 iopl=0         nv up ei pl nz na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000206
CoolType!CTInit+0x447b6:
6c6f7e16 740d            je      CoolType!CTInit+0x447c5 (6c6f7e25)      [br=0]
0:000> p
eax=00000000 ebx=00000080 ecx=97180fec edx=00002d00 esi=00000000 edi=2366eff8
eip=6c6f7e18 esp=050fc3d0 ebp=050fc408 iopl=0         nv up ei pl nz na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000206
CoolType!CTInit+0x447b8:
6c6f7e18 40              inc     eax
0:000> p
eax=00000001 ebx=00000080 ecx=97180fec edx=00002d00 esi=00000000 edi=2366eff8
eip=6c6f7e19 esp=050fc3d0 ebp=050fc408 iopl=0         nv up ei pl nz na po nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000202
CoolType!CTInit+0x447b9:
6c6f7e19 83c108          add     ecx,8
0:000> p
eax=00000001 ebx=00000080 ecx=97180ff4 edx=00002d00 esi=00000000 edi=2366eff8
eip=6c6f7e1c esp=050fc3d0 ebp=050fc408 iopl=0         nv up ei ng nz ac po nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000292
CoolType!CTInit+0x447bc:
6c6f7e1c 3bc2            cmp     eax,edx                                       ;  <---------------------- (13)
0:000> p
eax=00000001 ebx=00000080 ecx=97180ff4 edx=00002d00 esi=00000000 edi=2366eff8
eip=6c6f7e1e esp=050fc3d0 ebp=050fc408 iopl=0         nv up ei ng nz na po cy
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000283
CoolType!CTInit+0x447be:
6c6f7e1e 7cf4            jl      CoolType!CTInit+0x447b4 (6c6f7e14)      [br=1] ; <-------------------- (14)
0:000> g
(248c.112c): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000003 ebx=00000080 ecx=97181004 edx=00002d00 esi=00000000 edi=2366eff8
eip=6c6f7e14 esp=050fc3d0 ebp=050fc408 iopl=0         nv up ei ng nz na pe cy
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010287
CoolType!CTInit+0x447b4:
6c6f7e14 3b39            cmp     edi,dword ptr [ecx]  ds:002b:97181004=???????? ;<--------------------------(15)
0:000> u
CoolType!CTInit+0x447b4:
6c6f7e14 3b39            cmp     edi,dword ptr [ecx]
6c6f7e16 740d            je      CoolType!CTInit+0x447c5 (6c6f7e25)
6c6f7e18 40              inc     eax
6c6f7e19 83c108          add     ecx,8
6c6f7e1c 3bc2            cmp     eax,edx
6c6f7e1e 7cf4            jl      CoolType!CTInit+0x447b4 (6c6f7e14)
6c6f7e20 e974ffffff      jmp     CoolType!CTInit+0x44739 (6c6f7d99)
6c6f7e25 8b4d10          mov     ecx,dword ptr [ebp+10h]

0:000> kb
 # ChildEBP RetAddr      Args to Child              
WARNING: Stack unwind information not available. Following frames may be wrong.
00 050fc408 6c6f7842     9a994bd8 31eda900 050fc474 CoolType!CTInit+0x447b4
01 050fc884 6c6f76d0     9a994bd8 00000001 050fc8d0 CoolType!CTInit+0x441e2
02 050fc898 6c6d7c29     9a994bd8 050fc8d0 6306fdb6 CoolType!CTInit+0x44070
03 050fc8f8 6c6df633     6c9bed54 00000001 00000000 CoolType!CTInit+0x245c9
04 050fc92c 6c6eb3ef     9a994bd8 6c9bed54 00000001 CoolType!CTInit+0x2bfd3
05 050fc984 6c6eb09d     050fc9ac 050fcbb4 050fcbb8 CoolType!CTInit+0x37d8f
06 050fc9c0 6c6ead61     050fcbb4 050fcbb8 6306fcba CoolType!CTInit+0x37a3d
07 050fc9f4 6c6ea8c2     050fcbb4 050fcbb8 6306ffea CoolType!CTInit+0x37701
08 050fcaa4 6c6e98db     a0da8da8 00000032 050fcb78 CoolType!CTInit+0x37262
09 050fd404 6c6e8f5e     a5bea8fc 050fd438 6306e22e CoolType!CTInit+0x3627b
0a 050fd760 6c6e8e7c     a5bea8fc a5bea8e4 6306e2d2 CoolType!CTInit+0x358fe
0b 050fd79c 6ca5c1e1     8839ad90 a5bea8fc a5bea8e4 CoolType!CTInit+0x3581c
0c 050fd7b0 6ca5373e     a5bea8e4 6ca53570 3eb22954 AGM!AGMInitialize+0x22be1
0d 050fd7c4 6ca4efb7     3eb22960 6ced2a68 00000001 AGM!AGMInitialize+0x1a13e
0e 050fd7e8 6ca5afea     050fd84c 050fd868 050fd8f8 AGM!AGMInitialize+0x159b7
0f 050fd7fc 6ca5b03b     00000001 3241391f 00000000 AGM!AGMInitialize+0x219ea
10 050fd810 77a55e1e     00000000 00000000 000000fc AGM!AGMInitialize+0x21a3b
11 00000000 00000000     00000000 00000000 00000000 ntdll!RtlAllocateHeap+0x3e

In the above code, a loop starts at (11) and ends at (14). It reads the vulnerable buffer numGlyphs times.The vulnerable buffer size is controlled by CharStringsCount. In this case, numGlyphs is greater than CharStringsCount, so a crash occurs if we continue the excution: The out of bounds read can be observed at (15).

Using this vulnerability, it is possible to read arbitrary memory of the process. Because of complex interactions between PDF reader and font subcomponents, especially in the presence of a JavaScript engine, it is possible that sensitive contents of arbitrary memory could be disclosed, which could aid in further exploitation and exploit mitigation bypass.

VENDOR RESPONSE

The vendor released a security bulletin at: https://helpx.adobe.com/security/products/acrobat/apsb24-07.html Patches can be found linked from this site

TIMELINE

2024-01-11 - Vendor Disclosure
2024-02-13 - Vendor Patch Release
2024-02-15 - Public Release

Credit

Discovered by KPC of Cisco Talos.