1
0
mirror of synced 2024-11-24 05:50:11 +01:00

Micekeychip rework; MiceFS

This commit is contained in:
Bottersnike 2023-04-11 02:29:59 +09:00
parent 69cc1ce5b7
commit 358d1880dd
No known key found for this signature in database
43 changed files with 1085 additions and 314 deletions

View File

@ -53,15 +53,8 @@ dist:
@copy /Y "$(BUILD_DIR)/src/micetools/miceboot\TrueCrypt.exe" "$(DIST_DIR)/Execute/TrueCrypt.exe" @copy /Y "$(BUILD_DIR)/src/micetools/miceboot\TrueCrypt.exe" "$(DIST_DIR)/Execute/TrueCrypt.exe"
@copy /Y "$(BUILD_DIR)/src/micetools/miceboot\mxmaster.exe" "$(DIST_DIR)/Execute/S/mxmaster.exe" @copy /Y "$(BUILD_DIR)/src/micetools/miceboot\mxmaster.exe" "$(DIST_DIR)/Execute/S/mxmaster.exe"
# @copy /Y "$(BUILD_DIR)/src/micetools/micepatch\micepatch.exe" "$(DIST_DIR)/util/micepatch.exe" @copy /Y "$(BUILD_DIR)/src/micetools/util\*.exe" "$(DIST_DIR)/util/"
@copy /Y "$(BUILD_DIR)/src/micetools/util\micedump.exe" "$(DIST_DIR)/util/micedump.exe" @copy /Y "$(BUILD_DIR)/src/micetools/util\*.pdb" "$(DIST_DIR)/util/"
@copy /Y "$(BUILD_DIR)/src/micetools/util\micedump.pdb" "$(DIST_DIR)/util/micedump.pdb"
@copy /Y "$(BUILD_DIR)/src/micetools/util\micetinker.exe" "$(DIST_DIR)/util/micetinker.exe"
@copy /Y "$(BUILD_DIR)/src/micetools/util\micemonitor.exe" "$(DIST_DIR)/util/micemonitor.exe"
@copy /Y "$(BUILD_DIR)/src/micetools/util\exio_test.exe" "$(DIST_DIR)/util/exio_test.exe"
@copy /Y "$(BUILD_DIR)/src/micetools/util\dongleDecrypt.exe" "$(DIST_DIR)/util/dongleDecrypt.exe"
@copy /Y "$(BUILD_DIR)/src/micetools/util\testBin.exe" "$(DIST_DIR)/util/testBin.exe"
@copy /Y "$(BUILD_DIR)/src/micetools/util\micegbdisk.exe" "$(DIST_DIR)/util/micegbdisk.exe"
@copy /Y "$(BUILD_DIR)/src/micetools/system_dummy\dummymaster\dummymaster.exe" "$(DIST_DIR)/system_dummy/dummymaster.exe" @copy /Y "$(BUILD_DIR)/src/micetools/system_dummy\dummymaster\dummymaster.exe" "$(DIST_DIR)/system_dummy/dummymaster.exe"
@copy /Y "$(BUILD_DIR)/src/micetools/system_dummy\dummyinstaller\dummyinstaller.exe" "$(DIST_DIR)/system_dummy/dummyinstaller.exe" @copy /Y "$(BUILD_DIR)/src/micetools/system_dummy\dummyinstaller\dummyinstaller.exe" "$(DIST_DIR)/system_dummy/dummyinstaller.exe"

View File

