Talos Vulnerability Report

TALOS-2023-1729

Accusoft ImageGear CreateDIBfromPict out-of-bounds write vulnerability

September 25, 2023
CVE Number

CVE-2023-23567

SUMMARY

A heap-based buffer overflow vulnerability exists in the CreateDIBfromPict functionality of Accusoft ImageGear 20.1. A specially crafted file can lead to arbitrary code execution. An attacker can provide a malicious file to trigger this vulnerability.

CONFIRMED VULNERABLE VERSIONS

The versions below were either tested or verified to be vulnerable by Talos or confirmed to be vulnerable by the vendor.

Accusoft ImageGear 20.1

PRODUCT URLS

ImageGear - https://www.accusoft.com/products/imagegear-collection/

CVSSv3 SCORE

8.1 - CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H

CWE

CWE-119 - Improper Restriction of Operations within the Bounds of a Memory Buffer

DETAILS

The ImageGear library is a document-imaging developer toolkit that offers image conversion, creation, editing, annotation and more. It supports more than 100 formats such as DICOM, PDF, Microsoft Office and others.

A specially crafted PICT or Quickdraw v2 file can lead to a heap-based buffer overflow in CreateDIBfromPict, due to a wrongly sized heap buffer due to a missing size check.

Trying to load a malformed PICT, we end up in the following situation:

First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=0d354fe0 ebx=00000020 ecx=00000040 edx=00000040 esi=0d354fa0 edi=0d327000
eip=6fe9091a esp=0019f62c ebp=0019f644 iopl=0         nv up ei ng nz na pe cy
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010287
igCore20d!IG_GUI_page_title_set+0x3ce4a:
6fe9091a f3a4            rep movs byte ptr es:[edi],byte ptr [esi]
*** WARNING: Unable to verify checksum for Fuzzme.exe

Looking at source of buffer pointed by the register esi, we can observe how to control the source:

0:000> db esi
0d354fa0  32 00 00 33 00 01 34 00-00 35 00 00 36 00 00 37  2..3..4..5..6..7
0d354fb0  00 00 38 00 fd 39 00 7f-30 00 00 31 00 00 32 00  ..8..9..0..1..2.
0d354fc0  01 33 00 00 34 00 00 35-00 00 36 00 21 37 00 21  .3..4..5..6.!7.!
0d354fd0  38 00 21 39 00 21 30 00-21 31 00 21 32 00 21 33  8.!9.!0.!1.!2.!3
0d354fe0  00 21 34 00 21 44 00 c0-45 00 c0 41 00 c0 44 00  .!4.!D..E..A..D.
0d354ff0  c0 42 00 c0 45 00 c0 41-00 c0 46 00 c0 30 10 c0  .B..E..A..F..0..
0d355000  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  ????????????????
0d355010  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  ????????????????

The destination buffer pointer by the register edi has a size of 0xae0 bytes and is allocated in the heap:

0:000> !heap -p -a edi
    address 0d327000 found in
    _DPH_HEAP_ROOT @ 2cc1000
    in busy allocation (  DPH_HEAP_BLOCK:         UserAddr         UserSize -         VirtAddr         VirtSize)
                                 d1e3c64:          d326520              ae0 -          d326000             2000
          unknown!fillpattern
    7009a8b0 verifier!AVrfDebugPageHeapAllocate+0x00000240
    77f0f53e ntdll!RtlDebugAllocateHeap+0x00000039
    77e771b0 ntdll!RtlpAllocateHeap+0x000000f0
    77e76f0c ntdll!RtlpAllocateHeapInternal+0x0000104c
    77e75eae ntdll!RtlAllocateHeap+0x0000003e
    6fe91fa6 igCore20d!IG_GUI_page_title_set+0x0003e4d6
    6fcd661d igCore20d!AF_memm_alloc+0x0000001d
    6fdbaf66 igCore20d!IG_mpi_page_set+0x000dee46
    6fdba321 igCore20d!IG_mpi_page_set+0x000de201
    6fcb15b9 igCore20d!IG_image_savelist_get+0x00000b29
    6fcf08bc igCore20d!IG_mpi_page_set+0x0001479c
    6fcf0239 igCore20d!IG_mpi_page_set+0x00014119
    6fc85bc7 igCore20d!IG_load_file+0x00000047
    00402399 Fuzzme!fuzzme+0x00000019
    004026c0 Fuzzme!fuzzme+0x00000340
    00408407 Fuzzme!fuzzme+0x00006087
    75fb00f9 KERNEL32!BaseThreadInitThunk+0x00000019
    77e97bbe ntdll!__RtlUserThreadStart+0x0000002f
    77e97b8e ntdll!_RtlUserThreadStart+0x0000001b

