cocafe / msr-utility

Little CLI utility to control Model Specific Registers (MSRs) on Windows via WinRing0 driver, 64+ cores supported

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How to use this to mitigate zenbleed? (converting from wrmsr command

nl255 opened this issue · comments

commented

According to the zenbleed writeup it can be mitigated by setting the chicken bit but it only gives the command for Linux which is
wrmsr -a 0xc0011029 $(($(rdmsr -c 0xc0011029) | (1<<9))) . How can this be done using msr-cmd?

commented

i'm here for the same reason haha! let me know if we get this figured out

Download the latest release.

Try to read this register first to make sure it can be accessed, (I am not sure this REG can be accessed on windows, on ZEN4 cannot read this REG):
msr-cmd read 0xc0011029

Then you can use python to compute the value quickly or use calc programming mode to click bit 9 to get the value, to set for all processors:
msr-cmd -A write <edx 63-32bits> <eax>

You can use the my private shell script below to do the job, run on cygwin with admin privilege:

#!/bin/bash

MSR_CMD=/cygdrive/d/Program/msr-watchdog/msr-cmd.exe

NR_CPU=`cat /proc/cpuinfo | grep processor | wc -l`
NR_CPUGRP=$((${NR_CPU} / 64))

if [ ${NR_CPUGRP} -eq 0 ]; then
  NR_CPUGRP=1
fi

IS_PROC_GROUPED=0
if [ ${NR_CPU} -gt 64 ]; then
  IS_PROC_GROUPED=1
fi

err_echo()
{
  >&2 echo $@
}

msr_setbit()
{
  local pkg=$1
  local cpu=$2
  local reg=$3
  local bit=$4
  local val=$5

  local regval=0

  if [ $# -ne 5 ]; then
    err_echo "invalid parameters: $@"
    err_echo "press any key to exit..."
    read
    exit -1
  fi

  if [ x"$pkg" != x"A" -a x"$pkg" != x"a" ]; then
    if [ $pkg -ge 1 -a ${IS_PROC_GROUPED} == 0 ]; then
      return 0
    fi
  fi

  if [ $bit -gt 63 -o $bit -lt 0 ]; then
    err_echo "invalid bit shift: $bit"
    read
    exit -1
  fi

  if [ "$val" != "0" -a "$val" != "1" ]; then
    err_echo "invalid bit value: $val"
    read
  fi

  err_echo "msr setbit: $@"

  #
  # FIXME: !!! LAZY IMPL !!!
  #
  if [ "$cpu" = "A" -o "$cpu" = "ALL" ]; then
    if [ x"$pkg" = x"A" -o x"$pkg" = x"a" ]; then
      regval=`${MSR_CMD} -d -g 0 -p 0 read $reg`
    else
      regval=`${MSR_CMD} -d -g $pkg -p 0 read $reg`
    fi
  else
    if [ x"$pkg" = x"A" -o x"$pkg" = x"a" ]; then
      regval=`${MSR_CMD} -d -g 0 -p $cpu read $reg`
    else
      regval=`${MSR_CMD} -d -g $pkg -p $cpu read $reg`
    fi
  fi
  if [ "$regval" == "" ]; then
    err_echo "failed to read $reg"
    return -1
  fi

  local edx=`echo $regval | awk '{print $4}'`
  local eax=`echo $regval | awk '{print $5}'`
  edx=`printf "0x%x" $edx`
  eax=`echo $eax | tr -d '\r'`
  eax=`printf "0x%x" $eax`

  if [ $bit -gt 31 ]; then
    bit=$(($bit - 32))
    edx=`printf "0x%x" $((    ($edx & ~(1 << $bit)) | ($val << $bit)    ))`
  else
    eax=`printf "0x%x" $((    ($eax & ~(1 << $bit)) | ($val << $bit)    ))`
  fi

  if [ "$cpu" = "A" -o "$cpu" = "ALL" ]; then
      if [ x"$pkg" = x"A" -o x"$pkg" = x"a" ]; then
        ${MSR_CMD} -A -s -d write $reg $edx $eax
      else
        ${MSR_CMD} -g $pkg -a -s -d write $reg $edx $eax
      fi
  else
    if [ x"$pkg" = x"A" -o x"$pkg" = x"a" ]; then
      local i=0
      while [ $i -lt ${NR_CPUGRP} ]; do
        ${MSR_CMD} -g $i -p $cpu -s -d write $reg $edx $eax
        i=$(($i + 1))
      done
    else
      ${MSR_CMD} -g $pkg -p $cpu -s -d write $reg $edx $eax
    fi
  fi

  local ret=$?

  if [ $ret -ne 0 ]; then
    err_echo "write msr failed: package: $pkg cpu: $cpu reg: $reg edx: $edx eax: $eax"
    err_echo "press any key to continue..."
    read
  fi

  return $ret
}

# SET FOR ALL PROCESSORS CROSS ALL SOCKETS
msr_setbit A A 0xc0011029 9 1
commented

It seems to work fine and though I only have one system to test it on it seems that EAX never changes for a given system (so once you get the right values you can set it to run on startup). Using the full edx value doesn't seem to make a difference and also works fine. Unfortunately I haven't been able to test that it actually mitigates the vulnerability because every time I try to run zenbleed in virtualbox (both with and without the bit set) I get an illegal instruction error.

C:\cygwin64\bin>msr-cmd read 0xc0011029
GROUP    CPU      REG        EDX        EAX
0        0        0xc0011029 0x00030003 0x10e08002

msr-cmd.exe -A -s -d write 0xc0011029 0x00030003 0x10e08202


C:\cygwin64\bin>msr-cmd read 0xc0011029
GROUP    CPU      REG        EDX        EAX
0        0        0xc0011029 0x00030003 0x10e08202
commented

For anyone else having trouble using the calculator this should help.

ZenBleedMsr

commented

could the zenbleed test be compiled for windows so we can make absolutely sure?

commented

could the zenbleed test be compiled for windows so we can make absolutely sure?

No, it would need to be completely rewritten for Windows.