388 lines
12 KiB
C
388 lines
12 KiB
C
#include <Windows.h>
|
|
//
|
|
#include <Ntddscsi.h>
|
|
#include <stdio.h>
|
|
#define _CRT_RAND_S
|
|
#include <stdlib.h>
|
|
#include <winioctl.h>
|
|
|
|
#include "../dll/hooks/drive/irb.h"
|
|
#include "../lib/ami/amiDebug.h"
|
|
|
|
#define ATA_VENDOR_HOST_PROOF 0xC1
|
|
#define ATA_VENDOR_PROOF_DEVICE 0xC2
|
|
#define ATA_IDENTIFY_DEVICE 0xEC
|
|
#define ATA_SECURITY_UNLOCK 0xF2
|
|
#define ATA_SECURITY_FREEZE_LOCK 0xF5
|
|
|
|
#pragma pack(push, 1)
|
|
typedef struct {
|
|
UCHAR bFeaturesReg;
|
|
UCHAR bSectorCountReg;
|
|
UCHAR bSectorNumberReg;
|
|
UCHAR bCylLowReg;
|
|
UCHAR bCylHighReg;
|
|
UCHAR bDriveHeadReg;
|
|
UCHAR bCommandReg;
|
|
UCHAR bReserved;
|
|
} ATA_TASK_FILE_OUT;
|
|
typedef struct {
|
|
UCHAR bErrorReg;
|
|
UCHAR bSectorCountReg;
|
|
UCHAR bSectorNumberReg;
|
|
UCHAR bCylLowReg;
|
|
UCHAR bCylHighReg;
|
|
UCHAR bDriveHeadReg;
|
|
UCHAR bStatusReg;
|
|
UCHAR bReserved;
|
|
} ATA_TASK_FILE_IN;
|
|
typedef struct _ATA_PASS_THROUGH_EX_512 {
|
|
ATA_PASS_THROUGH_EX Ata;
|
|
UCHAR Data[512];
|
|
} ATA_PASS_THROUGH_EX_512, *PATA_PASS_THROUGH_EX_512;
|
|
typedef struct _ATA_PASS_THROUGH_EX_256 {
|
|
ATA_PASS_THROUGH_EX Ata;
|
|
UCHAR Data[256];
|
|
} ATA_PASS_THROUGH_EX_256, *PATA_PASS_THROUGH_EX_256;
|
|
#pragma pack(pop)
|
|
|
|
#define TASK_FILE_OUT(Ata) (*((ATA_TASK_FILE_OUT *)(void *)(&Ata.CurrentTaskFile)))
|
|
#define TASK_FILE_IN(Ata) (*((ATA_TASK_FILE_IN *)(void *)(&Ata.CurrentTaskFile)))
|
|
|
|
typedef enum {
|
|
mseOk = 0,
|
|
mseNg = -1,
|
|
mseInvalidParam = -2,
|
|
mseNoInit = -3,
|
|
mseAlreadyInit = -4,
|
|
mseDiskError = -5,
|
|
mseAtaDeviceError = -6,
|
|
} mxk_ssd_err_t;
|
|
|
|
HANDLE PD0_HANDLE = INVALID_HANDLE_VALUE;
|
|
BOOL PD0_HAS_INIT = FALSE;
|
|
|
|
mxk_ssd_err_t mxkGetSystemDiskNumber(DWORD *disk) {
|
|
// TODO: This
|
|
if (disk != NULL) *disk = 1;
|
|
return mseOk;
|
|
}
|
|
|
|
mxk_ssd_err_t mxkSsdInit(void) {
|
|
if (PD0_HAS_INIT) return mseAlreadyInit;
|
|
|
|
DWORD disk;
|
|
mxk_ssd_err_t err = mxkGetSystemDiskNumber(&disk);
|
|
if (err != mseOk) return mseDiskError;
|
|
|
|
char path[32] = { 0 };
|
|
sprintf_s(path, sizeof path, "\\\\.\\PhysicalDrive%d", disk);
|
|
amiDebugLog("Using disk: %s", path);
|
|
PD0_HANDLE = CreateFileA(path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
NULL, OPEN_EXISTING, 0, NULL);
|
|
if (PD0_HANDLE == INVALID_HANDLE_VALUE) {
|
|
amiDebugLog("CreateFile Error : Error No = %d", GetLastError());
|
|
return mseDiskError;
|
|
}
|
|
|
|
PD0_HAS_INIT = TRUE;
|
|
return mseOk;
|
|
}
|
|
mxk_ssd_err_t mxkSsdExit(void) {
|
|
if (!PD0_HAS_INIT) return mseNoInit;
|
|
|
|
if (PD0_HANDLE != INVALID_HANDLE_VALUE) CloseHandle(PD0_HANDLE);
|
|
PD0_HAS_INIT = FALSE;
|
|
return mseOk;
|
|
}
|
|
|
|
mxk_ssd_err_t mxkAtaPioOutCommand(HANDLE hDrive, PATA_PASS_THROUGH_EX pAtaBuffer, UCHAR *data) {
|
|
ATA_PASS_THROUGH_EX response;
|
|
ATA_PASS_THROUGH_EX_512 request;
|
|
|
|
ZeroMemory(&request, sizeof request);
|
|
memcpy(&request.Ata, pAtaBuffer, sizeof request.Ata);
|
|
|
|
DWORD sendBytes;
|
|
if (data == NULL) {
|
|
sendBytes = sizeof request.Ata;
|
|
} else {
|
|
memcpy(request.Data, data, sizeof request.Data);
|
|
request.Ata.DataTransferLength = sizeof request.Data;
|
|
sendBytes = sizeof request;
|
|
}
|
|
|
|
request.Ata.Length = sizeof request.Ata;
|
|
request.Ata.DataBufferOffset = sizeof request.Ata;
|
|
request.Ata.AtaFlags = ATA_FLAGS_DATA_OUT;
|
|
request.Ata.TimeOutValue = 35;
|
|
|
|
DWORD dwBytesReturned = 0;
|
|
BOOL bResult = DeviceIoControl(hDrive, IOCTL_ATA_PASS_THROUGH, &request, sendBytes, &response,
|
|
sizeof response, &dwBytesReturned, NULL);
|
|
|
|
memcpy(pAtaBuffer, &response, sizeof response);
|
|
|
|
if (!bResult || (TASK_FILE_IN(response).bStatusReg & 1) != 0) {
|
|
amiDebugLog("Error DeviceIoControl() : %d/%02x:%02x", GetLastError(),
|
|
TASK_FILE_IN(response).bStatusReg, TASK_FILE_IN(response).bErrorReg);
|
|
return mseAtaDeviceError;
|
|
}
|
|
return mseOk;
|
|
}
|
|
|
|
mxk_ssd_err_t mxkAtaPioInCommand(HANDLE hDrive, PATA_PASS_THROUGH_EX pAtaBuffer, UCHAR *dataOut) {
|
|
ATA_PASS_THROUGH_EX request;
|
|
ATA_PASS_THROUGH_EX_512 response;
|
|
|
|
ZeroMemory(&response.Ata, sizeof response.Ata);
|
|
memcpy(&request, pAtaBuffer, sizeof request);
|
|
|
|
request.Length = sizeof request;
|
|
request.DataBufferOffset = sizeof request;
|
|
request.AtaFlags = ATA_FLAGS_DATA_IN;
|
|
request.TimeOutValue = 5;
|
|
|
|
DWORD dwBytesReturned = 0;
|
|
BOOL bResult = DeviceIoControl(hDrive, IOCTL_ATA_PASS_THROUGH, &request, sizeof request,
|
|
&response, sizeof response, &dwBytesReturned, NULL);
|
|
|
|
memcpy(pAtaBuffer, &response, sizeof response.Ata);
|
|
|
|
if (!bResult || (TASK_FILE_IN(response.Ata).bStatusReg & 1) != 0) {
|
|
amiDebugLog("Error DeviceIoControl() : %d", GetLastError());
|
|
return mseAtaDeviceError;
|
|
}
|
|
|
|
memcpy(dataOut, response.Data, sizeof response.Data);
|
|
return mseOk;
|
|
}
|
|
|
|
mxk_ssd_err_t mxkSsdDeviceProofSet(UCHAR *data) {
|
|
ATA_PASS_THROUGH_EX request;
|
|
UCHAR localData[512];
|
|
|
|
if (!PD0_HAS_INIT) return mseNoInit;
|
|
if (data == NULL) return mseInvalidParam;
|
|
|
|
ZeroMemory(&request, sizeof request);
|
|
memcpy(localData, data, 128);
|
|
|
|
TASK_FILE_OUT(request).bCommandReg = ATA_VENDOR_PROOF_DEVICE;
|
|
TASK_FILE_OUT(request).bFeaturesReg = 17;
|
|
|
|
return mxkAtaPioOutCommand(PD0_HANDLE, &request, localData);
|
|
}
|
|
|
|
mxk_ssd_err_t mxkSsdDeviceProofGet(UCHAR *data) {
|
|
ATA_PASS_THROUGH_EX request;
|
|
UCHAR buffer[512];
|
|
|
|
if (!PD0_HAS_INIT) return mseNoInit;
|
|
if (data == NULL) return mseInvalidParam;
|
|
|
|
ZeroMemory(&request, sizeof request);
|
|
TASK_FILE_OUT(request).bCommandReg = ATA_VENDOR_PROOF_DEVICE;
|
|
TASK_FILE_OUT(request).bFeaturesReg = 18;
|
|
request.DataTransferLength = sizeof buffer;
|
|
|
|
mxk_ssd_err_t err = mxkAtaPioInCommand(PD0_HANDLE, &request, buffer);
|
|
if (err != 0) return err;
|
|
memcpy(data, buffer, 128);
|
|
return mseOk;
|
|
}
|
|
|
|
#define SSD_PROOF_NBYTES 16
|
|
int mxkSsdProofDevice(UCHAR *seed, UCHAR *response, UCHAR *code) {
|
|
UCHAR workBuf[128];
|
|
|
|
if (response == NULL || seed == NULL) {
|
|
if (code != NULL) *code = 54;
|
|
return 3;
|
|
}
|
|
if (code == NULL) return 3;
|
|
|
|
*code = 0;
|
|
memcpy_s(workBuf, sizeof workBuf, seed, SSD_PROOF_NBYTES);
|
|
|
|
unsigned int randVal;
|
|
for (int i = SSD_PROOF_NBYTES; i < sizeof workBuf; i++) {
|
|
rand_s(&randVal);
|
|
workBuf[i] = randVal & 0xFF;
|
|
}
|
|
|
|
mxk_ssd_err_t err;
|
|
err = mxkSsdDeviceProofSet(workBuf);
|
|
if (err != mseOk) {
|
|
amiDebugLog("Error mxkSsdDeviceProofSet()!!! Code:%d", err);
|
|
*code = 2;
|
|
return 1;
|
|
}
|
|
|
|
ZeroMemory(workBuf, sizeof workBuf);
|
|
err = mxkSsdDeviceProofGet(workBuf);
|
|
if (err != mseOk) {
|
|
amiDebugLog("Error mxkSsdDeviceProofGet()!!! Code:%d", err);
|
|
*code = 2;
|
|
return 1;
|
|
}
|
|
|
|
memcpy_s(response, SSD_PROOF_NBYTES, workBuf, SSD_PROOF_NBYTES);
|
|
return 0;
|
|
}
|
|
|
|
mxk_ssd_err_t mxkSsdSecurityUnlock(UCHAR *password, DWORD nPassword, BOOL userPassword) {
|
|
ATA_PASS_THROUGH_EX request;
|
|
UCHAR localData[512];
|
|
|
|
if (!PD0_HAS_INIT) return mseNoInit;
|
|
if (password == NULL) return mseInvalidParam;
|
|
|
|
ZeroMemory(&request, sizeof request);
|
|
ZeroMemory(localData, sizeof localData);
|
|
if (userPassword)
|
|
localData[0] = 0x00;
|
|
else
|
|
localData[0] = 0x01;
|
|
memcpy_s(localData + 2, sizeof localData, password, nPassword);
|
|
|
|
TASK_FILE_OUT(request).bCommandReg = ATA_SECURITY_UNLOCK;
|
|
|
|
return mxkAtaPioOutCommand(PD0_HANDLE, &request, localData);
|
|
}
|
|
|
|
mxk_ssd_err_t mxkSsdIdentify(PIDENTIFY_DEVICE_DATA response) {
|
|
if (!PD0_HAS_INIT) return mseNoInit;
|
|
if (response == NULL) return mseInvalidParam;
|
|
|
|
ATA_PASS_THROUGH_EX_256 ata = { 0 };
|
|
ata.Ata.Length = sizeof ata.Ata;
|
|
ata.Ata.AtaFlags = ATA_FLAGS_DATA_IN | ATA_FLAGS_DRDY_REQUIRED;
|
|
ata.Ata.DataTransferLength = sizeof ata.Data;
|
|
ata.Ata.DataBufferOffset = sizeof ata.Ata;
|
|
ata.Ata.TimeOutValue = 10;
|
|
ata.Ata.CurrentTaskFile[6] = ATA_IDENTIFY_DEVICE;
|
|
ata.Ata.CurrentTaskFile[7] = 0;
|
|
|
|
DWORD dwBytesReturned = 0;
|
|
BOOL bResult = DeviceIoControl(PD0_HANDLE, IOCTL_ATA_PASS_THROUGH, &ata, sizeof(ata), &ata,
|
|
sizeof(ata), &dwBytesReturned, NULL);
|
|
|
|
if (!bResult) {
|
|
amiDebugLog("Error DeviceIoControl() : %d", GetLastError());
|
|
return mseAtaDeviceError;
|
|
}
|
|
|
|
memcpy(response, ata.Data, sizeof ata.Data);
|
|
return mseOk;
|
|
}
|
|
|
|
void printf_word_string(UCHAR *wordString, DWORD nShorts) {
|
|
while (nShorts--) {
|
|
printf("%c", wordString[1]);
|
|
printf("%c", wordString[0]);
|
|
wordString += 2;
|
|
}
|
|
}
|
|
|
|
void printIdentity(PIDENTIFY_DEVICE_DATA identity) {
|
|
puts("[ Identification ]");
|
|
printf("Serial number : ");
|
|
printf_word_string(identity->SerialNumber, 10);
|
|
printf("\nModel number : ");
|
|
printf_word_string(identity->ModelNumber, 20);
|
|
puts("\n[ Security ]");
|
|
printf(" Supported : %s\n", identity->SecurityStatus.SecuritySupported ? "YES" : "NO");
|
|
printf(" Enabled : %s\n", identity->SecurityStatus.SecurityEnabled ? "YES" : "NO");
|
|
printf(" Frozen : %s\n", identity->SecurityStatus.SecurityFrozen ? "YES" : "NO");
|
|
printf(" Locked : %s\n", identity->SecurityStatus.SecurityLocked ? "YES" : "NO");
|
|
printf(" # Expired : %s\n", identity->SecurityStatus.SecurityCountExpired ? "YES" : "NO");
|
|
printf(" Master Pass : %s\n", identity->SecurityStatus.SecurityLevel ? "Maximum" : "High");
|
|
}
|
|
|
|
int main(int argc, char **argv) {
|
|
puts("mice GBDisk utility tool.");
|
|
|
|
printf("Opening drive\n");
|
|
|
|
mxk_ssd_err_t err;
|
|
err = mxkSsdInit();
|
|
if (err != mseOk) {
|
|
printf("Failed to open SSD: %d\n", err);
|
|
return 1;
|
|
}
|
|
|
|
puts("Requesting identity");
|
|
IDENTIFY_DEVICE_DATA identity;
|
|
err = mxkSsdIdentify(&identity);
|
|
if (err != mseOk) {
|
|
printf("Failed to identify: %d\n", err);
|
|
mxkSsdExit();
|
|
return 1;
|
|
}
|
|
printIdentity(&identity);
|
|
if (!identity.SecurityStatus.SecurityLocked) {
|
|
puts("Security is not enabled. Nothing to do!");
|
|
mxkSsdExit();
|
|
return 0;
|
|
}
|
|
if (identity.SecurityStatus.SecurityFrozen) {
|
|
puts("Security is frozen. We have no hope of unlocking this drive!");
|
|
mxkSsdExit();
|
|
return 2;
|
|
}
|
|
|
|
puts("Sending security unlock");
|
|
UCHAR password[32] = {
|
|
0x72, 0x42, 0x52, 0x5A, 0xBA, 0x52, 0x6A, 0x5A, 0xEA, 0x72, 0x62,
|
|
0x78, 0xCA, 0x42, 0xDA, 0x4A, 0x2A, 0x22, 0x3A, 0x2A, 0x0A, 0x22,
|
|
0x1A, 0x2A, 0x6A, 0x02, 0x7A, 0x0A, 0x5C, 0xCE, 0x4A, 0x0A,
|
|
};
|
|
err = mxkSsdSecurityUnlock(password, sizeof password, TRUE);
|
|
printf("Security unlock result: %d\n", err);
|
|
|
|
mxkSsdExit();
|
|
return 0;
|
|
}
|
|
|
|
// int main() {
|
|
// HANDLE hDevice = CreateFile("\\\\.\\PhysicalDrive1", GENERIC_READ | GENERIC_WRITE,
|
|
// FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0,
|
|
// NULL);
|
|
// if (hDevice == INVALID_HANDLE_VALUE) {
|
|
// printf("Error: could not open device\n");
|
|
// return 1;
|
|
// }
|
|
|
|
// ATA_PASS_THROUGH_EX_256 ata = { 0 };
|
|
// ata.Ata.Length = sizeof ata.Ata;
|
|
// ata.Ata.AtaFlags = ATA_FLAGS_DATA_IN | ATA_FLAGS_DRDY_REQUIRED;
|
|
// ata.Ata.DataTransferLength = 256;
|
|
// ata.Ata.DataBufferOffset = sizeof ata.Ata;
|
|
// ata.Ata.TimeOutValue = 10;
|
|
// ata.Ata.CurrentTaskFile[6] = ATA_IDENTIFY_DEVICE;
|
|
// ata.Ata.CurrentTaskFile[7] = 0;
|
|
|
|
// DWORD dwBytesReturned = 0;
|
|
// BOOL bResult = DeviceIoControl(hDevice, IOCTL_ATA_PASS_THROUGH, &ata, sizeof(ata), &ata,
|
|
// sizeof(ata), &dwBytesReturned, NULL);
|
|
// if (!bResult) {
|
|
// printf("Error: could not send IDENTIFY DEVICE request %d\n", GetLastError());
|
|
// CloseHandle(hDevice);
|
|
// return 1;
|
|
// }
|
|
|
|
// for (int i = 0; i < 256; i++) {
|
|
// printf(" %02x", ata.Data[i]);
|
|
// if (i % 32 == 31) {
|
|
// printf(" ");
|
|
// for (int j = i - 31; j <= i; j++) {
|
|
// if (10 <= ata.Data[j] && ata.Data[j] < 128)
|
|
// printf("%c", ata.Data[j]);
|
|
// else
|
|
// printf(".");
|
|
// }
|
|
// puts("");
|
|
// }
|
|
// }
|
|
// }
|