CVE-2017-12107
An memory corruption vulnerability exists in the .PCX parsing functionality of Computerinsel Photoline 20.02. A specially crafted .PCX file can cause a vulnerability resulting in potential code execution. An attacker can send a specific .PCX file to trigger this vulnerability.
Computerinsel Photoline 20.02
8.8 - CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
CWE-787: Out-of-bounds Write
The code responsible for the vulnerability is provided below:
.text:00B8D3AA xor edi, edi ; ebp=loop1 max count | edi = counter
.text:00B8D3AC test ebp, ebp
.text:00B8D3AE jle short loop_done2
.text:00B8D3B0
.text:00B8D3B0 loc_B8D3B0: ; CODE XREF: pcx_bad_func+D5°j
.text:00B8D3B0 mov al, [esi] ; [esi] point to attacker's data
.text:00B8D3B2 mov dl, al
.text:00B8D3B4 and dl, 0C0h
.text:00B8D3B7 cmp dl, 0C0h ; condition 1
.text:00B8D3BA jnz short loc_B8D3DE
.text:00B8D3BC and al, 3Fh
.text:00B8D3BE movzx ax, al
.text:00B8D3C2 movzx eax, ax
.text:00B8D3C5 cwde
.text:00B8D3C6 inc esi
.text:00B8D3C7 test eax, eax ; condition 2 (and a loop2 counter)
.text:00B8D3C9 jle short loc_B8D3DA
.text:00B8D3CB jmp short loc_B8D3D0 ; overwrite
.text:00B8D3CB ; ---------------------------------------------------------------------------
.text:00B8D3CD align 10h
.text:00B8D3D0
.text:00B8D3D0 loc_B8D3D0: ; CODE XREF: pcx_bad_func+BB^j
.text:00B8D3D0 ; pcx_bad_func+C8°j
.text:00B8D3D0 mov dl, [esi]
.text:00B8D3D2 mov [ecx], dl ; copy attacker's data byte by byte
.text:00B8D3D4 inc ecx
.text:00B8D3D5 sub eax, 1
.text:00B8D3D8 jnz short loc_B8D3D0 ; continue write (loop 2)
.text:00B8D3DA
.text:00B8D3DA loc_B8D3DA: ; CODE XREF: pcx_bad_func+B9^j
.text:00B8D3DA inc esi
.text:00B8D3DB inc edi
.text:00B8D3DC jmp short is_loop_done1
.text:00B8D3DE loc_B8D3DE: ; CODE XREF: pcx_bad_func+AA^j
.text:00B8D3DE mov [ecx], al
.text:00B8D3E0 inc ecx
.text:00B8D3E1 inc esi
.text:00B8D3E2
.text:00B8D3E2 is_loop_done1: ; CODE XREF: pcx_bad_func+CC^j
.text:00B8D3E2 inc edi
.text:00B8D3E3 cmp edi, ebp
.text:00B8D3E5 jl short loc_B8D3B0 ; loop 1, again
An attacker can control the number of “loop 2” iterations because the max loop iteration value is obtained directly from the PCX file (instruction at 0x00B8D3D0). This can cause a memory corruption where attacker controls the size and the source data.
HEAP[PhotoLine32.exe]: Heap block at 06DEE068 modified at 06DEE3A1 past requested size of 331
(89c.3698): Break instruction exception - code 80000003 (first chance)
eax=06dee068 ebx=06dee3a1 ecx=778e3733 edx=0018e2d5 esi=06dee068 edi=00000331
eip=7794071c esp=0018e51c ebp=0018e51c iopl=0 nv up ei pl nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000202
ntdll!RtlpBreakPointHeap+0x23:
7794071c cc int 3
0:000> !heap
NtGlobalFlag enables following debugging aids for new heaps: tail checking
free checking
validate parameters
Stop inside heap manager...validating heap address 0x06dee068
Index Address Name Debugging options enabled
1: 01760000
Segment at 01760000 to 01860000 (000a1000 bytes committed)
2: 00350000
Segment at 00350000 to 00360000 (0000a000 bytes committed)
Segment at 03a30000 to 03b30000 (000bd000 bytes committed)
3: 030a0000
Segment at 030a0000 to 030b0000 (00001000 bytes committed)
4: 032a0000
Segment at 032a0000 to 032b0000 (00010000 bytes committed)
Segment at 02f80000 to 03080000 (00100000 bytes committed)
Segment at 03b30000 to 03d30000 (00200000 bytes committed)
Segment at 04110000 to 04510000 (00400000 bytes committed)
Segment at 05100000 to 05900000 (00800000 bytes committed)
Segment at 05ea0000 to 06e70000 (00fd0000 bytes committed)
Segment at 07190000 to 08160000 (0008f000 bytes committed)
Flags: 40001062
ForceFlags: 40000060
Granularity: 8 bytes
Segment Reserve: 02fa0000
Segment Commit: 00002000
DeCommit Block Thres: 00000200
DeCommit Total Thres: 00002000
Total Free Size: 0000c9f3
Max. Allocation Size: 7ffdefff
Lock Variable at: 032a0138
Next TagIndex: 0000
Maximum TagIndex: 0000
Tag Entries: 00000000
PsuedoTag Entries: 00000000
Virtual Alloc List: 032a00a0
Unable to read nt!_HEAP_VIRTUAL_ALLOC_ENTRY structure at 05be0000
Uncommitted ranges: 032a0090
FreeList[ 00 ] at 032a00c4: 0512f228 . 06de6c20 Unable to read nt!_HEAP_FREE_ENTRY structure at fffffff7
(632 blocks)
06dee020: 00030 . 00048 [107] - busy (30), tail fill
06dee068: 00048 . 00350 [107] - busy (331), tail fill (Handle ffffffff) (Tag ffff)
Stack traces not enabled (ntdll!RtlpStackTraceDataBase is null).
Heap block at 06dee068 modified at 06dee3a1 past requested size of 331 (6a * 8 - 1f)
06dee3b8: 55960 . 6b288 [01] - busy (5b289)
##CORRUPTION FOUND at 0x06DEE3B8
PreviousSize field does not match Size field in previous entry
Entry->PreviousSize == 0xd651
PreviousEntry->Size == 0x9
##CORRUPTION FOUND at 0x06E59640
PreviousSize field does not match Size field in previous entry
Entry->PreviousSize == 0xf00d
PreviousEntry->Size == 0xab2c
##The above errors were found in segment at 0x05EA0000
Flags: 40001062
ForceFlags: 40000060
Granularity: 8 bytes
Segment Reserve: 02fa0000
Segment Commit: 00002000
DeCommit Block Thres: 00000200
DeCommit Total Thres: 00002000
Total Free Size: 0000c9f3
Max. Allocation Size: 7ffdefff
Lock Variable at: 032a0138
Next TagIndex: 0000
Maximum TagIndex: 0000
Tag Entries: 00000000
PsuedoTag Entries: 00000000
Virtual Alloc List: 032a00a0
Unable to read nt!_HEAP_VIRTUAL_ALLOC_ENTRY structure at 05be0000
Uncommitted ranges: 032a0090
FreeList[ 00 ] at 032a00c4: 0512f228 . 06de6c20 Unable to read nt!_HEAP_FREE_ENTRY structure at fffffff7
(632 blocks)
06dee020: 00030 . 00048 [107] - busy (30), tail fill
06dee068: 00048 . 00350 [107] - busy (331), tail fill (Handle ffffffff) (Tag ffff)
Stack traces not enabled (ntdll!RtlpStackTraceDataBase is null).
Heap block at 06dee068 modified at 06dee3a1 past requested size of 331 (6a * 8 - 1f)
06dee3b8: 55960 . 6b288 [01] - busy (5b289)
##CORRUPTION FOUND at 0x06DEE3B8
PreviousSize field does not match Size field in previous entry
Entry->PreviousSize == 0xd651
PreviousEntry->Size == 0x9
##CORRUPTION FOUND at 0x06E59640
PreviousSize field does not match Size field in previous entry
Entry->PreviousSize == 0xf00d
PreviousEntry->Size == 0xab2c
##The above errors were found in segment at 0x05EA0000
2017-10-11 - Vendor Disclosure
2017-10-30 - Public Release
Discovered by Piotr Bania of Cisco Talos