Added new class Msr.

This commit is contained in:
XMRig 2021-01-22 23:50:25 +07:00
parent 3730bcd434
commit c48e2e6af8
No known key found for this signature in database
GPG key ID: 446A53638BE94409
8 changed files with 438 additions and 29 deletions

204
src/hw/msr/Msr_win.cpp Normal file
View file

@ -0,0 +1,204 @@
/* XMRig
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "hw/msr/Msr.h"
#include "base/io/log/Log.h"
#include <string>
#include <vector>
#include <windows.h>
#define SERVICE_NAME L"WinRing0_1_2_0"
#define IOCTL_READ_MSR CTL_CODE(40000, 0x821, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_WRITE_MSR CTL_CODE(40000, 0x822, METHOD_BUFFERED, FILE_ANY_ACCESS)
namespace xmrig {
static const wchar_t *kServiceName = SERVICE_NAME;
class MsrPrivate
{
public:
bool uninstall()
{
if (driver != INVALID_HANDLE_VALUE) {
CloseHandle(driver);
}
if (!service) {
return true;
}
bool result = true;
if (!reuse) {
SERVICE_STATUS serviceStatus;
if (!ControlService(service, SERVICE_CONTROL_STOP, &serviceStatus)) {
result = false;
}
if (!DeleteService(service)) {
LOG_ERR("%s " RED("failed to remove WinRing0 driver, error %u"), Msr::tag(), GetLastError());
result = false;
}
}
CloseServiceHandle(service);
service = nullptr;
return result;
}
bool reuse = false;
HANDLE driver = INVALID_HANDLE_VALUE;
SC_HANDLE manager = nullptr;
SC_HANDLE service = nullptr;
};
} // namespace xmrig
xmrig::Msr::Msr() : d_ptr(new MsrPrivate())
{
DWORD err = 0;
d_ptr->manager = OpenSCManager(nullptr, nullptr, SC_MANAGER_ALL_ACCESS);
if (!d_ptr->manager) {
if ((err = GetLastError()) == ERROR_ACCESS_DENIED) {
LOG_WARN("%s " YELLOW_BOLD("to access MSR registers Administrator privileges required."), tag());
}
else {
LOG_ERR("%s " RED("failed to open service control manager, error %u"), tag(), err);
}
return;
}
std::vector<wchar_t> dir;
do {
dir.resize(dir.empty() ? MAX_PATH : dir.size() * 2);
GetModuleFileNameW(nullptr, dir.data(), dir.size());
err = GetLastError();
} while (err == ERROR_INSUFFICIENT_BUFFER);
if (err != ERROR_SUCCESS) {
LOG_ERR("%s " RED("failed to get path to driver, error %u"), tag(), err);
return;
}
for (auto it = dir.end() - 1; it != dir.begin(); --it) {
if ((*it == L'\\') || (*it == L'/')) {
++it;
*it = L'\0';
break;
}
}
const std::wstring path = std::wstring(dir.data()) + L"WinRing0x64.sys";
d_ptr->service = OpenServiceW(d_ptr->manager, kServiceName, SERVICE_ALL_ACCESS);
if (d_ptr->service) {
LOG_WARN("%s " YELLOW("service ") YELLOW_BOLD("WinRing0_1_2_0") YELLOW(" already exists"), tag());
SERVICE_STATUS status;
const auto rc = QueryServiceStatus(d_ptr->service, &status);
if (rc) {
DWORD dwBytesNeeded = 0;
QueryServiceConfigA(d_ptr->service, nullptr, 0, &dwBytesNeeded);
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
std::vector<BYTE> buffer(dwBytesNeeded);
auto config = reinterpret_cast<LPQUERY_SERVICE_CONFIGA>(buffer.data());
if (QueryServiceConfigA(d_ptr->service, config, buffer.size(), &dwBytesNeeded)) {
LOG_INFO("%s " YELLOW("service path: ") YELLOW_BOLD("\"%s\""), tag(), config->lpBinaryPathName);
}
}
}
if (rc && status.dwCurrentState == SERVICE_RUNNING) {
d_ptr->reuse = true;
}
else if (!d_ptr->uninstall()) {
return;
}
}
if (!d_ptr->reuse) {
d_ptr->service = CreateServiceW(d_ptr->manager, kServiceName, kServiceName, SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, path.c_str(), nullptr, nullptr, nullptr, nullptr, nullptr);
if (!d_ptr->service) {
LOG_ERR("%s " RED("failed to install WinRing0 driver, error %u"), tag(), GetLastError());
return;
}
if (!StartService(d_ptr->service, 0, nullptr)) {
err = GetLastError();
if (err != ERROR_SERVICE_ALREADY_RUNNING) {
if (err == ERROR_FILE_NOT_FOUND) {
LOG_ERR("%s " RED("failed to start WinRing0 driver: ") RED_BOLD("\"WinRing0x64.sys not found\""), tag());
}
else {
LOG_ERR("%s " RED("failed to start WinRing0 driver, error %u"), tag(), err);
}
d_ptr->uninstall();
return;
}
}
}
d_ptr->driver = CreateFileW(L"\\\\.\\" SERVICE_NAME, GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
if (d_ptr->driver == INVALID_HANDLE_VALUE) {
LOG_ERR("%s " RED("failed to connect to WinRing0 driver, error %u"), tag(), GetLastError());;
}
}
xmrig::Msr::~Msr()
{
d_ptr->uninstall();
delete d_ptr;
}
bool xmrig::Msr::isAvailable() const
{
return d_ptr->driver != INVALID_HANDLE_VALUE;
}
bool xmrig::Msr::rdmsr(uint32_t reg, int32_t, uint64_t &value) const
{
DWORD size = 0;
return DeviceIoControl(d_ptr->driver, IOCTL_READ_MSR, &reg, sizeof(reg), &value, sizeof(value), &size, nullptr) != 0;
}