The exception happens at LINE152 in the __memcpy function:

LINE1   void * __cdecl __memcpy(void *_Dst,void *_Src,size_t _Size)
LINE2   
LINE3   {
            [...]
LINE148   puVar23 = (undefined *)_Dst;
LINE149   if ((DAT_1031d754 >> 1 & 1) != 0) {
LINE150                     /* WARNING: Load size is inaccurate */
LINE151     for (; _Size != 0; _Size = _Size - 1) {
LINE152       *puVar23 = *_Src;
LINE153       _Src = (undefined *)((int)_Src + 1);
LINE154       puVar23 = puVar23 + 1;
LINE155     }
LINE156     return _Dst;
LINE157   }
            [...]
LINE532 }

Investigating the call stack will guide us to the culprit function. We can observe the __memcpy function is called at LINE550 by a function named perform_OS_memcpy with the following pseudo-code:

LINE537 void perform_OS_memcpy(void *dest,size_t size,void *src,dword size_copy,dword pixelSize,
LINE538                       dword x_value_top_left,dword _number_of_element,dword dstRect_width)
LINE539 
LINE540 {
LINE541   if ((int)pixelSize < 8) {
LINE542     OS_memcpy((void *)((int)x_value_top_left / (int)(8 / (longlong)(int)pixelSize) + (int)dest),src,
LINE543               size_copy);
LINE544     return;
LINE545   }
LINE546   if (pixelSize == 8) {
LINE547     OS_memcpy((void *)(x_value_top_left + (int)dest),src,size_copy);
LINE548     return;
LINE549   }
LINE550   OS_memcpy((void *)(((16 < (int)pixelSize) + 2) * x_value_top_left + (int)dest),src,size_copy);
LINE551   return;
LINE552 }
LINE553 

After investigation, we can see this is happening only when a pixelSize has value bigger than 8. Continuing through the call stack leads us to LINE767 in a function named CreateDIBfromPict.