@ -5,6 +5,7 @@
#include <openssl/rand.h> #include <openssl/rand.h>
#include "../../lib/mxk/mxk.h" #include "../../lib/mxk/mxk.h"
#include "../../segastructs.h"
#include "../../sysconf.h" #include "../../sysconf.h"
#include "_devices.h" #include "_devices.h"
@ -50,36 +51,24 @@ typedef struct {
DWORD m_Crc; DWORD m_Crc;
BYTE Rsv04[12]; BYTE Rsv04[12];
char m_KeyId[16]; char m_KeyId[16];
struct { AM_APPBOOT_128 m_Appboot;
DWORD m_Crc;
DWORD m_Format;
char m_GameId[4];
BYTE m_Region;
BYTE m_ModelType;
BYTE m_SystemFlag;
BYTE Rsv0f;
//
char m_PlatformId[3];
BYTE m_DvdFlag;
DWORD m_NetworkAddr;
BYTE Unk00[88];
BYTE m_Seed[16];
} m_Appboot;
} N2_KEYCHIP_INFO, *PN2_KEYCHIP_INFO; } N2_KEYCHIP_INFO, *PN2_KEYCHIP_INFO;
#pragma pack(pop) #pragma pack(pop)
N2_KEYCHIP_INFO n2_keychip_info = { N2_KEYCHIP_INFO n2_keychip_info = {
.m_KeyId = KEY_ID, .m_KeyId = KEY_ID,
.m_Appboot = { .m_Appboot = {
.m_Format = 1, .m_Header = {
.m_GameId = GAME_ID, .m_Format = 1,
.m_Region = 0xff, .m_GameId = GAME_ID,
.m_ModelType = 2, .m_Region = 0xff,
.m_SystemFlag = 0x24, .m_ModelType = 2,
.m_PlatformId = HW_ID, .m_SystemFlag = 0x24,
.m_DvdFlag = 1, .m_PlatformId = HW_ID,
.m_NetworkAddr = .m_DvdFlag = 1,
(192 << 0) | (168 << 8) | (103 << 16) | (0 << 24), .m_NetworkAddr =
(192 << 0) | (168 << 8) | (103 << 16) | (0 << 24),
},
}, },
}; };
@ -134,8 +123,8 @@ WORD n2_read_keychip_id(WORD paramSize, LPBYTE dataIn, LPBYTE dataOut, LPWORD nO
*nOut = (nbytes & 0xff) + 2; *nOut = (nbytes & 0xff) + 2;
n2_keychip_info.m_Appboot.m_Crc = amiCrc32RCalc(sizeof n2_keychip_info.m_Appboot - 4, n2_keychip_info.m_Appboot.m_Header.m_Crc = amiCrc32RCalc(
(LPBYTE)&n2_keychip_info.m_Appboot + 4, 0); sizeof n2_keychip_info.m_Appboot - 4, (LPBYTE)&n2_keychip_info.m_Appboot + 4, 0);
n2_keychip_info.m_Crc = n2_keychip_info.m_Crc =
amiCrc32RCalc(sizeof n2_keychip_info - 4, (LPBYTE)&n2_keychip_info + 4, 0); amiCrc32RCalc(sizeof n2_keychip_info - 4, (LPBYTE)&n2_keychip_info + 4, 0);

View File

@ -95,13 +95,6 @@ void apply_patches(HMODULE hModule) {
void prebind_hooks() { void prebind_hooks() {
hook_all(); hook_all();
install_devices(); install_devices();
// TODO: Figure out why we're needing to call this manually (medium priority)
// if (wcscmp(exeName, L"ALLNetProc.exe") == 0) {
// log_warning(plfBoot, "Making explicit call to OPENSSL_add_all_algorithms_noconf");
// // OPENSSL_add_all_algorithms_noconf
// ((void (*)(void))(0x00459770))();
// }
} }
void init_injection(HMODULE hModule) { void init_injection(HMODULE hModule) {
@ -117,8 +110,45 @@ void init_injection(HMODULE hModule) {
MiceSetLogBasename(exeNameC); MiceSetLogBasename(exeNameC);
log_info(plfBoot, "Handover complete. Now executing within %ls", exeName); log_info(plfBoot, "Handover complete. Now executing within %ls", exeName);
// Start Mice FS
BOOL success = TRUE;
success &= MiceFSInit();
if (success) success &= MiceFSAddRingedgeLayers(FALSE);
if (!success) {
log_error(plfFile, "Failed to initialise Mice FS stack: %d", GetLastError());
exit(1);
}
if (MiceConfig.mice.original && MiceConfig.mice.original[0] == '\0') {
CHAR szCurrentDir[MAX_PATH + 1];
GetCurrentDirectoryA(sizeof szCurrentDir, szCurrentDir);
MiceFSAddLayer(RING_MOUNT_ORIGINAL, szCurrentDir);
MiceFSAddLayer(RING_MOUNT_GAME, szCurrentDir);
} else {
MiceFSAddLayer(RING_MOUNT_ORIGINAL, MiceConfig.mice.original);
MiceFSAddLayer(RING_MOUNT_GAME, MiceConfig.mice.original);
}
if (MiceConfig.mice.patch && MiceConfig.mice.patch[0] != '\0') {
MiceFSAddLayer(RING_MOUNT_PATCH, MiceConfig.mice.patch);
MiceFSAddLayer(RING_MOUNT_GAME, MiceConfig.mice.patch);
}
if (MiceConfig.mice.extend && MiceConfig.mice.extend[0] != '\0') {
MiceFSAddLayer(RING_MOUNT_EXTEND_VOL, MiceConfig.mice.extend);
MiceFSAddLayer(RING_MOUNT_GAME, MiceConfig.mice.extend);
}
if (MiceConfig.mice.extend2 && MiceConfig.mice.extend2[0] != '\0') {
MiceFSAddLayer(RING_MOUNT_EXTEND2_VOL, MiceConfig.mice.extend2);
MiceFSAddLayer(RING_MOUNT_GAME, MiceConfig.mice.extend2);
}
if (success) success &= MiceFSAddDevLayers();
MiceFSSetCwd(RING_MOUNT_GAME);
// Setup default COM devices
init_com_devices(); init_com_devices();
// Apply any in-memory patches requested
if (MiceConfig.mice.apply_patches) apply_patches(hModule); if (MiceConfig.mice.apply_patches) apply_patches(hModule);
// Columba: Driver-level memory access, used to read the DMI tables // Columba: Driver-level memory access, used to read the DMI tables
@ -144,6 +174,21 @@ void init_injection(HMODULE hModule) {
// Must be the last thing called! // Must be the last thing called!
prebind_hooks(); prebind_hooks();
// TODO: Figure out why we're needing to call this manually (medium priority)
if (wcscmp(exeName, L"ALLNetProc.exe") == 0) {
log_warning(plfBoot, "Making explicit call to OPENSSL_add_all_algorithms_noconf");
DWORD imageBase = GetImageBase();
imageOffset = (DWORD)hModule - imageBase;
// OPENSSL_add_all_algorithms_noconf (old exe)
// ((void (*)(void))(0x00459770 + imageOffset))();
// OPENSSL_add_all_algorithms_noconf (new exe)
((void (*)(void))(0x00463480 + imageOffset))();
}
setup_hooks(); setup_hooks();
} }

View File

@ -10,20 +10,22 @@ BYTE parallel_data = 0x00;
BYTE KEYCHIP_ID[16] = KEY_ID; BYTE KEYCHIP_ID[16] = KEY_ID;
BYTE _MAIN_ID[16] = MAIN_ID; BYTE _MAIN_ID[16] = MAIN_ID;
appboot_t APPBOOT = { AM_APPBOOT_256 APPBOOT = {
.format = 1, .m_Header = {
.game_id = GAME_ID, .m_Format = 1,
.region = 8 | 4 | 2 | 1, .m_GameId = GAME_ID,
.model_type = 2, .m_Region = 8 | 4 | 2 | 1,
// Bitfield .m_ModelType = 2,
// 1 = use flash for appboot // Bitfield
.system_flag = 0x24, // 1 = use flash for appboot
._ = 0, .m_SystemFlag = 0x24,
.platform_id = HW_ID, .Rsv0f = 0,
.dvd_flag = 1, .m_PlatformId = HW_ID,
.network_addr = (192 << 0) | (168 << 8) | (103 << 16) | (0 << 24), .m_DvdFlag = 1,
.__ = 0, .m_NetworkAddr = (192 << 0) | (168 << 8) | (103 << 16) | (0 << 24),
.seed = 1, },
.Rsv18 = 0,
.m_Seed = 1,
}; };
billing_t BILLING = { billing_t BILLING = {
.playlimit = 21046, .playlimit = 21046,
@ -46,9 +48,10 @@ uint32_t BILLING_PLAYCOUNT = 69420;
overlappedComplete(len); \ overlappedComplete(len); \
} while (0) } while (0)
BOOL WINAPI mxparallel_DeviceIoControl(file_context_t* ctx, DWORD dwIoControlCode, LPVOID lpInBuffer, BOOL WINAPI mxparallel_DeviceIoControl(file_context_t* ctx, DWORD dwIoControlCode,
DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer,
LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) { DWORD nOutBufferSize, LPDWORD lpBytesReturned,
LPOVERLAPPED lpOverlapped) {
log_trace(plfMxParallel, "DeviceIoControl(<mxparallel>, 0x%08x, 0x%p, 0x%x, -, 0x%x, -, -)", log_trace(plfMxParallel, "DeviceIoControl(<mxparallel>, 0x%08x, 0x%p, 0x%x, -, 0x%x, -, -)",
dwIoControlCode, lpInBuffer, nInBufferSize, nOutBufferSize); dwIoControlCode, lpInBuffer, nInBufferSize, nOutBufferSize);
@ -273,7 +276,8 @@ void mxparallel_process_packet(BYTE* request) {
log_warning(plfMxParallel, "GetAppBootInfo[%d] unexpected!", request[1]); log_warning(plfMxParallel, "GetAppBootInfo[%d] unexpected!", request[1]);
} }
APPBOOT.crc = amiCrc32RCalc(sizeof APPBOOT - 4, (unsigned char*)&APPBOOT + 4, 0); APPBOOT.m_Header.m_Crc =
amiCrc32RCalc(sizeof APPBOOT - 4, (unsigned char*)&APPBOOT + 4, 0);
for (int i = 0; i < sizeof APPBOOT; i += 16) { for (int i = 0; i < sizeof APPBOOT; i += 16) {
micexkSendPacket((unsigned char*)(&APPBOOT) + i); micexkSendPacket((unsigned char*)(&APPBOOT) + i);
} }

View File

@ -23,7 +23,7 @@ void micexkSendPacket(unsigned char* send_data);
void micexkTransportRecv(unsigned char* buffer, int nbytes); void micexkTransportRecv(unsigned char* buffer, int nbytes);
void micexkRecvPacket(unsigned char* packet); void micexkRecvPacket(unsigned char* packet);
static appboot_t APPBOOT; static AM_APPBOOT_256 APPBOOT;
static billing_t BILLING; static billing_t BILLING;
static uint32_t BILLING_PLAYCOUNT; static uint32_t BILLING_PLAYCOUNT;

View File

@ -102,7 +102,10 @@ void mice_got_game_id(char game_id[4]) {
MiceConfig.devices.com7 = ""; MiceConfig.devices.com7 = "";
MiceConfig.devices.com8 = ""; MiceConfig.devices.com8 = "";
} else { } else {
if (game_id[0] != '\0') return log_warning(plfBoot, "Unknown game ID: %.4s", game_id); if (game_id[0] != '\0') {
log_warning(plfBoot, "Unknown game ID: %.4s", game_id);
return;
}
return; return;
} }

View File

@ -126,8 +126,8 @@ physical_disk_t APM_HDD = {
physical_disk_t* PHYSICAL_DISKS[] = { physical_disk_t* PHYSICAL_DISKS[] = {
&SSD, &SSD,
&UPDATE_USB, &UPDATE_USB,
&APM_HDD, // &APM_HDD,
&LOG_USB, // &LOG_USB,
// &ALPHA_DVD, // &ALPHA_DVD,
}; };

View File

@ -474,7 +474,7 @@ void init_volume(disk_volume_t* vol) {
StringFromGUID2(&guid, volume_name + 10, MAX_PATH + 1 - 10); StringFromGUID2(&guid, volume_name + 10, MAX_PATH + 1 - 10);
file_hook_t* volume_hook = new_file_hook(volume_name); file_hook_t* volume_hook = new_file_hook(volume_name);
log_misc(plfDrive, "Creating fake volume: %ls", volume_name); log_misc(plfDrive, "Creating fake volume: %ls (for %s)", volume_name, vol->m_Name);
volume_hook->DeviceIoControl = &volume_DeviceIoControl; volume_hook->DeviceIoControl = &volume_DeviceIoControl;
volume_hook->hook_data = (void*)vol; volume_hook->hook_data = (void*)vol;
@ -702,7 +702,7 @@ void hook_drives() {
q_drive->DeviceIoControl = &q_drive_DeviceIoControl; q_drive->DeviceIoControl = &q_drive_DeviceIoControl;
q_drive->ReadFile = &q_drive_ReadFile; q_drive->ReadFile = &q_drive_ReadFile;
hook_file(q_drive); hook_file(q_drive);
// ewwwwwwwwwwwwwwwwww // TODO: ewwwwwwwwwwwwwwwwww
file_hook_t* q_drive_lower = new_file_hook(L"\\\\.\\q:"); file_hook_t* q_drive_lower = new_file_hook(L"\\\\.\\q:");
q_drive_lower->DeviceIoControl = &q_drive_DeviceIoControl; q_drive_lower->DeviceIoControl = &q_drive_DeviceIoControl;
q_drive_lower->ReadFile = &q_drive_ReadFile; q_drive_lower->ReadFile = &q_drive_ReadFile;

View File

@ -1,7 +1,22 @@
#define _MICE_FILES #define _MICE_FILES
#include "files.h" #include "files.h"
#include "../util/_util.h" #include "../util/_util.h"
// TODO: This should be part of MiceFS I think
file_hook_t* MiceFSLocateHookW(_In_ LPCWSTR lpFileName);
file_hook_t* MiceFSLocateHookW(LPCWSTR lpFileName) {
file_hook_t* file_hook = file_hook_list;
while (file_hook != NULL) {
if (wcscmp(lpFileName, file_hook->filename) == 0 ||
(file_hook->altFilename != NULL && wcscmp(lpFileName, file_hook->altFilename) == 0)) {
return file_hook;
}
file_hook = file_hook->next;
}
return NULL;
}
HANDLE open_hook(file_hook_t* file_hook) { HANDLE open_hook(file_hook_t* file_hook) {
open_hook_t* opened = (open_hook_t*)malloc(sizeof(open_hook_t)); open_hook_t* opened = (open_hook_t*)malloc(sizeof(open_hook_t));
ZeroMemory(opened, sizeof *opened); ZeroMemory(opened, sizeof *opened);
@ -97,78 +112,11 @@ void hook_file_with_buffer(LPCWSTR filename, LPBYTE buffer, DWORD nBytes, DWORD
hook_file(hook); hook_file(hook);
} }
drive_redirect_t DRIVE_REDIRECT_TABLE[] = {
// Note: Had to create last_shime.log
{ .drive = "C:\\Documents and Settings\\AppUser\\temp\\", .path = ".\\dev\\temp\\" },
// {.drive = "C:\\ProgramData/boost_interprocess/", .path = "\\\\.\\ipc\\"},
};
char _redirected_path[MAX_PATH];
file_hook_t* find_hook(LPCWSTR lpFileName) {
file_hook_t* file_hook = file_hook_list;
while (file_hook != NULL) {
if (wcscmp(lpFileName, file_hook->filename) == 0 ||
(file_hook->altFilename != NULL && wcscmp(lpFileName, file_hook->altFilename) == 0)) {
return file_hook;
}
file_hook = file_hook->next;
}
return NULL;
};
BOOL redirect_path(LPCSTR path, LPCSTR* redirected) {
for (int i = 0; i < sizeof DRIVE_REDIRECT_TABLE / sizeof DRIVE_REDIRECT_TABLE[0]; i++) {
drive_redirect_t row = DRIVE_REDIRECT_TABLE[i];
if (PathPrefix(path, row.drive)) {
log_trace(plfHooks, "Redirecting '%s' to '%s'", path, row.path);
size_t new_len = strlen(path) - strlen(row.drive) + strlen(row.path);
strcpy_s(_redirected_path, new_len + 1, row.path);
char* dst = _redirected_path + strlen(row.path);
size_t len = strlen(path) - strlen(row.drive);
const char* src = path + strlen(row.drive);
for (; len > 0; len--) (dst++)[0] = (src++)[0];
dst[0] = 0;
log_trace(plfHooks, "New filename: '%s'", _redirected_path);
make_dirs(_redirected_path);
*redirected = _redirected_path;
return TRUE;
}
}
// Don't redirect local paths
if (IsGamedataLocalPath(path)) return FALSE;
if ((('a' <= path[0] && path[0] <= 'z') || ('A' <= path[0] && path[0] <= 'Z')) &&
path[1] == ':' && (path[2] == '/' || path[2] == '\\')) {
ZeroMemory(_redirected_path, sizeof _redirected_path);
snprintf(_redirected_path, sizeof _redirected_path, "dev\\%c\\%s", char_lower(path[0]),
path + 3);
make_dirs(_redirected_path);
*redirected = _redirected_path;
return TRUE;
}
return FALSE;
}
BOOL redirect_path_w(LPCWSTR lpFileName, LPCSTR* redirected) {
char cFileName[MAX_PATH] = { 0 };
WideCharToMultiByte(CP_ACP, 0, lpFileName, wcslen(lpFileName), cFileName, sizeof cFileName,
NULL, NULL);
return redirect_path(cFileName, redirected);
}
HANDLE WINAPI FakeCreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, HANDLE WINAPI FakeCreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes, LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile) { HANDLE hTemplateFile) {
file_hook_t* found_fh = find_hook(lpFileName); file_hook_t* found_fh = MiceFSLocateHookW(lpFileName);
if (found_fh != NULL) { if (found_fh != NULL) {
HANDLE handle = open_hook(found_fh); HANDLE handle = open_hook(found_fh);
log_info(plfHooks, "CreateFileW(%ls) -> 0x%p", lpFileName, handle); log_info(plfHooks, "CreateFileW(%ls) -> 0x%p", lpFileName, handle);
@ -177,16 +125,10 @@ HANDLE WINAPI FakeCreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD d
HANDLE handle; HANDLE handle;
LPCSTR redirected; MiceFSRedirectPathW(lpFileName, &lpFileName);
if (redirect_path_w(lpFileName, &redirected)) { handle = TrueCreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
handle = TrueCreateFileA(redirected, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); log_misc(plfHooks, "CreateFileW(%ls) -> 0x%p", lpFileName, handle);
log_misc(plfHooks, "CreateFileW(%s) -> 0x%p", redirected, handle);
} else {
handle = TrueCreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
log_misc(plfHooks, "CreateFileW(%ls) -> 0x%p", lpFileName, handle);
}
return handle; return handle;
} }
@ -197,14 +139,14 @@ HANDLE WINAPI FakeCreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dw
WCHAR wideFileName[MAX_PATH + 1]; WCHAR wideFileName[MAX_PATH + 1];
MultiByteToWideChar(CP_ACP, 0, lpFileName, -1, (LPWSTR)&wideFileName, MAX_PATH + 1); MultiByteToWideChar(CP_ACP, 0, lpFileName, -1, (LPWSTR)&wideFileName, MAX_PATH + 1);
file_hook_t* found_fh = find_hook(wideFileName); file_hook_t* found_fh = MiceFSLocateHookW(wideFileName);
if (found_fh != NULL) { if (found_fh != NULL) {
HANDLE handle = open_hook(found_fh); HANDLE handle = open_hook(found_fh);
log_info(plfHooks, "CreateFileA(%s) -> 0x%p", lpFileName, handle); log_info(plfHooks, "CreateFileA(%s) -> 0x%p", lpFileName, handle);
return handle; return handle;
} }
redirect_path(lpFileName, &lpFileName); MiceFSRedirectPathA(lpFileName, &lpFileName);
HANDLE handle = TrueCreateFileA(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, HANDLE handle = TrueCreateFileA(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
log_misc(plfHooks, "CreateFileA(%s) -> 0x%p", lpFileName, handle); log_misc(plfHooks, "CreateFileA(%s) -> 0x%p", lpFileName, handle);
@ -212,32 +154,24 @@ HANDLE WINAPI FakeCreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dw
} }
BOOL WINAPI FakePathFileExistsA(LPCSTR pszPath) { BOOL WINAPI FakePathFileExistsA(LPCSTR pszPath) {
log_misc(plfHooks, "PathFileExists(%s)", pszPath); MiceFSRedirectPathA(pszPath, &pszPath);
redirect_path(pszPath, &pszPath);
BOOL ret = TruePathFileExistsA(pszPath); BOOL ret = TruePathFileExistsA(pszPath);
log_misc(plfHooks, "PathFileExistsA(%s) = %d", pszPath, ret);
return ret; return ret;
} }
BOOL WINAPI FakePathFileExistsW(LPCWSTR pszPath) { BOOL WINAPI FakePathFileExistsW(LPCWSTR pszPath) {
log_misc(plfHooks, "PathFileExists(%ls)", pszPath); MiceFSRedirectPathW(pszPath, &pszPath);
LPCSTR redirected; BOOL ret = TruePathFileExistsW(pszPath);
if (redirect_path_w(pszPath, &redirected)) { log_misc(plfHooks, "PathFileExistsW(%ls) = %d", pszPath, ret);
return TruePathFileExistsA(redirected); return ret;
}
return TruePathFileExistsW(pszPath);
} }
BOOL WINAPI FakeDeleteFileA(LPCSTR pszPath) { BOOL WINAPI FakeDeleteFileA(LPCSTR pszPath) {
LPCSTR redirected; MiceFSRedirectPathA(pszPath, &pszPath);
if (redirect_path(pszPath, &redirected)) {
return TrueDeleteFileA(redirected);
}
return TrueDeleteFileA(pszPath); return TrueDeleteFileA(pszPath);
} }
BOOL WINAPI FakeDeleteFileW(LPCWSTR pszPath) { BOOL WINAPI FakeDeleteFileW(LPCWSTR pszPath) {
LPCSTR redirected; MiceFSRedirectPathW(pszPath, &pszPath);
if (redirect_path_w(pszPath, &redirected)) {
return TrueDeleteFileA(redirected);
}
return TrueDeleteFileW(pszPath); return TrueDeleteFileW(pszPath);
} }
@ -387,38 +321,35 @@ BOOL WINAPI FakeCloseHandle(HANDLE hObject) {
} }
int WINAPIV Fake_stat64i32(const char* path, struct _stat64i32* buffer) { int WINAPIV Fake_stat64i32(const char* path, struct _stat64i32* buffer) {
redirect_path((char*)path, &path); MiceFSRedirectPathA((char*)path, &path);
return True_stat64i32(path, buffer); return True_stat64i32(path, buffer);
}; };
DWORD WINAPI FakeGetFileAttributesA(LPCSTR lpFileName) { DWORD WINAPI FakeGetFileAttributesA(LPCSTR lpFileName) {
// The game quits out if MiniDump is present! // The game quits out if MiniDump is present!
if (PathEqual(lpFileName, "Y:\\MiniDump\\") == 0) { if (PathEqual(lpFileName, "Y:\\MiniDump\\")) {
return 0; return 0;
} }
return (DWORD)-1;
LPCSTR redirected; MiceFSRedirectPathA(lpFileName, &lpFileName);
if (redirect_path(lpFileName, &redirected)) {
return TrueGetFileAttributesA(redirected);
}
return TrueGetFileAttributesA(lpFileName); return TrueGetFileAttributesA(lpFileName);
} }
DWORD WINAPI FakeGetFileAttributesW(LPCWSTR lpFileName) { DWORD WINAPI FakeGetFileAttributesW(LPCWSTR lpFileName) {
LPCSTR redirected; MiceFSRedirectPathW(lpFileName, &lpFileName);
if (redirect_path_w(lpFileName, &redirected)) {
return TrueGetFileAttributesA(redirected);
}
return TrueGetFileAttributesW(lpFileName); return TrueGetFileAttributesW(lpFileName);
} }
HANDLE WINAPI FakeFindFirstFileA(LPCSTR lpFileName, LPWIN32_FIND_DATA lpFindFileData) { HANDLE WINAPI FakeFindFirstFileA(LPCSTR lpFileName, LPWIN32_FIND_DATA lpFindFileData) {
LPCSTR redirected; MiceFSRedirectPathA(lpFileName, &lpFileName);
if (redirect_path(lpFileName, &redirected)) {
return TrueFindFirstFileA(redirected, lpFindFileData);
}
return TrueFindFirstFileA(lpFileName, lpFindFileData); return TrueFindFirstFileA(lpFileName, lpFindFileData);
} }
DWORD WINAPI FakeGetCurrentDirectoryA(DWORD nBufferLength, LPSTR lpBuffer) {
strcpy_s(lpBuffer, nBufferLength, MiceFSGetCwd());
}
DWORD WINAPI FakeGetCurrentDirectoryW(DWORD nBufferLength, LPWSTR lpBuffer) {
MultiByteToWideChar(CP_ACP, 0, MiceFSGetCwd(), -1, lpBuffer, nBufferLength);
}
void hook_io() { void hook_io() {
hook("Kernel32.dll", "DeviceIoControl", FakeDeviceIoControl, (void**)&TrueDeviceIoControl); hook("Kernel32.dll", "DeviceIoControl", FakeDeviceIoControl, (void**)&TrueDeviceIoControl);
@ -436,6 +367,10 @@ void hook_io() {
hook("Shlwapi.dll", "PathFileExistsW", FakePathFileExistsW, (void**)&TruePathFileExistsW); hook("Shlwapi.dll", "PathFileExistsW", FakePathFileExistsW, (void**)&TruePathFileExistsW);
hook("Kernel32.dll", "DeleteFileA", FakeDeleteFileA, (void**)&TrueDeleteFileA); hook("Kernel32.dll", "DeleteFileA", FakeDeleteFileA, (void**)&TrueDeleteFileA);
hook("Kernel32.dll", "DeleteFileW", FakeDeleteFileW, (void**)&TrueDeleteFileW); hook("Kernel32.dll", "DeleteFileW", FakeDeleteFileW, (void**)&TrueDeleteFileW);
hook("Kernel32.dll", "GetCurrentDirectoryA", FakeGetCurrentDirectoryA,
(void**)&TrueGetCurrentDirectoryA);
hook("Kernel32.dll", "GetCurrentDirectoryW", FakeGetCurrentDirectoryW,
(void**)&TrueGetCurrentDirectoryW);
hook("Kernel32.dll", "FindFirstFileA", FakeFindFirstFileA, (void**)&TrueFindFirstFileA); hook("Kernel32.dll", "FindFirstFileA", FakeFindFirstFileA, (void**)&TrueFindFirstFileA);

View File

@ -1,5 +1,4 @@
#pragma once #pragma once
#include "../common.h"
#include "com.h" #include "com.h"
#ifndef _MICE_FILES #ifndef _MICE_FILES
@ -41,6 +40,8 @@ _MICE_FILES BOOL(WINAPI* TrueDeleteFileW)(LPCWSTR lpFileName);
_MICE_FILES HANDLE(WINAPI* TrueFindFirstFileA)(LPCSTR lpFileName, LPWIN32_FIND_DATA lpFindFileData); _MICE_FILES HANDLE(WINAPI* TrueFindFirstFileA)(LPCSTR lpFileName, LPWIN32_FIND_DATA lpFindFileData);
_MICE_FILES DWORD(WINAPI* TrueGetFileAttributesA)(LPCSTR lpFileName); _MICE_FILES DWORD(WINAPI* TrueGetFileAttributesA)(LPCSTR lpFileName);
_MICE_FILES DWORD(WINAPI* TrueGetFileAttributesW)(LPCWSTR lpFileName); _MICE_FILES DWORD(WINAPI* TrueGetFileAttributesW)(LPCWSTR lpFileName);
_MICE_FILES DWORD(WINAPI* TrueGetCurrentDirectoryA)(DWORD nBufferLength, LPSTR lpBuffer);
_MICE_FILES DWORD(WINAPI* TrueGetCurrentDirectoryW)(DWORD nBufferLength, LPWSTR lpBuffer);
typedef struct { typedef struct {
HANDLE m_Handle; HANDLE m_Handle;
@ -75,6 +76,10 @@ static int(WINAPIV* True_stat64i32)(const char* path, _stat64i32_t* buffer);
#define _SetFilePointer (TrueSetFilePointer ? TrueSetFilePointer : SetFilePointer) #define _SetFilePointer (TrueSetFilePointer ? TrueSetFilePointer : SetFilePointer)
#define _SetFilePointerEx (TrueSetFilePointerEx ? TrueSetFilePointerEx : SetFilePointerEx) #define _SetFilePointerEx (TrueSetFilePointerEx ? TrueSetFilePointerEx : SetFilePointerEx)
#define _PathFileExistsA (TruePathFileExistsA ? TruePathFileExistsA : PathFileExistsA) #define _PathFileExistsA (TruePathFileExistsA ? TruePathFileExistsA : PathFileExistsA)
#define _GetCurrentDirectoryA \
(TrueGetCurrentDirectoryA ? TrueGetCurrentDirectoryA : GetCurrentDirectoryA)
#define _GetCurrentDirectoryW \
(TrueGetCurrentDirectoryW ? TrueGetCurrentDirectoryA : GetCurrentDirectoryA)
typedef struct drive_redirect { typedef struct drive_redirect {
const CHAR* drive; const CHAR* drive;

View File

@ -258,6 +258,9 @@ static HRESULT(STDMETHODCALLTYPE* TrueCreateDevice)(IDirect3D9* this, UINT Adapt
DWORD BehaviorFlags, DWORD BehaviorFlags,
D3DPRESENT_PARAMETERS* pPresentationParameters, D3DPRESENT_PARAMETERS* pPresentationParameters,
IDirect3DDevice9** ppReturnedDeviceInterface); IDirect3DDevice9** ppReturnedDeviceInterface);
static HRESULT(STDMETHODCALLTYPE* TrueEnumAdapterModes)(IDirect3D9* this, UINT Adapter,
D3DFORMAT Format, UINT Mode,
D3DDISPLAYMODE* pMode);
extern RECT monitorRect; extern RECT monitorRect;
HRESULT STDMETHODCALLTYPE FakeCreateDevice(IDirect3D9* this, UINT Adapter, D3DDEVTYPE DeviceType, HRESULT STDMETHODCALLTYPE FakeCreateDevice(IDirect3D9* this, UINT Adapter, D3DDEVTYPE DeviceType,
@ -309,6 +312,23 @@ HRESULT STDMETHODCALLTYPE FakeCreateDevice(IDirect3D9* this, UINT Adapter, D3DDE
break; break;
} }
} }
log_info(plfD3D9, "Device created: %d", res);
return res;
}
HRESULT STDMETHODCALLTYPE FakeEnumAdapterModes(IDirect3D9* this, UINT Adapter, D3DFORMAT Format,
UINT Mode, D3DDISPLAYMODE* pMode) {
HRESULT res = TrueEnumAdapterModes(this, Adapter, Format, Mode, pMode);
if (res == S_OK) {
// printf("Found: %dx%d @ %d\n", pMode->Width, pMode->Height, pMode->RefreshRate);
// TODO: Is this going to ever cause issues?
pMode->Width = MiceConfig.window.w;
pMode->Height = MiceConfig.window.h;
pMode->RefreshRate = 60;
}
// printf("Request format: %d/%d. Result: %d\n", Format, Mode, res);
// pMode->Format = Format;
return res; return res;
} }
@ -320,6 +340,10 @@ IDirect3D9* WINAPI FakeDirect3DCreate9(UINT SDKVersion) {
DWORD patch = (DWORD)&FakeCreateDevice; DWORD patch = (DWORD)&FakeCreateDevice;
patch_at(&pD3D->lpVtbl->CreateDevice, (char*)&patch, 4); patch_at(&pD3D->lpVtbl->CreateDevice, (char*)&patch, 4);
TrueEnumAdapterModes = pD3D->lpVtbl->EnumAdapterModes;
patch = (DWORD)&FakeEnumAdapterModes;
patch_at(&pD3D->lpVtbl->EnumAdapterModes, (char*)&patch, 4);
return pD3D; return pD3D;
}; };

View File

@ -5,7 +5,7 @@ int WINAPI Fake_connect(SOCKET s, const SOCKADDR* name, int namelen) {
USHORT port = _byteswap_ushort(((SOCKADDR_IN*)name)->sin_port); USHORT port = _byteswap_ushort(((SOCKADDR_IN*)name)->sin_port);
// Poorly exclude nxauth and mxgcatcher. // Poorly exclude nxauth and mxgcatcher.
// TODO: better // TODO: better
if (port != 40190 && port != 40110) { if (port != 40190 && port != 40110 && port != 40102 && port != 40103) {
log_info(plfNetwork, "connect(%hhu.%hhu.%hhu.%hhu:%hu)", (addr >> 24) & 0xff, log_info(plfNetwork, "connect(%hhu.%hhu.%hhu.%hhu:%hu)", (addr >> 24) & 0xff,
(addr >> 16) & 0xff, (addr >> 8) & 0xff, addr & 0xff, port); (addr >> 16) & 0xff, (addr >> 8) & 0xff, addr & 0xff, port);
} }
@ -26,7 +26,7 @@ int WINAPI Fake_bind(SOCKET s, const SOCKADDR* name, int namelen) {
#define MAC_PREFIX_1 0xBB #define MAC_PREFIX_1 0xBB
#define MAC_PREFIX_2 0xC1 #define MAC_PREFIX_2 0xC1
DWORD WINAPI FakeGetIfTable(PMIB_IFTABLE pIfTable, PULONG pdwSize, BOOL bOrder) { DWORD WINAPI FakeGetIfTable(PMIB_IFTABLE pIfTable, PULONG pdwSize, BOOL bOrder) {
log_info(plfNetwork, "Injecting fake IfTable"); log_misc(plfNetwork, "Injecting fake IfTable");
MIB_IFROW* row; MIB_IFROW* row;
uint32_t nbytes; uint32_t nbytes;

View File

@ -1,17 +1,13 @@
#include "processes.h" #include "processes.h"
const wchar_t* HOOK_BINARIES[] = {
L"app\\ALLNetProc.exe",
L"app\\CameraUploader.exe",
L"app\\GmSync.exe",
};
BOOL WINAPI FakeCreateProcessA(LPCSTR lpApplicationName, LPSTR lpCommandLine, BOOL WINAPI FakeCreateProcessA(LPCSTR lpApplicationName, LPSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles,
DWORD dwCreationFlags, LPVOID lpEnvironment, DWORD dwCreationFlags, LPVOID lpEnvironment,
LPCSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPCSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation) { LPPROCESS_INFORMATION lpProcessInformation) {
// Somewhat janky way to identify when this is a loopback from start_and_inject
// TODO: _CreateProcessA()
if (dwCreationFlags & CREATE_SUSPENDED) { if (dwCreationFlags & CREATE_SUSPENDED) {
return TrueCreateProcessA(lpApplicationName, lpCommandLine, lpProcessAttributes, return TrueCreateProcessA(lpApplicationName, lpCommandLine, lpProcessAttributes,
lpThreadAttributes, bInheritHandles, dwCreationFlags, lpThreadAttributes, bInheritHandles, dwCreationFlags,
@ -19,10 +15,33 @@ BOOL WINAPI FakeCreateProcessA(LPCSTR lpApplicationName, LPSTR lpCommandLine,
lpProcessInformation); lpProcessInformation);
} }
if (strcmp(lpCommandLine, "s:\\mxkeychip.exe") == 0 ||
strcmp(lpCommandLine, "C:\\WINDOWS\\system32\\regini.exe S:\\default_regset.txt") == 0) {
if (lpProcessInformation) {
lpProcessInformation->hProcess = CreateEventA(NULL, FALSE, TRUE, NULL);
lpProcessInformation->hThread = CreateEventA(NULL, FALSE, TRUE, NULL);
}
return TRUE;
}
CHAR szApplicationName[MAX_PATH + 1];
if (lpApplicationName == NULL) {
strcpy_s(szApplicationName, sizeof szApplicationName, lpCommandLine);
for (int i = 0; i < sizeof szApplicationName; i++) {
if (szApplicationName[i] == ' ') {
szApplicationName[i] = '\0';
break;
}
}
lpApplicationName = szApplicationName;
}
MiceFSRedirectPathA(lpApplicationName, &lpApplicationName);
log_info(plfProcesses, "CreateProcessA %s %s", lpApplicationName, lpCommandLine); log_info(plfProcesses, "CreateProcessA %s %s", lpApplicationName, lpCommandLine);
return start_and_inject(INVALID_HANDLE_VALUE, lpApplicationName, lpCommandLine, return start_and_inject(INVALID_HANDLE_VALUE, lpApplicationName, lpCommandLine, MICELIB, FALSE,
MICELIB, FALSE, 0, NULL, 0, lpProcessInformation); 0, NULL, 0, lpProcessInformation);
} }
BOOL WINAPI FakeCreateProcessW(LPCWSTR lpApplicationName, LPWSTR lpCommandLine, BOOL WINAPI FakeCreateProcessW(LPCWSTR lpApplicationName, LPWSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpProcessAttributes,
@ -32,16 +51,40 @@ BOOL WINAPI FakeCreateProcessW(LPCWSTR lpApplicationName, LPWSTR lpCommandLine,
LPPROCESS_INFORMATION lpProcessInformation) { LPPROCESS_INFORMATION lpProcessInformation) {
log_info(plfProcesses, "CreateProcessW %ls %ls", lpApplicationName, lpCommandLine); log_info(plfProcesses, "CreateProcessW %ls %ls", lpApplicationName, lpCommandLine);
CHAR applicationName[MAX_PATH + 1]; if (wcsncmp(lpCommandLine, L"chkdsk.exe", wcslen(L"chkdsk.exe")) == 0) {
WideCharToMultiByte(CP_ACP, 0, lpApplicationName, -1, applicationName, sizeof applicationName, if (lpProcessInformation) {
NULL, NULL); lpProcessInformation->hProcess = CreateEventA(NULL, FALSE, TRUE, NULL);
lpProcessInformation->hThread = CreateEventA(NULL, FALSE, TRUE, NULL);
}
return TRUE;
}
int nMultiChars = WideCharToMultiByte(CP_ACP, 0, lpCommandLine, -1, NULL, 0, NULL, NULL); int nMultiChars = WideCharToMultiByte(CP_ACP, 0, lpCommandLine, -1, NULL, 0, NULL, NULL);
LPSTR commandLine = malloc(nMultiChars); LPSTR commandLine = malloc(nMultiChars);
WideCharToMultiByte(CP_ACP, 0, lpCommandLine, -1, commandLine, nMultiChars, NULL, NULL); WideCharToMultiByte(CP_ACP, 0, lpCommandLine, -1, commandLine, nMultiChars, NULL, NULL);
return start_and_inject(INVALID_HANDLE_VALUE, applicationName, commandLine, MICELIB, CHAR szApplicationName[MAX_PATH + 1];
FALSE, 0, NULL, 0, lpProcessInformation); LPCSTR lpApplicationNameA;
if (lpApplicationName == NULL) {
strcpy_s(szApplicationName, sizeof szApplicationName, commandLine);
for (int i = 0; i < sizeof szApplicationName; i++) {
if (szApplicationName[i] == ' ') {
szApplicationName[i] = '\0';
break;
}
}
lpApplicationNameA = szApplicationName;
} else {
WideCharToMultiByte(CP_ACP, 0, lpApplicationName, -1, szApplicationName,
sizeof szApplicationName, NULL, NULL);
lpApplicationNameA = szApplicationName;
}
MiceFSRedirectPathA(lpApplicationNameA, &lpApplicationNameA);
return start_and_inject(INVALID_HANDLE_VALUE, lpApplicationNameA, commandLine, MICELIB, FALSE,
0, NULL, 0, lpProcessInformation);
} }
BOOL WINAPI FakeGetExitCodeProcess(HANDLE hProcess, LPDWORD lpExitCode) { BOOL WINAPI FakeGetExitCodeProcess(HANDLE hProcess, LPDWORD lpExitCode) {
@ -52,5 +95,5 @@ BOOL WINAPI FakeGetExitCodeProcess(HANDLE hProcess, LPDWORD lpExitCode) {
void hook_processes() { void hook_processes() {
hook("Kernel32.dll", "CreateProcessW", FakeCreateProcessW, (void**)&TrueCreateProcessW); hook("Kernel32.dll", "CreateProcessW", FakeCreateProcessW, (void**)&TrueCreateProcessW);
hook("Kernel32.dll", "CreateProcessA", FakeCreateProcessA, (void**)&TrueCreateProcessA); hook("Kernel32.dll", "CreateProcessA", FakeCreateProcessA, (void**)&TrueCreateProcessA);
// hook("Kernel32.dll", "GetExitCodeProcess", FakeGetExitCodeProcess, NULL); hook("Kernel32.dll", "GetExitCodeProcess", FakeGetExitCodeProcess, NULL);
} }

View File

@ -1,29 +1,34 @@
#include "registry.h" #include "registry.h"
// TODO: Do we want to make a proper registry emulation?
static BOOL bHALDeleted = FALSE;
LSTATUS WINAPI FakeRegCloseKey(HKEY hKey) { LSTATUS WINAPI FakeRegCloseKey(HKEY hKey) {
log_trace(plfRegistry, "RegCloseKey %08x", hKey); log_misc(plfRegistry, "RegCloseKey %08x", hKey);
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
LSTATUS WINAPI FakeRegCreateKeyExA(HKEY hKey, LPCSTR lpSubKey, DWORD Reserved, LPSTR lpClass, LSTATUS WINAPI FakeRegCreateKeyExA(HKEY hKey, LPCSTR lpSubKey, DWORD Reserved, LPSTR lpClass,
DWORD dwOptions, REGSAM samDesired, DWORD dwOptions, REGSAM samDesired,
const LPSECURITY_ATTRIBUTES lpSecurityAttributes, const LPSECURITY_ATTRIBUTES lpSecurityAttributes,
PHKEY phkResult, LPDWORD lpdwDisposition) { PHKEY phkResult, LPDWORD lpdwDisposition) {
log_trace(plfRegistry, "RegCreateKeyExA %08x %s", hKey, lpSubKey); log_misc(plfRegistry, "RegCreateKeyExA %08x %s", hKey, lpSubKey);
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
LSTATUS WINAPI FakeRegDeleteKeyA(HKEY hKey, LPCSTR lpSubKey) { LSTATUS WINAPI FakeRegDeleteKeyA(HKEY hKey, LPCSTR lpSubKey) {
log_trace(plfRegistry, "RegDeleteKeyA %08x %s", hKey, lpSubKey); log_misc(plfRegistry, "RegDeleteKeyA %08x %s", hKey, lpSubKey);
bHALDeleted = TRUE;
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
LSTATUS WINAPI FakeRegDeleteKeyValueA(HKEY hKey, LPCSTR lpSubKey, LPCSTR lpValueName) { LSTATUS WINAPI FakeRegDeleteKeyValueA(HKEY hKey, LPCSTR lpSubKey, LPCSTR lpValueName) {
log_trace(plfRegistry, "RegDeleteKeyValueA %08x %s %s", hKey, lpSubKey, lpValueName); log_misc(plfRegistry, "RegDeleteKeyValueA %08x %s %s", hKey, lpSubKey, lpValueName);
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
LSTATUS WINAPI FakeRegEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpName, LPDWORD lpcchName, LSTATUS WINAPI FakeRegEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpName, LPDWORD lpcchName,
LPDWORD lpReserved, LPSTR lpClass, LPDWORD lpcchClass, LPDWORD lpReserved, LPSTR lpClass, LPDWORD lpcchClass,
PFILETIME lpftLastWriteTime) { PFILETIME lpftLastWriteTime) {
log_trace(plfRegistry, "RegEnumKeyExA %08x[%d]", hKey, dwIndex); log_misc(plfRegistry, "RegEnumKeyExA %08x[%d]", hKey, dwIndex);
if (dwIndex == 0) { if (dwIndex == 0 && !bHALDeleted) {
strcpy(lpName, "Direct3D HAL"); strcpy(lpName, "Direct3D HAL");
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
@ -32,7 +37,7 @@ LSTATUS WINAPI FakeRegEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpName, LPDWORD
LSTATUS WINAPI FakeRegEnumValueA(HKEY hKey, DWORD dwIndex, LPSTR lpValueName, LSTATUS WINAPI FakeRegEnumValueA(HKEY hKey, DWORD dwIndex, LPSTR lpValueName,
LPDWORD lpcchValueName, LPDWORD lpReserved, LPDWORD lpType, LPDWORD lpcchValueName, LPDWORD lpReserved, LPDWORD lpType,
LPBYTE lpData, LPDWORD lpcbData) { LPBYTE lpData, LPDWORD lpcbData) {
log_trace(plfRegistry, "RegEnumValueA %08x %s", hKey, lpValueName); log_misc(plfRegistry, "RegEnumValueA %08x %s", hKey, lpValueName);
return ERROR_NO_MORE_ITEMS; return ERROR_NO_MORE_ITEMS;
} }

View File

@ -49,7 +49,6 @@ BOOL WINAPI Fake_GetLocalTime(SYSTEMTIME* lpSystemTime) {
return TrueGetLocalTime(lpSystemTime); return TrueGetLocalTime(lpSystemTime);
} }
BOOL WINAPI Fake_GetSystemTime(SYSTEMTIME* lpSystemTime) { BOOL WINAPI Fake_GetSystemTime(SYSTEMTIME* lpSystemTime) {
log_trace(plfTime, "GetSystemTime");
if (stCache) { if (stCache) {
memcpy(lpSystemTime, &systemTime, sizeof systemTime); memcpy(lpSystemTime, &systemTime, sizeof systemTime);
return TRUE; return TRUE;

View File

@ -129,7 +129,7 @@ static DWORD WINAPI MiceMailslotWatcher(HANDLE* pSlot) {
} }
if (!inVt100) WriteFile(hLogFile, &(readBuffer[i]), 1, &nWrote, NULL); if (!inVt100) WriteFile(hLogFile, &(readBuffer[i]), 1, &nWrote, NULL);
} }
FlushFileBuffers(hLogFile); // FlushFileBuffers(hLogFile);
} }
} }
} }

View File

@ -4,9 +4,12 @@
#include "../lib/mice/mice.h" #include "../lib/mice/mice.h"
spawn_t mxspawns[3] = { spawn_t mxspawns[3] = {
{ "keychip", SPAWN_DUMMY, MdkThreadProc, MxkThreadProc }, // { "keychip", SPAWN_DUMMY, MdkThreadProc, MxkThreadProc },
{ "master", SPAWN_DUMMY, MdmThreadProc, NULL }, // { "master", SPAWN_DUMMY, MdmThreadProc, NULL },
{ "installer", SPAWN_DUMMY, MdiThreadProc, NULL }, // { "installer", SPAWN_DUMMY, MdiThreadProc, NULL },
{ "keychip", SPAWN_NONE, MdkThreadProc, MxkThreadProc },
{ "master", SPAWN_NONE, MdmThreadProc, NULL },
{ "installer", SPAWN_NONE, MdiThreadProc, NULL },
}; };
int mxkMain(); int mxkMain();

View File

@ -18,6 +18,10 @@ CFG_bool(mice, log_to_file, true, "Also log out to log_file")
CFG_str(mice, log_file, "log.txt", "The file to log to if log_to_file is enabled") CFG_str(mice, log_file, "log.txt", "The file to log to if log_to_file is enabled")
CFG_bool(mice, apply_patches, true, "Load and apply patches from patches_file at runtime") CFG_bool(mice, apply_patches, true, "Load and apply patches from patches_file at runtime")
CFG_str(mice, patches_file, "patches.index", "The file to read patches from") CFG_str(mice, patches_file, "patches.index", "The file to read patches from")
CFG_str(mice, original, "", "Location of the 'original' partition. The current directory is used by default")
CFG_str(mice, patch, "", "Location of the 'patch' partition. No patch is configured by default")
CFG_str(mice, extend, "", "Location of the 'extend' partition. No extend is configured by default")
CFG_str(mice, extend2, "", "Location of the 'extend2' partition. No extend2 is configured by default")
ENDSECTION(mice) ENDSECTION(mice)
SECTION(launcher, "These options are only used during initial bootstrapping") SECTION(launcher, "These options are only used during initial bootstrapping")

View File

@ -0,0 +1,41 @@
#include "kcf.h"
#include <Windows.h>
#include <stdio.h>
inline static void scramble(LPBYTE data, DWORD a, DWORD b, DWORD c, DWORD d) {
BYTE temp;
temp = data[a];
data[a] = data[b];
data[b] = temp;
temp = data[c];
data[c] = data[d];
data[d] = temp;
}
BOOL MiceParseKcf(LPCSTR lpFileName, PAM_KCF pKcf) {
// Load in scrambled data
HANDLE hFile =
CreateFileA(lpFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
return FALSE;
}
DWORD nNumberOfBytesRead;
if (!ReadFile(hFile, pKcf, sizeof *pKcf, &nNumberOfBytesRead, NULL)) {
CloseHandle(hFile);
return FALSE;
}
CloseHandle(hFile);
if (nNumberOfBytesRead != sizeof *pKcf) {
return FALSE;
}
// Unscramble
scramble(pKcf->m_Seed, 1, 8, 12, 15);
scramble(pKcf->m_Key, 0, 4, 2, 14);
scramble(pKcf->m_Iv, 0, 11, 5, 15);
return TRUE;
}

View File

@ -0,0 +1,18 @@
#pragma once
#include <Windows.h>
#include "../../segastructs.h"
#pragma pack(push, 1)
typedef struct _AM_KCF {
AM_APPBOOT m_Header;
BYTE m_AppData[216];
BYTE m_Seed[16];
BYTE m_Key[16];
BYTE m_Iv[16];
BYTE Unk[128];
} AM_KCF, *PAM_KCF;
#pragma pack(pop)
BOOL MiceParseKcf(LPCSTR lpFileName, PAM_KCF pKcf);

View File

@ -6,6 +6,8 @@ mice_lib = static_library(
'patch.c', 'patch.c',
'ringbuf.c', 'ringbuf.c',
'config.c', 'config.c',
'kcf.c',
'micefs.c',
], ],
link_with: [ link_with: [
inih.get_variable('lib_inih'), inih.get_variable('lib_inih'),

View File

@ -8,7 +8,9 @@
#include "config.h" #include "config.h"
#include "exe.h" #include "exe.h"
#include "ioctl.h" #include "ioctl.h"
#include "kcf.h"
#include "log.h" #include "log.h"
#include "micefs.h"
#include "patch.h" #include "patch.h"
#include "ringbuf.h" #include "ringbuf.h"
#include "version_fallback.h" #include "version_fallback.h"

View File

@ -0,0 +1,323 @@
#include "micefs.h"
#pragma comment(lib, "Shlwapi.lib")
#include <shlwapi.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// TODO: This is awful
extern BOOL(WINAPI* TruePathFileExistsA)(LPCSTR pszPath);
#define _PathFileExistsA (TruePathFileExistsA ? TruePathFileExistsA : PathFileExistsA)
static char miceFSCwd[MAX_PATH + 1];
/* Filesystem layer storage. When locating files, the first found result will be used. New items are
* inserted at the start of the list. */
static MICE_FS_LAYER miceFsRoot = {
.m_lpMountPoint = NULL,
.m_lpTargetPath = NULL,
.m_Next = NULL,
};
static volatile LONG miceFsLockCount = 0;
#define MiceTakeLockExclusive(lock) \
do { \
LONG __miceLockCount = (lock); \
if (__miceLockCount == 0) { \
if (InterlockedCompareExchange(&(lock), -1, 0) == 0) break; \
} \
SwitchToThread(); \
} while (1)
#define MiceReleaseLockExclusive(lock) \
do { \
(lock) = 0; \
} while (0)
#define MiceTakeLockShared(lock) \
do { \
LONG __miceLockCount = (lock); \
if (__miceLockCount != -1) { \
if (InterlockedCompareExchange(&(lock), __miceLockCount + 1, __miceLockCount) == \
__miceLockCount) \
break; \
} \
SwitchToThread(); \
} while (1)
#define MiceReleaseLockShared(lock) \
do { \
(lock)--; \
} while (0)
BOOL MiceFSInit(VOID) {
// By not using MiceFSSetCwd we can save a buffer allocation
GetCurrentDirectoryA(sizeof miceFSCwd, miceFSCwd);
return TRUE;
}
LPCSTR MiceFSGetCwd(VOID) { return miceFSCwd; }
VOID MiceFSSetCwd(LPCSTR lpNewCwd) { strcpy_s(miceFSCwd, sizeof miceFSCwd, lpNewCwd); }
BOOL MiceFSAddLayer(LPCSTR lpMountPoint, LPCSTR lpTargetPath) {
DWORD dwMountLength = strlen(lpMountPoint) + 1;
DWORD dwTargetlength = strlen(lpTargetPath) + 1;
if (dwMountLength <= 1 || dwTargetlength <= 1) {
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
PMICE_FS_LAYER layer = malloc(sizeof *layer);
if (layer == NULL) return FALSE;
LPSTR szMountPoint = malloc(MAX_PATH + 1);
if (szMountPoint == NULL) {
free(layer);
return FALSE;
}
LPSTR szTargetPath = malloc(MAX_PATH + 1);
if (szTargetPath == NULL) {
free(szMountPoint);
free(layer);
return FALSE;
}
ZeroMemory(szMountPoint, MAX_PATH + 1);
if (!GetFullPathNameA(lpMountPoint, MAX_PATH + 1, szMountPoint, NULL)) {
free(szTargetPath);
free(szMountPoint);
free(layer);
return FALSE;
}
ZeroMemory(szTargetPath, MAX_PATH + 1);
if (!GetFullPathNameA(lpTargetPath, MAX_PATH + 1, szTargetPath, NULL)) {
free(szTargetPath);
free(szMountPoint);
free(layer);
return FALSE;
}
// Mount and target are promoted to LPCSTR from LPSTR here
layer->m_lpMountPoint = szMountPoint;
layer->m_lpTargetPath = szTargetPath;
// Commit ourselves to the FS
MiceTakeLockExclusive(miceFsLockCount);
layer->m_Next = miceFsRoot.m_Next;
miceFsRoot.m_Next = layer;
MiceReleaseLockExclusive(miceFsLockCount);
SetLastError(ERROR_SUCCESS);
return TRUE;
}
BOOL MiceFSAddDevLayers(VOID) {
CHAR szMountPoint[4];
CHAR szTargetPath[MAX_PATH + 1];
ZeroMemory(szTargetPath, sizeof szTargetPath);
strcpy_s(szTargetPath, sizeof szTargetPath, ".\\dev\\x\\");
BOOL success = TRUE;
for (int i = 0; i < 26; i++) {
szMountPoint[0] = 'A' + (char)i;
szMountPoint[1] = ':';
szMountPoint[2] = '\\';
szMountPoint[3] = '\0';
szTargetPath[6] = 'a' + (char)i;
success &= MiceFSAddLayer(szMountPoint, szTargetPath);
}
return success;
}
BOOL MiceFSAddRingedgeLayers(BOOL bIsOsupdate) {
BOOL success = TRUE;
// Windows file systems
success &= MiceFSAddLayer(RING_MOUNT_OS, "mount/os");
success &= MiceFSAddLayer(RING_MOUNT_EXTEND, "mount/extend");
success &= MiceFSAddLayer(RING_MOUNT_RECOVERY, "mount/os_recovery");
// TrueCrypt Volumes
success &= MiceFSAddLayer(RING_MOUNT_SYSTEM, "mount/system");
success &= MiceFSAddLayer(RING_MOUNT_ORIGINAL, "mount/original");
success &= MiceFSAddLayer(RING_MOUNT_PATCH, "mount/patch");
if (bIsOsupdate) {
success &= MiceFSAddLayer(RING_MOUNT_OS_UPDATE, "mount/os_update");
success &= MiceFSAddLayer(RING_MOUNT_OS_DEFAULT_DRVIERS, "mount/os_default_drivers");
} else {
success &= MiceFSAddLayer(RING_MOUNT_EXTEND_VOL, "mount/extend/extend");
success &= MiceFSAddLayer(RING_MOUNT_EXTEND2_VOL, "mount/extend/extend2");
}
// geminifs
success &= MiceFSAddLayer(RING_MOUNT_GAME, "mount/original");
success &= MiceFSAddLayer(RING_MOUNT_GAME, "mount/patch");
// External media
success &= MiceFSAddLayer(RING_MOUNT_APM, "mount/apm");
success &= MiceFSAddLayer(RING_MOUNT_AM_LOG, "mount/am_log");
success &= MiceFSAddLayer(RING_MOUNT_DVD, "mount/dvd");
success &= MiceFSAddLayer(RING_MOUNT_DEV, "mount/dev");
// TODO: Configurable!
MiceFSAddLayer("R:", "H:\\Arcades\\USBs\\FiNALE_DL\\usb");
MiceFSAddLayer("S:", "C:\\Users\\Nathan\\Desktop\\ac_research\\sega\\S-Drive");
MiceFSAddLayer("C:\\System\\Execute", "C:\\Users\\Nathan\\Desktop\\ac_research\\sega\\S-Drive");
return success;
}
LPSTR MiceFSPathTokA(LPSTR lpPath, DWORD dwPath, PMICE_FS_PATH_TOK lpWork) {
DWORD dwWorkPtr = 0;
LPSTR lpPathStart;
if (lpPath != NULL) {
// A zero-length string has no tokens (as oppoed to a single empty token)
if (lpPath[0] == '\0') {
SetLastError(ERROR_SUCCESS);
return NULL;
}
lpWork->m_lpPath = lpPath;
lpPathStart = lpPath;
lpWork->m_dwWorkPtr = dwWorkPtr;
lpWork->m_dwPath = dwPath;
} else {
// We just finished processing the last token!
if (lpWork->m_cSave == '\0') {
SetLastError(ERROR_SUCCESS);
return NULL;
}
dwWorkPtr = lpWork->m_dwWorkPtr;
lpPath = lpWork->m_lpPath;
lpPath[dwWorkPtr++] = lpWork->m_cSave;
lpPathStart = lpPath + dwWorkPtr;
}
DWORD dwComponentStart = dwWorkPtr;
for (; dwWorkPtr < lpWork->m_dwPath; dwWorkPtr++) {
CHAR cWork = lpPath[dwWorkPtr];
if (cWork == '\0' || cWork == '\\' || cWork == '/') {
// Omit 0-length components, with the exception of the very first position in the
// string, as that would indicate a double-backslash prefix, which is syntax for a path
// namespace and should not be treated the same as a single backslash there.
if (dwWorkPtr == dwComponentStart && dwWorkPtr != 0) {
// Special case: Trailing slashes
if (cWork == '\0') {
SetLastError(ERROR_SUCCESS);
return NULL;
}
dwComponentStart++;
continue;
}
lpWork->m_dwComponentStart = dwComponentStart;
lpWork->m_dwWorkPtr = dwWorkPtr;
lpWork->m_cSave = cWork;
lpPath[dwWorkPtr] = '\0';
return lpPathStart;
}
}
// Will only occur if lpPath was not null terminated within dwPath bytes. lpPathStart at this
// point does not point to a null-terminated string, and therefore we cannot return it.
// This is technically an error condition, so allow diligent users to catch this
SetLastError(ERROR_BUFFER_OVERFLOW);
return NULL;
}
VOID MiceFSPathTokRestA(PMICE_FS_PATH_TOK lpWork, LPSTR lpPath, DWORD dwPath) {
lpWork->m_lpPath[lpWork->m_dwWorkPtr] = lpWork->m_cSave;
memcpy_s(lpPath, dwPath, lpWork->m_lpPath + lpWork->m_dwComponentStart,
lpWork->m_dwPath - lpWork->m_dwComponentStart);
}
BOOL MiceFSMatchPathA(LPCSTR lpPath, LPCSTR lpPrefix, LPSTR lpTail, DWORD dwTail) {
CHAR szPath[MAX_PATH + 1];
CHAR szPrefix[MAX_PATH + 1];
strcpy_s(szPath, sizeof szPath, lpPath);
strcpy_s(szPrefix, sizeof szPrefix, lpPrefix);
MICE_FS_PATH_TOK pathTok;
MICE_FS_PATH_TOK matchTok;
LPSTR pathComponent = MiceFSPathTokA(szPath, _countof(szPath), &pathTok);
LPSTR prefixComponent = MiceFSPathTokA(szPrefix, _countof(szPrefix), &matchTok);
while (pathComponent && prefixComponent) {
if (lstrcmpiA(pathComponent, prefixComponent) != 0) return FALSE;
pathComponent = MiceFSPathTokNextA(&pathTok);
prefixComponent = MiceFSPathTokNextA(&matchTok);
}
// We still had parts of the prefic left!
if (prefixComponent) return FALSE;
if (lpTail && dwTail) {
if (pathComponent)
MiceFSPathTokRestA(&pathTok, lpTail, dwTail);
else
lpTail[0] = '\0';
}
return TRUE;
}
inline static DWORD MiceFSGetFullPathNameA(LPCSTR lpFileName, DWORD nBufferLength, LPSTR lpBuffer,
LPSTR* lpFilePart) {
if (PathIsRelativeA(lpFileName)) {
CHAR newPath[MAX_PATH + 1];
PathCombineA(newPath, miceFSCwd, lpFileName);
return GetFullPathNameA(newPath, nBufferLength, lpBuffer, lpFilePart);
}
return GetFullPathNameA(lpFileName, nBufferLength, lpBuffer, lpFilePart);
}
// TODO: Ewwwwwwww why are these globals (it's a bodge to not need free)
static char _redirected_path[MAX_PATH + 1];
static wchar_t _redirected_path_w[MAX_PATH + 1];
BOOL MiceFSRedirectPathA(LPCSTR lpFilename, LPCSTR* pszRedirected) {
CHAR szExpanded[MAX_PATH + 1];
if (!MiceFSGetFullPathNameA(lpFilename, sizeof szExpanded, szExpanded, NULL)) return FALSE;
MiceTakeLockShared(miceFsLockCount);
PMICE_FS_LAYER layer = miceFsRoot.m_Next;
CHAR szTail[MAX_PATH + 1];
BOOL bFound = FALSE;
while (layer) {
if (MiceFSMatchPathA(szExpanded, layer->m_lpMountPoint, szTail, sizeof szTail)) {
_redirected_path[0] = '\0';
PathCombineA(_redirected_path, layer->m_lpTargetPath, szTail);
*pszRedirected = _redirected_path;
if (_PathFileExistsA(_redirected_path)) {
MiceReleaseLockShared(miceFsLockCount);
return TRUE;
}
bFound = TRUE;
}
layer = layer->m_Next;
}
MiceReleaseLockShared(miceFsLockCount);
return bFound;
}
// TODO: This is kinda awful, because we do two roundtrips through string conversion...
BOOL MiceFSRedirectPathW(LPCWSTR lpFileName, LPCWSTR* pszRedirected) {
char szFileName[MAX_PATH] = { 0 };
WideCharToMultiByte(CP_ACP, 0, lpFileName, wcslen(lpFileName), szFileName, sizeof szFileName,
NULL, NULL);
LPCSTR szRedirected;
BOOL bRedirected = MiceFSRedirectPathA(szFileName, &szRedirected);
if (!bRedirected) return FALSE;
MultiByteToWideChar(CP_ACP, 0, szRedirected, -1, _redirected_path_w, sizeof _redirected_path_w);
*pszRedirected = _redirected_path_w;
return bRedirected;
}

View File

@ -0,0 +1,155 @@
#pragma once
#include <Windows.h>
#define RING_MOUNT_OS "C:"
#define RING_MOUNT_EXTEND "Y:"
#define RING_MOUNT_RECOVERY "Z:"
#define RING_MOUNT_SYSTEM "S:"
#define RING_MOUNT_ORIGINAL "O:"
#define RING_MOUNT_PATCH "P:"
#define RING_MOUNT_OS_UPDATE "W:"
#define RING_MOUNT_OS_DEFAULT_DRVIERS "V:"
#define RING_MOUNT_EXTEND_VOL "W:"
#define RING_MOUNT_EXTEND2_VOL "V:"
#define RING_MOUNT_GAME "X:"
#define RING_MOUNT_APM "I:"
#define RING_MOUNT_AM_LOG "L:"
#define RING_MOUNT_DVD "Q:"
#define RING_MOUNT_DEV "Z:"
typedef enum {
MICE_FS_NS_WIN32,
MICE_FS_NS_DEVICE,
} MICE_FS_NAMESPACE;
typedef struct MICE_FS_PATH MICE_FS_PATH, *PMICE_FS_PATH;
struct MICE_FS_PATH {
MICE_FS_NAMESPACE m_dwNamespace;
LPCSTR m_lpComponents;
};
typedef struct MICE_FS_LAYER MICE_FS_LAYER, *PMICE_FS_LAYER;
struct MICE_FS_LAYER {
LPCSTR m_lpMountPoint;
LPCSTR m_lpTargetPath;
PMICE_FS_LAYER m_Next;
};
typedef struct {
LPSTR m_lpPath;
DWORD m_dwPath;
DWORD m_dwComponentStart;
DWORD m_dwWorkPtr;
CHAR m_cSave;
} MICE_FS_PATH_TOK, *PMICE_FS_PATH_TOK;
/**
* @brief Initialise the Mice filesystem emulation stack
*/
BOOL MiceFSInit(VOID);
/**
* @brief Get the currently emulated CWD
*/
LPCSTR MiceFSGetCwd(VOID);
/**
* @brief Set the currently emulated CWD
*
* @param lpNewCwd New CWD
*/
VOID MiceFSSetCwd(LPCSTR lpNewCwd);
/**
* @brief Add a new layer to the emulation stack
* Layers added later will be used preferentially.
*
* @param lpMountPoint Virtual path to mount this layer at
* @param lpTargetPath Real location that will serve files for this layer
* @return BOOL Success. Use GetLastError to identify the cause of failiure.
*/
BOOL MiceFSAddLayer(_In_z_ LPCSTR lpMountPoint, _In_z_ LPCSTR lpTargetPath);
/**
* @brief Add layers for all drive letters backed by ".\dev\[letter]"
* If used, this should be the first set of layers added, to act as a fallback
*
* @return BOOL Success. As this function adds 26 layers, and failiure could occur at any time,
* failiure of this function should be considered a fatal failiure and MiceFS should be considered
* to be in an indeterminate state.
*/
BOOL MiceFSAddDevLayers(VOID);
/**
* @brief Add layers for all RingEdge system partitions.
*
* @return BOOL Success. See MiceFSAddDevLayers rearding when this is FALSE.
*/
BOOL MiceFSAddRingedgeLayers(BOOL bIsOsupdate);
/**
* @brief Tokenise a path, returning each individual token (think, strtok)
*
* The first call to this function should provide lpPath and dwPath to initialise the operation.
* Subsequence calls should provide NULL and 0 respectively. The "MiceFSPathTokNextA" macro aids in
* this.
*
* Empty strings are defined as having no components, and as such NULL will be returned on the first
* call.
*
* Multiple slashes in a row will be combined, rather than returning an empty component.
*
* Special handling is applied for paths starting with slashes. The first component returned will be
* a 0-length string. This is the only time this function returns 0-length strings. The second
* component will contain all but the first slash.
* That is, \\.\demo will return "", "\.", "demo", NULL. Tihis is done to allow handling of path
* namespaces.
*
* @param lpPath Path to split. This buffer will be modified!
* @param dwPath Length of lpPath including the null termination
* @param lpWork Pointer to a work structure to identify this path operation
* @return LPSTR The path component, or NULL when the operation is completed.
*/
LPSTR MiceFSPathTokA(_In_reads_opt_z_(dwPath) LPSTR lpPath, _In_ DWORD dwPath,
_In_ PMICE_FS_PATH_TOK lpWork);
#define MiceFSPathTokNextA(lpWork) MiceFSPathTokA(NULL, 0, lpWork)
/**
* @brief Return the full path in a tokenising buffer, starting with the current component
*
* @param lpWork Work buffer
* @param lpPath Destination buffer
* @param dwPath Size of lpPath
*/
VOID MiceFSPathTokRestA(_In_ PMICE_FS_PATH_TOK lpWork, _Out_writes_z_(dwPath) LPSTR lpPath,
_In_ DWORD dwPath);
/**
* @brief Attempt to a path against a prefix
*
* @param lpPath The path to test
* @param lpPrefix The prefix to match against
* @param lpTail (Optional) Received the tail of lpPath after lpPrefix
* @param dwTail Size of lptail
*/
BOOL MiceFSMatchPathA(_In_z_ LPCSTR lpPath, _In_z_ LPCSTR lpPrefix,
_Out_writes_z_(dwTail) LPSTR lpTail, _In_ DWORD dwTail);
/**
* @brief Redirect a virtual path to a real path using Mice FS layers.
*
* The first layer to match with an existing file on disk will be selected.
*
* If redirection does not occur, the value of pszRedirected is unchanged.
*
* It is safe to (lpFilename, &lpFilename) as an argument pair.
*
* @param lpFileName Virtual filename
* @param pszRedirected Redirected real filename
* @return BOOL If redirection occured
*/
BOOL MiceFSRedirectPathA(_In_z_ LPCSTR lpFileName, _Out_ LPCSTR* pszRedirected);
/**
* @brief Wide variant of MiceFSRedirectPathA
*/
BOOL MiceFSRedirectPathW(_In_z_ LPCWSTR lpFileName, _Out_ LPCWSTR* pszRedirected);

View File

@ -199,7 +199,7 @@ MXK_STATUS mxkGetKeychipIdFromN2(void) {
amiCrc32RInit(); amiCrc32RInit();
uint32_t crcCalc = amiCrc32RCalc((sizeof kcId.m_AppBoot) - 4, (LPBYTE)&kcId.m_AppBoot + 4, 0); uint32_t crcCalc = amiCrc32RCalc((sizeof kcId.m_AppBoot) - 4, (LPBYTE)&kcId.m_AppBoot + 4, 0);
if (crcCalc != kcId.m_AppBoot.m_Crc) { if (crcCalc != kcId.m_AppBoot.m_Header.m_Crc) {
amiDebugLog("Error AppBootInfo CRC!!!"); amiDebugLog("Error AppBootInfo CRC!!!");
return MXK_STATUS_ERROR; return MXK_STATUS_ERROR;
} }
@ -213,16 +213,16 @@ MXK_STATUS mxkGetKeychipIdFromN2(void) {
// N2 keychip ID is a smaller, more compact, format than normal appboot. Restructure it to match // N2 keychip ID is a smaller, more compact, format than normal appboot. Restructure it to match
// before committing it to memory! // before committing it to memory!
unsigned char keyId[16]; unsigned char keyId[16];
appboot_t appboot; AM_APPBOOT_256 appboot;
memcpy_s(keyId, sizeof keyId, kcId.m_KeyId, sizeof kcId.m_KeyId); memcpy_s(keyId, sizeof keyId, kcId.m_KeyId, sizeof kcId.m_KeyId);
memcpy_s(&appboot, sizeof appboot, &kcId.m_AppBoot, memcpy_s(&appboot, sizeof appboot, &kcId.m_AppBoot,
sizeof kcId.m_AppBoot - sizeof kcId.m_AppBoot.m_Seed); sizeof kcId.m_AppBoot - sizeof kcId.m_AppBoot.m_Seed);
memcpy_s(appboot.seed, sizeof appboot.seed, kcId.m_AppBoot.m_Seed, memcpy_s(appboot.m_Seed, sizeof appboot.m_Seed, kcId.m_AppBoot.m_Seed,
sizeof kcId.m_AppBoot.m_Seed); sizeof kcId.m_AppBoot.m_Seed);
printf("Got N2 key ID: %.16s\n", keyId); printf("Got N2 key ID: %.16s\n", keyId);
printf("Got N2 game ID: %.4s\n", kcId.m_AppBoot.m_GameId); printf("Got N2 game ID: %.4s\n", kcId.m_AppBoot.m_Header.m_GameId);
// ...but we're not actually committing it to memory at the moment! // ...but we're not actually committing it to memory at the moment!
// memcpy_s(&APPBOOT, 256, &appboot, sizeof appboot); // memcpy_s(&APPBOOT, 256, &appboot, sizeof appboot);

View File

@ -20,7 +20,7 @@ MXK_STATUS mxkGetAppBootInfo(void) {
return status; return status;
} }
appboot_t appBoot; AM_APPBOOT_256 appBoot;
for (int i = 0; i < sizeof appBoot; i += 16) { for (int i = 0; i < sizeof appBoot; i += 16) {
status = mxkRecvPacket((unsigned char*)(&appBoot) + i); status = mxkRecvPacket((unsigned char*)(&appBoot) + i);
if (status != MXK_STATUS_OK) { if (status != MXK_STATUS_OK) {
@ -30,7 +30,8 @@ MXK_STATUS mxkGetAppBootInfo(void) {
} }
amiCrc32RInit(); amiCrc32RInit();
if (amiCrc32RCalc(sizeof appBoot - 4, (unsigned char*)&appBoot + 4, 0) != appBoot.crc) { if (amiCrc32RCalc(sizeof appBoot - 4, (unsigned char*)&appBoot + 4, 0) !=
appBoot.m_Header.m_Crc) {
amiDebugLog("Error CRC AppBootInfo"); amiDebugLog("Error CRC AppBootInfo");
return MXK_STATUS_ERROR; return MXK_STATUS_ERROR;
} }
@ -75,11 +76,11 @@ MXK_STATUS mxkAbSystemFlag(MXK_CACHE cache, unsigned char* systemFlag, unsigned
if (status == MXK_STATUS_OK) { if (status == MXK_STATUS_OK) {
LAB_00401d7b: LAB_00401d7b:
if (AppBoot.m_Cache.format != 1) { if (AppBoot.m_Cache.m_Header.m_Format != 1) {
*systemFlag = 0; *systemFlag = 0;
return MXK_STATUS_OK; return MXK_STATUS_OK;
} }
*systemFlag = AppBoot.m_Cache.system_flag; *systemFlag = AppBoot.m_Cache.m_Header.m_SystemFlag;
return MXK_STATUS_OK; return MXK_STATUS_OK;
} }
@ -127,18 +128,18 @@ MXK_STATUS mxkAbGameId(MXK_CACHE cache, char* gameId, unsigned char* err) {
if (status == MXK_STATUS_OK) { if (status == MXK_STATUS_OK) {
LAB_00401c7f: LAB_00401c7f:
if (AppBoot.m_Cache.format != 1) { if (AppBoot.m_Cache.m_Header.m_Format != 1) {
gameId[0] = '_'; gameId[0] = '_';
gameId[1] = '_'; gameId[1] = '_';
gameId[2] = '_'; gameId[2] = '_';
gameId[3] = '_'; gameId[3] = '_';
return MXK_STATUS_OK; return MXK_STATUS_OK;
} }
if (!mxkValidString(AppBoot.m_Cache.game_id, 4)) { if (!mxkValidString(AppBoot.m_Cache.m_Header.m_GameId, 4)) {
*err = 55; *err = 55;
return MXK_STATUS_ERROR; return MXK_STATUS_ERROR;
} }
memcpy(gameId, AppBoot.m_Cache.game_id, 4); memcpy(gameId, AppBoot.m_Cache.m_Header.m_GameId, 4);
return MXK_STATUS_OK; return MXK_STATUS_OK;
} }
LAB_00401c6a: LAB_00401c6a:

View File

@ -2,30 +2,14 @@
#include <Windows.h> #include <Windows.h>
#include <stdbool.h> #include <stdbool.h>
#include "../../segastructs.h"
#include "../ami/ami.h" #include "../ami/ami.h"
#include "mxkDefs.h" #include "mxkDefs.h"
#pragma pack(push, 1)
typedef struct {
DWORD crc;
DWORD format;
char game_id[4];
BYTE region;
BYTE model_type;
BYTE system_flag;
BYTE _;
char platform_id[3];
BYTE dvd_flag;
DWORD network_addr;
BYTE __[216];
BYTE seed[16];
} appboot_t;
#pragma pack(pop)
typedef struct { typedef struct {
bool m_useFlash; bool m_useFlash;
bool m_cacheDirty; bool m_cacheDirty;
appboot_t m_Cache; AM_APPBOOT_256 m_Cache;
} APP_BOOT; } APP_BOOT;
extern APP_BOOT AppBoot; extern APP_BOOT AppBoot;

View File

@ -185,7 +185,7 @@ MXK_STATUS mxkCryptDecryptAes128CBC(const unsigned char* key, const unsigned cha
int outl; int outl;
EVP_DecryptUpdate(ctx, pt, &outl, ct, nbytes); EVP_DecryptUpdate(ctx, pt, &outl, ct, nbytes);
unsigned char dump[16]; unsigned char dump[16];
EVP_EncryptFinal_ex(ctx, dump, &outl); EVP_DecryptFinal_ex(ctx, dump, &outl);
EVP_CIPHER_CTX_free(ctx); EVP_CIPHER_CTX_free(ctx);
return MXK_STATUS_OK; return MXK_STATUS_OK;

View File

@ -53,6 +53,26 @@ typedef struct {
} N2DeviceInfo_t; } N2DeviceInfo_t;
N2DeviceInfo_t N2DeviceInfo; N2DeviceInfo_t N2DeviceInfo;
/**
* Device keys for:
*
* RingEdge:
* Key: 76ec42b6ae0cb048105171ad8cb2fb07
* IV: 8e300ba42e154baf651532f570041f5b
* Auth: 96ed31b2287105a5a330540f25bed851a5c83621
*
* ELEFUN:
* Key: 519aaa25b5ed20b53d28bb56731d7c8d
* IV: 40a1bfc5341340d3dfdbd1a12b855700
* Auth: 998e952b6a4899ba42d1d0e8a4fdc87775e19c26
*
* Nu:
* Key: c21c966cbd8b00b9cf4c51bab2c3dfa5
* IV: 0b137aab20acc7eea0bbec594957dc6d
* Auth: 74935ef7e0181c0661f7bb7118c5512a130a5d19
*/
// Auth = 96ed31b2287105a5a330540f25bed851a5c83621
unsigned char N2_KEY_HMAC[2][20] = { unsigned char N2_KEY_HMAC[2][20] = {
{ 0x2c, 0xf8, 0x3e, 0x5e, 0x51, 0xf0, 0x60, 0x1b, 0xf6, 0xb1, { 0x2c, 0xf8, 0x3e, 0x5e, 0x51, 0xf0, 0x60, 0x1b, 0xf6, 0xb1,
0x49, 0x11, 0x3a, 0xaf, 0x36, 0xe1, 0x51, 0x1c, 0x16, 0x05 }, 0x49, 0x11, 0x3a, 0xaf, 0x36, 0xe1, 0x51, 0x1c, 0x16, 0x05 },
@ -60,6 +80,8 @@ unsigned char N2_KEY_HMAC[2][20] = {
0x1d, 0x1e, 0x1f, 0x11, 0xee, 0xb0, 0xf4, 0xd4, 0x20, 0x24 } 0x1d, 0x1e, 0x1f, 0x11, 0xee, 0xb0, 0xf4, 0xd4, 0x20, 0x24 }
}; };
// Key = 76ec42b6ae0cb048105171ad8cb2fb07
// IV = 8e300ba42e154baf651532f570041f5b
AESKey_t N2_KEY_AES[2] = { AESKey_t N2_KEY_AES[2] = {
{ { 0xd7, 0xf6, 0x86, 0xfb, 0x63, 0x44, 0xff, 0xa5, 0x60, 0x9d, 0x4e, 0xf0, 0x18, 0xe9, 0x45, { { 0xd7, 0xf6, 0x86, 0xfb, 0x63, 0x44, 0xff, 0xa5, 0x60, 0x9d, 0x4e, 0xf0, 0x18, 0xe9, 0x45,
0xb4 }, 0xb4 },

View File

@ -4,26 +4,14 @@
#include <varargs.h> #include <varargs.h>
#include "mxkCrypt.h" #include "mxkCrypt.h"
#include "../../segastructs.h"
#pragma pack(push, 1) #pragma pack(push, 1)
typedef struct { typedef struct {
uint32_t m_Crc; uint32_t m_Crc;
uint8_t m_Unk04[12]; uint8_t m_Unk04[12];
uint8_t m_KeyId[16]; uint8_t m_KeyId[16];
struct { AM_APPBOOT_128 m_AppBoot;
uint32_t m_Crc;
uint32_t m_FormatType;
uint8_t m_GameId[4];
uint8_t m_Region;
uint8_t m_ModelType;
uint8_t m_SystemFlags;
uint8_t Rsv0f;
uint8_t m_PlatformId[3];
uint8_t m_DvdFlag;
uint8_t m_NetworkAddr[4];
uint8_t Unk10[88];
uint8_t m_Seed[16];
} m_AppBoot;
} N2KeychipId_t; } N2KeychipId_t;
#pragma pack(pop) #pragma pack(pop)

View File

@ -1,77 +1,92 @@
#include "../config.h"
#include "../lib/libpcp/libpcp.h" #include "../lib/libpcp/libpcp.h"
#include "callbacks.h" #include "callbacks.h"
void mxkPcpAbGameId(pcpa_t* stream, void* data) { pcpaSetSendPacket(stream, AB_GAMEID, Config.appboot_gameid); } void mxkPcpAbGameId(pcpa_t* stream, void* data) {
char gameId[5];
memcpy_s(gameId, 5, mxkKcfConfig.m_Header.m_GameId, 4);
gameId[4] = '\0';
pcpaSetSendPacket(stream, AB_GAMEID, gameId);
}
void mxkPcpAbSystemFlag(pcpa_t* stream, void* data) { void mxkPcpAbSystemFlag(pcpa_t* stream, void* data) {
char sf[3]; char sf[3];
snprintf(sf, 3, "%02X", Config.appboot_systemflag); sprintf_s(sf, 3, "%02X", mxkKcfConfig.m_Header.m_SystemFlag);
pcpaSetSendPacket(stream, AB_SYSTEMFLAG, sf); pcpaSetSendPacket(stream, AB_SYSTEMFLAG, sf);
} }
void mxkPcpAbModelType(pcpa_t* stream, void* data) { void mxkPcpAbModelType(pcpa_t* stream, void* data) {
char mt[3]; char mt[3];
snprintf(mt, 3, "%02X", Config.appboot_modeltype); sprintf_s(mt, 3, "%02X", mxkKcfConfig.m_Header.m_ModelType);
pcpaSetSendPacket(stream, AB_MODELTYPE, mt); pcpaSetSendPacket(stream, AB_MODELTYPE, mt);
} }
void mxkPcpAbFormatType(pcpa_t* stream, void* data) { void mxkPcpAbFormatType(pcpa_t* stream, void* data) {
char ft[3]; char ft[3];
snprintf(ft, 3, "%02X", Config.appboot_formattype); sprintf_s(ft, 3, "%02X", mxkKcfConfig.m_Header.m_Format);
pcpaSetSendPacket(stream, AB_FORMATTYPE, ft); pcpaSetSendPacket(stream, AB_FORMATTYPE, ft);
} }
void mxkPcpAbRegion(pcpa_t* stream, void* data) { void mxkPcpAbRegion(pcpa_t* stream, void* data) {
char rg[3]; char rg[3];
snprintf(rg, 3, "%02X", Config.appboot_region); sprintf_s(rg, 3, "%02X", mxkKcfConfig.m_Header.m_Region);
pcpaSetSendPacket(stream, AB_REGION, rg); pcpaSetSendPacket(stream, AB_REGION, rg);
} }
void mxkPcpAbPlatformId(pcpa_t* stream, void* data) { void mxkPcpAbPlatformId(pcpa_t* stream, void* data) {
pcpaSetSendPacket(stream, AB_PLATFORMID, Config.appboot_platformid); char platformId[4];
memcpy_s(platformId, 4, mxkKcfConfig.m_Header.m_PlatformId, 3);
platformId[3] = '\0';
pcpaSetSendPacket(stream, AB_PLATFORMID, platformId);
} }
void mxkPcpAbNetworkAddress(pcpa_t* stream, void* data) { void mxkPcpAbNetworkAddress(pcpa_t* stream, void* data) {
pcpaSetSendPacket(stream, AB_NETWORKADDRESS, Config.appboot_network); char networkAddr[16];
sprintf_s(networkAddr, sizeof networkAddr, "%d.%d.%d.%d",
(mxkKcfConfig.m_Header.m_NetworkAddr >> 0) & 0xff,
(mxkKcfConfig.m_Header.m_NetworkAddr >> 8) & 0xff,
(mxkKcfConfig.m_Header.m_NetworkAddr >> 16) & 0xff,
(mxkKcfConfig.m_Header.m_NetworkAddr >> 24) & 0xff);
pcpaSetSendPacket(stream, AB_NETWORKADDRESS, networkAddr);
} }
void mxkPcpAbDvd(pcpa_t* stream, void* data) { void mxkPcpAbDvd(pcpa_t* stream, void* data) {
char dvd[3]; char dvd[3];
snprintf(dvd, 3, "%02X", Config.appboot_dvdflag); sprintf_s(dvd, 3, "%02X", mxkKcfConfig.m_Header.m_DvdFlag);
pcpaSetSendPacket(stream, AB_DVD, dvd); pcpaSetSendPacket(stream, AB_DVD, dvd);
} }
#define SEED_BUF_MAX 1024 // #define SEED_BUF_MAX 1024
byte SEED_BUF[SEED_BUF_MAX]; // byte SEED_BUF[SEED_BUF_MAX];
int SEED_BUF_LEN = 0; // int SEED_BUF_LEN = 0;
void mxkPcpAbSeed(pcpa_t* stream, void* data) { void mxkPcpAbSeed(pcpa_t* stream, void* data) {
if (SEED_BUF_LEN == 0) { // if (SEED_BUF_LEN == 0) {
FILE* fCert; // FILE* fCert;
fopen_s(&fCert, Config.appboot_seed, "r"); // fopen_s(&fCert, Config.appboot_seed, "r");
if (fCert == NULL) // if (fCert == NULL)
SEED_BUF_LEN = -1; // SEED_BUF_LEN = -1;
else { // else {
fseek(fCert, 0, SEEK_END); // fseek(fCert, 0, SEEK_END);
SEED_BUF_LEN = ftell(fCert); // SEED_BUF_LEN = ftell(fCert);
if (SEED_BUF_LEN > SEED_BUF_MAX) SEED_BUF_LEN = SEED_BUF_MAX; // if (SEED_BUF_LEN > SEED_BUF_MAX) SEED_BUF_LEN = SEED_BUF_MAX;
rewind(fCert); // rewind(fCert);
fread(SEED_BUF, SEED_BUF_LEN, 1, fCert); // fread(SEED_BUF, SEED_BUF_LEN, 1, fCert);
fclose(fCert); // fclose(fCert);
} // }
} // }
if (SEED_BUF_LEN == -1) { // if (SEED_BUF_LEN == -1) {
// TODO: Fix this maybe? // // TODO: Fix this maybe?
pcpaSetBinaryMode(stream, binary_mode_none); // pcpaSetBinaryMode(stream, binary_mode_none);
pcpaSetSendPacket(stream, AB_SEED, "-1"); // pcpaSetSendPacket(stream, AB_SEED, "-1");
return; // return;
} // }
pcpaSetBinaryMode(stream, binary_mode_send); pcpaSetBinaryMode(stream, binary_mode_send);
pcpaSetBeforeBinaryModeCallBackFunc(stream, mxkBinaryCallback, NULL); pcpaSetBeforeBinaryModeCallBackFunc(stream, mxkBinaryCallback, NULL);
BINARY_DATA_LEN = SEED_BUF_LEN; BINARY_DATA_LEN = sizeof mxkKcfConfig.m_Seed;
memcpy(BINARY_DATA, SEED_BUF, SEED_BUF_LEN); memcpy(BINARY_DATA, mxkKcfConfig.m_Seed, sizeof mxkKcfConfig.m_Seed);
pcpaSetRecvBinaryBuffer(stream, BINARY_DATA, BINARY_DATA_LEN); pcpaSetRecvBinaryBuffer(stream, BINARY_DATA, BINARY_DATA_LEN);
pcpaSetSendPacket(stream, AB_SEED, "0"); pcpaSetSendPacket(stream, AB_SEED, "0");
pcpaAddSendPacket(stream, "port", "40107"); pcpaAddSendPacket(stream, "port", "40107");
char sSize[16]; // todo: nicer lol
_itoa_s(SEED_BUF_LEN, sSize, sizeof sSize, 10); char sSize[16];
sprintf_s(sSize, sizeof sSize, "%d", sizeof mxkKcfConfig.m_Seed);
pcpaAddSendPacket(stream, "size", sSize); pcpaAddSendPacket(stream, "size", sSize);
} }

View File

@ -2,8 +2,12 @@
#include "../lib/libpcp/libpcp.h" #include "../lib/libpcp/libpcp.h"
#include "callbacks.h" #include "callbacks.h"
void mxkPcpPbKeyId(pcpa_t* stream, void* data) { pcpaSetSendPacket(stream, BIL_KEYID, Config.billing_keyid); } void mxkPcpPbKeyId(pcpa_t* stream, void* data) {
void mxkPcpPbMainId(pcpa_t* stream, void* data) { pcpaSetSendPacket(stream, BIL_MAINID, Config.billing_mainid); } pcpaSetSendPacket(stream, BIL_KEYID, Config.billing_keyid);
}
void mxkPcpPbMainId(pcpa_t* stream, void* data) {
pcpaSetSendPacket(stream, BIL_MAINID, Config.billing_mainid);
}
void mxkPcpPbPlayCount(pcpa_t* stream, void* data) { void mxkPcpPbPlayCount(pcpa_t* stream, void* data) {
char pc[9]; char pc[9];
snprintf(pc, sizeof pc, "%08X", Config.billing_playcount); snprintf(pc, sizeof pc, "%08X", Config.billing_playcount);

View File

@ -1,4 +1,10 @@
#include "../lib/libpcp/libpcp.h" #include "../lib/libpcp/libpcp.h"
#include "../lib/mice/kcf.h"
#define N2_VERSION 0x0106
#define PIC_VERSION 0x0104
extern AM_KCF mxkKcfConfig;
pcpa_callback mxkBinaryCallback; pcpa_callback mxkBinaryCallback;
extern byte BINARY_DATA[4096]; extern byte BINARY_DATA[4096];

View File

@ -1,12 +1,73 @@
#include <openssl/evp.h>
#include <openssl/pem.h>
#include "../../lib/util/hex.h"
#include "callbacks.h" #include "callbacks.h"
void mxkPcpDsCompute(pcpa_t* stream, void* data) { pcpaSetSendPacket(stream, "code", "54"); } void mxkPcpDsCompute(pcpa_t* stream, void* data) { pcpaSetSendPacket(stream, "code", "54"); }
void mxkPcpSsdProof(pcpa_t* stream, void* data) { pcpaSetSendPacket(stream, "code", "54"); } void mxkPcpSsdProof(pcpa_t* stream, void* data) { pcpaSetSendPacket(stream, "code", "54"); }
void mxkPcpSsdHostProof(pcpa_t* stream, void* data) {} void mxkPcpSsdHostProof(pcpa_t* stream, void* data) {}
EVP_CIPHER_CTX* ctxEnc = NULL;
EVP_CIPHER_CTX* ctxDec = NULL;
void mxkPcpEncrypt(pcpa_t* stream, void* data) { void mxkPcpEncrypt(pcpa_t* stream, void* data) {
pcpaSetSendPacket(stream, KC_ENCRYPT, "B6787E941C3956EAC70095D6A91E635C"); char* ptHex = pcpaGetCommand(stream, KC_ENCRYPT);
unsigned char pt[16];
memset(pt, 0, sizeof(pt));
hex_to_bin(ptHex, pt, strlen(ptHex) > 32 ? 32 : strlen(ptHex));
if (ctxEnc == NULL) {
ctxEnc = EVP_CIPHER_CTX_new();
EVP_CipherInit_ex(ctxEnc, EVP_aes_128_cbc(), NULL, mxkKcfConfig.m_Key, mxkKcfConfig.m_Iv,
1);
}
int outl;
unsigned char ct[16];
memset(ct, 0, sizeof(ct));
EVP_EncryptUpdate(ctxEnc, ct, &outl, pt, 16);
char ctHex[33];
bin_to_hex(ctHex, ct, 16);
pcpaSetSendPacket(stream, KC_ENCRYPT, ctHex);
} }
unsigned char workingIv[16];
void mxkPcpDecrypt(pcpa_t* stream, void* data) { void mxkPcpDecrypt(pcpa_t* stream, void* data) {
pcpaSetSendPacket(stream, KC_DECRYPT, "68271898FB92ABFB49321FAF72F04FF1"); char* ctHex = pcpaGetCommand(stream, KC_DECRYPT);
unsigned char ct[16];
memset(ct, 0, sizeof(ct));
hex_to_bin(ctHex, ct, strlen(ctHex) > 32 ? 32 : strlen(ctHex));
if (ctxDec == NULL) {
ctxDec = EVP_CIPHER_CTX_new();
memcpy(workingIv, mxkKcfConfig.m_Iv, 16);
} else {
EVP_CIPHER_CTX_cleanup(ctxDec);
}
EVP_CipherInit_ex(ctxDec, EVP_aes_128_cbc(), NULL, mxkKcfConfig.m_Key, workingIv, 0);
memcpy(workingIv, ct, 16);
int outl = 0;
unsigned char pt[16];
memset(pt, 0, sizeof(pt));
EVP_DecryptUpdate(ctxDec, pt, &outl, ct, 16);
char ptHex[33];
bin_to_hex(ptHex, pt, 16);
pcpaSetSendPacket(stream, KC_DECRYPT, ptHex);
}
void mxkPcpSetIv(pcpa_t* stream, void* data) {
if (ctxEnc != NULL) {
EVP_CIPHER_CTX_cleanup(ctxEnc);
} else {
ctxEnc = EVP_CIPHER_CTX_new();
}
EVP_CipherInit_ex(ctxEnc, EVP_aes_128_cbc(), NULL, mxkKcfConfig.m_Key, mxkKcfConfig.m_Iv, 1);
memcpy(workingIv, mxkKcfConfig.m_Iv, 16);
pcpaSetSendPacket(stream, KC_SETIV, "1");
} }
void mxkPcpSetIv(pcpa_t* stream, void* data) { pcpaSetSendPacket(stream, KC_SETIV, "1"); }

View File

@ -1,4 +1,3 @@
#include "../config.h"
#include "callbacks.h" #include "callbacks.h"
void mxkPcpVersion(pcpa_t* stream, void* data) { void mxkPcpVersion(pcpa_t* stream, void* data) {
@ -9,12 +8,12 @@ void mxkPcpVersion(pcpa_t* stream, void* data) {
char version[5]; char version[5];
if (sDevice && strcmp(sDevice, "n2") == 0) if (sDevice && strcmp(sDevice, "n2") == 0)
snprintf(version, 5, "%04X", Config.keychip_dongle_version); snprintf(version, 5, "%04X", N2_VERSION);
else else
snprintf(version, 5, "%04X", Config.keychip_pic_version); snprintf(version, 5, "%04X", PIC_VERSION);
pcpaSetSendPacket(stream, KC_VERSION, version); pcpaSetSendPacket(stream, KC_VERSION, version);
} }
void mxkPcpStatus(pcpa_t* stream, void* data) { void mxkPcpStatus(pcpa_t* stream, void* data) {
pcpaSetSendPacket(stream, KC_STATUS, Config.keychip_status); pcpaSetSendPacket(stream, KC_STATUS, "available");
} }

View File

@ -7,27 +7,14 @@
HEADER("The main config file for micekeychip") HEADER("The main config file for micekeychip")
SECTION(config, "")
CFG_str(config, kcf_path, "", "Path to a KCF file for appboot config")
SECTION(pcp, "") SECTION(pcp, "")
CFG_int(pcp, control_port, 40106, "The port to bind for control") CFG_int(pcp, control_port, 40106, "The port to bind for control")
CFG_int(pcp, binary_port, 40107, "The port to bind for binary transfer") CFG_int(pcp, binary_port, 40107, "The port to bind for binary transfer")
CFG_bool(pcp, bind_global, false, "Should we bind to 0.0.0.0 instead of 127.0.0.1") CFG_bool(pcp, bind_global, false, "Should we bind to 0.0.0.0 instead of 127.0.0.1")
SECTION(keychip, "")
CFG_hex(keychip, pic_version, 4, 0104, "The version to report for the pic")
CFG_hex(keychip, dongle_version, 4, 0104, "The version to report for the dongle")
CFG_str(keychip, status, "available", "Status to report")
SECTION(appboot, "")
CFG_str(appboot, gameid, "SDEY", "4-letter game ID this keychip is for")
CFG_hex(appboot, systemflag, 2, 6C, "System flags")
CFG_int(appboot, modeltype, 2, "System model this keychip is for")
CFG_int(appboot, formattype, 1, "")
CFG_int(appboot, region, 1, "Region bitmask\n; 8 4 2 1\n; CN EX US JP")
CFG_str(appboot, platformid, "AAS", "The platform this keychip is for. AAM=AMD, AAS=Nvidia")
CFG_str(appboot, network, "192.168.103.0", "The subnet this keychip allows for networking. Must be 192.168.103.0 for network checks to pass")
CFG_int(appboot, dvdflag, 1, "")
CFG_str(appboot, seed, "C:\\system\\device\\seed.bin", "Path to constant appboot.seed (indev)")
SECTION(crypto, "") SECTION(crypto, "")
CFG_bool(crypto, ds_enable, false, "Process keychip.ds.compute?") CFG_bool(crypto, ds_enable, false, "Process keychip.ds.compute?")
CFG_bool(crypto, ssd_enable, false, "Process keychip.ssd.proof?") CFG_bool(crypto, ssd_enable, false, "Process keychip.ssd.proof?")

View File

@ -1,5 +1,5 @@
dependencies = [] dependencies = [openssl_lib]
link_with = [inih.get_variable('lib_inih'), libpcp] link_with = [inih.get_variable('lib_inih'), libpcp, mice_lib]
rc = import('windows').compile_resources('micekeychip.rc', depend_files: micekeychip_ico) rc = import('windows').compile_resources('micekeychip.rc', depend_files: micekeychip_ico)
@ -18,6 +18,10 @@ mxk = static_library(
'mxk', 'mxk',
sources: sources, sources: sources,
link_with: link_with, link_with: link_with,
dependencies: dependencies,
include_directories: [
openssl_inc,
],
) )
executable( executable(
'micekeychip', 'micekeychip',
@ -25,4 +29,7 @@ executable(
sources: sources + ['main.c'], sources: sources + ['main.c'],
link_with: link_with, link_with: link_with,
dependencies: dependencies, dependencies: dependencies,
include_directories: [
openssl_inc,
],
) )

View File

@ -1,5 +1,7 @@
#include "mxk.h" #include "mxk.h"
AM_KCF mxkKcfConfig;
byte SERVER_STATE = 0; byte SERVER_STATE = 0;
pcpa_t PCP; pcpa_t PCP;
pcpa_cb_table_t CALLBACK_FUNCTION_BUFFER[40]; pcpa_cb_table_t CALLBACK_FUNCTION_BUFFER[40];
@ -162,6 +164,11 @@ e_pcpa_t mxkPcpServer() {
return err; return err;
} }
static LPCSTR kcfSearchPaths[] = {
"S:\\config.kcf",
"C:\\system\\device\\config.kcf",
};
int mxkMain(void) { int mxkMain(void) {
DWORD dwAttrib = GetFileAttributes(CONFIG_PATH); DWORD dwAttrib = GetFileAttributes(CONFIG_PATH);
if (dwAttrib == INVALID_FILE_ATTRIBUTES || (dwAttrib & FILE_ATTRIBUTE_DIRECTORY)) if (dwAttrib == INVALID_FILE_ATTRIBUTES || (dwAttrib & FILE_ATTRIBUTE_DIRECTORY))
@ -169,6 +176,27 @@ int mxkMain(void) {
mxkLoadConfig(); mxkLoadConfig();
ZeroMemory(&mxkKcfConfig, sizeof mxkKcfConfig);
BOOL kcfLoaded = false;
if (Config.config_kcf_path && Config.config_kcf_path[0]) {
kcfLoaded = MiceParseKcf(Config.config_kcf_path, &mxkKcfConfig);
}
if (!kcfLoaded) {
for (int i = 0; i < _countof(kcfSearchPaths); i++) {
kcfLoaded = MiceParseKcf(kcfSearchPaths[i], &mxkKcfConfig);
if (kcfLoaded) break;
}
}
if (!kcfLoaded) {
amiDebugLog("Failed to parse kcf!");
} else {
amiDebugLog("Loaded KCF for:");
amiDebugLog("Game ID : %.4s", mxkKcfConfig.m_Header.m_GameId);
amiDebugLog("Platform : %.3s", mxkKcfConfig.m_Header.m_PlatformId);
amiDebugLog("System Fag : %02x", mxkKcfConfig.m_Header.m_SystemFlag);
}
int err = mxkInit(); int err = mxkInit();
if (err != 0) { if (err != 0) {
amiDebugLog("Error mxkInit. Code %d", err); amiDebugLog("Error mxkInit. Code %d", err);

View File

@ -2,9 +2,12 @@
#include "../../../subprojects/inih_dep/ini.h" #include "../../../subprojects/inih_dep/ini.h"
#include "../lib/libpcp/libpcp.h" #include "../lib/libpcp/libpcp.h"
#include "../lib/mice/kcf.h"
#include "callbacks/callbacks.h" #include "callbacks/callbacks.h"
#include "config.h" #include "config.h"
extern AM_KCF mxkKcfConfig;
void mxkBinaryCallback(pcpa_t* stream, void* data); void mxkBinaryCallback(pcpa_t* stream, void* data);
int mxkInit(); int mxkInit();
e_pcpa_t mxkPcpStreamInit(); e_pcpa_t mxkPcpStreamInit();

View File

@ -0,0 +1,30 @@
#pragma once
#include <stdint.h>
#pragma pack(push, 1)
typedef struct _AM_APPBOOT {
uint32_t m_Crc;
uint32_t m_Format;
char m_GameId[4];
uint8_t m_Region;
uint8_t m_ModelType;
uint8_t m_SystemFlag;
uint8_t Rsv0f;
char m_PlatformId[3];
uint8_t m_DvdFlag;
uint32_t m_NetworkAddr;
} AM_APPBOOT;
typedef struct _AM_APPBOOT_128 {
AM_APPBOOT m_Header;
uint8_t Rsv18[88];
uint8_t m_Seed[16];
} AM_APPBOOT_128;
typedef struct _AM_APPBOOT_256 {
AM_APPBOOT m_Header;
uint8_t Rsv18[216];
uint8_t m_Seed[16];
} AM_APPBOOT_256;
#pragma pack(pop)

View File

@ -81,3 +81,14 @@ executable(
amiDebug, amiDebug,
], ],
) )
executable(
'micefs_test',
win_subsystem: subsystem,
sources: [
'micefs_test.c',
],
link_with: [
mice_lib,
],
)

View File

@ -289,7 +289,7 @@ BOOL dump_keychip() {
printf("Keychip ID:\t%.16s\n", KEYCHIP_ID); printf("Keychip ID:\t%.16s\n", KEYCHIP_ID);
} }
appboot_t appboot; AM_APPBOOT_256 appboot;
if (!mxkGetAppBootInfo(mxparallel, &appboot)) { if (!mxkGetAppBootInfo(mxparallel, &appboot)) {
puts("Failed to request appboot info!"); puts("Failed to request appboot info!");
} else { } else {

View File

@ -0,0 +1,32 @@
#include <stdio.h>
#include "../lib/mice/mice.h"
// TODO: Ewww
BOOL(WINAPI* TruePathFileExistsA)(LPCSTR pszPath) = PathFileExistsA;
int main() {
MiceFSInit();
// MiceFSAddDevLayers();
// MiceFSAddRingedgeLayers(FALSE);
CHAR path[MAX_PATH + 1];
strcpy_s(path, sizeof path, "X:\\Systemconfig.txt");
MICE_FS_PATH_TOK pathTok;
LPSTR pathComponent = MiceFSPathTokA(path, _countof(path), &pathTok);
while (pathComponent) {
printf("Component : '%s'\n", pathComponent);
pathComponent = MiceFSPathTokNextA(&pathTok);
}
// CHAR tail[MAX_PATH + 1];
// printf("Test 1: %d\n", MiceFSMatchPathA("C:\\windows\\system32\\etc\\help.exe", "C:\\WINDOWS", tail, sizeof(tail)));
// printf("Tail: %s\n", tail);
// LPSTR redirected = NULL;
// MiceFSRedirectPathA("X:\\game.bat", &redirected);
// printf("Redirected path: %s\n", redirected);
}