Talos Vulnerability Report

TALOS-2017-0273

National Instruments LabVIEW RSRC Arbitrary Null Write Code Execution Vulnerability

August 29, 2017
CVE Number

CVE-2017-2779

Summary

An exploitable memory corruption vulnerability exists in the RSRC segment parsing functionality of LabVIEW. A specially crafted VI file can cause an attacker controlled looping condition resulting in an arbitrary null write. An attacker controlled VI file can be used to trigger this vulnerability and can potentially result in code execution.

Tested Versions

LabVIEW 2016 version 16.0

Product URLs

http://www.ni.com/labview/

CVSSv3 Score

7.5 - CVSS:3.0/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H

CWE

CWE-787: Out-of-bounds Write

Details

LabVIEW provides engineers a simple environment to build measurement or control systems. LabVIEW is used to abstract many of the low-level details of various hardware and signal-processing libraries into a single platform. It uses a graphical programming approach to achieve this goal.

Modules utilized in this vulnerability:

start    end        module name
03cc0000 03d76000   mgcore_SH_16_0   (export symbols)       C:\Program Files\National Instruments\LabVIEW 2016\resource\mgcore_SH_16_0.dll
    Loaded symbol image file: C:\Program Files\National Instruments\LabVIEW 2016\resource\mgcore_SH_16_0.dll
    Image path: C:\Program Files\National Instruments\LabVIEW 2016\resource\mgcore_SH_16_0.dll
    Image name: mgcore_SH_16_0.dll
    Browse all global symbols  functions  data
    Timestamp:        Wed Jun 08 10:00:01 2016 (57584F11)
    CheckSum:         000B192B
    ImageSize:        000B6000
    File version:     16.0.0.49152

While opening a VI file, an RSRC segment can be parsed. An example of the beginning of this segment is shown below:

0:000> dc esi
0acf6690  43525352 03000a0d 4e49564c 5756424c  RSRC....LVINLBVW
0acf66a0  d00b0000 eb020000 20000000 b00b0000  ........... ....
0acf66b0  00000000 00000000 20000000 34000000  ........... ...4
0acf66c0  d8020000 14000000 5253564c 00000000  ........LVSR....
0acf66d0  00010000 47535452 00000000 14010000  ....RTSG........
0acf66e0  73726576 00000000 28010000 504e4f43  vers.......(CONP
0acf66f0  00000000 3c010000 6976494c 00000000  .......<LIvi....
0acf6700  50010000 57504442 00000000 64010000  ...PBDPW.......d

After parsing the RSRC segment into an internal RSRC struct, LabVIEW tries to clean up data handles created in this process. To begin this process, the loop counter is first extracted from the RSRC segment.

mgcore_SH_16_0!LVResFile::ClearAllDataHdls+0x18:
.text:1001FF98 008                 mov     esi, [ecx+2Ch] // [0] ecx is beginning of segment (0xacf6690 above)
.text:1001FF9B 008                 add     esi, ecx       // [1]
.text:1001FF9D 008                 mov     eax, [esi]     // [2]

Extracted first is the offset to the loop counter [0]. This value is then added to the beginning of the RSRC segment [1]. This new address is accessed to extract the loop counter used for termination of the main loop for clearing data handles.

The loop responsible for clearing the data handles is below:

mgcore_SH_16_0!LVResFile::ClearAllDataHdls+0x30:
.text:1001FFB0     loop_top:                            
.text:1001FFB0 00C                 mov     eax, [edx]        // [4] edx is our current pointer (starting at 0xacf66d0 above)
.text:1001FFB2 00C                 mov     ecx, [edx-4]    
.text:1001FFB5 00C                 add     eax, esi          // [5]
.text:1001FFB7 00C                 test    ecx, ecx
.text:1001FFB9 00C                 jl      short dec_counter
.text:1001FFBB 00C                 add     eax, 10h
.text:1001FFBE 00C                 inc     ecx             
.text:1001FFBF 00C                 nop
.text:1001FFC0
.text:1001FFC0     loop_inner:                             
.text:1001FFC0 00C                 mov     dword ptr [eax], 0 // [6]
.text:1001FFC6 00C                 add     eax, 14h
.text:1001FFC9 00C                 sub     ecx, 1
.text:1001FFCC 00C                 jnz     short loop_inner 
.text:1001FFCE
.text:1001FFCE     dec_counter:                            
.text:1001FFCE 00C                 add     edx, 0Ch           // [7]
.text:1001FFD1 00C                 sub     edi, 1
.text:1001FFD4 00C                 jnz     short loop_top
.text:1001FFD6 00C                 pop     edi

The loop extracts the value under the current pointer [4] and adds it to the beginning of the segment [5]. This address is then cleared [6] and the pointer moves to the next section [7].

An attacker can control the loop counter as well as the offsets read from the RSRC struct used to calculate which address to clear, causing a write null anywhere situation. This null overwrite could potentially be leveraged into code execution.

Crash Information

0:000> r
eax=57f416eb ebx=0b8be230 ecx=4c56494f edx=0bb1c1b0 esi=0bb1c084 edi=13ffffe9
eip=03d8ffc0 esp=0012d3d0 ebp=0012d3d8 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010202
mgcore_SH_16_0!LVResFile::ClearAllDataHdls+0x40:
03d8ffc0 c70000000000    mov     dword ptr [eax],0    ds:0023:57f416eb=????????
0:000> !exploitable

!exploitable 1.6.0.0
Exploitability Classification: EXPLOITABLE
Recommended Bug Title: Exploitable - User Mode Write AV starting at mgcore_SH_16_0!LVResFile::ClearAllDataHdls+0x0000000000000040 (Hash=0x74591f62.0x054d4767)

User mode write access violations that are not near NULL are exploitable.

Timeline

2017-01-25 - Vendor Disclosure
2017-08-29 - Public Release

Credit

Discovered by Cory Duplantis of Cisco Talos.