LINE557 BOOLEAN CreateDIBfromPict(mys_table_function *mys_table_function,uint param_2,undefined4 param_3,PICT_Header *pict_header,HIGDIBINFO higdibinfo)
LINE558 {
LINE559  [...]  
LINE560 
LINE561   local_14[3] = DAT_10319e74 ^ (uint)&stack0xfffffffc;
LINE562   _kind_of_heap = param_2;
LINE563   _pict_header = pict_header;
LINE564   pixelsize_32_component_count4 = 0;
LINE565   io_buff.buffer_size = 0;
LINE566   DIB_width_get(higdibinfo);
LINE567   Height = DIB_height_get(higdibinfo);
LINE568   __size_src_buffer = IO_raster_size_get(higdibinfo);
LINE569   p_opcode_data = pict_header->opcode_data;
LINE570   local_68 = (int)(short)(p_opcode_data->bounds).x_value_lower_right -
LINE571              (int)(short)(p_opcode_data->bounds).x_value_top_left;
LINE572   related_bound_size = local_68 * 5;
LINE573   if ((int)related_bound_size < (int)__size_src_buffer) {
LINE574     AF_err_record_set("..\\..\\..\\..\\Common\\Formats\\pctwread.c",0x2f6,-0x194,0,__size_src_buffer
LINE575                       ,local_68,(LPCHAR)0x0);
LINE576   }
LINE577   else {
LINE578     pixelSize = (uint)p_opcode_data->pixelSize;
LINE579     component_count = p_opcode_data->component_count;
LINE580     b_break_dowhile = IO_DIB_create_ex(mys_table_function,higdibinfo);
LINE581     __sz_src_buffer = __size_src_buffer;
LINE582     if (b_break_dowhile != False) {
LINE583       AF_err_record_set("..\\..\\..\\..\\Common\\Formats\\pctwread.c",0x2ff,-0x9a0,0,0,0,(LPCHAR)0x0
LINE584                        );
LINE585       BVar1 = @__security_check_cookie@4();
LINE586       return BVar1;
LINE587     }
LINE588     raster_source_buffer = (BYTE *)AF_memm_alloc(_kind_of_heap,__size_src_buffer);
LINE589     __source_buffer = (undefined4 *)AF_memm_alloc(_kind_of_heap,related_bound_size);
LINE590     size_target_buffer = __sz_src_buffer * Height;
LINE591     ___source_buffer = __source_buffer;
LINE592     _target_buffer = (byte *)AF_memm_alloc(_kind_of_heap,size_target_buffer);
LINE593     another_buffer = AF_memm_alloc(_kind_of_heap,size_target_buffer);
LINE594     if (((raster_source_buffer == (BYTE *)0x0) || (__source_buffer == (undefined4 *)0x0)) ||
LINE595        (_target_buffer == (byte *)0x0)) {
LINE596       b_break_dowhile =
LINE597            AF_err_record_set("..\\..\\..\\..\\Common\\Formats\\pctwread.c",0x309,-1000,0,0,0,
LINE598                              (LPCHAR)0x0);
LINE599     }
LINE600     else if ((pixelSize == 0x20) && (component_count == 4)) {
LINE601       pixelsize_32_component_count4 = 1;
LINE602     }
LINE603     __target_buffer = _target_buffer;
LINE604     OS_memset(_target_buffer,0,size_target_buffer);
LINE605     _wide_size = _kind_of_heap;
LINE606     bIobInit = IOb_init(mys_table_function,_kind_of_heap,&io_buff,0x5000,1);
LINE607     __pict_header = _pict_header;
LINE608     b_break_dowhile = b_break_dowhile + bIobInit;
LINE609     if (b_break_dowhile == False) {
LINE610       IO_attribute_set(mys_table_function,4,
LINE611                        (AT_RESOLUTION *)&_pict_header->original_horizontal_resolution);
LINE612       opcode_data_processed = 0;
LINE613       index_opcode_data = 0;
LINE614       do {
LINE615         _index_opcode_data = index_opcode_data;
LINE616         if ((int)__pict_header->len_opcode_data <= opcode_data_processed) break;
LINE617         p_opcode_data = __pict_header->opcode_data;
LINE618         nb_component = (dword)*(ushort *)((int)&p_opcode_data->component_count + index_opcode_data);
LINE619         if (2 < nb_component) {
LINE620           nb_component = 3;
LINE621         }
LINE622         iVar2 = 0;
LINE623         if ((bits_per_channel_table *)nb_component != (bits_per_channel_table *)0x0) {
LINE624           do {
LINE625             local_14[iVar2] =
LINE626                  (uint)*(ushort *)((int)&p_opcode_data->component_size + index_opcode_data);
LINE627             iVar2 = iVar2 + 1;
LINE628           } while (iVar2 < (int)nb_component);
LINE629         }
LINE630         _wide_size = (int)*(short *)((int)&(p_opcode_data->dstRect).x_value_lower_right +
LINE631                                     index_opcode_data) -
LINE632                      (int)*(short *)((int)&(p_opcode_data->dstRect).x_value_top_left +
LINE633                                     index_opcode_data);
LINE634         _height_size = (int)*(short *)((int)&(p_opcode_data->dstRect).y_value_lower_right +
LINE635                                       index_opcode_data) -
LINE636                        (int)*(short *)((int)&(p_opcode_data->dstRect).y_value_top_left +
LINE637                                       index_opcode_data);
LINE638         dstRect_width = _wide_size;
LINE639         IO_raster_size_calc(_wide_size,nb_component,(int *)local_14);
LINE640         if (pixelSize == 1) {
LINE641           raster_size_calculated = DIB1bit_packed_raster_size_calc(_wide_size);
LINE642         }
LINE643         else {
LINE644           raster_size_calculated =
LINE645                DIBStd_raster_size_calc_simple
LINE646                          (_wide_size,(bits_per_channel_table *)nb_component,
LINE647                           (uint)*(ushort *)
LINE648                                  ((int)&_pict_header->opcode_data->component_size +
LINE649                                  _index_opcode_data));
LINE650         }
LINE651         related_bound_size = __size_src_buffer;
LINE652         __raster_size_calculated = raster_size_calculated;
LINE653         if ((int)__size_src_buffer < (int)raster_size_calculated) {
LINE654           AF_err_record_set("..\\..\\..\\..\\Common\\Formats\\pctwread.c",0x348,-0x834,0,0,0,
LINE655                             (LPCHAR)0x0);
LINE656           break;
LINE657         }
LINE658         p_opcode_data = _pict_header->opcode_data;
LINE659         bounds_rect_width =
LINE660              (int)*(short *)((int)&(p_opcode_data->bounds).x_value_lower_right + _index_opcode_data)
LINE661              - (int)*(short *)((int)&(p_opcode_data->bounds).x_value_top_left + _index_opcode_data);
LINE662         IOb_seek(&io_buff,*(int *)((int)&p_opcode_data->current_offset + _index_opcode_data),
LINE663                  SEEK_SET);
LINE664         OS_memset(raster_source_buffer,0,related_bound_size);
LINE665         if (pixelSize != 0x18) {
LINE666           raster_size_calculated =
LINE667                (uint)*(ushort *)((int)&_pict_header->opcode_data->rowBytes + index_opcode_data);
LINE668         }
LINE669         p_opcode_data = _pict_header->opcode_data;
LINE670         io_buff.size_buffer =
LINE671              (jpeg_related *)(uint)*(ushort *)((int)&p_opcode_data->packType + index_opcode_data);
LINE672         _number_of_element =
LINE673              (int)*(short *)((int)&(p_opcode_data->dstRect).x_value_lower_right + index_opcode_data)
LINE674              - (int)*(short *)((int)&(p_opcode_data->dstRect).x_value_top_left + index_opcode_data);
LINE675         _loop_count = 0;
LINE676         local_64 = raster_size_calculated;
LINE677         if (b_break_dowhile == False) {
LINE678           for (; __source_buffer = (undefined4 *)raster_source_buffer,
LINE679               _wide_size = __size_src_buffer, _loop_count < _height_size;
LINE680               _loop_count = _loop_count + 1) {
LINE681             if (((7 < (int)raster_size_calculated) && (io_buff.size_buffer != (jpeg_related *)0x1))
LINE682                && ((io_buff.size_buffer != (jpeg_related *)0x2 || ((int)pixelSize < 0x18)))) {
LINE683               if ((int)raster_size_calculated < 0xfb) {
LINE684                 b_read = IOb_byte_read(&io_buff,&local_25);
LINE685                 if (b_read != False) {
LINE686                   _lsize_to_read = (uint)local_25;
LINE687                   goto process_data;
LINE688                 }
LINE689                 _index_opcode_data = 0x38b;
LINE690               }
LINE691               else {
LINE692                 BVar1 = IOBuff_Read_ushort(&io_buff,local_58);
LINE693                 if (BVar1 == False) {
LINE694                   _index_opcode_data = 0x382;
LINE695                 }
LINE696                 else {
LINE697                   _lsize_to_read = (uint)local_58[0];
LINE698 process_data:
LINE699                   _read_from_file = get_data_from_file(&io_buff,_lsize_to_read);
LINE700                   src = (BYTE *)___source_buffer;
LINE701                   if (_read_from_file != (byte *)0x0) {
LINE702                     switch(pixelSize) {
LINE703                     case 1:
LINE704                     case 8:
LINE705                       perform_some_copy_on_dest
LINE706                                 (raster_source_buffer,_read_from_file,_lsize_to_read,
LINE707                                  __raster_size_calculated);
LINE708                       break;
LINE709                     case 4:
LINE710                       __target_buffer = raster_source_buffer + (int)_wide_size / 2;
LINE711                       perform_some_copy_on_dest
LINE712                                 (__target_buffer,_read_from_file,_lsize_to_read,
LINE713                                  __raster_size_calculated);
LINE714                       FUN_10023390(1,pixelSize,local_68,__target_buffer,raster_source_buffer,
LINE715                                    (int)_wide_size / 2);
LINE716                       raster_size_calculated = local_64;
LINE717                       break;
LINE718                     case 0x10:
LINE719                       FUN_1014c6b0(___source_buffer,_read_from_file,_lsize_to_read,
LINE720                                    raster_size_calculated);
LINE721                       goto switchD_1014b26f_caseD_10;
LINE722                     case 0x18:
LINE723                     case 0x20:
LINE724                       perform_some_copy_on_dest
LINE725                                 ((byte *)___source_buffer,_read_from_file,_lsize_to_read,
LINE726                                  raster_size_calculated);
LINE727                       copySomeData_2(raster_source_buffer,src,dstRect_width,bounds_rect_width,
LINE728                                      pixelsize_32_component_count4);
LINE729                     }
LINE730                     goto switchD_1014b26f_caseD_2;
LINE731                   }
LINE732                   _index_opcode_data = 0x393;
LINE733                 }
LINE734               }
LINE735 LAB_1014b340:
LINE736               b_break_dowhile =
LINE737                    AF_err_record_set("..\\..\\..\\..\\Common\\Formats\\pctwread.c",
LINE738                                      _index_opcode_data,-0x834,0,0,0,(LPCHAR)0x0);
LINE739               break;
LINE740             }
LINE741             src = get_data_from_file(&io_buff,raster_size_calculated);
LINE742             _wide_size = dstRect_width;
LINE743             if (src == (BYTE *)0x0) {
LINE744               _index_opcode_data = 0x365;
LINE745               goto LAB_1014b340;
LINE746             }
LINE747             switch(pixelSize) {
LINE748             case 1:
LINE749             case 4:
LINE750             case 8:
LINE751               _wide_size = raster_size_calculated;
LINE752 LAB_1014b29c:
LINE753               OS_memcpy(__source_buffer,src,_wide_size);
LINE754               break;
LINE755             case 0x10:
LINE756 switchD_1014b26f_caseD_10:
LINE757               copySomeData(raster_source_buffer,src,dstRect_width);
LINE758               break;
LINE759             case 0x18:
LINE760             case 0x20:
LINE761               copySomeData_2(raster_source_buffer,src,dstRect_width,bounds_rect_width,
LINE762                              pixelsize_32_component_count4);
LINE763               __source_buffer = ___source_buffer;
LINE764               if (pixelsize_32_component_count4 != 0) goto LAB_1014b29c;
LINE765             }
LINE766 switchD_1014b26f_caseD_2:
LINE767             perform_OS_memcpy(_target_buffer +                                                                                      
LINE768                               (*(short *)((int)&(_pict_header->opcode_data->dstRect).
LINE769                                                 y_value_top_left + index_opcode_data) + _loop_count)
LINE770                               * __size_src_buffer,__size_src_buffer,raster_source_buffer,
LINE771                               __raster_size_calculated,pixelSize,
LINE772                               (int)*(short *)((int)&(_pict_header->opcode_data->dstRect).
LINE773                                                     x_value_top_left + index_opcode_data),
LINE774                               _number_of_element,dstRect_width);
LINE775           }
LINE776         }
            [...]
LINE818 }

The destination buffer represented by _target_buffer at LINE767 corresponding to our edi register is allocated at LINE592, and the size represented by size_target_buffer is computed at LINE590 with the product of two variables: Height and __sz_src_buffer.

The source buffer represented by raster_source_buffer passed as third parameter of perform_OS_memcpy is allocated at LINE588 and is also controlled by __sz_src_buffer.
The values used for the size calculation are directly read from the PICT file, either from the PICT header or the values from a DirectBitsRect opcode data.

The vulnerability ocurs when the _height_size is bigger than Height. The _height_size is used to control, at LINE678, the maximum number of times the for-loop repeats to perform the copy. This same _height_size value is also computed for the dstRect record data following the pixmap records of the DirectBitsRect opcode data.

This issue allows for an out-of-bounds write in heap, which could in turn allow an attacker to execute arbitrary code.

Crash Information

**0:000> !analyze -v
*******************************************************************************
*                                                                             *
*                        Exception Analysis                                   *
*                                                                             *
*******************************************************************************


KEY_VALUES_STRING: 1

    Key  : AV.Fault
    Value: Write

    Key  : Analysis.CPU.Sec
    Value: 1

    Key  : Analysis.DebugAnalysisProvider.CPP
    Value: Create: 8007007e on DESKTOP-I6GKV78

    Key  : Analysis.DebugData
    Value: CreateObject

    Key  : Analysis.DebugModel
    Value: CreateObject

    Key  : Analysis.Elapsed.Sec
    Value: 3

    Key  : Analysis.Memory.CommitPeak.Mb
    Value: 92

    Key  : Analysis.System
    Value: CreateObject

    Key  : Timeline.OS.Boot.DeltaSec
    Value: 1319490

    Key  : Timeline.Process.Start.DeltaSec
    Value: 102


NTGLOBALFLAG:  2100000

PROCESS_BAM_CURRENT_THROTTLED: 0

PROCESS_BAM_PREVIOUS_THROTTLED: 0

APPLICATION_VERIFIER_FLAGS:  0

APPLICATION_VERIFIER_LOADED: 1

EXCEPTION_RECORD:  (.exr -1)
ExceptionAddress: 6fe9091a (igCore20d!IG_GUI_page_title_set+0x0003ce4a)
   ExceptionCode: c0000005 (Access violation)
  ExceptionFlags: 00000000
NumberParameters: 2
   Parameter[0]: 00000001
   Parameter[1]: 0d327000
Attempt to write to address 0d327000

FAULTING_THREAD:  0000171c

PROCESS_NAME:  Fuzzme.exe

WRITE_ADDRESS:  0d327000 

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:  0d327000

STACK_TEXT:  
WARNING: Stack unwind information not available. Following frames may be wrong.
0019f644 6fdba3d5 0d327000 0d354fa0 00000040 igCore20d!IG_GUI_page_title_set+0x3ce4a
0019f658 6fdbb2d7 0d327000 00000060 0d354fa0 igCore20d!IG_mpi_page_set+0xde2b5
0019f734 6fdba321 0019fc3c 1000001e 0fd08ff8 igCore20d!IG_mpi_page_set+0xdf1b7
0019fbb4 6fcb15b9 0019fc3c 0fd08ff8 00000001 igCore20d!IG_mpi_page_set+0xde201
0019fbec 6fcf08bc 00000000 0fd08ff8 0019fc3c igCore20d!IG_image_savelist_get+0xb29
0019fe68 6fcf0239 00000000 05361fe0 00000001 igCore20d!IG_mpi_page_set+0x1479c
0019fe88 6fc85bc7 00000000 05361fe0 00000001 igCore20d!IG_mpi_page_set+0x14119
0019fea8 00402399 05361fe0 0019febc 75fafb80 igCore20d!IG_load_file+0x47
0019fec0 004026c0 05361fe0 0019fef8 052bdf40 Fuzzme!fuzzme+0x19
0019ff28 00408407 00000005 052b6f98 052bdf40 Fuzzme!fuzzme+0x340
0019ff70 75fb00f9 003e3000 75fb00e0 0019ffdc Fuzzme!fuzzme+0x6087
0019ff80 77e97bbe 003e3000 5b1011ff 00000000 KERNEL32!BaseThreadInitThunk+0x19
0019ffdc 77e97b8e ffffffff 77eb8d0b 00000000 ntdll!__RtlUserThreadStart+0x2f
0019ffec 00000000 0040848f 003e3000 00000000 ntdll!_RtlUserThreadStart+0x1b


STACK_COMMAND:  ~0s ; .cxr ; kb

SYMBOL_NAME:  igCore20d!IG_GUI_page_title_set+3ce4a

MODULE_NAME: igCore20d

IMAGE_NAME:  igCore20d.dll

FAILURE_BUCKET_ID:  INVALID_POINTER_WRITE_AVRF_c0000005_igCore20d.dll!IG_GUI_page_title_set

OS_VERSION:  10.0.19041.1

BUILDLAB_STR:  vb_release

OSPLATFORM_TYPE:  x86

OSNAME:  Windows 10

FAILURE_ID_HASH:  {b42f49c1-788b-e135-f7d3-b58730240707}

Followup:     MachineOwner
---------
VENDOR RESPONSE

Release notes from the vendor can be found here:

https://help.accusoft.com/ImageGear/v20.3/Windows/DLL/webframe.html#release-notes.html

https://help.accusoft.com/ImageGear/v20.3/Linux/webframe.html#release-notes.html

TIMELINE

2023-03-16 - Vendor Disclosure
2023-09-20 - Vendor Patch Release
2023-09-25 - Public Release

Credit

Discovered by Emmanuel Tacheau of Cisco Talos.