CVE-2020-6075
An exploitable out-of-bounds write vulnerability exists in the store_data_buffer
function of the igcore19d.dll library of Accusoft ImageGear 19.5.0. A specially crafted PNG file can cause an out-of-bounds write, resulting in a remote code execution. An attacker needs to provide a malformed file to the victim to trigger the vulnerability.
Accusoft ImageGear 19.5.0
https://www.accusoft.com/products/imagegear/overview/
9.8 - CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
CWE-194: Unexpected Sign Extension
The ImageGear library is a document imaging developer toolkit providing all kinds of functionality related to image conversion, creation, editing, annotation, etc. It supports more than 100 formats, including many image formats, DICOM, PDF, Microsoft Office and others.
There is a vulnerability in the store_data_buffer
function due to an invalid cast conversion. A specially crafted PNG file can lead to an out-of-bounds, write which can result in remote code execution.
Trying to load a malformed PNG file via IG_load_file
function, we end up in the following situation:
eax=00004504 ebx=0f30e5f8 ecx=000000c0 edx=0000c0c0 esi=0f306fc9 edi=7fffc503
eip=670c0cb2 esp=009dd524 ebp=009dd530 iopl=0 nv up ei ng nz na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010286
igCore19d!IG_mpi_page_set+0xe5922:
670c0cb2 66891443 mov word ptr [ebx+eax*2],dx ds:002b:0f317000=????
0:000> kb
# ChildEBP RetAddr Args to Child
WARNING: Stack unwind information not available. Following frames may be wrong.
00 0019d520 64c01114 0ead65c0 0e3a45f8 ffff8a07 igCore19d!IG_mpi_page_set+0xe5922
01 0019d540 64bff981 0ead65c0 0e5fe5c0 0e3a45f8 igCore19d!IG_mpi_page_set+0xe5d84
02 0019f1cc 64c00c74 0019f71c 1000001b 099acfe8 igCore19d!IG_mpi_page_set+0xe45f1
03 0019f200 64bfe32c 0019f71c 1000001b 099acfe8 igCore19d!IG_mpi_page_set+0xe58e4
04 0019f694 64af07c9 0019f71c 099acfe8 00000001 igCore19d!IG_mpi_page_set+0xe2f9c
05 0019f6cc 64b2fb97 00000000 099acfe8 0019f71c igCore19d!IG_image_savelist_get+0xb29
06 0019f948 64b2f4f9 00000000 09505fa8 00000001 igCore19d!IG_mpi_page_set+0x14807
07 0019f968 64ac6007 00000000 09505fa8 00000001 igCore19d!IG_mpi_page_set+0x14169
08 0019f988 006059ac 09505fa8 0019fa74 0019fa98 igCore19d!IG_load_file+0x47
09 0019fa88 006061a7 09505fa8 0019fbbc 00000021 simple_exe_141+0x159ac
0a 0019fc54 00606cbe 00000005 094b2f50 09397f40 simple_exe_141+0x161a7
0b 0019fc68 00606b27 d2316a2d 006015e1 006015e1 simple_exe_141+0x16cbe
0c 0019fcc4 006069bd 0019fcd4 00606d38 0019fce4 simple_exe_141+0x16b27
0d 0019fccc 00606d38 0019fce4 75286359 002a8000 simple_exe_141+0x169bd
0e 0019fcd4 75286359 002a8000 75286340 0019fd40 simple_exe_141+0x16d38
0f 0019fce4 779c7b74 002a8000 63abcc02 00000000 KERNEL32!BaseThreadInitThunk+0x19
10 0019fd40 779c7b44 ffffffff 779e8f15 00000000 ntdll!__RtlUserThreadStart+0x2f
11 0019fd50 00000000 006015e1 002a8000 00000000 ntdll!_RtlUserThreadStart+0x1b
As we can see, an out-of-bounds write operation occurred.
The pseudo-code of this vulnerable function looks like this:
LINE 1 unsigned int __cdecl store_data_buffer(int src_buffer, int dst_buffer, int size)
LINE 2 {
LINE 3 unsigned int index; // eax
LINE 4 unsigned __int8 *v4; // esi
LINE 5
LINE 6 index = 0;
LINE 7 if ( (unsigned int)(size - 1) >> 1 )
LINE 8 {
LINE 9 _src_buffer = (unsigned __int8 *)(src_buffer + 1);
LINE 10 do
LINE 11 {
LINE 12 *(_WORD *)(dst_buffer + 2 * index++) = __ROL2__(*_src_buffer | (_src_buffer[1] << 8), 8); [1]
LINE 13
LINE 14 _src_buffer += 2;
LINE 15 }
LINE 16 while ( index < (unsigned int)(size - 1) >> 1 ); [2]
LINE 17 }
LINE 18 return index;
LINE 19 }
In this algorithm we can observe a function store_data_buffer
, whose objective is to copy the content of src_buffer
into dst_buffer
, is crashing while filling the buffer dst_buffer
in [1].
The copy operation is controlled by a loop [2], with a range from 0
to size-1
.
This is happening because the dst_buffer
is too small compared to the size argument.
Let’s see how the size of the target buffer and the size argument are computed.
LINE 22 unsigned __int8 __cdecl sub_670C1030(int src_data, int a2, void *buffer_mem, int a4, int size, int a6, int a7, int a8, int a9)
LINE 23 {
LINE 24 unsigned __int8 param_7; // al
LINE 25 unsigned int i; // ecx
LINE 26 _BYTE *v11; // esi
LINE 27 _BYTE *v12; // ebx
LINE 28 unsigned int v13; // edx
LINE 29 char v14; // cl
LINE 30 char v15; // cl
LINE 31
LINE 32 switch ( *(unsigned __int8 *)src_data )
LINE 33 {
LINE 34 case 1u:
LINE 35 sub_670BE9C0(src_data, size, a6);
LINE 36 break;
LINE 37 case 2u:
LINE 38 sub_670BEA10(src_data, a2, size);
LINE 39 break;
LINE 40 case 3u:
LINE 41 sub_670BEA60(src_data, a2, size, (unsigned __int8)a6);
LINE 42 break;
LINE 43 case 4u:
LINE 44 sub_670BEAF0(src_data, a2, size, a6);
LINE 45 break;
LINE 46 default:
LINE 47 break;
LINE 48 }
LINE 49 param_7 = a7;
LINE 50 switch ( *(unsigned __int8 *)(a7 + 9) )
LINE 51 {
LINE 52 case 0u:
LINE 53 if ( *(_BYTE *)(a7 + 8) == 2 )
LINE 54 goto LABEL_13;
LINE 55 param_7 = *(_BYTE *)(a7 + 8) - 16;
LINE 56 if ( *(_BYTE *)(a7 + 8) == 16 )
LINE 57 {
LINE 58 param_7 = sub_670BE850(src_data, buffer_mem, size);
LINE 59 }
LINE 60 else
LINE 61 {
LINE 62 for ( i = 1; i < size; ++i )
LINE 63 {
LINE 64 param_7 = *(_BYTE *)(i + src_data);
LINE 65 *((char *)buffer_mem + i - 1) = param_7;
LINE 66 }
LINE 67 }
LINE 68 break;
LINE 69 case 2u:
LINE 70 param_7 = *(_BYTE *)(a7 + 8);
LINE 71 if ( param_7 == 8 )
LINE 72 {
LINE 73 if ( (unsigned int)size > 1 )
LINE 74 {
LINE 75 v11 = buffer_mem;
LINE 76 v12 = (_BYTE *)(src_data + 2);
LINE 77 v13 = (size - 2) / 3u + 1;
LINE 78 do
LINE 79 {
LINE 80 *v11 = *(v12 - 1);
LINE 81 v11[1] = *v12;
LINE 82 param_7 = v12[1];
LINE 83 v11[2] = param_7;
LINE 84 v11 += 3;
LINE 85 v12 += 3;
LINE 86 --v13;
LINE 87 }
LINE 88 while ( v13 );
LINE 89 }
LINE 90 }
LINE 91 else if ( param_7 == 16 )
LINE 92 {
LINE 93 param_7 = store_data_buffer(src_data, (int)buffer_mem, size); [3]
LINE 94 }
LINE 95 break;
[...]
LINE 140}
The store_data_buffer
is called from the function named sub_670C1030
in [3] but we can see that size
and buffer_mem
are passed as arguments so we need to go back further. This leads us to the function process_raster_png
:
LINE141 int __stdcall process_raster_png(table_function *a1, void *arg4, int a3, int a4, int a5, IGDIBOject *a6, int a7, int a8)
LINE142 {
LINE143 int v8; // esi
LINE144 size_t v10; // edi
LINE145 byte *v11; // edi
LINE146 unsigned int size_buffer_mem; // edi
LINE147 byte *buffer_mem; // ebx
LINE148 int v14; // esi
LINE149 int v15; // eax
LINE150 unsigned int v16; // edi
LINE151 byte *v17; // eax
LINE152 byte *v18; // edx
LINE153 unsigned int i; // ecx
LINE154 int *v20; // ecx
LINE155 int v21; // eax
LINE156 int v22; // esi
LINE157 size_t v23; // edx
LINE158 int v24; // esi
LINE159 char v25; // cl
LINE160 int v26; // ecx
LINE161 int v27; // esi
LINE162 unsigned __int8 v28; // al
LINE163 unsigned __int8 v29; // bl
LINE164 int v30; // ecx
LINE165 int v31; // eax
LINE166 __int16 v32; // ax
LINE167 char v33; // cl
LINE168 __int16 v34; // ax
LINE169 char v35; // al
LINE170 int v36; // esi
LINE171 int v37; // eax
LINE172 int v38; // edx
LINE173 int v39; // edi
LINE174 int v40; // esi
LINE175 int j; // ecx
LINE176 unsigned __int8 v42; // al
LINE177 char v43; // al
LINE178 bool v44; // zf
LINE179 int v45; // esi
LINE180 int k; // ecx
LINE181 byte v47; // al
LINE182 byte v48; // al
LINE183 int v49; // eax
LINE184 unsigned int l; // esi
LINE185 void *v51; // eax
LINE186 void *v52; // ebx
LINE187 int v53; // ebx
LINE188 byte *v54; // edi
LINE189 int v55; // esi
LINE190 char v56; // cl
LINE191 int v57; // esi
LINE192 __int16 v58; // [esp-4h] [ebp-1C64h]
LINE193 unsigned __int8 v59; // [esp+Ch] [ebp-1C54h]
LINE194 unsigned int v60; // [esp+10h] [ebp-1C50h]
LINE195 __int16 v61; // [esp+14h] [ebp-1C4Ch]
LINE196 png_struct *table_of_size; // [esp+1Ch] [ebp-1C44h]
LINE197 unsigned int v63; // [esp+20h] [ebp-1C40h]
LINE198 int v64; // [esp+24h] [ebp-1C3Ch]
LINE199 int a6a; // [esp+28h] [ebp-1C38h]
LINE200 int v66; // [esp+2Ch] [ebp-1C34h]
LINE201 int v67; // [esp+30h] [ebp-1C30h]
LINE202 int v68; // [esp+34h] [ebp-1C2Ch]
LINE203 int v69; // [esp+38h] [ebp-1C28h]
LINE204 size_t size; // [esp+3Ch] [ebp-1C24h]
LINE205 byte *v71; // [esp+40h] [ebp-1C20h]
LINE206 int *v72; // [esp+44h] [ebp-1C1Ch]
LINE207 unsigned int ___size; // [esp+4Ch] [ebp-1C14h]
LINE208 unsigned int v74; // [esp+50h] [ebp-1C10h]
LINE209 byte *a2; // [esp+54h] [ebp-1C0Ch]
LINE210 int v76; // [esp+58h] [ebp-1C08h]
LINE211 byte *v77; // [esp+5Ch] [ebp-1C04h]
LINE212 byte *Src; // [esp+60h] [ebp-1C00h]
LINE213 byte *_buffer_mem; // [esp+64h] [ebp-1BFCh]
LINE214 unsigned int _size; // [esp+68h] [ebp-1BF8h]
LINE215 size_t v81; // [esp+74h] [ebp-1BECh]
LINE216 int v82; // [esp+78h] [ebp-1BE8h]
LINE217 int v83; // [esp+644h] [ebp-161Ch]
LINE218 int v84; // [esp+1C3Ch] [ebp-24h]
LINE219 int v85; // [esp+1C40h] [ebp-20h]
LINE220 int v86; // [esp+1C44h] [ebp-1Ch]
LINE221 int v87; // [esp+1C48h] [ebp-18h]
LINE222 int v88; // [esp+1C4Ch] [ebp-14h]
LINE223 int v89; // [esp+1C50h] [ebp-10h]
LINE224 int v90; // [esp+1C54h] [ebp-Ch]
LINE225 int v91; // [esp+1C58h] [ebp-8h]
LINE226
LINE227 v84 = 0x200000F;
LINE228 v85 = 0x1000100;
LINE229 v86 = 0x4000F;
LINE230 v87 = 0x10002;
LINE231 v90 = 0x404040F;
LINE232 v91 = 0x1010202;
LINE233 v88 = 0x408080F;
LINE234 v89 = 0x1020204;
LINE235 v76 = 0;
LINE236 v8 = 0;
LINE237 table_of_size = (png_struct *)AF_memm_alloc((int)arg4, 48u, (int)"..\\..\\..\\..\\Common\\Formats\\pngread.c", 2934);
LINE238 if ( !table_of_size )
LINE239 return kind_of_print_error((int)"..\\..\\..\\..\\Common\\Formats\\pngread.c", 2938, -1000, 0, 48, (int)arg4, 0);
LINE240 _size = compute_raster_size(a4);
LINE241 v10 = _size - (_size & 0x3F) + 64;
LINE242 Src = AF_memm_alloc((int)arg4, v10, (int)"..\\..\\..\\..\\Common\\Formats\\pngread.c", 2948);
LINE243 if ( !Src )
LINE244 {
LINE245 sub_66FD60E0((int)arg4, (int)"..\\..\\..\\..\\Common\\Formats\\pngread.c", 2951);
LINE246 return kind_of_print_error((int)"..\\..\\..\\..\\Common\\Formats\\pngread.c", 2952, -1000, 0, _size, (int)arg4, 0);
LINE247 }
LINE248 v11 = AF_memm_alloc((int)arg4, v10, (int)"..\\..\\..\\..\\Common\\Formats\\pngread.c", 2958);
LINE249 v77 = v11;
LINE250 if ( !v11 )
LINE251 {
LINE252 sub_66FD60E0((int)arg4, (int)"..\\..\\..\\..\\Common\\Formats\\pngread.c", 2961);
LINE253 return kind_of_print_error((int)"..\\..\\..\\..\\Common\\Formats\\pngread.c", 2962, -1000, 0, _size, (int)arg4, 0);
LINE254 }
LINE255 v71 = AF_memm_alloc((int)arg4, _size, (int)"..\\..\\..\\..\\Common\\Formats\\pngread.c", 2967);
LINE256 if ( !v71 )
LINE257 {
LINE258 sub_66FD60E0((int)arg4, (int)"..\\..\\..\\..\\Common\\Formats\\pngread.c", 2970);
LINE259 return kind_of_print_error((int)"..\\..\\..\\..\\Common\\Formats\\pngread.c", 2971, -1000, 0, _size, (int)arg4, 0);
LINE260 }
LINE261 if ( _size )
LINE262 memset(v11, 0, _size);
LINE263 size_buffer_mem = lead_to_compute_size_based_width_bits(a6); [6]
LINE264 _size = size_buffer_mem;
LINE265 buffer_mem = AF_memm_alloc((int)arg4, size_buffer_mem, (int)"..\\..\\..\\..\\Common\\Formats\\pngread.c", 2981); [5]
LINE266 _buffer_mem = buffer_mem;
LINE267 if ( !buffer_mem )
LINE268 {
LINE269 sub_66FD60E0((int)arg4, (int)"..\\..\\..\\..\\Common\\Formats\\pngread.c", 2984);
LINE270 return kind_of_print_error(
LINE271 (int)"..\\..\\..\\..\\Common\\Formats\\pngread.c",
LINE272 2985,
LINE273 -1000,
LINE274 0,
LINE275 size_buffer_mem,
LINE276 (int)arg4,
LINE277 0);
LINE278 }
LINE279 wrapper_memset(&v81, 0, 0x1BC8u);
LINE280 v82 = 2;
LINE281 if ( *(_BYTE *)(a4 + 12) == 1 )
LINE282 {
LINE283 v14 = 4 * ((getSizeY_0(a6) + 7) / 8);
LINE284 if ( v14 > 0xFFFF )
LINE285 {
LINE286 v15 = getSizeY_0(a6);
LINE287 return kind_of_print_error(
LINE288 (int)"..\\..\\..\\..\\Common\\Formats\\pngread.c",
LINE289 3023,
LINE290 -1005,
LINE291 0,
LINE292 v15,
LINE293 0,
LINE294 "Interlaced png image has too big heght. Can't load image.");
LINE295 }
LINE296 if ( size_buffer_mem > 0xFFFF )
LINE297 return kind_of_print_error(
LINE298 (int)"..\\..\\..\\..\\Common\\Formats\\pngread.c",
LINE299 3029,
LINE300 -1005,
LINE301 0,
LINE302 size_buffer_mem,
LINE303 0,
LINE304 "Interlaced png image has too big raster size. Can't load image.");
LINE305 a2 = AF_memm_alloc((int)arg4, 4 * v14, (int)"..\\..\\..\\..\\Common\\Formats\\pngread.c", 3034);
LINE306 if ( !a2 )
LINE307 return kind_of_print_error(
LINE308 (int)"..\\..\\..\\..\\Common\\Formats\\pngread.c",
LINE309 3038,
LINE310 -1000,
LINE311 0,
LINE312 4 * v14,
LINE313 (int)arg4,
LINE314 0);
LINE315 v16 = 0;
LINE316 v63 = (unsigned __int16)v14;
LINE317 if ( (_WORD)v14 )
LINE318 {
LINE319 do
LINE320 {
LINE321 v17 = AF_memm_alloc((int)arg4, ___size, (int)"..\\..\\..\\..\\Common\\Formats\\pngread.c", 3044);
LINE322 *(_DWORD *)&a2[4 * v16] = v17;
LINE323 if ( !v17 )
LINE324 return kind_of_print_error(
LINE325 (int)"..\\..\\..\\..\\Common\\Formats\\pngread.c",
LINE326 3048,
LINE327 -1000,
LINE328 0,
LINE329 ___size,
LINE330 (int)arg4,
LINE331 0);
LINE332 ++v16;
LINE333 }
LINE334 while ( v16 < (unsigned __int16)v14 );
LINE335 if ( (_WORD)v14 )
LINE336 {
LINE337 v18 = a2;
LINE338 v14 = (unsigned __int16)v14;
LINE339 do
LINE340 {
LINE341 for ( i = 0; i < ___size; *(_BYTE *)(i + *(_DWORD *)v18 - 1) = -1 )
LINE342 ++i;
LINE343 v18 += 4;
LINE344 --v14;
LINE345 }
LINE346 while ( v14 );
LINE347 }
LINE348 }
LINE349 sub_670C0A50(table_of_size, (__int16 *)a4);
LINE350 v20 = &table_of_size->field_A;
LINE351 v21 = 1;
LINE352 v22 = 0;
LINE353 v66 = 1;
LINE354 v72 = &table_of_size->field_A;
LINE355 v69 = 0;
LINE356 do
LINE357 {
LINE358 if ( *(_WORD *)v20 )
LINE359 {
LINE360 if ( _size )
LINE361 {
LINE362 memset(v77, 0, _size);
LINE363 v20 = v72;
LINE364 }
LINE365 v23 = *((__int16 *)v20 - 2);
LINE366 v64 = *((__int16 *)v20 - 1);
LINE367 v67 = *((unsigned __int8 *)&v84 + v22 + 1);
LINE368 v16 = 0;
LINE369 v24 = *(unsigned __int16 *)(a4 + 4);
LINE370 size = *((__int16 *)v20 - 2); [8]
LINE371 v74 = 0;
LINE372 v76 = *(unsigned __int16 *)(a4 + 4);
LINE373 if ( v64 > 0 )
LINE374 {
LINE375 v60 = v23 - 1;
LINE376 do
LINE377 {
LINE378 sub_670C0090((int)a1, (size_t)&v81, Src, v23);
LINE379 v25 = v60 / *(__int16 *)v72;
LINE380 if ( !v25 )
LINE381 v25 = 1;
LINE382 LOBYTE(a6a) = v25;
LINE383 v59 = v25;
LINE384 sub_670C1030((int)Src, (int)v77, buffer_mem, 0, size, a6a, a5, a8, *(_DWORD *)(a3 + 16)); [4]
[...]
LINE494 }
LINE495 while ( v64 > 0 );
LINE496 v20 = v72;
LINE497 }
LINE498 v21 = v66;
LINE499 v22 = v69;
LINE500 }
LINE501 ++v21;
LINE502 ++v22;
LINE503 v20 = (int *)((char *)v20 + 6);
LINE504 v66 = v21;
LINE505 v69 = v22;
LINE506 v72 = v20;
LINE507 }
LINE508 while ( (__int16)v21 <= 7 );
[...]
LINE566 return 0;
LINE567 }
In [4] we can identify our function call with our parameters named here buffer_mem
and size
respectively. The buffer_mem
is allocated in [5] and the size for his allocation is computed in [6] through a call to the function lead_to_compute_size_based_width_bits
returning an unsigned value as we can see in the following pseudo code where the indirect call lands to the function compute_size
LINE568 unsigned int __thiscall compute_size(IGDIBOject *this)
LINE569 {
LINE570 return ((this->width * this->colorspace_related * this->depth + 31) >> 3) & 0xFFFFFFFC; [7]
LINE571 }
We can see the final size for the buffer_mem
is computed from a field directly taken to from file, like width
and other valued derived from bits
and colorspace
computation in [7].
Now if take a look back to the size
parameter we can observe it’s computed differently, getting its value from v20
at [8]. This is a pointer to signed integers, where size
is 32-bits unsigned integer.
When looking further into how this table of integer is filled, we land to function compute_raster_size
, which is computing a size using bits
and width
through a test case of PNG_COLOR_SPACE_TYPE_color_type
.
LINE 145 unsigned int __cdecl compute_raster_size(int a1)
LINE 146 {
LINE 147 unsigned int v1; // eax
LINE 148 unsigned int raster_size; // eax
LINE 149
LINE 150 v1 = 0;
LINE 151 switch ( PNG_COLOR_SPACE_TYPE_color_type )
LINE 152 {
LINE 153 case 0u:
LINE 154 case 3u:
LINE 155 raster_size = ((bits * width) + 7) >> 3) + 1;
LINE 156 break;
LINE 157 case 2u:
LINE 158 raster_size = ((3 * bits * width) >> 3) + 1;
LINE 159 break;
LINE 160 case 4u:
LINE 161 raster_size = (2 * ((bits * width) >> 3)) + 1;
LINE 162 break;
LINE 163 case 6u:
LINE 164 v1 = (4 * bits * width) >> 3;
LINE 165 goto LABEL_6;
LINE 166 default:
LINE 167 LABEL_6:
LINE 168 raster_size = v1 + 1;
LINE 169 break;
LINE 170 }
LINE 171 return raster_size;
LINE 172 }
The cast conversion to int16
at [8], of the value computed from compute_raster_size
, causes a sign extension when transforming the value into a larger data type (from int16 to size_t) at [8]. This in turn increases the loop count via the size
variable, allowing an attacker to cause an out-of-bounds write leading to memory corruption, which could result in remote code execution.
0:000> !analyze -v
*******************************************************************************
* *
* Exception Analysis *
* *
*******************************************************************************
KEY_VALUES_STRING: 1
Key : AV.Fault
Value: Write
Key : Analysis.CPU.Sec
Value: 0
Key : Analysis.DebugAnalysisProvider.CPP
Value: Create: 8007007e on DESKTOP-PJK7PVH
Key : Analysis.DebugData
Value: CreateObject
Key : Analysis.DebugModel
Value: CreateObject
Key : Analysis.Elapsed.Sec
Value: 4
Key : Analysis.Memory.CommitPeak.Mb
Value: 78
Key : Analysis.System
Value: CreateObject
Key : Timeline.OS.Boot.DeltaSec
Value: 91061
Key : Timeline.Process.Start.DeltaSec
Value: 8
ADDITIONAL_XML: 1
APPLICATION_VERIFIER_LOADED: 1
EXCEPTION_RECORD: (.exr -1)
ExceptionAddress: 670c0cb2 (igCore19d!IG_mpi_page_set+0x000e5922)
ExceptionCode: c0000005 (Access violation)
ExceptionFlags: 00000000
NumberParameters: 2
Parameter[0]: 00000001
Parameter[1]: 0f317000
Attempt to write to address 0f317000
FAULTING_THREAD: 000010cc
PROCESS_NAME: simple.exe_141.exe
WRITE_ADDRESS: 0f317000
ERROR_CODE: (NTSTATUS) 0xc0000005 - The instruction at 0x%p referenced memory at 0x%p. The memory could not be %s.
EXCEPTION_CODE_STR: c0000005
EXCEPTION_PARAMETER1: 00000001
EXCEPTION_PARAMETER2: 0f317000
STACK_TEXT:
WARNING: Stack unwind information not available. Following frames may be wrong.
009dd530 670c1114 0f2fe5c0 0f30e5f8 ffff8a07 igCore19d!IG_mpi_page_set+0xe5922
009dd550 670bf981 0f2fe5c0 0ee305c0 0f30e5f8 igCore19d!IG_mpi_page_set+0xe5d84
009df1dc 670c0c74 009df72c 1000001b 0e64afe8 igCore19d!IG_mpi_page_set+0xe45f1
009df210 670be32c 009df72c 1000001b 0e64afe8 igCore19d!IG_mpi_page_set+0xe58e4
009df6a4 66fb07c9 009df72c 0e64afe8 00000001 igCore19d!IG_mpi_page_set+0xe2f9c
009df6dc 66fefb97 00000000 0e64afe8 009df72c igCore19d!IG_image_savelist_get+0xb29
009df958 66fef4f9 00000000 09e01fa8 00000001 igCore19d!IG_mpi_page_set+0x14807
009df978 66f86007 00000000 09e01fa8 00000001 igCore19d!IG_mpi_page_set+0x14169
009df998 006059ac 09e01fa8 009dfa84 009dfaa8 igCore19d!IG_load_file+0x47
009dfa98 006061a7 09e01fa8 009dfbcc 00000021 simple_exe_141+0x159ac
009dfc64 00606cbe 00000005 09daef50 09c93f40 simple_exe_141+0x161a7
009dfc78 00606b27 f7329ef4 006015e1 006015e1 simple_exe_141+0x16cbe
009dfcd4 006069bd 009dfce4 00606d38 009dfcf4 simple_exe_141+0x16b27
009dfcdc 00606d38 009dfcf4 75286359 00bc4000 simple_exe_141+0x169bd
009dfce4 75286359 00bc4000 75286340 009dfd50 simple_exe_141+0x16d38
009dfcf4 779c7b74 00bc4000 469eabd0 00000000 KERNEL32!BaseThreadInitThunk+0x19
009dfd50 779c7b44 ffffffff 779e8f0f 00000000 ntdll!__RtlUserThreadStart+0x2f
009dfd60 00000000 006015e1 00bc4000 00000000 ntdll!_RtlUserThreadStart+0x1b
STACK_COMMAND: ~0s ; .cxr ; kb
SYMBOL_NAME: igCore19d!IG_mpi_page_set+e5922
MODULE_NAME: igCore19d
IMAGE_NAME: igCore19d.dll
FAILURE_BUCKET_ID: INVALID_POINTER_WRITE_AVRF_c0000005_igCore19d.dll!IG_mpi_page_set
OS_VERSION: 10.0.18362.239
BUILDLAB_STR: 19h1_release_svc_prod1
OSPLATFORM_TYPE: x86
OSNAME: Windows 10
FAILURE_ID_HASH: {39ff52ad-9054-81fd-3e4d-ef5d82e4b2c1}
Followup: MachineOwner
---------
2020-01-30 - Vendor Disclosure
2020-04-30 - Vendor Patched
2020-05-05 - Public Release
Discovered by Emmanuel Tacheau of Cisco Talos.