Talos Vulnerability Report


LEADTOOLS TIF ImageWidth code execution vulnerability

November 5, 2019
CVE Number



An exploitable heap out-of-bounds write vulnerability exists in the TIF-parsing functionality of LEADTOOLS 20. A specially crafted TIF image can cause an offset beyond the bounds of a heap allocation to be written, potentially resulting in code execution. An attacker can specially craft a TIF image to trigger this vulnerability.

Tested Versions

LEADTOOLS 20.0.2019.3.15

Product URLs


CVSSv3 Score

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


LEADTOOLS, according to the website, "is a collection of comprehensive toolkits to integrate document, medical, multimedia, and imaging technologies into desktop, server, tablet, and mobile applications". It offers prebuilt and portable libraries with an SDK for most platforms (Windows, Linux, Android, etc), that are all geared toward building applications for medical systems.

The modules analyzed in this vulnerability are below:

Loaded symbol image file: lfTifX.DLL
Mapped memory image file: C:\LEADTOOLS 20\Bin\CDLL\x64\lfTifX.DLL
Image path: C:\LEADTOOLS 20\Bin\CDLL\x64\lfTifX.DLL
Image name: lfTifX.DLL
Browse all global symbols  functions  data
Timestamp:        Thu Feb 21 14:14:07 2019 (5C6F068F)
CheckSum:         0004FE45
ImageSize:        0004C000
File version:
Product version:

Loaded symbol image file: Ltkrnx.dll
Mapped memory image file: C:\LEADTOOLS 20\Bin\CDLL\x64\Ltkrnx.dll
Image path: C:\LEADTOOLS 20\Bin\CDLL\x64\Ltkrnx.dll
Image name: Ltkrnx.dll
Browse all global symbols  functions  data
Timestamp:        Fri Mar  1 13:35:30 2019 (5C798982)
CheckSum:         0017FA3E
ImageSize:        00176000
File version:
Product version:

One toolkit provided by LEADTOOLS is a TIF image parser. This image parser can be hit from a variety of example applications included the Barcode reader and ImageViewer.

When parsing a TIF image, the following heap allocation is made in fltLoadTif:

.text:0000000000002EF1                         loc_2EF1:
.text:0000000000002EF1 BA 01 00 00 00          mov     edx, 1
.text:0000000000002EF6 48 8B CE                mov     rcx, rsi
.text:0000000000002EF9 4C 8D 0D E0 3F 03 00    lea     r9, aDSrcmLead15Api ; "d:\\srcm\\lead15\\api\\filters\\tif\\co"...
.text:0000000000002F00 44 8D 42 3E             lea     r8d, [rdx+3Eh]
.text:0000000000002F04 48 0F AF CF             imul    rcx, rdi
.text:0000000000002F08 48 83 C1 03             add     rcx, 3
.text:0000000000002F0C 48 89 4B 08             mov     [rbx+8], rcx
.text:0000000000002F10 FF 15 92 24 03 00       call    cs:L_LocalAlloc

The allocation size comes from the following equation from the function TIFGetBytesPerTileRow.

.text:00000000000060D1                         loc_60D1:
.text:00000000000060D1 8B 81 C8 00 00 00       mov     eax, [rcx+0C8h]  
.text:00000000000060D7 0F AF 41 64             imul    eax, [rcx+64h]   
.text:00000000000060DB 83 C0 07                add     eax, 7
.text:00000000000060DE C1 E8 03                shr     eax, 3
.text:00000000000060E1 C3                      retn

This buffer is then handed off to L_ConvertBuffer. From the documentation, this function "converts data in the specified buffer to the specified bits per pixel and color order. You can convert from any bits per pixel to any bits per pixel." The first two parameters to this function are a pointer to the input buffer and the width of the image in pixels. The width of the image is calculated using the following equation based on the ImageWidth and SamplesPerPixel.

.text:00000000000079D3                 cmp     dword ptr [r14+44h], 2
.text:00000000000079D8                 mov     eax, [r14+64h]
.text:00000000000079DC                 jz      short loc_79E6
.text:00000000000079DE                 imul    eax, [r14+0C0h]

During L_ConvertBuffer, an offset is calculated to write data into the allocated buffer.

.text:00000000000306F3                 movsxd  rax, ebx
.text:00000000000306F6                 mov     r8d, ebx
.text:00000000000306F9                 mov     r9, rax
.text:00000000000306FC                 and     r8d, 7
.text:0000000000030700                 sar     r9, 3
.text:0000000000030704                 add     r9, rsi ; Offset into the allocated buffer

This offset is then populated with image data.

.text:0000000000030716 loc_30716:                              
.text:0000000000030716                 mov     eax, r8d
.text:0000000000030719                 sub     r8d, 1
.text:000000000003071D                 jns     short loc_30726
.text:000000000003071F                 lea     r8d, [rax+7]
.text:0000000000030723                 dec     r9
.text:0000000000030726 loc_30726:                              
.text:0000000000030726                 movzx   edx, byte ptr [r9]
.text:000000000003072A                 dec     r10
.text:000000000003072D                 mov     ecx, 7
.text:0000000000030732                 sub     cl, r8b
.text:0000000000030735                 shr     rdx, cl
.text:0000000000030738                 and     edx, 1
.text:000000000003073B                 movzx   eax, [rsp+rdx+170h+var_140]
.text:0000000000030740                 mov     [r10], al   ; Writing to the offset in the allocated buffer
.text:0000000000030743                 sub     r11, 1
.text:0000000000030747                 jnz     short loc_30716

A specially crafted TIF file can cause this offset to be out of bounds from the original heap allocation. This would result in an out of bounds write on the heap, potentially leading to code execution.

Crash Information

>>> analyze -v
IMAGE_NAME:  Ltkrnx.dll


2019-08-08 - Vendor Disclosure
2019-11-03 - Vendor Patched
2019-11-05 - Public Release


Discovered by Marcin Towalski and Cory Duplantis of Cisco Talos.