[하루한줄] CVE-2025-27158: Adobe Acrobat Reader의 Uninitialized Pointer로 인한 RCE 취약점
URL
Target
- Adobe Acrobat Reader
- 24.001.30225
- 20.005.30748
- 25.001.20428 및 이전 버전
Explain
CVE-2025-27158은 Adobe Acrobat Reader에서 PDF에 포함된 OTF(OpenType Font) 파일을 처리하는 과정에서 발생했습니다.
OTF 파일은 크게 TableDirectory와 TableRecords로 구성되어 있어, 먼저 TableDirectory 구조를 살펴보겠습니다.
Offset Size Name
------ ----- --------------------------------------
0x00 0x04 sfntVersion (0x00010000 or 0x74727565 or 0x4F54544F )
0x04 0x02 numTables
0x06 0x02 searchRange
0x08 0x02 entrySelector
0x0c 0x02 rangeShift
sfntVersion 값이 0x00010000 또는 0x74727565인 경우 글꼴에 TrueType 데이터가 포함되고, 0x4F54544F인 경우 CFF 데이터가 포함됩니다.
numTables는 TableRecord 개수로 TableRecord 구조는 아래와 같습니다.
Offset Size Name
------ ----- ----------------------------------
0x00 0x04 tableTag
0x04 0x04 tableChecksum
0x08 0x04 tableOffset
0x0C 0x04 tableLength
tableTag의 값이 “CFF2”이면 CFF2 테이블을 가리킵니다.
CFF2(Compact Font Format version 2) 테이블의 구조는 헤더, Top DICT, Global Subr INDEX, VariationStore으로 되어 있어 헤더부터 살펴보면 아래와 같습니다.
Offset Size Name
------ ----- --------------------------------------
0x00 0x01 cff2MajorVersion
0x01 0x01 cfff2MinorVersion
0x02 0x01 cff2HeaderSize
0x03 0x02 topDictLength
여기서 topDictLength는 말 그대로 Top DICT 데이터의 길이를 나타냅니다.
Top DICT는 폰트의 주요 정보를 담은 데이터로 아래와 같이 다양한 정보가 포함될 수 있습니다.
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)
취약한 OTF 파일은 아래 3개의 Top DICT 데이터가 존재했습니다.
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)
이 중 vstore(0x18)의 offset은 0x1C로 CFF2 테이블에서 0x1C만큼 떨어진 곳에 VariationStore가 존재하고 구조는 아래와 같습니다.
Offset Size Name
-----------------------------------------------------------------------
0x00 0x02 Length
0x02 0x02 Format
0x04 0x04 variationRegionListOffset
0x06 0x02 itemVariationDataCount (N)
0x08 0x04 * N itemVariationDataOffsets[N]
itemVariationDataCount는 하위 테이블의 개수(N)를 나타내며 itemVariationDataOffsets는 각 하위 테이블의 offset이 존재합니다.
itemVariationData의 하위 테이블 구조는 아래와 같습니다.
Offset Size Name
-----------------------------------------------------------------------
0x00 0x02 itemCount
0x02 0x02 shortDeltaCount
0x04 0x02 regionIndexCount (C)
0x06 0x02 * C regionIndexes[C]
취약점은 itemVariationDataCount를 통해 할당한 메모리 영역을 초기화하지 않고 사용해 발생했습니다.
[...]
0:002> p
Time Travel Position: E92AE:1C21
eax=00000010 ebx=f3a2a970 ecx=00000004 edx=00000100 esi=00001b7c edi=f3a2a970
eip=6ee28da7 esp=052fc4b4 ebp=052fc4dc 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!CTGetVersion+0xb5877:
6ee28da7 e8b73ee6ff call CoolType!CTInit+0x195e3 (6ec8cc63) <- [1]
0:002> p
Time Travel Position: E92AE:1C3B
eax=00000002 ebx=f3a2a970 ecx=00000002 edx=00000100 esi=00001b7c edi=f3a2a970
eip=6ee28dac esp=052fc4b4 ebp=052fc4dc 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!CTGetVersion+0xb587c:
6ee28dac 66898738020000 mov word ptr [edi+238h],ax ds:002b:f3a2aba8=ffff <- [2]
0:002> p
Time Travel Position: E92AE:1C3C
eax=00000002 ebx=f3a2a970 ecx=00000002 edx=00000100 esi=00001b7c edi=f3a2a970
eip=6ee28db3 esp=052fc4b4 ebp=052fc4dc 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!CTGetVersion+0xb5883:
6ee28db3 0fb7c0 movzx eax,ax
0:002> p
allocate vuln buffer of size 0x20
Time Travel Position: E92AE:1C3D
eax=00000002 ebx=f3a2a970 ecx=00000002 edx=00000100 esi=00001b7c edi=f3a2a970
eip=6ee28db6 esp=052fc4b4 ebp=052fc4dc 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!CTGetVersion+0xb5886:
6ee28db6 c1e004 shl eax,4 <- [3]
0:002> p
Time Travel Position: E92AE:1C3E
eax=00000020 ebx=f3a2a970 ecx=00000002 edx=00000100 esi=00001b7c edi=f3a2a970
eip=6ee28db9 esp=052fc4b4 ebp=052fc4dc 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!CTGetVersion+0xb5889:
6ee28db9 50 push eax
0:002> p
Time Travel Position: E92AE:1C3F
eax=00000020 ebx=f3a2a970 ecx=00000002 edx=00000100 esi=00001b7c edi=f3a2a970
eip=6ee28dba esp=052fc4b0 ebp=052fc4dc 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!CTGetVersion+0xb588a:
6ee28dba e817cee4ff call CoolType!CTInit+0x2556 (6ec75bd6) <- [4]
0:002> p
Time Travel Position: E92B1:1394
eax=0a02b330 ebx=f3a2a970 ecx=6ec75bfe edx=00000000 esi=00001b7c edi=f3a2a970
eip=6ee28dbf esp=052fc4b0 ebp=052fc4dc 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!CTGetVersion+0xb588f:
6ee28dbf 89873c020000 mov dword ptr [edi+23Ch],eax ds:002b:f3a2abac=00000000<- [5]
0:002> dd eax; <- [6]
0a02b330 e0e0e0e0 e0e0e0e0 e0e0e0e0 e0e0e0e0
0a02b340 e0e0e0e0 e0e0e0e0 e0e0e0e0 e0e0e0e0
0a02b350 a0a0a0a0 a0a0a0a0 00000000 00000000
0:002> p
Time Travel Position: E92B1:1395
eax=0a02b330 ebx=f3a2a970 ecx=6ec75bfe edx=00000000 esi=00001b7c edi=f3a2a970
eip=6ee28dc5 esp=052fc4b0 ebp=052fc4dc 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!CTGetVersion+0xb5895:
6ee28dc5 0fb78738020000 movzx eax,word ptr [edi+238h] ds:002b:f3a2aba8=0002
[1]에서 CoolType!CTInit+0x195e3
함수를 통해 VariationStore 구조체 itemVariationDataCount 값을 가져옵니다. [2]에서 itemVariationDataCount 값(0x02)을 확인할 수 있습니다.
[3]에서 itemVariationDataCount 값을 통해 버퍼 크기(0x20)를 계산합니다. 이후 [4]에서 CoolType!CTInit+0x2556
함수를 호출하여 malloc으로 0x20 바이트 크기의 버퍼를 할당합니다.
[6]에서 할당된 버퍼(0x0a02b330)를 확인하면, 더미 데이터(0xe0e0e0e0)가 존재하는 것을 알 수 있습니다.
[...]
0:002>
Time Travel Position: E92BA:1BB5
eax=db00d000 ebx=00000000 ecx=0000016b edx=052fc380 esi=0a02b330 edi=f3a2a970
eip=6ee28e65 esp=052fc4a8 ebp=052fc4dc iopl=0 nv up ei pl nz ac po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000212
CoolType!CTGetVersion+0xb5935:
6ee28e65 e8f93de6ff call CoolType!CTInit+0x195e3 (6ec8cc63) <-[8]
0:002> p
Time Travel Position: E92BA:1BCF
eax=00000000 ebx=00000000 ecx=00000000 edx=052fc380 esi=0a02b330 edi=f3a2a970
eip=6ee28e6a esp=052fc4a8 ebp=052fc4dc 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!CTGetVersion+0xb593a:
6ee28e6a 57 push edi
0:002> p
Time Travel Position: E92BA:1BD0
eax=00000000 ebx=00000000 ecx=00000000 edx=052fc380 esi=0a02b330 edi=f3a2a970
eip=6ee28e6b esp=052fc4a4 ebp=052fc4dc 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!CTGetVersion+0xb593b:
6ee28e6b 668906 mov word ptr [esi],ax ds:002b:0a02b330=e0e0 <-[9]
0:002> p
Breakpoint 1 hit
Time Travel Position: E92BA:1BD1
eax=00000000 ebx=00000000 ecx=00000000 edx=052fc380 esi=0a02b330 edi=f3a2a970
eip=6ee28e6e esp=052fc4a4 ebp=052fc4dc 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!CTGetVersion+0xb593e:
6ee28e6e e8f03de6ff call CoolType!CTInit+0x195e3 (6ec8cc63) <-[10]
0:002> db esi L20
0a02b330 00 00 e0 e0 e0 e0 e0 e0-e0 e0 e0 e0 e0 e0 e0 e0 ................
0a02b340 e0 e0 e0 e0 e0 e0 e0 e0-e0 e0 e0 e0 e0 e0 e0 e0 ................
0:002> p
Time Travel Position: E92BA:1BEB
eax=00000000 ebx=00000000 ecx=00000000 edx=052fc380 esi=0a02b330 edi=f3a2a970
eip=6ee28e73 esp=052fc4a4 ebp=052fc4dc 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!CTGetVersion+0xb5943:
6ee28e73 57 push edi
0:002> p
Time Travel Position: E92BA:1BEC
eax=00000000 ebx=00000000 ecx=00000000 edx=052fc380 esi=0a02b330 edi=f3a2a970
eip=6ee28e74 esp=052fc4a0 ebp=052fc4dc 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!CTGetVersion+0xb5944:
6ee28e74 66894602 mov word ptr [esi+2],ax ds:002b:0a02b332=e0e0 <-[11]
0:002> p
Breakpoint 1 hit
Time Travel Position: E92BA:1BED
eax=00000000 ebx=00000000 ecx=00000000 edx=052fc380 esi=0a02b330 edi=f3a2a970
eip=6ee28e78 esp=052fc4a0 ebp=052fc4dc 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!CTGetVersion+0xb5948:
6ee28e78 e8e63de6ff call CoolType!CTInit+0x195e3 (6ec8cc63) <-[12]
0:002> p
Time Travel Position: E92BA:1C07
eax=00008000 ebx=00000000 ecx=00000000 edx=052fc380 esi=0a02b330 edi=f3a2a970
eip=6ee28e7d esp=052fc4a0 ebp=052fc4dc 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!CTGetVersion+0xb594d:
6ee28e7d b900800000 mov ecx,8000h
0:002> p
Time Travel Position: E92BA:1C08
eax=00008000 ebx=00000000 ecx=00008000 edx=052fc380 esi=0a02b330 edi=f3a2a970
eip=6ee28e82 esp=052fc4a0 ebp=052fc4dc 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!CTGetVersion+0xb5952:
6ee28e82 66894604 mov word ptr [esi+4],ax ds:002b:0a02b334=e0e0 <-[13]
[...]
0:002> p
Time Travel Position: E92BA:1C0D
eax=00008000 ebx=00000000 ecx=00008000 edx=052fc380 esi=0a02b330 edi=f3a2a970
eip=6ee28e95 esp=052fc4b8 ebp=052fc4dc 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!CTGetVersion+0xb5965:
6ee28e95 03c0 add eax,eax <-[14]
0:002> p
Time Travel Position: E92BA:1C0E
eax=00010000 ebx=00000000 ecx=00008000 edx=052fc380 esi=0a02b330 edi=f3a2a970
eip=6ee28e97 esp=052fc4b8 ebp=052fc4dc 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!CTGetVersion+0xb5967:
6ee28e97 50 push eax
0:002> p
Time Travel Position: E92BA:1C0F
eax=00010000 ebx=00000000 ecx=00008000 edx=052fc380 esi=0a02b330 edi=f3a2a970
eip=6ee28e98 esp=052fc4b4 ebp=052fc4dc 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!CTGetVersion+0xb5968:
6ee28e98 e839cde4ff call CoolType!CTInit+0x2556 (6ec75bd6) <-[15]
0:002> p
Time Travel Position: E92C1:108
eax=f2bca0c8 ebx=00000000 ecx=6ec75bfe edx=00000000 esi=0a02b330 edi=f3a2a970
eip=6ee28e9d esp=052fc4b4 ebp=052fc4dc 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!CTGetVersion+0xb596d:
6ee28e9d 8365ec00 and dword ptr [ebp-14h],0 ss:002b:052fc4c8=f3a2e384
0:002> db f2bca0c8
f2bca0c8 e0 e0 e0 e0 e0 e0 e0 e0-e0 e0 e0 e0 e0 e0 e0 e0 ................
f2bca0d8 e0 e0 e0 e0 e0 e0 e0 e0-e0 e0 e0 e0 e0 e0 e0 e0 ................
f2bca0e8 e0 e0 e0 e0 e0 e0 e0 e0-e0 e0 e0 e0 e0 e0 e0 e0 ................
f2bca0f8 e0 e0 e0 e0 e0 e0 e0 e0-e0 e0 e0 e0 e0 e0 e0 e0 ................
f2bca108 e0 e0 e0 e0 e0 e0 e0 e0-e0 e0 e0 e0 e0 e0 e0 e0 ................
f2bca118 e0 e0 e0 e0 e0 e0 e0 e0-e0 e0 e0 e0 e0 e0 e0 e0 ................
f2bca128 e0 e0 e0 e0 e0 e0 e0 e0-e0 e0 e0 e0 e0 e0 e0 e0 ................
f2bca138 e0 e0 e0 e0 e0 e0 e0 e0-e0 e0 e0 e0 e0 e0 e0 e0 ................
0:002> p
Time Travel Position: E92C1:109
eax=f2bca0c8 ebx=00000000 ecx=6ec75bfe edx=00000000 esi=0a02b330 edi=f3a2a970
eip=6ee28ea1 esp=052fc4b4 ebp=052fc4dc 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!CTGetVersion+0xb5971:
6ee28ea1 894608 mov dword ptr [esi+8],eax ds:002b:0a02b338=e0e0e0e0 <-[16]
[...]
0:002> p
Time Travel Position: E92C1:10F
eax=00000000 ebx=00000000 ecx=00010000 edx=00000000 esi=0a02b330 edi=f3a2a970
eip=6ee28eb0 esp=052fc4b8 ebp=052fc4dc iopl=0 ov up ei ng nz na pe cy
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000a87
CoolType!CTGetVersion+0xb5980:
6ee28eb0 57 push edi <-[17]
0:002> p
Time Travel Position: E92C1:110
eax=00000000 ebx=00000000 ecx=00010000 edx=00000000 esi=0a02b330 edi=f3a2a970
eip=6ee28eb1 esp=052fc4b4 ebp=052fc4dc iopl=0 ov up ei ng nz na pe cy
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000a87
CoolType!CTGetVersion+0xb5981:
6ee28eb1 e8ad3de6ff call CoolType!CTInit+0x195e3 (6ec8cc63)
0:002> p
Time Travel Position: E92C1:12A
eax=00000000 ebx=00000000 ecx=00000000 edx=00000000 esi=0a02b330 edi=f3a2a970
eip=6ee28eb6 esp=052fc4b4 ebp=052fc4dc 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!CTGetVersion+0xb5986:
6ee28eb6 59 pop ecx
0:002> u
CoolType!CTGetVersion+0xb5986:
6ee28eb6 59 pop ecx
6ee28eb7 0fb7d0 movzx edx,ax
6ee28eba 8b4608 mov eax,dword ptr [esi+8]
6ee28ebd 0fb7cb movzx ecx,bx
6ee28ec0 43 inc ebx
6ee28ec1 66891448 mov word ptr [eax+ecx*2],dx
6ee28ec5 663b5e04 cmp bx,word ptr [esi+4]
6ee28ec9 72e5 jb CoolType!CTGetVersion+0xb5980 (6ee28eb0) <-[18]
[8], [10], [12]에서 각각 itemCount, shortDeltaCount, regionIndexCount 값을 읽어와 [9], [11], [13]을 통해 0a02b330, 0a02b330+2, 0a02b330+4 주소에 write 합니다.
위 세 가지 값은 첫 번째 하위 테이블의 정보를 나타내며, 특히 regionIndexCount은 regionIndexes 배열의 크기를 결정합니다.
[14]에서 regionIndexCount 값(0x8000)을 통해 버퍼 크기(0x10000)를 계산합니다. 이후 [15]에서 CoolType!CTInit+0x2556
을 호출해 regionIndexes 버퍼를 할당합니다.
[16]에서 할당된 regionIndexes 버퍼의 포인터(0xf2bca0c8)를 [4]에서 할당한 버퍼(0a02b330+8)에 기록합니다.
[17]에서 시작해 [18]에서 끝나는 루프는 첫 번째 itemVariationData 하위 테이블 regionIndex를 통해 해당 값을 regionIndexes 버퍼에 write 합니다.
이때, 파일 데이터가 부족해 regionIndexes 데이터를 모두 읽지 못하면 할당된 모든 버퍼를 해제하려고 합니다.
0:002> g
Time Travel Position: E9353:6D
eax=00000000 ebx=00000000 ecx=f3a36e40 edx=09cf0000 esi=f3a2a970 edi=00000000
eip=6ee279d9 esp=052fc1d8 ebp=052fc1e4 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!CTGetVersion+0xb44a9:
6ee279d9 8b863c020000 mov eax,dword ptr [esi+23Ch] ds:002b:f3a2abac=0a02b330
0:002> t
Time Travel Position: E9353:6E
eax=0a02b330 ebx=00000000 ecx=f3a36e40 edx=09cf0000 esi=f3a2a970 edi=00000000
eip=6ee279df esp=052fc1d8 ebp=052fc1e4 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!CTGetVersion+0xb44af:
6ee279df ff740708 push dword ptr [edi+eax+8] ds:002b:0a02b338=f2bca0c8 <-[19]
0:002> dd 0a02b330
0a02b330 00000000 e0e08000 f2bca0c8 e0e0e0e0
0a02b340 e0e0e0e0 e0e0e0e0 e0e0e0e0 e0e0e0e0
0:002> p
Time Travel Position: E9353:6F
eax=0a02b330 ebx=00000000 ecx=f3a36e40 edx=09cf0000 esi=f3a2a970 edi=00000000
eip=6ee279e3 esp=052fc1d4 ebp=052fc1e4 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!CTGetVersion+0xb44b3:
6ee279e3 e82a4ce5ff call CoolType!CTInit+0x8f92 (6ec7c612) <-[20]
0:002> p
Time Travel Position: E935D:2382
eax=00000001 ebx=00000000 ecx=f2bca0c8 edx=09cf0000 esi=f3a2a970 edi=00000000
eip=6ee279e8 esp=052fc1d4 ebp=052fc1e4 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!CTGetVersion+0xb44b8:
6ee279e8 0fb78638020000 movzx eax,word ptr [esi+238h] ds:002b:f3a2aba8=0002
0:002> dd f2bca0c8 <-[21]
f2bca0c8 f0f0f0f0 f0f0f0f0 f0f0f0f0 f0f0f0f0
f2bca0d8 f0f0f0f0 f0f0f0f0 f0f0f0f0 f0f0f0f0
f2bca0e8 f0f0f0f0 f0f0f0f0 f0f0f0f0 f0f0f0f0
f2bca0f8 f0f0f0f0 f0f0f0f0 f0f0f0f0 f0f0f0f0
f2bca108 f0f0f0f0 f0f0f0f0 f0f0f0f0 f0f0f0f0
f2bca118 f0f0f0f0 f0f0f0f0 f0f0f0f0 f0f0f0f0
f2bca128 f0f0f0f0 f0f0f0f0 f0f0f0f0 f0f0f0f0
f2bca138 f0f0f0f0 f0f0f0f0 f0f0f0f0 f0f0f0f0
[...]
0:002> t
Time Travel Position: E935D:2389
eax=0a02b330 ebx=00000001 ecx=f2bca0c8 edx=09cf0000 esi=f3a2a970 edi=00000010
eip=6ee279df esp=052fc1d8 ebp=052fc1e4 iopl=0 nv up ei ng nz ac pe cy
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000297
CoolType!CTGetVersion+0xb44af:
6ee279df ff740708 push dword ptr [edi+eax+8] ds:002b:0a02b348=e0e0e0e0 <-[22]
0:002> t
Time Travel Position: E935D:238A
eax=0a02b330 ebx=00000001 ecx=f2bca0c8 edx=09cf0000 esi=f3a2a970 edi=00000010
eip=6ee279e3 esp=052fc1d4 ebp=052fc1e4 iopl=0 nv up ei ng nz ac pe cy
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000297
CoolType!CTGetVersion+0xb44b3:
6ee279e3 e82a4ce5ff call CoolType!CTInit+0x8f92 (6ec7c612) <-[23]
[19]에서 첫 번째 regionIndexes 버퍼의 주소(0xf2bca0c8)를 스택에 push 합니다.
[20]에서 CoolType!CTInit+0x8f92
를 호출해 첫 번째 버퍼를 해제합니다.
[22]에서 두 번째 하위 테이블의 regionIndexes 버퍼 주소를 push 하려 하지만, 할당이 안되었기 때문에 더미 데이터(0xe0e0e0e0)를 push 해 [23] 실행 시 크래시가 발생합니다.
따라서, 공격자는 [4]에서 할당된 버퍼(0x0a02b330)를 조작할 수 있으면 임의의 코드를 실행할 수 있습니다.
본 글은 CC BY-SA 4.0 라이선스로 배포됩니다. 공유 또는 변경 시 반드시 출처를 남겨주시기 바랍니다.