Implement CrackProof drivers
This commit is contained in:
parent
701887940c
commit
d3ff2e7c24
@ -165,6 +165,8 @@ void init_injection(HMODULE hModule) {
|
||||
if (MiceConfig.drivers.mxsmbus) setup_mxsmbus();
|
||||
// MX Parallel: The parallel port (i.e. keychip)
|
||||
if (MiceConfig.drivers.mxparallel) setup_mxparallel();
|
||||
// CrackProof
|
||||
if (MiceConfig.drivers.htsysmnt) setup_htsysmnt();
|
||||
|
||||
if (MiceConfig.drivers.platform) {
|
||||
if (!add_fake_device(&PLATFORM_GUID, L"\\\\.\\platform")) {
|
||||
|
113
src/micetools/dll/drivers/htsysmnt.c
Normal file
113
src/micetools/dll/drivers/htsysmnt.c
Normal file
@ -0,0 +1,113 @@
|
||||
#include "mx.h"
|
||||
|
||||
#pragma pack(push, 1)
|
||||
typedef struct {
|
||||
LPBYTE dest;
|
||||
LPBYTE src;
|
||||
DWORD nBytes;
|
||||
} HTSYSMNT_1x, *LPHTSYSMNT_1x;
|
||||
|
||||
typedef struct {
|
||||
DWORD offset;
|
||||
LPBYTE data;
|
||||
DWORD nBytes;
|
||||
} HTSYSMNT_2x, *LPHTSYSMNT_2x;
|
||||
|
||||
typedef struct {
|
||||
void (*callback)(void);
|
||||
} HTSYSMNT_3x, *LPHTSYSMNT_3x;
|
||||
#pragma pack(pop)
|
||||
|
||||
static BYTE HTSYS_BUFFER[256];
|
||||
|
||||
static BOOL htsysmntBufferTransact(DWORD offset, LPBYTE data, DWORD nbytes, BOOL doWrite) {
|
||||
LPBYTE source;
|
||||
LPBYTE destination;
|
||||
|
||||
if (!(offset < 16 && nbytes < 16)) return FALSE;
|
||||
|
||||
destination = HTSYS_BUFFER + offset * 16;
|
||||
source = data;
|
||||
if (!doWrite) {
|
||||
source = destination;
|
||||
destination = data;
|
||||
}
|
||||
memcpy(destination, source, nbytes);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL htsysmntExchangeBuffers(LPBYTE dest, LPBYTE src, DWORD nBytes, BOOL direction) {
|
||||
if (dest == NULL || src == NULL || nBytes == 0) return FALSE;
|
||||
|
||||
LPBYTE destination;
|
||||
destination = dest;
|
||||
if (!direction) {
|
||||
destination = src;
|
||||
src = dest;
|
||||
}
|
||||
|
||||
memcpy(src, destination, nBytes);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL WINAPI htsysmnt_DeviceIoControl(file_context_t* ctx, DWORD dwIoControlCode, LPVOID lpInBuffer,
|
||||
DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize,
|
||||
LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) {
|
||||
DWORD expectedIn = 0;
|
||||
DWORD expectedOut = /* 4 */ sizeof(BOOL);
|
||||
|
||||
switch (dwIoControlCode) {
|
||||
case IOCTL_CRACKPROOF_10:
|
||||
case IOCTL_CRACKPROOF_11:
|
||||
case IOCTL_CRACKPROOF_20:
|
||||
case IOCTL_CRACKPROOF_21:
|
||||
expectedIn = 12;
|
||||
break;
|
||||
case IOCTL_CRACKPROOF_30:
|
||||
expectedIn = 4;
|
||||
break;
|
||||
default:
|
||||
log_warning(plfHtsysmnt, "unhandled 0x%08x", dwIoControlCode);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (nInBufferSize != expectedIn || nOutBufferSize != expectedOut) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL result = TRUE;
|
||||
|
||||
switch (dwIoControlCode) {
|
||||
case IOCTL_CRACKPROOF_10:
|
||||
case IOCTL_CRACKPROOF_11: {
|
||||
result = htsysmntExchangeBuffers(
|
||||
((LPHTSYSMNT_1x)lpInBuffer)->dest, ((LPHTSYSMNT_1x)lpInBuffer)->src,
|
||||
((LPHTSYSMNT_1x)lpInBuffer)->nBytes, dwIoControlCode == IOCTL_CRACKPROOF_11);
|
||||
break;
|
||||
}
|
||||
|
||||
case IOCTL_CRACKPROOF_20:
|
||||
case IOCTL_CRACKPROOF_21: {
|
||||
result = htsysmntBufferTransact(
|
||||
((LPHTSYSMNT_2x)lpInBuffer)->offset, ((LPHTSYSMNT_2x)lpInBuffer)->data,
|
||||
((LPHTSYSMNT_2x)lpInBuffer)->nBytes, dwIoControlCode == IOCTL_CRACKPROOF_21);
|
||||
break;
|
||||
}
|
||||
|
||||
case IOCTL_CRACKPROOF_30:
|
||||
result = TRUE;
|
||||
((LPHTSYSMNT_3x)lpInBuffer)->callback();
|
||||
break;
|
||||
}
|
||||
|
||||
*(LPBOOL)lpOutBuffer = result;
|
||||
*lpBytesReturned = expectedOut;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void setup_htsysmnt() {
|
||||
file_hook_t* htsysmnt = new_file_hook(L"\\\\.\\Htsysm");
|
||||
htsysmnt->DeviceIoControl = &htsysmnt_DeviceIoControl;
|
||||
|
||||
hook_file(htsysmnt);
|
||||
}
|
@ -6,4 +6,5 @@ drivers_files = files(
|
||||
'mxsmbus.c',
|
||||
'mxsram.c',
|
||||
'mxsuperio.c',
|
||||
'htsysmnt.c',
|
||||
)
|
@ -26,3 +26,6 @@ void setup_columba();
|
||||
|
||||
FnDeviceIoControl mxparallel_DeviceIoControl;
|
||||
void setup_mxparallel();
|
||||
|
||||
FnDeviceIoControl htsysmnt_DeviceIoControl;
|
||||
void setup_htsysmnt();
|
||||
|
@ -28,7 +28,6 @@ physical_disk_t SSD = {
|
||||
{ 0x403947, MBR_FS_FAT16, SPD_Patch1, .m_ReadFunc = NULL }, // 2GB patch1
|
||||
{ 0x48ed459, MBR_FS_NTFS, SPD_AppData, .m_ReadFunc = NULL }, // 40GB something
|
||||
{
|
||||
// mxinstaller.exe -cmdport 40102 -bindport 40103
|
||||
// 16GB partition for the game
|
||||
// The real value here should be "0x20014aa,"
|
||||
0x20014aa, // 16GB, FiNALE
|
||||
|
@ -78,6 +78,7 @@ CFG_bool(drivers, mxjvs, true, "")
|
||||
CFG_bool(drivers, mxhwreset, true, "")
|
||||
CFG_bool(drivers, mxsmbus, true, "")
|
||||
CFG_bool(drivers, mxparallel, true, "")
|
||||
CFG_bool(drivers, htsysmnt, true, "")
|
||||
CFG_bool(drivers, platform, true, "")
|
||||
ENDSECTION(drivers)
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <winioctl.h>
|
||||
|
||||
#define FILE_DEVICE_SEGA 0x9c40
|
||||
#define FILE_DEVICE_HTSYS 0xaa00
|
||||
|
||||
// amSramInit
|
||||
#define IOCTL_MXSRAM_PING \
|
||||
@ -83,3 +84,10 @@
|
||||
(DWORD) CTL_CODE(FILE_DEVICE_SEGA, 0x806, METHOD_BUFFERED, FILE_WRITE_ACCESS)
|
||||
#define IOCTL_MXPARALLEL_READ_FLAGS \
|
||||
(DWORD) CTL_CODE(FILE_DEVICE_SEGA, 0x807, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
|
||||
// CrackProof
|
||||
#define IOCTL_CRACKPROOF_10 CTL_CODE(FILE_DEVICE_HTSYS, 0x810, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_CRACKPROOF_11 CTL_CODE(FILE_DEVICE_HTSYS, 0x811, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_CRACKPROOF_20 CTL_CODE(FILE_DEVICE_HTSYS, 0x820, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_CRACKPROOF_21 CTL_CODE(FILE_DEVICE_HTSYS, 0x821, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_CRACKPROOF_30 CTL_CODE(FILE_DEVICE_HTSYS, 0x830, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
@ -39,3 +39,4 @@ _LF(Drivers, MxSuperio, "mxsuperio")
|
||||
_LF(Drivers, MxSmbus, "mxsmbus")
|
||||
_LF(Drivers, MxHwreset, "mxhwreset")
|
||||
_LF(Drivers, Platform, "platform")
|
||||
_LF(Drivers, Htsysmnt, "htsysmnt")
|
||||
|
@ -66,3 +66,14 @@ executable(
|
||||
amiDebug,
|
||||
],
|
||||
)
|
||||
executable(
|
||||
'storagecraft',
|
||||
win_subsystem: subsystem,
|
||||
sources: [
|
||||
'storagecraft.c',
|
||||
],
|
||||
link_with: [
|
||||
amiCrc,
|
||||
amiDebug,
|
||||
],
|
||||
)
|
||||
|
249
src/micetools/util/storagecraft.c
Normal file
249
src/micetools/util/storagecraft.c
Normal file
@ -0,0 +1,249 @@
|
||||
#include <Windows.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../dll/hooks/drive/drive.h"
|
||||
|
||||
physical_disk_t newSSD = {
|
||||
.m_SerialNumber = 0x00144DB0,
|
||||
|
||||
.m_BusType = BusTypeAta,
|
||||
.m_BootPartition = 1,
|
||||
.m_HasSegaboot = TRUE,
|
||||
.m_BlockSize = BLOCK_SIZE_HDD,
|
||||
.m_TotalSize = 64 * 1024 * 1024 * (1024 / BLOCK_SIZE_HDD),
|
||||
.m_DiskType = DiskType_HardDisk,
|
||||
.m_IsFormatted = true,
|
||||
.m_Partitions = {
|
||||
// 1.5GB boot partition
|
||||
{ .m_Size = 0x300B85, .m_Filesystem = MBR_FS_NTFS },
|
||||
// 1.5GB OS recovery
|
||||
{ .m_Size = 0x300BC4, .m_Filesystem = MBR_FS_NTFS },
|
||||
},
|
||||
.m_Extended = {
|
||||
{ 0x102d83, MBR_FS_FAT16, SPD_OS }, // 512MB OS update
|
||||
{ 0x403947, MBR_FS_FAT16, SPD_Patch0 }, // 2GB patch0
|
||||
{ 0x403947, MBR_FS_FAT16, SPD_Patch1 }, // 2GB patch1
|
||||
{ 0x48ed459, MBR_FS_NTFS, SPD_AppData }, // 40GB appdata
|
||||
{ 0x20014aa, MBR_FS_FAT16, SPD_Original0 }, // 16GB original0
|
||||
{ 0 }, // End of table
|
||||
},
|
||||
};
|
||||
|
||||
sbr_t SegaBootRecord0;
|
||||
sbr_t SegaBootRecord1;
|
||||
sbr_slot_t* get_sbr_slot(spd_slot_t slot) {
|
||||
switch (slot) {
|
||||
case SPD_Original0:
|
||||
return &SegaBootRecord0.slot_original0;
|
||||
case SPD_Original1:
|
||||
return NULL;
|
||||
case SPD_Patch0:
|
||||
return &SegaBootRecord0.slot_patch0;
|
||||
case SPD_Patch1:
|
||||
return &SegaBootRecord0.slot_patch1;
|
||||
case SPD_OS:
|
||||
return &SegaBootRecord0.slot_os;
|
||||
case SPD_AppData:
|
||||
return &SegaBootRecord0.slot_appdata;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
void init_pd(physical_disk_t* pConfig) {
|
||||
// Apply default block sizes
|
||||
if (!pConfig->m_BlockSize) {
|
||||
switch (pConfig->m_DiskType) {
|
||||
case DiskType_HardDisk:
|
||||
pConfig->m_BlockSize = BLOCK_SIZE_HDD;
|
||||
break;
|
||||
case DiskType_Flash:
|
||||
pConfig->m_BlockSize = BLOCK_SIZE_FLASH;
|
||||
break;
|
||||
case DiskType_CdRom:
|
||||
pConfig->m_BlockSize = BLOCK_SIZE_CDROM;
|
||||
break;
|
||||
default:
|
||||
printf("Unable to guess block size for drive %d", pConfig->m_DriveNumber);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Non-SCSI devices don't have a SCSI type to report
|
||||
if (pConfig->m_BusType != BusTypeScsi) pConfig->m_DeviceType = DeviceTypeUnknown;
|
||||
|
||||
// If we need to initialise the partition tables, do so
|
||||
if (pConfig->m_IsFormatted) {
|
||||
DWORD partitionNumber = 1;
|
||||
DWORD currentLBA = MBR_LBA_GAP;
|
||||
|
||||
// Init MBR
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (pConfig->m_Partitions[i].m_Size == 0) break;
|
||||
|
||||
pConfig->m_Partitions[i].m_PartitionNumber = partitionNumber++;
|
||||
pConfig->m_Partitions[i].m_PhysicalLBA = currentLBA;
|
||||
|
||||
pConfig->m_Partitions[i].m_Volume.m_pDrive = pConfig;
|
||||
pConfig->m_Partitions[i].m_Volume.m_pPartition = &(pConfig->m_Partitions[i]);
|
||||
|
||||
currentLBA += pConfig->m_Partitions[i].m_Size;
|
||||
}
|
||||
|
||||
// If we have any extended partitions
|
||||
DWORD extendedPartNo = 0;
|
||||
if (pConfig->m_Extended[0].m_Size) {
|
||||
if (partitionNumber == 5) {
|
||||
printf("Fatal: Too many paritions in drive %d!", pConfig->m_DriveNumber);
|
||||
exit(1);
|
||||
}
|
||||
pConfig->m_Partitions[partitionNumber - 1].m_Filesystem = MBR_FS_EXT_LBA;
|
||||
pConfig->m_Partitions[partitionNumber - 1].m_PhysicalLBA = currentLBA;
|
||||
extendedPartNo = partitionNumber;
|
||||
|
||||
// Note: We don't increment partitionNumber, to keep the presence of this partition
|
||||
// transparent elsewhere.
|
||||
}
|
||||
DWORD extendedStart = currentLBA;
|
||||
|
||||
// Init extended partitions
|
||||
for (int i = 0;; i++) {
|
||||
if (!pConfig->m_Extended[i].m_Size) break;
|
||||
|
||||
pConfig->m_Extended[i].m_PartitionNumber = partitionNumber++;
|
||||
|
||||
currentLBA += EXT_HEADER_GAP;
|
||||
pConfig->m_Extended[i].m_PhysicalLBA = currentLBA;
|
||||
pConfig->m_Extended[i].m_SlotLBA = currentLBA;
|
||||
currentLBA += pConfig->m_Extended[i].m_Size;
|
||||
|
||||
pConfig->m_Extended[i].m_Volume.m_pDrive = pConfig;
|
||||
pConfig->m_Extended[i].m_Volume.m_pPartition = &(pConfig->m_Extended[i]);
|
||||
|
||||
sbr_slot_t* pslot = get_sbr_slot(pConfig->m_Extended[i].m_SPDContent);
|
||||
if (pslot != NULL) {
|
||||
DWORD slot_size = ((LONGLONG)pslot->segcount * (LONGLONG)pslot->segsize) /
|
||||
(long long)pConfig->m_BlockSize;
|
||||
DWORD slot_offset = pConfig->m_Extended[i].m_Size - slot_size;
|
||||
pConfig->m_Extended[i].m_SlotLBA += slot_offset;
|
||||
}
|
||||
}
|
||||
|
||||
// Back-fill, if needed
|
||||
if (extendedPartNo) {
|
||||
pConfig->m_Partitions[extendedPartNo - 1].m_Size = currentLBA - extendedStart;
|
||||
}
|
||||
} else {
|
||||
// Raw disks have just a single spanning volume
|
||||
pConfig->m_Partitions[0].m_PartitionNumber = 1;
|
||||
pConfig->m_Partitions[0].m_PhysicalLBA = 0;
|
||||
pConfig->m_Partitions[0].m_Size = pConfig->m_TotalSize;
|
||||
pConfig->m_Partitions[0].m_Volume.m_pDrive = pConfig;
|
||||
pConfig->m_Partitions[0].m_Volume.m_pPartition = &(pConfig->m_Partitions[0]);
|
||||
}
|
||||
}
|
||||
|
||||
BYTE writeBuffer[1024];
|
||||
void write_buffer(HANDLE hDisk, LONG nOffset, DWORD nBytes, physical_disk_t* pConfig) {
|
||||
LARGE_INTEGER offset;
|
||||
offset.QuadPart = nOffset * pConfig->m_BlockSize;
|
||||
SetFilePointerEx(hDisk, offset, NULL, FILE_BEGIN);
|
||||
DWORD nOut;
|
||||
WriteFile(hDisk, writeBuffer, nBytes, &nOut, NULL);
|
||||
}
|
||||
|
||||
// TODO: Write start_chs lol
|
||||
void write_mbr(HANDLE hDisk, LONG nOffset, physical_disk_t* pConfig) {
|
||||
printf("Writing MBR at block %d\n", nOffset);
|
||||
mbr_t* mbr = (mbr_t*)writeBuffer;
|
||||
|
||||
memset(mbr, 0, sizeof *mbr);
|
||||
mbr->sig[0] = 0x55;
|
||||
mbr->sig[1] = 0xAA;
|
||||
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
if (pConfig->m_Partitions[i].m_Size == 0) break;
|
||||
|
||||
mbr->partitions[i].status =
|
||||
(pConfig->m_BootPartition == i + 1) ? MBR_FLAG_BOOTABLE : MBR_FLAG_NONE;
|
||||
mbr->partitions[i].type = pConfig->m_Partitions[i].m_Filesystem;
|
||||
mbr->partitions[i].lba = pConfig->m_Partitions[i].m_PhysicalLBA;
|
||||
mbr->partitions[i].sectors = pConfig->m_Partitions[i].m_Size;
|
||||
}
|
||||
|
||||
write_buffer(hDisk, nOffset, sizeof *mbr, pConfig);
|
||||
}
|
||||
void write_ext_header(HANDLE hDisk, LONG nOffset, physical_disk_t* pConfig, DWORD nPartition) {
|
||||
printf("Writing extended header at block %d\n", nOffset);
|
||||
|
||||
mbr_t* mbr = (mbr_t*)writeBuffer;
|
||||
|
||||
memset(mbr, 0, sizeof *mbr);
|
||||
mbr->sig[0] = 0x55;
|
||||
mbr->sig[1] = 0xAA;
|
||||
|
||||
mbr->partitions[0].status = MBR_FLAG_NONE;
|
||||
mbr->partitions[0].type = pConfig->m_Extended[nPartition].m_Filesystem;
|
||||
mbr->partitions[0].lba = EXT_HEADER_GAP;
|
||||
mbr->partitions[0].sectors = pConfig->m_Extended[nPartition].m_Size;
|
||||
|
||||
if (pConfig->m_Extended[nPartition + 1].m_Size) {
|
||||
mbr->partitions[1].status = MBR_FLAG_NONE;
|
||||
// ! mxinstaller expects to see CHS here, then uses the LBA values
|
||||
mbr->partitions[1].type = MBR_FS_EXT_CHS;
|
||||
mbr->partitions[1].lba = pConfig->m_Extended[nPartition + 1].m_PhysicalLBA -
|
||||
pConfig->m_Extended[0].m_PhysicalLBA;
|
||||
mbr->partitions[1].sectors = pConfig->m_Extended[nPartition + 1].m_Size + EXT_HEADER_GAP;
|
||||
}
|
||||
|
||||
write_buffer(hDisk, nOffset, sizeof *mbr, pConfig);
|
||||
}
|
||||
|
||||
void write_pd(HANDLE hDisk, physical_disk_t* pConfig) {
|
||||
puts("Force-allocating disk space");
|
||||
write_buffer(hDisk, pConfig->m_TotalSize - 1, pConfig->m_BlockSize, pConfig);
|
||||
|
||||
// Write MBR headers
|
||||
write_mbr(hDisk, 0, pConfig);
|
||||
for (size_t i = 0; pConfig->m_Extended[i].m_Size; i++) {
|
||||
DWORD headerLBA = pConfig->m_Extended[i].m_PhysicalLBA - EXT_HEADER_GAP;
|
||||
write_ext_header(hDisk, headerLBA, pConfig, i);
|
||||
|
||||
if (i == 0 && pConfig->m_HasSegaboot) {
|
||||
puts("Writing segaboot");
|
||||
|
||||
// SEGA Partition Description
|
||||
spd_t* spd = (spd_t*)writeBuffer;
|
||||
|
||||
spd->version = SPD_VERSION;
|
||||
for (size_t j = 0; pConfig->m_Extended[j].m_Size; j++) {
|
||||
spd->slots[j].block_size = pConfig->m_BlockSize & 0xFFFF;
|
||||
spd->slots[j].block_count = pConfig->m_Extended[j].m_Size;
|
||||
spd->slots[j].slot_content = pConfig->m_Extended[j].m_SPDContent;
|
||||
spd->slots[j].uk1 = pConfig->m_Extended[j].m_Filesystem == MBR_FS_FAT16 ? 0 : 1;
|
||||
}
|
||||
|
||||
spd->crc = amiCrc32RCalc(sizeof *spd - 4, &(spd->version), 0);
|
||||
write_buffer(hDisk, headerLBA + SPD_OFFSET, sizeof *spd, pConfig);
|
||||
|
||||
// SEGA Boot Record 0 and 1. The two are a redundant copy of each other
|
||||
memcpy(writeBuffer, &SegaBootRecord0, sizeof SegaBootRecord0);
|
||||
write_buffer(hDisk, headerLBA + SBR0_OFFSET, sizeof SegaBootRecord0, pConfig);
|
||||
|
||||
memcpy(writeBuffer, &SegaBootRecord1, sizeof SegaBootRecord1);
|
||||
write_buffer(hDisk, headerLBA + SBR1_OFFSET, sizeof SegaBootRecord1, pConfig);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
init_pd(&newSSD);
|
||||
|
||||
HANDLE hDisk = INVALID_HANDLE_VALUE;
|
||||
|
||||
hDisk = CreateFileA("H:\\NewDiskImage.img", GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, NULL);
|
||||
|
||||
write_pd(hDisk, &newSSD);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user