Micekeychip rework; MiceFS
This commit is contained in:
parent
69cc1ce5b7
commit
358d1880dd
11
Makefile
11
Makefile
@ -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\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\micedump.exe" "$(DIST_DIR)/util/micedump.exe"
|
||||
@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/util\*.exe" "$(DIST_DIR)/util/"
|
||||
@copy /Y "$(BUILD_DIR)/src/micetools/util\*.pdb" "$(DIST_DIR)/util/"
|
||||
|
||||
@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"
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <openssl/rand.h>
|
||||
|
||||
#include "../../lib/mxk/mxk.h"
|
||||
#include "../../segastructs.h"
|
||||
#include "../../sysconf.h"
|
||||
#include "_devices.h"
|
||||
|
||||
@ -50,36 +51,24 @@ typedef struct {
|
||||
DWORD m_Crc;
|
||||
BYTE Rsv04[12];
|
||||
char m_KeyId[16];
|
||||
struct {
|
||||
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;
|
||||
AM_APPBOOT_128 m_Appboot;
|
||||
} N2_KEYCHIP_INFO, *PN2_KEYCHIP_INFO;
|
||||
#pragma pack(pop)
|
||||
|
||||
N2_KEYCHIP_INFO n2_keychip_info = {
|
||||
.m_KeyId = KEY_ID,
|
||||
.m_Appboot = {
|
||||
.m_Format = 1,
|
||||
.m_GameId = GAME_ID,
|
||||
.m_Region = 0xff,
|
||||
.m_ModelType = 2,
|
||||
.m_SystemFlag = 0x24,
|
||||
.m_PlatformId = HW_ID,
|
||||
.m_DvdFlag = 1,
|
||||
.m_NetworkAddr =
|
||||
(192 << 0) | (168 << 8) | (103 << 16) | (0 << 24),
|
||||
.m_Header = {
|
||||
.m_Format = 1,
|
||||
.m_GameId = GAME_ID,
|
||||
.m_Region = 0xff,
|
||||
.m_ModelType = 2,
|
||||
.m_SystemFlag = 0x24,
|
||||
.m_PlatformId = HW_ID,
|
||||
.m_DvdFlag = 1,
|
||||
.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;
|
||||
|
||||
n2_keychip_info.m_Appboot.m_Crc = amiCrc32RCalc(sizeof n2_keychip_info.m_Appboot - 4,
|
||||
(LPBYTE)&n2_keychip_info.m_Appboot + 4, 0);
|
||||
n2_keychip_info.m_Appboot.m_Header.m_Crc = amiCrc32RCalc(
|
||||
sizeof n2_keychip_info.m_Appboot - 4, (LPBYTE)&n2_keychip_info.m_Appboot + 4, 0);
|
||||
n2_keychip_info.m_Crc =
|
||||
amiCrc32RCalc(sizeof n2_keychip_info - 4, (LPBYTE)&n2_keychip_info + 4, 0);
|
||||
|
||||
|
@ -95,13 +95,6 @@ void apply_patches(HMODULE hModule) {
|
||||
void prebind_hooks() {
|
||||
hook_all();
|
||||
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) {
|
||||
@ -117,8 +110,45 @@ void init_injection(HMODULE hModule) {
|
||||
MiceSetLogBasename(exeNameC);
|
||||
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();
|
||||
|
||||
// Apply any in-memory patches requested
|
||||
if (MiceConfig.mice.apply_patches) apply_patches(hModule);
|
||||
|
||||
// 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!
|
||||
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();
|
||||
}
|
||||
|
||||
|
@ -10,20 +10,22 @@ BYTE parallel_data = 0x00;
|
||||
BYTE KEYCHIP_ID[16] = KEY_ID;
|
||||
BYTE _MAIN_ID[16] = MAIN_ID;
|
||||
|
||||
appboot_t APPBOOT = {
|
||||
.format = 1,
|
||||
.game_id = GAME_ID,
|
||||
.region = 8 | 4 | 2 | 1,
|
||||
.model_type = 2,
|
||||
// Bitfield
|
||||
// 1 = use flash for appboot
|
||||
.system_flag = 0x24,
|
||||
._ = 0,
|
||||
.platform_id = HW_ID,
|
||||
.dvd_flag = 1,
|
||||
.network_addr = (192 << 0) | (168 << 8) | (103 << 16) | (0 << 24),
|
||||
.__ = 0,
|
||||
.seed = 1,
|
||||
AM_APPBOOT_256 APPBOOT = {
|
||||
.m_Header = {
|
||||
.m_Format = 1,
|
||||
.m_GameId = GAME_ID,
|
||||
.m_Region = 8 | 4 | 2 | 1,
|
||||
.m_ModelType = 2,
|
||||
// Bitfield
|
||||
// 1 = use flash for appboot
|
||||
.m_SystemFlag = 0x24,
|
||||
.Rsv0f = 0,
|
||||
.m_PlatformId = HW_ID,
|
||||
.m_DvdFlag = 1,
|
||||
.m_NetworkAddr = (192 << 0) | (168 << 8) | (103 << 16) | (0 << 24),
|
||||
},
|
||||
.Rsv18 = 0,
|
||||
.m_Seed = 1,
|
||||
};
|
||||
billing_t BILLING = {
|
||||
.playlimit = 21046,
|
||||
@ -46,9 +48,10 @@ uint32_t BILLING_PLAYCOUNT = 69420;
|
||||
overlappedComplete(len); \
|
||||
} while (0)
|
||||
|
||||
BOOL WINAPI mxparallel_DeviceIoControl(file_context_t* ctx, DWORD dwIoControlCode, LPVOID lpInBuffer,
|
||||
DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize,
|
||||
LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) {
|
||||
BOOL WINAPI mxparallel_DeviceIoControl(file_context_t* ctx, DWORD dwIoControlCode,
|
||||
LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer,
|
||||
DWORD nOutBufferSize, LPDWORD lpBytesReturned,
|
||||
LPOVERLAPPED lpOverlapped) {
|
||||
log_trace(plfMxParallel, "DeviceIoControl(<mxparallel>, 0x%08x, 0x%p, 0x%x, -, 0x%x, -, -)",
|
||||
dwIoControlCode, lpInBuffer, nInBufferSize, nOutBufferSize);
|
||||
|
||||
@ -273,7 +276,8 @@ void mxparallel_process_packet(BYTE* request) {
|
||||
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) {
|
||||
micexkSendPacket((unsigned char*)(&APPBOOT) + i);
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ void micexkSendPacket(unsigned char* send_data);
|
||||
void micexkTransportRecv(unsigned char* buffer, int nbytes);
|
||||
void micexkRecvPacket(unsigned char* packet);
|
||||
|
||||
static appboot_t APPBOOT;
|
||||
static AM_APPBOOT_256 APPBOOT;
|
||||
static billing_t BILLING;
|
||||
static uint32_t BILLING_PLAYCOUNT;
|
||||
|
||||
|
@ -102,7 +102,10 @@ void mice_got_game_id(char game_id[4]) {
|
||||
MiceConfig.devices.com7 = "";
|
||||
MiceConfig.devices.com8 = "";
|
||||
} 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;
|
||||
}
|
||||
|
||||
|
@ -126,8 +126,8 @@ physical_disk_t APM_HDD = {
|
||||
physical_disk_t* PHYSICAL_DISKS[] = {
|
||||
&SSD,
|
||||
&UPDATE_USB,
|
||||
&APM_HDD,
|
||||
// &APM_HDD,
|
||||
|
||||
&LOG_USB,
|
||||
// &LOG_USB,
|
||||
// &ALPHA_DVD,
|
||||
};
|
||||
|
@ -474,7 +474,7 @@ void init_volume(disk_volume_t* vol) {
|
||||
StringFromGUID2(&guid, volume_name + 10, MAX_PATH + 1 - 10);
|
||||
|
||||
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->hook_data = (void*)vol;
|
||||
@ -702,7 +702,7 @@ void hook_drives() {
|
||||
q_drive->DeviceIoControl = &q_drive_DeviceIoControl;
|
||||
q_drive->ReadFile = &q_drive_ReadFile;
|
||||
hook_file(q_drive);
|
||||
// ewwwwwwwwwwwwwwwwww
|
||||
// TODO: ewwwwwwwwwwwwwwwwww
|
||||
file_hook_t* q_drive_lower = new_file_hook(L"\\\\.\\q:");
|
||||
q_drive_lower->DeviceIoControl = &q_drive_DeviceIoControl;
|
||||
q_drive_lower->ReadFile = &q_drive_ReadFile;
|
||||
|
@ -1,7 +1,22 @@
|
||||
#define _MICE_FILES
|
||||
#include "files.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) {
|
||||
open_hook_t* opened = (open_hook_t*)malloc(sizeof(open_hook_t));
|
||||
ZeroMemory(opened, sizeof *opened);
|
||||
@ -97,78 +112,11 @@ void hook_file_with_buffer(LPCWSTR filename, LPBYTE buffer, DWORD nBytes, DWORD
|
||||
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,
|
||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
|
||||
DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes,
|
||||
HANDLE hTemplateFile) {
|
||||
file_hook_t* found_fh = find_hook(lpFileName);
|
||||
file_hook_t* found_fh = MiceFSLocateHookW(lpFileName);
|
||||
if (found_fh != NULL) {
|
||||
HANDLE handle = open_hook(found_fh);
|
||||
log_info(plfHooks, "CreateFileW(%ls) -> 0x%p", lpFileName, handle);
|
||||
@ -177,16 +125,10 @@ HANDLE WINAPI FakeCreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD d
|
||||
|
||||
HANDLE handle;
|
||||
|
||||
LPCSTR redirected;
|
||||
if (redirect_path_w(lpFileName, &redirected)) {
|
||||
handle = TrueCreateFileA(redirected, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
|
||||
dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
|
||||
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);
|
||||
}
|
||||
MiceFSRedirectPathW(lpFileName, &lpFileName);
|
||||
handle = TrueCreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
|
||||
dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
|
||||
log_misc(plfHooks, "CreateFileW(%ls) -> 0x%p", lpFileName, handle);
|
||||
|
||||
return handle;
|
||||
}
|
||||
@ -197,14 +139,14 @@ HANDLE WINAPI FakeCreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dw
|
||||
WCHAR 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) {
|
||||
HANDLE handle = open_hook(found_fh);
|
||||
log_info(plfHooks, "CreateFileA(%s) -> 0x%p", lpFileName, handle);
|
||||
return handle;
|
||||
}
|
||||
|
||||
redirect_path(lpFileName, &lpFileName);
|
||||
MiceFSRedirectPathA(lpFileName, &lpFileName);
|
||||
HANDLE handle = TrueCreateFileA(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
|
||||
dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
|
||||
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) {
|
||||
log_misc(plfHooks, "PathFileExists(%s)", pszPath);
|
||||
redirect_path(pszPath, &pszPath);
|
||||
MiceFSRedirectPathA(pszPath, &pszPath);
|
||||
BOOL ret = TruePathFileExistsA(pszPath);
|
||||
log_misc(plfHooks, "PathFileExistsA(%s) = %d", pszPath, ret);
|
||||
return ret;
|
||||
}
|
||||
BOOL WINAPI FakePathFileExistsW(LPCWSTR pszPath) {
|
||||
log_misc(plfHooks, "PathFileExists(%ls)", pszPath);
|
||||
LPCSTR redirected;
|
||||
if (redirect_path_w(pszPath, &redirected)) {
|
||||
return TruePathFileExistsA(redirected);
|
||||
}
|
||||
return TruePathFileExistsW(pszPath);
|
||||
MiceFSRedirectPathW(pszPath, &pszPath);
|
||||
BOOL ret = TruePathFileExistsW(pszPath);
|
||||
log_misc(plfHooks, "PathFileExistsW(%ls) = %d", pszPath, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
BOOL WINAPI FakeDeleteFileA(LPCSTR pszPath) {
|
||||
LPCSTR redirected;
|
||||
if (redirect_path(pszPath, &redirected)) {
|
||||
return TrueDeleteFileA(redirected);
|
||||
}
|
||||
MiceFSRedirectPathA(pszPath, &pszPath);
|
||||
return TrueDeleteFileA(pszPath);
|
||||
}
|
||||
BOOL WINAPI FakeDeleteFileW(LPCWSTR pszPath) {
|
||||
LPCSTR redirected;
|
||||
if (redirect_path_w(pszPath, &redirected)) {
|
||||
return TrueDeleteFileA(redirected);
|
||||
}
|
||||
MiceFSRedirectPathW(pszPath, &pszPath);
|
||||
return TrueDeleteFileW(pszPath);
|
||||
}
|
||||
|
||||
@ -387,38 +321,35 @@ BOOL WINAPI FakeCloseHandle(HANDLE hObject) {
|
||||
}
|
||||
|
||||
int WINAPIV Fake_stat64i32(const char* path, struct _stat64i32* buffer) {
|
||||
redirect_path((char*)path, &path);
|
||||
MiceFSRedirectPathA((char*)path, &path);
|
||||
return True_stat64i32(path, buffer);
|
||||
};
|
||||
|
||||
DWORD WINAPI FakeGetFileAttributesA(LPCSTR lpFileName) {
|
||||
// The game quits out if MiniDump is present!
|
||||
if (PathEqual(lpFileName, "Y:\\MiniDump\\") == 0) {
|
||||
if (PathEqual(lpFileName, "Y:\\MiniDump\\")) {
|
||||
return 0;
|
||||
}
|
||||
return (DWORD)-1;
|
||||
|
||||
LPCSTR redirected;
|
||||
if (redirect_path(lpFileName, &redirected)) {
|
||||
return TrueGetFileAttributesA(redirected);
|
||||
}
|
||||
MiceFSRedirectPathA(lpFileName, &lpFileName);
|
||||
return TrueGetFileAttributesA(lpFileName);
|
||||
}
|
||||
DWORD WINAPI FakeGetFileAttributesW(LPCWSTR lpFileName) {
|
||||
LPCSTR redirected;
|
||||
if (redirect_path_w(lpFileName, &redirected)) {
|
||||
return TrueGetFileAttributesA(redirected);
|
||||
}
|
||||
MiceFSRedirectPathW(lpFileName, &lpFileName);
|
||||
return TrueGetFileAttributesW(lpFileName);
|
||||
}
|
||||
HANDLE WINAPI FakeFindFirstFileA(LPCSTR lpFileName, LPWIN32_FIND_DATA lpFindFileData) {
|
||||
LPCSTR redirected;
|
||||
if (redirect_path(lpFileName, &redirected)) {
|
||||
return TrueFindFirstFileA(redirected, lpFindFileData);
|
||||
}
|
||||
MiceFSRedirectPathA(lpFileName, &lpFileName);
|
||||
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() {
|
||||
hook("Kernel32.dll", "DeviceIoControl", FakeDeviceIoControl, (void**)&TrueDeviceIoControl);
|
||||
|
||||
@ -436,6 +367,10 @@ void hook_io() {
|
||||
hook("Shlwapi.dll", "PathFileExistsW", FakePathFileExistsW, (void**)&TruePathFileExistsW);
|
||||
hook("Kernel32.dll", "DeleteFileA", FakeDeleteFileA, (void**)&TrueDeleteFileA);
|
||||
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);
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
#pragma once
|
||||
#include "../common.h"
|
||||
#include "com.h"
|
||||
|
||||
#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 DWORD(WINAPI* TrueGetFileAttributesA)(LPCSTR 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 {
|
||||
HANDLE m_Handle;
|
||||
@ -75,6 +76,10 @@ static int(WINAPIV* True_stat64i32)(const char* path, _stat64i32_t* buffer);
|
||||
#define _SetFilePointer (TrueSetFilePointer ? TrueSetFilePointer : SetFilePointer)
|
||||
#define _SetFilePointerEx (TrueSetFilePointerEx ? TrueSetFilePointerEx : SetFilePointerEx)
|
||||
#define _PathFileExistsA (TruePathFileExistsA ? TruePathFileExistsA : PathFileExistsA)
|
||||
#define _GetCurrentDirectoryA \
|
||||
(TrueGetCurrentDirectoryA ? TrueGetCurrentDirectoryA : GetCurrentDirectoryA)
|
||||
#define _GetCurrentDirectoryW \
|
||||
(TrueGetCurrentDirectoryW ? TrueGetCurrentDirectoryA : GetCurrentDirectoryA)
|
||||
|
||||
typedef struct drive_redirect {
|
||||
const CHAR* drive;
|
||||
|
@ -258,6 +258,9 @@ static HRESULT(STDMETHODCALLTYPE* TrueCreateDevice)(IDirect3D9* this, UINT Adapt
|
||||
DWORD BehaviorFlags,
|
||||
D3DPRESENT_PARAMETERS* pPresentationParameters,
|
||||
IDirect3DDevice9** ppReturnedDeviceInterface);
|
||||
static HRESULT(STDMETHODCALLTYPE* TrueEnumAdapterModes)(IDirect3D9* this, UINT Adapter,
|
||||
D3DFORMAT Format, UINT Mode,
|
||||
D3DDISPLAYMODE* pMode);
|
||||
|
||||
extern RECT monitorRect;
|
||||
HRESULT STDMETHODCALLTYPE FakeCreateDevice(IDirect3D9* this, UINT Adapter, D3DDEVTYPE DeviceType,
|
||||
@ -309,6 +312,23 @@ HRESULT STDMETHODCALLTYPE FakeCreateDevice(IDirect3D9* this, UINT Adapter, D3DDE
|
||||
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;
|
||||
}
|
||||
|
||||
@ -320,6 +340,10 @@ IDirect3D9* WINAPI FakeDirect3DCreate9(UINT SDKVersion) {
|
||||
DWORD patch = (DWORD)&FakeCreateDevice;
|
||||
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;
|
||||
};
|
||||
|
||||
|
@ -5,7 +5,7 @@ int WINAPI Fake_connect(SOCKET s, const SOCKADDR* name, int namelen) {
|
||||
USHORT port = _byteswap_ushort(((SOCKADDR_IN*)name)->sin_port);
|
||||
// Poorly exclude nxauth and mxgcatcher.
|
||||
// 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,
|
||||
(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_2 0xC1
|
||||
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;
|
||||
uint32_t nbytes;
|
||||
|
@ -1,17 +1,13 @@
|
||||
#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,
|
||||
LPSECURITY_ATTRIBUTES lpProcessAttributes,
|
||||
LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles,
|
||||
DWORD dwCreationFlags, LPVOID lpEnvironment,
|
||||
LPCSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo,
|
||||
LPPROCESS_INFORMATION lpProcessInformation) {
|
||||
// Somewhat janky way to identify when this is a loopback from start_and_inject
|
||||
// TODO: _CreateProcessA()
|
||||
if (dwCreationFlags & CREATE_SUSPENDED) {
|
||||
return TrueCreateProcessA(lpApplicationName, lpCommandLine, lpProcessAttributes,
|
||||
lpThreadAttributes, bInheritHandles, dwCreationFlags,
|
||||
@ -19,10 +15,33 @@ BOOL WINAPI FakeCreateProcessA(LPCSTR lpApplicationName, LPSTR lpCommandLine,
|
||||
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);
|
||||
|
||||
return start_and_inject(INVALID_HANDLE_VALUE, lpApplicationName, lpCommandLine,
|
||||
MICELIB, FALSE, 0, NULL, 0, lpProcessInformation);
|
||||
return start_and_inject(INVALID_HANDLE_VALUE, lpApplicationName, lpCommandLine, MICELIB, FALSE,
|
||||
0, NULL, 0, lpProcessInformation);
|
||||
}
|
||||
BOOL WINAPI FakeCreateProcessW(LPCWSTR lpApplicationName, LPWSTR lpCommandLine,
|
||||
LPSECURITY_ATTRIBUTES lpProcessAttributes,
|
||||
@ -32,16 +51,40 @@ BOOL WINAPI FakeCreateProcessW(LPCWSTR lpApplicationName, LPWSTR lpCommandLine,
|
||||
LPPROCESS_INFORMATION lpProcessInformation) {
|
||||
log_info(plfProcesses, "CreateProcessW %ls %ls", lpApplicationName, lpCommandLine);
|
||||
|
||||
CHAR applicationName[MAX_PATH + 1];
|
||||
WideCharToMultiByte(CP_ACP, 0, lpApplicationName, -1, applicationName, sizeof applicationName,
|
||||
NULL, NULL);
|
||||
if (wcsncmp(lpCommandLine, L"chkdsk.exe", wcslen(L"chkdsk.exe")) == 0) {
|
||||
if (lpProcessInformation) {
|
||||
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);
|
||||
LPSTR commandLine = malloc(nMultiChars);
|
||||
WideCharToMultiByte(CP_ACP, 0, lpCommandLine, -1, commandLine, nMultiChars, NULL, NULL);
|
||||
|
||||
return start_and_inject(INVALID_HANDLE_VALUE, applicationName, commandLine, MICELIB,
|
||||
FALSE, 0, NULL, 0, lpProcessInformation);
|
||||
CHAR szApplicationName[MAX_PATH + 1];
|
||||
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) {
|
||||
@ -52,5 +95,5 @@ BOOL WINAPI FakeGetExitCodeProcess(HANDLE hProcess, LPDWORD lpExitCode) {
|
||||
void hook_processes() {
|
||||
hook("Kernel32.dll", "CreateProcessW", FakeCreateProcessW, (void**)&TrueCreateProcessW);
|
||||
hook("Kernel32.dll", "CreateProcessA", FakeCreateProcessA, (void**)&TrueCreateProcessA);
|
||||
// hook("Kernel32.dll", "GetExitCodeProcess", FakeGetExitCodeProcess, NULL);
|
||||
hook("Kernel32.dll", "GetExitCodeProcess", FakeGetExitCodeProcess, NULL);
|
||||
}
|
||||
|
@ -1,29 +1,34 @@
|
||||
#include "registry.h"
|
||||
|
||||
// TODO: Do we want to make a proper registry emulation?
|
||||
|
||||
static BOOL bHALDeleted = FALSE;
|
||||
|
||||
LSTATUS WINAPI FakeRegCloseKey(HKEY hKey) {
|
||||
log_trace(plfRegistry, "RegCloseKey %08x", hKey);
|
||||
log_misc(plfRegistry, "RegCloseKey %08x", hKey);
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
LSTATUS WINAPI FakeRegCreateKeyExA(HKEY hKey, LPCSTR lpSubKey, DWORD Reserved, LPSTR lpClass,
|
||||
DWORD dwOptions, REGSAM samDesired,
|
||||
const LPSECURITY_ATTRIBUTES lpSecurityAttributes,
|
||||
PHKEY phkResult, LPDWORD lpdwDisposition) {
|
||||
log_trace(plfRegistry, "RegCreateKeyExA %08x %s", hKey, lpSubKey);
|
||||
log_misc(plfRegistry, "RegCreateKeyExA %08x %s", hKey, lpSubKey);
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
LSTATUS WINAPI FakeRegEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpName, LPDWORD lpcchName,
|
||||
LPDWORD lpReserved, LPSTR lpClass, LPDWORD lpcchClass,
|
||||
PFILETIME lpftLastWriteTime) {
|
||||
log_trace(plfRegistry, "RegEnumKeyExA %08x[%d]", hKey, dwIndex);
|
||||
if (dwIndex == 0) {
|
||||
log_misc(plfRegistry, "RegEnumKeyExA %08x[%d]", hKey, dwIndex);
|
||||
if (dwIndex == 0 && !bHALDeleted) {
|
||||
strcpy(lpName, "Direct3D HAL");
|
||||
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,
|
||||
LPDWORD lpcchValueName, LPDWORD lpReserved, LPDWORD lpType,
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -49,7 +49,6 @@ BOOL WINAPI Fake_GetLocalTime(SYSTEMTIME* lpSystemTime) {
|
||||
return TrueGetLocalTime(lpSystemTime);
|
||||
}
|
||||
BOOL WINAPI Fake_GetSystemTime(SYSTEMTIME* lpSystemTime) {
|
||||
log_trace(plfTime, "GetSystemTime");
|
||||
if (stCache) {
|
||||
memcpy(lpSystemTime, &systemTime, sizeof systemTime);
|
||||
return TRUE;
|
||||
|
@ -129,7 +129,7 @@ static DWORD WINAPI MiceMailslotWatcher(HANDLE* pSlot) {
|
||||
}
|
||||
if (!inVt100) WriteFile(hLogFile, &(readBuffer[i]), 1, &nWrote, NULL);
|
||||
}
|
||||
FlushFileBuffers(hLogFile);
|
||||
// FlushFileBuffers(hLogFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,9 +4,12 @@
|
||||
#include "../lib/mice/mice.h"
|
||||
|
||||
spawn_t mxspawns[3] = {
|
||||
{ "keychip", SPAWN_DUMMY, MdkThreadProc, MxkThreadProc },
|
||||
{ "master", SPAWN_DUMMY, MdmThreadProc, NULL },
|
||||
{ "installer", SPAWN_DUMMY, MdiThreadProc, NULL },
|
||||
// { "keychip", SPAWN_DUMMY, MdkThreadProc, MxkThreadProc },
|
||||
// { "master", SPAWN_DUMMY, MdmThreadProc, NULL },
|
||||
// { "installer", SPAWN_DUMMY, MdiThreadProc, NULL },
|
||||
{ "keychip", SPAWN_NONE, MdkThreadProc, MxkThreadProc },
|
||||
{ "master", SPAWN_NONE, MdmThreadProc, NULL },
|
||||
{ "installer", SPAWN_NONE, MdiThreadProc, NULL },
|
||||
};
|
||||
|
||||
int mxkMain();
|
||||
|
@ -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_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, 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)
|
||||
|
||||
SECTION(launcher, "These options are only used during initial bootstrapping")
|
||||
|
41
src/micetools/lib/mice/kcf.c
Normal file
41
src/micetools/lib/mice/kcf.c
Normal 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;
|
||||
}
|
18
src/micetools/lib/mice/kcf.h
Normal file
18
src/micetools/lib/mice/kcf.h
Normal 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);
|
@ -6,6 +6,8 @@ mice_lib = static_library(
|
||||
'patch.c',
|
||||
'ringbuf.c',
|
||||
'config.c',
|
||||
'kcf.c',
|
||||
'micefs.c',
|
||||
],
|
||||
link_with: [
|
||||
inih.get_variable('lib_inih'),
|
||||
|
@ -8,7 +8,9 @@
|
||||
#include "config.h"
|
||||
#include "exe.h"
|
||||
#include "ioctl.h"
|
||||
#include "kcf.h"
|
||||
#include "log.h"
|
||||
#include "micefs.h"
|
||||
#include "patch.h"
|
||||
#include "ringbuf.h"
|
||||
#include "version_fallback.h"
|
||||
|
323
src/micetools/lib/mice/micefs.c
Normal file
323
src/micetools/lib/mice/micefs.c
Normal 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;
|
||||
}
|
155
src/micetools/lib/mice/micefs.h
Normal file
155
src/micetools/lib/mice/micefs.h
Normal 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);
|
@ -199,7 +199,7 @@ MXK_STATUS mxkGetKeychipIdFromN2(void) {
|
||||
|
||||
amiCrc32RInit();
|
||||
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!!!");
|
||||
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
|
||||
// before committing it to memory!
|
||||
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(&appboot, sizeof appboot, &kcId.m_AppBoot,
|
||||
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);
|
||||
|
||||
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!
|
||||
// memcpy_s(&APPBOOT, 256, &appboot, sizeof appboot);
|
||||
|
@ -20,7 +20,7 @@ MXK_STATUS mxkGetAppBootInfo(void) {
|
||||
return status;
|
||||
}
|
||||
|
||||
appboot_t appBoot;
|
||||
AM_APPBOOT_256 appBoot;
|
||||
for (int i = 0; i < sizeof appBoot; i += 16) {
|
||||
status = mxkRecvPacket((unsigned char*)(&appBoot) + i);
|
||||
if (status != MXK_STATUS_OK) {
|
||||
@ -30,7 +30,8 @@ MXK_STATUS mxkGetAppBootInfo(void) {
|
||||
}
|
||||
|
||||
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");
|
||||
return MXK_STATUS_ERROR;
|
||||
}
|
||||
@ -75,11 +76,11 @@ MXK_STATUS mxkAbSystemFlag(MXK_CACHE cache, unsigned char* systemFlag, unsigned
|
||||
|
||||
if (status == MXK_STATUS_OK) {
|
||||
LAB_00401d7b:
|
||||
if (AppBoot.m_Cache.format != 1) {
|
||||
if (AppBoot.m_Cache.m_Header.m_Format != 1) {
|
||||
*systemFlag = 0;
|
||||
return MXK_STATUS_OK;
|
||||
}
|
||||
*systemFlag = AppBoot.m_Cache.system_flag;
|
||||
*systemFlag = AppBoot.m_Cache.m_Header.m_SystemFlag;
|
||||
return MXK_STATUS_OK;
|
||||
}
|
||||
|
||||
@ -127,18 +128,18 @@ MXK_STATUS mxkAbGameId(MXK_CACHE cache, char* gameId, unsigned char* err) {
|
||||
|
||||
if (status == MXK_STATUS_OK) {
|
||||
LAB_00401c7f:
|
||||
if (AppBoot.m_Cache.format != 1) {
|
||||
if (AppBoot.m_Cache.m_Header.m_Format != 1) {
|
||||
gameId[0] = '_';
|
||||
gameId[1] = '_';
|
||||
gameId[2] = '_';
|
||||
gameId[3] = '_';
|
||||
return MXK_STATUS_OK;
|
||||
}
|
||||
if (!mxkValidString(AppBoot.m_Cache.game_id, 4)) {
|
||||
if (!mxkValidString(AppBoot.m_Cache.m_Header.m_GameId, 4)) {
|
||||
*err = 55;
|
||||
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;
|
||||
}
|
||||
LAB_00401c6a:
|
||||
|
@ -2,30 +2,14 @@
|
||||
#include <Windows.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "../../segastructs.h"
|
||||
#include "../ami/ami.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 {
|
||||
bool m_useFlash;
|
||||
bool m_cacheDirty;
|
||||
appboot_t m_Cache;
|
||||
AM_APPBOOT_256 m_Cache;
|
||||
} APP_BOOT;
|
||||
extern APP_BOOT AppBoot;
|
||||
|
||||
|
@ -185,7 +185,7 @@ MXK_STATUS mxkCryptDecryptAes128CBC(const unsigned char* key, const unsigned cha
|
||||
int outl;
|
||||
EVP_DecryptUpdate(ctx, pt, &outl, ct, nbytes);
|
||||
unsigned char dump[16];
|
||||
EVP_EncryptFinal_ex(ctx, dump, &outl);
|
||||
EVP_DecryptFinal_ex(ctx, dump, &outl);
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
|
||||
return MXK_STATUS_OK;
|
||||
|
@ -53,6 +53,26 @@ typedef struct {
|
||||
} N2DeviceInfo_t;
|
||||
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] = {
|
||||
{ 0x2c, 0xf8, 0x3e, 0x5e, 0x51, 0xf0, 0x60, 0x1b, 0xf6, 0xb1,
|
||||
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 }
|
||||
};
|
||||
|
||||
// Key = 76ec42b6ae0cb048105171ad8cb2fb07
|
||||
// IV = 8e300ba42e154baf651532f570041f5b
|
||||
AESKey_t N2_KEY_AES[2] = {
|
||||
{ { 0xd7, 0xf6, 0x86, 0xfb, 0x63, 0x44, 0xff, 0xa5, 0x60, 0x9d, 0x4e, 0xf0, 0x18, 0xe9, 0x45,
|
||||
0xb4 },
|
||||
|
@ -4,26 +4,14 @@
|
||||
#include <varargs.h>
|
||||
|
||||
#include "mxkCrypt.h"
|
||||
#include "../../segastructs.h"
|
||||
|
||||
#pragma pack(push, 1)
|
||||
typedef struct {
|
||||
uint32_t m_Crc;
|
||||
uint8_t m_Unk04[12];
|
||||
uint8_t m_KeyId[16];
|
||||
struct {
|
||||
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;
|
||||
AM_APPBOOT_128 m_AppBoot;
|
||||
} N2KeychipId_t;
|
||||
#pragma pack(pop)
|
||||
|
||||
|
@ -1,77 +1,92 @@
|
||||
#include "../config.h"
|
||||
#include "../lib/libpcp/libpcp.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) {
|
||||
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);
|
||||
}
|
||||
void mxkPcpAbModelType(pcpa_t* stream, void* data) {
|
||||
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);
|
||||
}
|
||||
void mxkPcpAbFormatType(pcpa_t* stream, void* data) {
|
||||
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);
|
||||
}
|
||||
void mxkPcpAbRegion(pcpa_t* stream, void* data) {
|
||||
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);
|
||||
}
|
||||
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) {
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
|
||||
#define SEED_BUF_MAX 1024
|
||||
byte SEED_BUF[SEED_BUF_MAX];
|
||||
int SEED_BUF_LEN = 0;
|
||||
// #define SEED_BUF_MAX 1024
|
||||
// byte SEED_BUF[SEED_BUF_MAX];
|
||||
// int SEED_BUF_LEN = 0;
|
||||
void mxkPcpAbSeed(pcpa_t* stream, void* data) {
|
||||
if (SEED_BUF_LEN == 0) {
|
||||
FILE* fCert;
|
||||
fopen_s(&fCert, Config.appboot_seed, "r");
|
||||
if (fCert == NULL)
|
||||
SEED_BUF_LEN = -1;
|
||||
else {
|
||||
fseek(fCert, 0, SEEK_END);
|
||||
SEED_BUF_LEN = ftell(fCert);
|
||||
if (SEED_BUF_LEN > SEED_BUF_MAX) SEED_BUF_LEN = SEED_BUF_MAX;
|
||||
rewind(fCert);
|
||||
// if (SEED_BUF_LEN == 0) {
|
||||
// FILE* fCert;
|
||||
// fopen_s(&fCert, Config.appboot_seed, "r");
|
||||
// if (fCert == NULL)
|
||||
// SEED_BUF_LEN = -1;
|
||||
// else {
|
||||
// fseek(fCert, 0, SEEK_END);
|
||||
// SEED_BUF_LEN = ftell(fCert);
|
||||
// if (SEED_BUF_LEN > SEED_BUF_MAX) SEED_BUF_LEN = SEED_BUF_MAX;
|
||||
// rewind(fCert);
|
||||
|
||||
fread(SEED_BUF, SEED_BUF_LEN, 1, fCert);
|
||||
fclose(fCert);
|
||||
}
|
||||
}
|
||||
// fread(SEED_BUF, SEED_BUF_LEN, 1, fCert);
|
||||
// fclose(fCert);
|
||||
// }
|
||||
// }
|
||||
|
||||
if (SEED_BUF_LEN == -1) {
|
||||
// TODO: Fix this maybe?
|
||||
pcpaSetBinaryMode(stream, binary_mode_none);
|
||||
pcpaSetSendPacket(stream, AB_SEED, "-1");
|
||||
return;
|
||||
}
|
||||
// if (SEED_BUF_LEN == -1) {
|
||||
// // TODO: Fix this maybe?
|
||||
// pcpaSetBinaryMode(stream, binary_mode_none);
|
||||
// pcpaSetSendPacket(stream, AB_SEED, "-1");
|
||||
// return;
|
||||
// }
|
||||
|
||||
pcpaSetBinaryMode(stream, binary_mode_send);
|
||||
pcpaSetBeforeBinaryModeCallBackFunc(stream, mxkBinaryCallback, NULL);
|
||||
|
||||
BINARY_DATA_LEN = SEED_BUF_LEN;
|
||||
memcpy(BINARY_DATA, SEED_BUF, SEED_BUF_LEN);
|
||||
BINARY_DATA_LEN = sizeof mxkKcfConfig.m_Seed;
|
||||
memcpy(BINARY_DATA, mxkKcfConfig.m_Seed, sizeof mxkKcfConfig.m_Seed);
|
||||
pcpaSetRecvBinaryBuffer(stream, BINARY_DATA, BINARY_DATA_LEN);
|
||||
|
||||
pcpaSetSendPacket(stream, AB_SEED, "0");
|
||||
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);
|
||||
}
|
||||
|
@ -2,8 +2,12 @@
|
||||
#include "../lib/libpcp/libpcp.h"
|
||||
#include "callbacks.h"
|
||||
|
||||
void mxkPcpPbKeyId(pcpa_t* stream, void* data) { pcpaSetSendPacket(stream, BIL_KEYID, Config.billing_keyid); }
|
||||
void mxkPcpPbMainId(pcpa_t* stream, void* data) { pcpaSetSendPacket(stream, BIL_MAINID, Config.billing_mainid); }
|
||||
void mxkPcpPbKeyId(pcpa_t* stream, void* data) {
|
||||
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) {
|
||||
char pc[9];
|
||||
snprintf(pc, sizeof pc, "%08X", Config.billing_playcount);
|
||||
|
@ -1,4 +1,10 @@
|
||||
#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;
|
||||
extern byte BINARY_DATA[4096];
|
||||
|
@ -1,12 +1,73 @@
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/pem.h>
|
||||
|
||||
#include "../../lib/util/hex.h"
|
||||
#include "callbacks.h"
|
||||
|
||||
void mxkPcpDsCompute(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) {}
|
||||
|
||||
EVP_CIPHER_CTX* ctxEnc = NULL;
|
||||
EVP_CIPHER_CTX* ctxDec = NULL;
|
||||
|
||||
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) {
|
||||
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"); }
|
||||
|
@ -1,4 +1,3 @@
|
||||
#include "../config.h"
|
||||
#include "callbacks.h"
|
||||
|
||||
void mxkPcpVersion(pcpa_t* stream, void* data) {
|
||||
@ -9,12 +8,12 @@ void mxkPcpVersion(pcpa_t* stream, void* data) {
|
||||
|
||||
char version[5];
|
||||
if (sDevice && strcmp(sDevice, "n2") == 0)
|
||||
snprintf(version, 5, "%04X", Config.keychip_dongle_version);
|
||||
snprintf(version, 5, "%04X", N2_VERSION);
|
||||
else
|
||||
snprintf(version, 5, "%04X", Config.keychip_pic_version);
|
||||
snprintf(version, 5, "%04X", PIC_VERSION);
|
||||
pcpaSetSendPacket(stream, KC_VERSION, version);
|
||||
}
|
||||
|
||||
void mxkPcpStatus(pcpa_t* stream, void* data) {
|
||||
pcpaSetSendPacket(stream, KC_STATUS, Config.keychip_status);
|
||||
pcpaSetSendPacket(stream, KC_STATUS, "available");
|
||||
}
|
||||
|
@ -7,27 +7,14 @@
|
||||
|
||||
HEADER("The main config file for micekeychip")
|
||||
|
||||
SECTION(config, "")
|
||||
CFG_str(config, kcf_path, "", "Path to a KCF file for appboot config")
|
||||
|
||||
SECTION(pcp, "")
|
||||
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_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, "")
|
||||
CFG_bool(crypto, ds_enable, false, "Process keychip.ds.compute?")
|
||||
CFG_bool(crypto, ssd_enable, false, "Process keychip.ssd.proof?")
|
||||
|
@ -1,5 +1,5 @@
|
||||
dependencies = []
|
||||
link_with = [inih.get_variable('lib_inih'), libpcp]
|
||||
dependencies = [openssl_lib]
|
||||
link_with = [inih.get_variable('lib_inih'), libpcp, mice_lib]
|
||||
|
||||
|
||||
rc = import('windows').compile_resources('micekeychip.rc', depend_files: micekeychip_ico)
|
||||
@ -18,6 +18,10 @@ mxk = static_library(
|
||||
'mxk',
|
||||
sources: sources,
|
||||
link_with: link_with,
|
||||
dependencies: dependencies,
|
||||
include_directories: [
|
||||
openssl_inc,
|
||||
],
|
||||
)
|
||||
executable(
|
||||
'micekeychip',
|
||||
@ -25,4 +29,7 @@ executable(
|
||||
sources: sources + ['main.c'],
|
||||
link_with: link_with,
|
||||
dependencies: dependencies,
|
||||
include_directories: [
|
||||
openssl_inc,
|
||||
],
|
||||
)
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "mxk.h"
|
||||
|
||||
AM_KCF mxkKcfConfig;
|
||||
|
||||
byte SERVER_STATE = 0;
|
||||
pcpa_t PCP;
|
||||
pcpa_cb_table_t CALLBACK_FUNCTION_BUFFER[40];
|
||||
@ -162,6 +164,11 @@ e_pcpa_t mxkPcpServer() {
|
||||
return err;
|
||||
}
|
||||
|
||||
static LPCSTR kcfSearchPaths[] = {
|
||||
"S:\\config.kcf",
|
||||
"C:\\system\\device\\config.kcf",
|
||||
};
|
||||
|
||||
int mxkMain(void) {
|
||||
DWORD dwAttrib = GetFileAttributes(CONFIG_PATH);
|
||||
if (dwAttrib == INVALID_FILE_ATTRIBUTES || (dwAttrib & FILE_ATTRIBUTE_DIRECTORY))
|
||||
@ -169,6 +176,27 @@ int mxkMain(void) {
|
||||
|
||||
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();
|
||||
if (err != 0) {
|
||||
amiDebugLog("Error mxkInit. Code %d", err);
|
||||
|
@ -2,9 +2,12 @@
|
||||
|
||||
#include "../../../subprojects/inih_dep/ini.h"
|
||||
#include "../lib/libpcp/libpcp.h"
|
||||
#include "../lib/mice/kcf.h"
|
||||
#include "callbacks/callbacks.h"
|
||||
#include "config.h"
|
||||
|
||||
extern AM_KCF mxkKcfConfig;
|
||||
|
||||
void mxkBinaryCallback(pcpa_t* stream, void* data);
|
||||
int mxkInit();
|
||||
e_pcpa_t mxkPcpStreamInit();
|
||||
|
30
src/micetools/segastructs.h
Normal file
30
src/micetools/segastructs.h
Normal 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)
|
@ -81,3 +81,14 @@ executable(
|
||||
amiDebug,
|
||||
],
|
||||
)
|
||||
|
||||
executable(
|
||||
'micefs_test',
|
||||
win_subsystem: subsystem,
|
||||
sources: [
|
||||
'micefs_test.c',
|
||||
],
|
||||
link_with: [
|
||||
mice_lib,
|
||||
],
|
||||
)
|
||||
|
@ -289,7 +289,7 @@ BOOL dump_keychip() {
|
||||
printf("Keychip ID:\t%.16s\n", KEYCHIP_ID);
|
||||
}
|
||||
|
||||
appboot_t appboot;
|
||||
AM_APPBOOT_256 appboot;
|
||||
if (!mxkGetAppBootInfo(mxparallel, &appboot)) {
|
||||
puts("Failed to request appboot info!");
|
||||
} else {
|
||||
|
32
src/micetools/util/micefs_test.c
Normal file
32
src/micetools/util/micefs_test.c
Normal 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);
|
||||
}
|
Loading…
Reference in New Issue
Block a user