Bunch of driver work, and json-based patching
This commit is contained in:
parent
331710e239
commit
463d94f1ee
1
Makefile
1
Makefile
@ -53,3 +53,4 @@ dist:
|
|||||||
|
|
||||||
@xcopy /E /H /C /R /Q /Y src\system "$(DIST_DIR)\system/*"
|
@xcopy /E /H /C /R /Q /Y src\system "$(DIST_DIR)\system/*"
|
||||||
@xcopy /E /H /C /R /Q /Y src\tools "$(DIST_DIR)\tools/*"
|
@xcopy /E /H /C /R /Q /Y src\tools "$(DIST_DIR)\tools/*"
|
||||||
|
@xcopy /E /H /C /R /Q /Y src\patches "$(DIST_DIR)\patches/*"
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include "com.h"
|
#include "com.h"
|
||||||
|
|
||||||
|
#include "../lib/mice/mice.h"
|
||||||
|
|
||||||
com_hook_t* com_hook_list = NULL;
|
com_hook_t* com_hook_list = NULL;
|
||||||
com_hook_t* new_com_hook(BYTE port) {
|
com_hook_t* new_com_hook(BYTE port) {
|
||||||
com_hook_t* hook = (com_hook_t*)malloc(sizeof *hook);
|
com_hook_t* hook = (com_hook_t*)malloc(sizeof *hook);
|
||||||
@ -19,9 +21,11 @@ com_hook_t* new_com_hook(BYTE port) {
|
|||||||
|
|
||||||
return hook;
|
return hook;
|
||||||
};
|
};
|
||||||
|
|
||||||
void hook_com(com_hook_t* hook) {
|
void hook_com(com_hook_t* hook) {
|
||||||
hook->next = NULL;
|
hook->next = NULL;
|
||||||
hook->virtual_handle = NULL;
|
hook->virtual_handle = (LPHANDLE)malloc(sizeof(HANDLE));
|
||||||
|
*hook->virtual_handle = NULL;
|
||||||
if (com_hook_list == NULL) {
|
if (com_hook_list == NULL) {
|
||||||
com_hook_list = hook;
|
com_hook_list = hook;
|
||||||
return;
|
return;
|
||||||
@ -33,97 +37,155 @@ void hook_com(com_hook_t* hook) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
BOOL WINAPI FakeGetCommState(HANDLE hFile, LPDCB lpDCB) {
|
BOOL WINAPI FakeGetCommState(HANDLE hFile, LPDCB lpDCB) {
|
||||||
log_misc("comm", "GetCommState(0x%p, 0x%p)", hFile, lpDCB);
|
log_misc(COMM_LOGGER, "GetCommState(0x%p, 0x%p)", hFile, lpDCB);
|
||||||
|
|
||||||
com_hook_t* hook = com_hook_list;
|
com_hook_t* hook = com_hook_list;
|
||||||
while (hook != NULL) {
|
while (hook != NULL) {
|
||||||
if (hook->virtual_handle == hFile && hook->GetCommState != NULL) {
|
if (*hook->virtual_handle == hFile) {
|
||||||
|
if (hook->GetCommState == NULL) {
|
||||||
|
log_error(COMM_LOGGER, "GetCommState(%ls) unimplemented", hook->wName);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
return hook->GetCommState(hook->data, lpDCB);
|
return hook->GetCommState(hook->data, lpDCB);
|
||||||
}
|
}
|
||||||
|
hook = hook->next;
|
||||||
}
|
}
|
||||||
return TrueGetCommState(hFile, lpDCB);
|
return TrueGetCommState(hFile, lpDCB);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL WINAPI FakeSetCommState(HANDLE hFile, LPDCB lpDCB) {
|
BOOL WINAPI FakeSetCommState(HANDLE hFile, LPDCB lpDCB) {
|
||||||
log_misc("comm", "SetCommState(0x%p, 0x%p)", hFile, lpDCB);
|
log_misc(COMM_LOGGER, "SetCommState(0x%p, 0x%p)", hFile, lpDCB);
|
||||||
|
|
||||||
com_hook_t* hook = com_hook_list;
|
com_hook_t* hook = com_hook_list;
|
||||||
while (hook != NULL) {
|
while (hook != NULL) {
|
||||||
if (hook->virtual_handle == hFile && hook->SetCommState != NULL) {
|
if (*hook->virtual_handle == hFile) {
|
||||||
|
if (hook->SetCommState == NULL) {
|
||||||
|
log_error(COMM_LOGGER, "SetCommState(%ls) unimplemented", hook->wName);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
return hook->SetCommState(hook->data, lpDCB);
|
return hook->SetCommState(hook->data, lpDCB);
|
||||||
}
|
}
|
||||||
|
hook = hook->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
return TrueSetCommState(hFile, lpDCB);
|
return TrueSetCommState(hFile, lpDCB);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL WINAPI FakeGetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts) {
|
BOOL WINAPI FakeGetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts) {
|
||||||
log_misc("comm", "GetCommTimeouts(0x%p, 0x%p)", hFile, lpCommTimeouts);
|
log_misc(COMM_LOGGER, "GetCommTimeouts(0x%p, 0x%p)", hFile, lpCommTimeouts);
|
||||||
|
|
||||||
com_hook_t* hook = com_hook_list;
|
com_hook_t* hook = com_hook_list;
|
||||||
while (hook != NULL) {
|
while (hook != NULL) {
|
||||||
if (hook->virtual_handle == hFile && hook->GetCommTimeouts != NULL) {
|
if (*hook->virtual_handle == hFile) {
|
||||||
|
if (hook->GetCommTimeouts == NULL) {
|
||||||
|
log_error(COMM_LOGGER, "GetCommTimeouts(%ls) unimplemented", hook->wName);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
return hook->GetCommTimeouts(hook->data, lpCommTimeouts);
|
return hook->GetCommTimeouts(hook->data, lpCommTimeouts);
|
||||||
}
|
}
|
||||||
|
hook = hook->next;
|
||||||
}
|
}
|
||||||
return TrueGetCommTimeouts(hFile, lpCommTimeouts);
|
return TrueGetCommTimeouts(hFile, lpCommTimeouts);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL WINAPI FakeSetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts) {
|
BOOL WINAPI FakeSetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts) {
|
||||||
log_misc("comm", "SetCommTimeouts(0x%p, 0x%p)", hFile, lpCommTimeouts);
|
log_misc(COMM_LOGGER, "SetCommTimeouts(0x%p, 0x%p)", hFile, lpCommTimeouts);
|
||||||
|
|
||||||
com_hook_t* hook = com_hook_list;
|
com_hook_t* hook = com_hook_list;
|
||||||
while (hook != NULL) {
|
while (hook != NULL) {
|
||||||
if (hook->virtual_handle == hFile && hook->SetCommTimeouts != NULL) {
|
if (*hook->virtual_handle == hFile) {
|
||||||
|
if (hook->SetCommTimeouts == NULL) {
|
||||||
|
log_error(COMM_LOGGER, "SetCommTimeouts(%ls) unimplemented", hook->wName);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
return hook->SetCommTimeouts(hook->data, lpCommTimeouts);
|
return hook->SetCommTimeouts(hook->data, lpCommTimeouts);
|
||||||
}
|
}
|
||||||
|
hook = hook->next;
|
||||||
}
|
}
|
||||||
return TrueSetCommTimeouts(hFile, lpCommTimeouts);
|
return TrueSetCommTimeouts(hFile, lpCommTimeouts);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL WINAPI FakeSetupComm(HANDLE hFile, DWORD dwInQueue, DWORD dwOutQueue) {
|
BOOL WINAPI FakeSetupComm(HANDLE hFile, DWORD dwInQueue, DWORD dwOutQueue) {
|
||||||
log_misc("comm", "SetupCom(0x%p, 0x%08x, 0x%08x)", hFile, dwInQueue, dwOutQueue);
|
log_misc(COMM_LOGGER, "SetupCom(0x%p, 0x%08x, 0x%08x)", hFile, dwInQueue, dwOutQueue);
|
||||||
|
|
||||||
com_hook_t* hook = com_hook_list;
|
com_hook_t* hook = com_hook_list;
|
||||||
while (hook != NULL) {
|
while (hook != NULL) {
|
||||||
if (hook->virtual_handle == hFile && hook->SetupComm != NULL) {
|
if (*hook->virtual_handle == hFile) {
|
||||||
|
if (hook->SetupComm == NULL) {
|
||||||
|
log_error(COMM_LOGGER, "SetupComm(%ls) unimplemented", hook->wName);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
return hook->SetupComm(hook->data, dwInQueue, dwOutQueue);
|
return hook->SetupComm(hook->data, dwInQueue, dwOutQueue);
|
||||||
}
|
}
|
||||||
|
hook = hook->next;
|
||||||
}
|
}
|
||||||
return TrueSetupComm(hFile, dwInQueue, dwOutQueue);
|
return TrueSetupComm(hFile, dwInQueue, dwOutQueue);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL WINAPI FakePurgeComm(HANDLE hFile, DWORD dwFlags) {
|
BOOL WINAPI FakePurgeComm(HANDLE hFile, DWORD dwFlags) {
|
||||||
log_misc("comm", "PurgeComm(0x%p, 0x%08x)", hFile, dwFlags);
|
log_misc(COMM_LOGGER, "PurgeComm(0x%p, 0x%08x)", hFile, dwFlags);
|
||||||
|
|
||||||
com_hook_t* hook = com_hook_list;
|
com_hook_t* hook = com_hook_list;
|
||||||
while (hook != NULL) {
|
while (hook != NULL) {
|
||||||
if (hook->virtual_handle == hFile && hook->PurgeComm != NULL) {
|
if (*hook->virtual_handle == hFile) {
|
||||||
|
if (hook->PurgeComm == NULL) {
|
||||||
|
log_error(COMM_LOGGER, "PurgeComm(%ls) unimplemented", hook->wName);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
return hook->PurgeComm(hook->data, dwFlags);
|
return hook->PurgeComm(hook->data, dwFlags);
|
||||||
}
|
}
|
||||||
|
hook = hook->next;
|
||||||
}
|
}
|
||||||
return TruePurgeComm(hFile, dwFlags);
|
return TruePurgeComm(hFile, dwFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL WINAPI FakeGetCommModemStatus(HANDLE hFile, LPDWORD lpModelStat) {
|
BOOL WINAPI FakeGetCommModemStatus(HANDLE hFile, LPDWORD lpModelStat) {
|
||||||
log_misc("comm", "GetCommModemStatus(0x%p, 0x%p)", hFile, lpModelStat);
|
log_misc(COMM_LOGGER, "GetCommModemStatus(0x%p, 0x%p)", hFile, lpModelStat);
|
||||||
|
|
||||||
com_hook_t* hook = com_hook_list;
|
com_hook_t* hook = com_hook_list;
|
||||||
while (hook != NULL) {
|
while (hook != NULL) {
|
||||||
if (hook->virtual_handle == hFile && hook->GetCommModemStatus != NULL) {
|
if (*hook->virtual_handle == hFile) {
|
||||||
|
if (hook->GetCommModemStatus == NULL) {
|
||||||
|
log_error(COMM_LOGGER, "GetCommModemStatus(%ls) unimplemented", hook->wName);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
return hook->GetCommModemStatus(hook->data, lpModelStat);
|
return hook->GetCommModemStatus(hook->data, lpModelStat);
|
||||||
}
|
}
|
||||||
|
hook = hook->next;
|
||||||
}
|
}
|
||||||
return TrueGetCommModemStatus(hFile, lpModelStat);
|
return TrueGetCommModemStatus(hFile, lpModelStat);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL WINAPI FakeWaitCommEvent(HANDLE hFile, LPDWORD lpEvtMask, LPOVERLAPPED lpOverlapped) {
|
BOOL WINAPI FakeWaitCommEvent(HANDLE hFile, LPDWORD lpEvtMask, LPOVERLAPPED lpOverlapped) {
|
||||||
log_misc("comm", "WaitCommEvent");
|
log_misc(COMM_LOGGER, "WaitCommEvent");
|
||||||
|
|
||||||
com_hook_t* hook = com_hook_list;
|
com_hook_t* hook = com_hook_list;
|
||||||
while (hook != NULL) {
|
while (hook != NULL) {
|
||||||
if (hook->virtual_handle == hFile && hook->WaitCommEvent != NULL) {
|
if (*hook->virtual_handle == hFile) {
|
||||||
|
if (hook->WaitCommEvent == NULL) {
|
||||||
|
log_error(COMM_LOGGER, "WaitCommEvent(%ls) unimplemented", hook->wName);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
return hook->WaitCommEvent(hook->data, lpEvtMask, lpOverlapped);
|
return hook->WaitCommEvent(hook->data, lpEvtMask, lpOverlapped);
|
||||||
}
|
}
|
||||||
|
hook = hook->next;
|
||||||
}
|
}
|
||||||
return TrueWaitCommEvent(hFile, lpEvtMask, lpOverlapped);
|
return TrueWaitCommEvent(hFile, lpEvtMask, lpOverlapped);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL WINAPI FakeClearCommError(HANDLE hFile, LPDWORD lpErrors, LPCOMSTAT lpStat) {
|
BOOL WINAPI FakeClearCommError(HANDLE hFile, LPDWORD lpErrors, LPCOMSTAT lpStat) {
|
||||||
log_misc("comm", "ClearCommError");
|
log_misc(COMM_LOGGER, "ClearCommError");
|
||||||
|
|
||||||
com_hook_t* hook = com_hook_list;
|
com_hook_t* hook = com_hook_list;
|
||||||
while (hook != NULL) {
|
while (hook != NULL) {
|
||||||
if (hook->virtual_handle == hFile && hook->ClearCommError != NULL) {
|
if (*hook->virtual_handle == hFile) {
|
||||||
|
if (hook->ClearCommError == NULL) {
|
||||||
|
log_error(COMM_LOGGER, "ClearCommError(%ls) unimplemented", hook->wName);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
return hook->ClearCommError(hook->data, lpErrors, lpStat);
|
return hook->ClearCommError(hook->data, lpErrors, lpStat);
|
||||||
}
|
}
|
||||||
|
hook = hook->next;
|
||||||
}
|
}
|
||||||
return TrueClearCommError(hFile, lpErrors, lpStat);
|
return TrueClearCommError(hFile, lpErrors, lpStat);
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ typedef BOOL(FnWaitCommEvent)(void* com, LPDWORD lpEvtMask, LPOVERLAPPED lpOverl
|
|||||||
typedef BOOL(FnClearCommError)(void* com, LPDWORD lpErrors, LPCOMSTAT lpStat);
|
typedef BOOL(FnClearCommError)(void* com, LPDWORD lpErrors, LPCOMSTAT lpStat);
|
||||||
|
|
||||||
typedef struct com_hook {
|
typedef struct com_hook {
|
||||||
HANDLE virtual_handle;
|
LPHANDLE virtual_handle;
|
||||||
WCHAR wName[7]; // max is COM255
|
WCHAR wName[7]; // max is COM255
|
||||||
BYTE com;
|
BYTE com;
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
#include <Winsock2.h>
|
||||||
#include <shlwapi.h>
|
#include <shlwapi.h>
|
||||||
#pragma comment(lib, "Shlwapi.lib")
|
#pragma comment(lib, "Shlwapi.lib")
|
||||||
|
|
||||||
@ -6,107 +7,52 @@
|
|||||||
|
|
||||||
#include "../lib/mice/mice.h"
|
#include "../lib/mice/mice.h"
|
||||||
#include "drivers/mx.h"
|
#include "drivers/mx.h"
|
||||||
#include "files.h"
|
|
||||||
#include "com.h"
|
|
||||||
#include "micesetupapi.h"
|
#include "micesetupapi.h"
|
||||||
|
#include "network.h"
|
||||||
|
#include "processes.h"
|
||||||
|
|
||||||
WCHAR exePath[MAX_PATH + 1];
|
WCHAR exePath[MAX_PATH + 1];
|
||||||
|
|
||||||
void enable_traces() {
|
void enable_traces() {
|
||||||
if (wcscmp(exePath, L"Game.exe") == 0) {
|
patches_t patches;
|
||||||
*(DWORD*)(0x008717a0) = 1;
|
char error[256];
|
||||||
*(DWORD*)(0x00871728) = 1;
|
if (!load_patches(&patches, "patches.json", error)) {
|
||||||
*(DWORD*)(0x00871cd8) = 1;
|
log_error(BOOT_LOGGER, "Failed to load patches file: %s", error);
|
||||||
*(DWORD*)(0x00872660) = 1;
|
|
||||||
*(DWORD*)(0x0087297c) = 1; // LOG_EN_EEPROM
|
|
||||||
*(DWORD*)(0x00872980) = 1;
|
|
||||||
*(DWORD*)(0x00872988) = 1;
|
|
||||||
*(DWORD*)(0x00873540) = 1;
|
|
||||||
*(DWORD*)(0x00873538) = 1;
|
|
||||||
*(DWORD*)(0x0087f890) = 1;
|
|
||||||
*(DWORD*)(0x00882ce4) = 1;
|
|
||||||
*(DWORD*)(0x00882cec) = 1;
|
|
||||||
*(DWORD*)(0x00883018) = 1;
|
|
||||||
*(DWORD*)(0x00886ff8) = 1;
|
|
||||||
*(DWORD*)(0x0088b1b8) = 1;
|
|
||||||
*(DWORD*)(0x0088b1c0) = 1;
|
|
||||||
} else if (wcscmp(exePath, L"ALLNetProc_Win.exe") == 0) {
|
|
||||||
*(DWORD*)(0x004f48b0) = 1; // LOG_EN_DONGLE
|
|
||||||
*(DWORD*)(0x004f989c) = 1; // LOG_EN_PCP
|
|
||||||
*(DWORD*)(0x004f7d04) = 1; // LOG_EN_EEPROM
|
|
||||||
*(DWORD*)(0x004f7d08) = 1; // LOG_EN_BACKUP
|
|
||||||
*(DWORD*)(0x004f8118) = 1; // LOG_EN_RTC
|
|
||||||
*(DWORD*)(0x004f96dc) = 1; // LOG_EN_GFETCHER
|
|
||||||
*(DWORD*)(0x004f8338) = 1; // LOG_EN_NETWORK
|
|
||||||
*(DWORD*)(0x004f88c0) = 1; // LOG_EN_MASTER
|
|
||||||
*(DWORD*)(0x004f88b0) = 1; // LOG_EN_HM
|
|
||||||
*(DWORD*)(0x004f8330) = 1; // LOG_EN_SRAM
|
|
||||||
*(DWORD*)(0x004f9728) = 1; // LOG_EN_PLATFORM
|
|
||||||
|
|
||||||
//*(DWORD*)(0x004f9e7c) = 5; // LOG_EN_ASSERTS (handled by the bellow
|
|
||||||
// instead)
|
|
||||||
*(DWORD*)(0x004e884c) = 10; // ALPB_LOG_LEVEL (0=None, 1=Error,
|
|
||||||
// 2=Warning, 3=Most, 4=Debug)
|
|
||||||
} else if (wcscmp(exePath, L"ORIG_mxsegaboot.exe") == 0 || wcscmp(exePath, L"mxsegaboot.exe") == 0) {
|
|
||||||
// start of am
|
|
||||||
*(DWORD*)(0x0054fcd8) = 1; // LOG_EN_JVS_DRIVER
|
|
||||||
*(DWORD*)(0x00538810) = 1; // LOG_EN_DIPSW
|
|
||||||
*(DWORD*)(0x0054afc8) = 1; // LOG_EN_ATA
|
|
||||||
*(DWORD*)(0x00544b78) = 1; // LOG_EN_DONGLE
|
|
||||||
*(DWORD*)(0x00536c98) = 1; // LOG_EN_EEPROM
|
|
||||||
*(DWORD*)(0x00537834) = 1; // LOG_EN_GCATCHER
|
|
||||||
*(DWORD*)(0x00537d4c) = 1; // LOG_EN_GDELIVER
|
|
||||||
*(DWORD*)(0x0053828c) = 1; // LOG_EN_GFETCHER
|
|
||||||
*(DWORD*)(0x00547fd0) = 1; // LOG_EN_HWRESET
|
|
||||||
*(DWORD*)(0x00547fd8) = 1; // LOG_EN_PLATFORM
|
|
||||||
*(DWORD*)(0x00548268) = 1; // LOG_EN_HM
|
|
||||||
*(DWORD*)(0x00536f30) = 1; // LOG_EN_BACKUP
|
|
||||||
*(DWORD*)(0x00547fcc) = 1; // LOG_EN_CMOS
|
|
||||||
*(DWORD*)(0x005382d8) = 1; // LOG_EN_INSTALL
|
|
||||||
*(DWORD*)(0x00538818) = 1; // LOG_EN_JVS
|
|
||||||
*(DWORD*)(0x00544b68) = 1; // LOG_EN_JVSP
|
|
||||||
*(DWORD*)(0x0054b3d8) = 1; // LOG_EN_MASTER
|
|
||||||
*(DWORD*)(0x00548280) = 1; // LOG_EN_NETWORK
|
|
||||||
*(DWORD*)(0x00548050) = 1; // LOG_EN_RTC
|
|
||||||
*(DWORD*)(0x00536c94) = 1; // LOG_EN_SRAM
|
|
||||||
*(DWORD*)(0x005487f8) = 1; // LOG_EN_STORAGE
|
|
||||||
*(DWORD*)(0x00536c90) = 1; // LOG_EN_SYS
|
|
||||||
// end of am
|
|
||||||
*(DWORD*)(0x00536c70) = 1; // LOG_EN_PCPT
|
|
||||||
} else if (wcscmp(exePath, L"maimai_dump_.exe") == 0) {
|
|
||||||
*(DWORD*)(0x00c8ab7c) = 1; // LOG_EN_SRAM
|
|
||||||
*(DWORD*)(0x00f406f0) = 1; // LOG_EN_CABINET_DL
|
|
||||||
*(DWORD*)(0x00c88680) = 1; // LOG_EN_INSTALL
|
|
||||||
*(DWORD*)(0x00c8ab78) = 1; // LOG_EN_EEPROM
|
|
||||||
*(DWORD*)(0x00c88608) = 1; // LOG_EN_PLATFORM
|
|
||||||
*(DWORD*)(0x00c88dd0) = 1; // LOG_EN_STORAGE
|
|
||||||
*(DWORD*)(0x00ca25ec) = 1; // LOG_EN_PCP
|
|
||||||
*(DWORD*)(0x00c96ed0) = 1; // LOG_EN_HM
|
|
||||||
*(DWORD*)(0x00f406ec) = 1; // LOG_EN_HTTP
|
|
||||||
*(DWORD*)(0x00c89ca8) = 1; // LOG_EN_DIPSW
|
|
||||||
*(DWORD*)(0x00c96ed8) = 1; // LOG_EN_DONGLE
|
|
||||||
*(DWORD*)(0x00c9a83c) = 1; // LOG_EN_JVSP
|
|
||||||
*(DWORD*)(0x00c89730) = 1; // LOG_EN_NETWORK
|
|
||||||
*(DWORD*)(0x00c9a440) = 1; // LOG_EN_JVST_THREAD
|
|
||||||
*(DWORD*)(0x00c8ab80) = 1; // LOG_EN_JVS
|
|
||||||
*(DWORD*)(0x00c89fc8) = 1; // LOG_EN_MASTER
|
|
||||||
*(DWORD*)(0x00c88bb8) = 1; // LOG_EN_RTC
|
|
||||||
*(DWORD*)(0x00c9e420) = 1; // LOG_EN_JVST_DRIVER
|
|
||||||
*(DWORD*)(0x00c89320) = 1; // LOG_EN_BACKUP
|
|
||||||
*(DWORD*)(0x00c88bb4) = 1; // LOG_EN_HWRESET
|
|
||||||
*(DWORD*)(0x00c830e8) = 1; // LOG_EN
|
|
||||||
} else if (wcscmp(exePath, L"mxnetwork.exe") == 0) {
|
|
||||||
*(DWORD*)(0x004438e0) = 1; // LOG_EN_PCP
|
|
||||||
*(DWORD*)(0x004433f8) = 1; // LOG_EN_UTL
|
|
||||||
} else {
|
} else {
|
||||||
log_warning("traces", "No known traces for %ls", exePath);
|
char exePathC[MAX_PATH + 1];
|
||||||
|
WideCharToMultiByte(CP_ACP, 0, exePath, -1, exePathC, sizeof exePathC, NULL, NULL);
|
||||||
|
|
||||||
|
for (int i = 0; i < patches.nopatchsets; i++) {
|
||||||
|
patchset_t* patchset = patches.patchsets[i];
|
||||||
|
|
||||||
|
// Require the binary explicitly named
|
||||||
|
if (patchset->binary_name == NULL || strcmp(patchset->binary_name, exePathC) != 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!patchset->apply) continue;
|
||||||
|
|
||||||
|
for (int j = 0; j < patchset->nopatches; j++) {
|
||||||
|
patch_t patch = patchset->patches[j];
|
||||||
|
|
||||||
|
if (memcmp(patch.from, (void*)patch.offset, patch.count) != 0) {
|
||||||
|
log_error(BOOT_LOGGER, "Patch %s[%d] failed! from-value missmatch", patchset->name, j);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy((void*)patch.offset, patch.to, patch.count);
|
||||||
|
log_misc(BOOT_LOGGER, "Patched %d bytes at %08x", patch.count, patch.offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
free_patches(&patches);
|
||||||
}
|
}
|
||||||
|
|
||||||
void prebind_hooks() {
|
void prebind_hooks() {
|
||||||
hook_setupapi();
|
hook_setupapi();
|
||||||
hook_commio();
|
hook_commio();
|
||||||
hook_io();
|
hook_io();
|
||||||
|
hook_processes();
|
||||||
|
hook_network();
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_injection() {
|
void init_injection() {
|
||||||
@ -114,8 +60,6 @@ void init_injection() {
|
|||||||
setup_logging();
|
setup_logging();
|
||||||
log_info(BOOT_LOGGER, "Handover complete. Now executing within %ls", exePath);
|
log_info(BOOT_LOGGER, "Handover complete. Now executing within %ls", exePath);
|
||||||
|
|
||||||
dmi_build_default();
|
|
||||||
|
|
||||||
enable_traces();
|
enable_traces();
|
||||||
|
|
||||||
setup_columba();
|
setup_columba();
|
||||||
|
@ -4,6 +4,17 @@
|
|||||||
#include "../lib/mice/mice.h"
|
#include "../lib/mice/mice.h"
|
||||||
#include "files.h"
|
#include "files.h"
|
||||||
|
|
||||||
|
// Much easier than pulling in winddk.h
|
||||||
|
typedef LARGE_INTEGER PHYSICAL_ADDRESS, *PPHYSICAL_ADDRESS;
|
||||||
|
typedef struct {
|
||||||
|
PHYSICAL_ADDRESS addr;
|
||||||
|
DWORD data_type;
|
||||||
|
DWORD bytes;
|
||||||
|
} columba_request;
|
||||||
|
|
||||||
|
#define DMI_HEADER_START 0x000f0000
|
||||||
|
#define DMI_TABLES_START 0x000f1000
|
||||||
|
|
||||||
BOOL columba_DeviceIoControl(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer,
|
BOOL columba_DeviceIoControl(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer,
|
||||||
DWORD nOutBufferSize, LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) {
|
DWORD nOutBufferSize, LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) {
|
||||||
switch (dwIoControlCode) {
|
switch (dwIoControlCode) {
|
||||||
@ -12,15 +23,23 @@ BOOL columba_DeviceIoControl(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nIn
|
|||||||
"DeviceIoControl(<columba>, <read dmi>, 0x%p, 0x%x, -, "
|
"DeviceIoControl(<columba>, <read dmi>, 0x%p, 0x%x, -, "
|
||||||
"0x%x, -, -)",
|
"0x%x, -, -)",
|
||||||
lpInBuffer, nInBufferSize, nOutBufferSize);
|
lpInBuffer, nInBufferSize, nOutBufferSize);
|
||||||
|
columba_request* request = (columba_request*)lpInBuffer;
|
||||||
|
log_info("columba", "Physical read: 0x%04x %ss at %08X", request->bytes,
|
||||||
|
request->data_type == 1 ? "byte"
|
||||||
|
: request->data_type == 2 ? "short"
|
||||||
|
: request->data_type == 4 ? "long"
|
||||||
|
: "void",
|
||||||
|
request->addr);
|
||||||
|
DWORD requested_size = request->data_type * request->bytes;
|
||||||
|
|
||||||
memset(lpOutBuffer, 0, nOutBufferSize);
|
memset(lpOutBuffer, 0, nOutBufferSize);
|
||||||
|
|
||||||
if (((LPWORD)lpInBuffer)[0] == 0x0000) {
|
if (request->addr.QuadPart == DMI_HEADER_START) {
|
||||||
DMI_HEADER dmi = {
|
DMI_HEADER dmi = {
|
||||||
.Signature = {'_', 'D', 'M', 'I', '_'},
|
.Signature = {'_', 'D', 'M', 'I', '_'},
|
||||||
.Checksum = 0,
|
.Checksum = 0,
|
||||||
.StructLength = dmi_size,
|
.StructLength = dmi_size,
|
||||||
.StructAddr = 0xdeeabeef,
|
.StructAddr = DMI_TABLES_START,
|
||||||
.NumberOfStructs = 0x20,
|
.NumberOfStructs = 0x20,
|
||||||
.BCDRevision = 0,
|
.BCDRevision = 0,
|
||||||
.Reserved = 0,
|
.Reserved = 0,
|
||||||
@ -28,10 +47,13 @@ BOOL columba_DeviceIoControl(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nIn
|
|||||||
dmi.Checksum = dmi_calc_checksum((char*)&dmi, 15);
|
dmi.Checksum = dmi_calc_checksum((char*)&dmi, 15);
|
||||||
|
|
||||||
memcpy(lpOutBuffer, &dmi, sizeof(DMI_HEADER));
|
memcpy(lpOutBuffer, &dmi, sizeof(DMI_HEADER));
|
||||||
if (lpBytesReturned) *lpBytesReturned = sizeof(DMI_HEADER);
|
if (lpBytesReturned) *lpBytesReturned = requested_size;
|
||||||
} else {
|
} else if (request->addr.QuadPart == DMI_TABLES_START) {
|
||||||
memcpy(lpOutBuffer, dmi_table, dmi_size);
|
memcpy(lpOutBuffer, dmi_table, dmi_size);
|
||||||
if (lpBytesReturned) *lpBytesReturned = dmi_size;
|
if (lpBytesReturned) *lpBytesReturned = 0x10000;
|
||||||
|
} else {
|
||||||
|
log_error("columna", "Request to unmapped memory location: %08x", request->addr);
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -40,10 +62,12 @@ BOOL columba_DeviceIoControl(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nIn
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return FALSE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup_columba() {
|
void setup_columba() {
|
||||||
|
dmi_build_default();
|
||||||
|
|
||||||
file_hook_t* columba = new_file_hook(L"\\\\.\\columba");
|
file_hook_t* columba = new_file_hook(L"\\\\.\\columba");
|
||||||
columba->DeviceIoControl = &columba_DeviceIoControl;
|
columba->DeviceIoControl = &columba_DeviceIoControl;
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#include "../com.h"
|
||||||
#include "../files.h"
|
#include "../files.h"
|
||||||
#include <initguid.h>
|
#include <initguid.h>
|
||||||
|
|
||||||
|
@ -3,16 +3,16 @@
|
|||||||
#include "../lib/mice/mice.h"
|
#include "../lib/mice/mice.h"
|
||||||
#include "mx.h"
|
#include "mx.h"
|
||||||
|
|
||||||
BOOL mxjvs_DeviceIoControl(DWORD dwIoControlCode, LPVOID lpInBuffer,
|
BOOL JVS_SENSE = false;
|
||||||
DWORD nInBufferSize, LPVOID lpOutBuffer,
|
|
||||||
DWORD nOutBufferSize, LPDWORD lpBytesReturned,
|
BOOL mxjvs_DeviceIoControl(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer,
|
||||||
LPOVERLAPPED lpOverlapped) {
|
DWORD nOutBufferSize, LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) {
|
||||||
switch (dwIoControlCode) {
|
switch (dwIoControlCode) {
|
||||||
case IOCTL_MXJVS_EXCHANGE:
|
case IOCTL_MXJVS_EXCHANGE:
|
||||||
log_misc("mxjvs",
|
log_error("mxjvs",
|
||||||
"DeviceIoControl(<mxjvs>, <exchange>, 0x%p, 0x%x, -, "
|
"DeviceIoControl(<mxjvs>, <exchange>, 0x%p, 0x%x, -, "
|
||||||
"0x%x, -, -)",
|
"0x%x, -, -)",
|
||||||
lpInBuffer, nInBufferSize, nOutBufferSize);
|
lpInBuffer, nInBufferSize, nOutBufferSize);
|
||||||
|
|
||||||
// mxjvsDevice->exchange(
|
// mxjvsDevice->exchange(
|
||||||
// lpbyte(lpInBuffer), nInBufferSize & 0xFFFF,
|
// lpbyte(lpInBuffer), nInBufferSize & 0xFFFF,
|
||||||
@ -29,9 +29,38 @@ BOOL mxjvs_DeviceIoControl(DWORD dwIoControlCode, LPVOID lpInBuffer,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOL mxjvs_SetupComm(void* com, DWORD dwInQueue, DWORD dwOutQueue) { return TRUE; }
|
||||||
|
BOOL mxjvs_PurgeComm(void* com, DWORD dwFlags) { return TRUE; }
|
||||||
|
BOOL mxjvs_GetCommState(void* com, LPDCB lpDCB) { return TRUE; }
|
||||||
|
BOOL mxjvs_SetCommTimeouts(void* com, LPCOMMTIMEOUTS lpDCB) { return TRUE; }
|
||||||
|
|
||||||
|
BOOL mxjvs_GetCommModemStatus(void* com, LPDWORD lpModelStat) {
|
||||||
|
*lpModelStat = JVS_SENSE ? MS_DSR_ON : 0;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL mxjvs_SetCommState(void* com, LPDCB lpDCB) {
|
||||||
|
char PARITY[] = {'N', 'O', 'E', 'M', 'S'};
|
||||||
|
char* STOP[] = {"1", "1.5", "2"};
|
||||||
|
log_info("mxjvs", "Switching to %d baud (%d%c%s)", lpDCB->BaudRate, lpDCB->ByteSize, PARITY[lpDCB->Parity],
|
||||||
|
STOP[lpDCB->StopBits]);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
void setup_mxjvs() {
|
void setup_mxjvs() {
|
||||||
file_hook_t* mxjvs = new_file_hook(L"\\\\.\\mxjvs");
|
file_hook_t* mxjvs = new_file_hook(L"\\\\.\\mxjvs");
|
||||||
mxjvs->DeviceIoControl = &mxjvs_DeviceIoControl;
|
mxjvs->DeviceIoControl = &mxjvs_DeviceIoControl;
|
||||||
|
|
||||||
|
com_hook_t* jvscom = new_com_hook(-1);
|
||||||
|
jvscom->GetCommState = mxjvs_GetCommState;
|
||||||
|
jvscom->SetCommState = mxjvs_SetCommState;
|
||||||
|
jvscom->SetCommTimeouts = mxjvs_SetCommTimeouts;
|
||||||
|
jvscom->SetupComm = mxjvs_SetupComm;
|
||||||
|
jvscom->PurgeComm = mxjvs_PurgeComm;
|
||||||
|
jvscom->GetCommModemStatus = mxjvs_GetCommModemStatus;
|
||||||
|
|
||||||
hook_file(mxjvs);
|
hook_file(mxjvs);
|
||||||
|
hook_com(jvscom);
|
||||||
|
free(jvscom->virtual_handle);
|
||||||
|
jvscom->virtual_handle = mxjvs->virtual_handle;
|
||||||
}
|
}
|
||||||
|
@ -208,15 +208,15 @@ BOOL mxsmbus_DeviceIoControl(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nIn
|
|||||||
case PCA9535_WRITE:
|
case PCA9535_WRITE:
|
||||||
switch (i2c_packet->reg) {
|
switch (i2c_packet->reg) {
|
||||||
case PCA9535_OUT1:
|
case PCA9535_OUT1:
|
||||||
log_error("mxsmbus", "pca9535 OUT1: %02x %02x", i2c_packet->data[0],
|
log_info("mxsmbus", "pca9535 OUT1: %02x %02x", i2c_packet->data[0],
|
||||||
i2c_packet->data[1]);
|
i2c_packet->data[1]);
|
||||||
break;
|
break;
|
||||||
case PCA9535_INV0:
|
case PCA9535_INV0:
|
||||||
log_error("mxsmbus", "pca9535 INV0: %02x %02x", i2c_packet->data[0],
|
log_info("mxsmbus", "pca9535 INV0: %02x %02x", i2c_packet->data[0],
|
||||||
i2c_packet->data[1]);
|
i2c_packet->data[1]);
|
||||||
break;
|
break;
|
||||||
case PCA9535_INV1:
|
case PCA9535_INV1:
|
||||||
log_error("mxsmbus", "pca9535 INV1: %02x %02x", i2c_packet->data[0],
|
log_info("mxsmbus", "pca9535 INV1: %02x %02x", i2c_packet->data[0],
|
||||||
i2c_packet->data[1]);
|
i2c_packet->data[1]);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -34,7 +34,7 @@ BOOL mxsram_DeviceIoControl(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInB
|
|||||||
|
|
||||||
switch (dwIoControlCode) {
|
switch (dwIoControlCode) {
|
||||||
case IOCTL_MXSRAM_PING: // Get version
|
case IOCTL_MXSRAM_PING: // Get version
|
||||||
log_misc("mxsram",
|
log_info("mxsram",
|
||||||
"DeviceIoControl(<mxsram>, <ping>, 0x%p, 0x%x, -, 0x%x, "
|
"DeviceIoControl(<mxsram>, <ping>, 0x%p, 0x%x, -, 0x%x, "
|
||||||
"-, -)",
|
"-, -)",
|
||||||
lpInBuffer, nInBufferSize, nOutBufferSize);
|
lpInBuffer, nInBufferSize, nOutBufferSize);
|
||||||
@ -43,7 +43,7 @@ BOOL mxsram_DeviceIoControl(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInB
|
|||||||
if (lpBytesReturned) *lpBytesReturned = 4;
|
if (lpBytesReturned) *lpBytesReturned = 4;
|
||||||
break;
|
break;
|
||||||
case IOCTL_DISK_GET_DRIVE_GEOMETRY:
|
case IOCTL_DISK_GET_DRIVE_GEOMETRY:
|
||||||
log_misc("mxsram",
|
log_info("mxsram",
|
||||||
"DeviceIoControl(<mxsram>, <get drive geom>, 0x%p, "
|
"DeviceIoControl(<mxsram>, <get drive geom>, 0x%p, "
|
||||||
"0x%x, -, 0x%x, -, -)",
|
"0x%x, -, 0x%x, -, -)",
|
||||||
lpInBuffer, nInBufferSize, nOutBufferSize);
|
lpInBuffer, nInBufferSize, nOutBufferSize);
|
||||||
@ -58,7 +58,7 @@ BOOL mxsram_DeviceIoControl(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInB
|
|||||||
if (lpBytesReturned) *lpBytesReturned = sizeof(DISK_GEOMETRY);
|
if (lpBytesReturned) *lpBytesReturned = sizeof(DISK_GEOMETRY);
|
||||||
break;
|
break;
|
||||||
case IOCTL_MXSRAM_GET_SECTOR_SIZE:
|
case IOCTL_MXSRAM_GET_SECTOR_SIZE:
|
||||||
log_misc("mxsram",
|
log_info("mxsram",
|
||||||
"DeviceIoControl(<mxsram>, <get sector size>, 0x%p, "
|
"DeviceIoControl(<mxsram>, <get sector size>, 0x%p, "
|
||||||
"0x%x, -, 0x%x, -, -)",
|
"0x%x, -, 0x%x, -, -)",
|
||||||
lpInBuffer, nInBufferSize, nOutBufferSize);
|
lpInBuffer, nInBufferSize, nOutBufferSize);
|
||||||
@ -118,6 +118,7 @@ void setup_mxsram() {
|
|||||||
sram_restore();
|
sram_restore();
|
||||||
|
|
||||||
file_hook_t* mxsram = new_file_hook(L"\\\\.\\mxsram");
|
file_hook_t* mxsram = new_file_hook(L"\\\\.\\mxsram");
|
||||||
|
mxsram->DeviceIoControl = &mxsram_DeviceIoControl;
|
||||||
mxsram->SetFilePointer = &mxsram_SetFilePointer;
|
mxsram->SetFilePointer = &mxsram_SetFilePointer;
|
||||||
mxsram->ReadFile = &mxsram_ReadFile;
|
mxsram->ReadFile = &mxsram_ReadFile;
|
||||||
mxsram->WriteFile = &mxsram_WriteFile;
|
mxsram->WriteFile = &mxsram_WriteFile;
|
||||||
|
@ -32,10 +32,10 @@ BOOL mxsuperio_DeviceIoControl(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD n
|
|||||||
if (lpBytesReturned) *lpBytesReturned = 4;
|
if (lpBytesReturned) *lpBytesReturned = 4;
|
||||||
break;
|
break;
|
||||||
case IOCTL_MXSUPERIO_READ:
|
case IOCTL_MXSUPERIO_READ:
|
||||||
log_warning("mxsuperio",
|
log_misc("mxsuperio",
|
||||||
"DeviceIoControl(<mxsuperio>, <read>, 0x%p, 0x%x, -, "
|
"DeviceIoControl(<mxsuperio>, <read>, 0x%p, 0x%x, -, "
|
||||||
"0x%x, -, -)",
|
"0x%x, -, -)",
|
||||||
lpInBuffer, nInBufferSize, nOutBufferSize);
|
lpInBuffer, nInBufferSize, nOutBufferSize);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
BYTE chipId = 0|1
|
BYTE chipId = 0|1
|
||||||
|
@ -19,7 +19,8 @@ file_hook_t* new_file_hook(LPCWSTR filename) {
|
|||||||
}
|
}
|
||||||
void hook_file(file_hook_t* hook) {
|
void hook_file(file_hook_t* hook) {
|
||||||
hook->next = NULL;
|
hook->next = NULL;
|
||||||
hook->virtual_handle = NULL;
|
hook->virtual_handle = (LPHANDLE)malloc(sizeof(HANDLE));
|
||||||
|
*hook->virtual_handle = NULL;
|
||||||
if (file_hook_list == NULL) {
|
if (file_hook_list == NULL) {
|
||||||
file_hook_list = hook;
|
file_hook_list = hook;
|
||||||
return;
|
return;
|
||||||
@ -30,8 +31,9 @@ void hook_file(file_hook_t* hook) {
|
|||||||
hl->next = hook;
|
hl->next = hook;
|
||||||
};
|
};
|
||||||
|
|
||||||
drive_redirect_t DRIVE_REDIRECT_TABLE[] = {{"Y:\\", ".\\dev\\Y\\"},
|
drive_redirect_t DRIVE_REDIRECT_TABLE[] = {
|
||||||
{"C:\\Documents and Settings\\AppUser\\temp\\", ".\\dev\\temp\\"}};
|
{.drive = "Y:\\", .path = ".\\dev\\Y\\"},
|
||||||
|
{.drive = "C:\\Documents and Settings\\AppUser\\temp\\", .path = ".\\dev\\temp\\"}};
|
||||||
|
|
||||||
char* redirect_path(char* path) {
|
char* redirect_path(char* path) {
|
||||||
for (int i = 0; i < sizeof DRIVE_REDIRECT_TABLE / sizeof DRIVE_REDIRECT_TABLE[0]; i++) {
|
for (int i = 0; i < sizeof DRIVE_REDIRECT_TABLE / sizeof DRIVE_REDIRECT_TABLE[0]; i++) {
|
||||||
@ -60,30 +62,17 @@ char* redirect_path(char* path) {
|
|||||||
HANDLE WINAPI FakeCreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
|
HANDLE WINAPI FakeCreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
|
||||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
|
LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
|
||||||
DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) {
|
DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) {
|
||||||
// for (int i = 0; i < (sizeof HOOKED_HANDLES) / (sizeof HANDLE_HOOK);
|
|
||||||
// i++) { HANDLE_HOOK hook = HOOKED_HANDLES[i]; if (lpFileName &&
|
|
||||||
// wcscmp(lpFileName, hook.wName) == 0) {
|
|
||||||
// log_warning(HOOKS_LOGGER, "CreateFileW intercepting driver file %ls",
|
|
||||||
// hook.wName); return hook.handle;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// HANDLE result = TrueCreateFileW(lpFileName, dwDesiredAccess,
|
|
||||||
// dwShareMode, lpSecurityAttributes, dwCreationDisposition,
|
|
||||||
// dwFlagsAndAttributes, hTemplateFile); log_misc(HOOKS_LOGGER,
|
|
||||||
// "CreateFileW(%ls) -> 0x%p", lpFileName, result);
|
|
||||||
|
|
||||||
HANDLE handle = NULL;
|
HANDLE handle = NULL;
|
||||||
|
|
||||||
file_hook_t* hook = file_hook_list;
|
file_hook_t* hook = file_hook_list;
|
||||||
while (hook != NULL) {
|
while (hook != NULL) {
|
||||||
if (wcscmp(lpFileName, hook->filename) == 0) {
|
if (wcscmp(lpFileName, hook->filename) == 0) {
|
||||||
if (hook->virtual_handle == NULL) {
|
if (*hook->virtual_handle == NULL) {
|
||||||
// TODO: Assign handles better!
|
// TODO: Assign handles better!
|
||||||
hook->virtual_handle = fake_handle;
|
*hook->virtual_handle = fake_handle;
|
||||||
((size_t)fake_handle)++;
|
((size_t)fake_handle)++;
|
||||||
}
|
}
|
||||||
handle = hook->virtual_handle;
|
handle = *hook->virtual_handle;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
hook = hook->next;
|
hook = hook->next;
|
||||||
@ -119,18 +108,23 @@ BOOL WINAPI FakeDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lp
|
|||||||
|
|
||||||
file_hook_t* hook = file_hook_list;
|
file_hook_t* hook = file_hook_list;
|
||||||
while (hook != NULL) {
|
while (hook != NULL) {
|
||||||
if (hook->virtual_handle == hDevice) {
|
if (*hook->virtual_handle == hDevice) {
|
||||||
if (hook->DeviceIoControl) {
|
if (hook->DeviceIoControl) {
|
||||||
// TODO: Less jank
|
// TODO: Less jank
|
||||||
if (lpOverlapped != NULL) SetEvent(lpOverlapped->hEvent);
|
if (lpOverlapped != NULL) SetEvent(lpOverlapped->hEvent);
|
||||||
|
|
||||||
return hook->DeviceIoControl(dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize,
|
return hook->DeviceIoControl(dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize,
|
||||||
lpBytesReturned, lpOverlapped);
|
lpBytesReturned, lpOverlapped);
|
||||||
|
} else {
|
||||||
|
log_error(HOOKS_LOGGER, "DeviceIoControl(%ls) unimplemented", hook->filename);
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hook = hook->next;
|
hook = hook->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// log_warning(HOOKS_LOGGER, "DeviceIoControl(0x%p, 0x%08x, -, -, -, -, 0, 0)", hDevice, dwIoControlCode);
|
||||||
|
|
||||||
return TrueDeviceIoControl(hDevice, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize,
|
return TrueDeviceIoControl(hDevice, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize,
|
||||||
lpBytesReturned, lpOverlapped);
|
lpBytesReturned, lpOverlapped);
|
||||||
}
|
}
|
||||||
@ -138,9 +132,12 @@ BOOL WINAPI FakeDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lp
|
|||||||
DWORD WINAPI FakeSetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod) {
|
DWORD WINAPI FakeSetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod) {
|
||||||
file_hook_t* hook = file_hook_list;
|
file_hook_t* hook = file_hook_list;
|
||||||
while (hook != NULL) {
|
while (hook != NULL) {
|
||||||
if (hook->virtual_handle == hFile) {
|
if (*hook->virtual_handle == hFile) {
|
||||||
if (hook->SetFilePointer) {
|
if (hook->SetFilePointer) {
|
||||||
return hook->SetFilePointer(lDistanceToMove, lpDistanceToMoveHigh, dwMoveMethod);
|
return hook->SetFilePointer(lDistanceToMove, lpDistanceToMoveHigh, dwMoveMethod);
|
||||||
|
} else {
|
||||||
|
log_error(HOOKS_LOGGER, "SetFilePointer(%ls) unimplemented", hook->filename);
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hook = hook->next;
|
hook = hook->next;
|
||||||
@ -153,9 +150,12 @@ DWORD WINAPI FakeWriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesT
|
|||||||
LPOVERLAPPED lpOverlapped) {
|
LPOVERLAPPED lpOverlapped) {
|
||||||
file_hook_t* hook = file_hook_list;
|
file_hook_t* hook = file_hook_list;
|
||||||
while (hook != NULL) {
|
while (hook != NULL) {
|
||||||
if (hook->virtual_handle == hFile) {
|
if (*hook->virtual_handle == hFile) {
|
||||||
if (hook->WriteFile) {
|
if (hook->WriteFile) {
|
||||||
return hook->WriteFile(lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped);
|
return hook->WriteFile(lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped);
|
||||||
|
} else {
|
||||||
|
log_error(HOOKS_LOGGER, "WriteFile(%ls) unimplemented", hook->filename);
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hook = hook->next;
|
hook = hook->next;
|
||||||
@ -168,9 +168,12 @@ BOOL WINAPI FakeReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRe
|
|||||||
LPOVERLAPPED lpOverlapped) {
|
LPOVERLAPPED lpOverlapped) {
|
||||||
file_hook_t* hook = file_hook_list;
|
file_hook_t* hook = file_hook_list;
|
||||||
while (hook != NULL) {
|
while (hook != NULL) {
|
||||||
if (hook->virtual_handle == hFile) {
|
if (*hook->virtual_handle == hFile) {
|
||||||
if (hook->WriteFile) {
|
if (hook->ReadFile) {
|
||||||
return hook->ReadFile(lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped);
|
return hook->ReadFile(lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped);
|
||||||
|
} else {
|
||||||
|
log_error(HOOKS_LOGGER, "ReadFile(%ls) unimplemented", hook->filename);
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hook = hook->next;
|
hook = hook->next;
|
||||||
@ -190,6 +193,11 @@ BOOL WINAPI FakeCloseHandle(HANDLE hObject) {
|
|||||||
return TrueCloseHandle(hObject);
|
return TrueCloseHandle(hObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int WINAPIV Fake_stat64i32(const char* path, struct _stat64i32* buffer) {
|
||||||
|
path = redirect_path((char*)path);
|
||||||
|
return True_stat64i32(path, buffer);
|
||||||
|
};
|
||||||
|
|
||||||
void hook_io() {
|
void hook_io() {
|
||||||
hook("Kernel32.dll", "DeviceIoControl", FakeDeviceIoControl, (void**)&TrueDeviceIoControl, 5);
|
hook("Kernel32.dll", "DeviceIoControl", FakeDeviceIoControl, (void**)&TrueDeviceIoControl, 5);
|
||||||
|
|
||||||
@ -201,5 +209,5 @@ void hook_io() {
|
|||||||
hook("Kernel32.dll", "WriteFile", FakeWriteFile, (void**)&TrueWriteFile, 6);
|
hook("Kernel32.dll", "WriteFile", FakeWriteFile, (void**)&TrueWriteFile, 6);
|
||||||
hook("Kernel32.dll", "ReadFile", FakeReadFile, (void**)&TrueReadFile, 6);
|
hook("Kernel32.dll", "ReadFile", FakeReadFile, (void**)&TrueReadFile, 6);
|
||||||
|
|
||||||
// hook("MSVCR90.DLL", "_stat64i32", Fake_stat64i32, &True_stat64i32, 5);
|
hook("MSVCR90.DLL", "_stat64i32", Fake_stat64i32, (void**)&True_stat64i32, 5);
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,7 @@ typedef BOOL(FnWriteFile)(LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
|
|||||||
LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped);
|
LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped);
|
||||||
typedef BOOL(FnReadFile)(LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead,
|
typedef BOOL(FnReadFile)(LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead,
|
||||||
LPOVERLAPPED lpOverlapped);
|
LPOVERLAPPED lpOverlapped);
|
||||||
|
static int(WINAPIV *True_stat64i32)(const char* path, struct _stat64i32* buffer);
|
||||||
|
|
||||||
#define _WriteFile (TrueWriteFile ? TrueWriteFile : WriteFile)
|
#define _WriteFile (TrueWriteFile ? TrueWriteFile : WriteFile)
|
||||||
#define _ReadFile (TrueReadFile ? TrueReadFile : ReadFile)
|
#define _ReadFile (TrueReadFile ? TrueReadFile : ReadFile)
|
||||||
@ -54,7 +55,7 @@ typedef struct file_hook {
|
|||||||
FnWriteFile* WriteFile;
|
FnWriteFile* WriteFile;
|
||||||
FnReadFile* ReadFile;
|
FnReadFile* ReadFile;
|
||||||
|
|
||||||
HANDLE virtual_handle;
|
LPHANDLE virtual_handle;
|
||||||
struct file_hook* next;
|
struct file_hook* next;
|
||||||
} file_hook_t;
|
} file_hook_t;
|
||||||
|
|
||||||
|
@ -14,6 +14,8 @@ shared_library(
|
|||||||
'setupapi.c',
|
'setupapi.c',
|
||||||
'com.c',
|
'com.c',
|
||||||
'comdevice.c',
|
'comdevice.c',
|
||||||
|
'processes.c',
|
||||||
|
'network.c',
|
||||||
],
|
],
|
||||||
link_with: [
|
link_with: [
|
||||||
dmi_lib,
|
dmi_lib,
|
||||||
|
59
src/micetools/dll/network.c
Normal file
59
src/micetools/dll/network.c
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
#include "network.h"
|
||||||
|
|
||||||
|
#include "../lib/mice/mice.h"
|
||||||
|
|
||||||
|
int WINAPI Fake_connect(SOCKET s, const SOCKADDR* name, int namelen) {
|
||||||
|
ULONG addr = _byteswap_ulong(((SOCKADDR_IN*)name)->sin_addr);
|
||||||
|
USHORT port = _byteswap_ushort(((SOCKADDR_IN*)name)->sin_port);
|
||||||
|
log_info("connect", "%hhu.%hhu.%hhu.%hhu:%hu", (addr >> 24) & 0xff, (addr >> 16) & 0xff, (addr >> 8) & 0xff,
|
||||||
|
addr & 0xff, port);
|
||||||
|
return True_connect(s, name, namelen);
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD WINAPI FakeGetIfTable(PMIB_IFTABLE pIfTable, PULONG pdwSize, BOOL bOrder) {
|
||||||
|
DWORD ret = TrueGetIfTable(pIfTable, pdwSize, bOrder);
|
||||||
|
if (ret == NO_ERROR) {
|
||||||
|
for (size_t i = 0; i < pIfTable->dwNumEntries; i++) {
|
||||||
|
pIfTable->table[i].bPhysAddr[0] = 0x00;
|
||||||
|
pIfTable->table[i].bPhysAddr[1] = 0xD0;
|
||||||
|
pIfTable->table[i].bPhysAddr[2] = 0xF1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
const char* INTERCEPT_DNS[] = {
|
||||||
|
"naominet.jp", // Startup
|
||||||
|
"ib.naominet.jp", // Billing
|
||||||
|
"aime.naominet.jp", // Aime (duh)
|
||||||
|
"tenporouter.loc", // Routers
|
||||||
|
"bbrouter.loc", "mobirouter.loc", "dslrouter.loc",
|
||||||
|
};
|
||||||
|
|
||||||
|
DNS_RECORDA dummy_record;
|
||||||
|
|
||||||
|
DNS_STATUS WINAPI FakeDnsQuery_A(PCSTR pszName, WORD wType, DWORD Options, PVOID pExtra, PDNS_RECORDA* ppQueryResults,
|
||||||
|
PVOID* pReserved) {
|
||||||
|
log_misc("dns", "DNS lookup for %s", pszName);
|
||||||
|
if (ppQueryResults) {
|
||||||
|
for (size_t i = 0; i < sizeof INTERCEPT_DNS / sizeof INTERCEPT_DNS[0]; i++) {
|
||||||
|
if (strcmp(pszName, INTERCEPT_DNS[i]) == 0) {
|
||||||
|
log_info("dns", "Replacing %s with 10.0.0.4", pszName);
|
||||||
|
|
||||||
|
// We only support replacing at most one address, but that's all we'll ever need to!
|
||||||
|
(*ppQueryResults) = &dummy_record;
|
||||||
|
(*ppQueryResults)->pNext = NULL;
|
||||||
|
(*ppQueryResults)->wType = DNS_TYPE_A;
|
||||||
|
(*ppQueryResults)->Data.A.IpAddress = 0x0400000a;
|
||||||
|
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return TrueDnsQuery_A(pszName, wType, Options, pExtra, ppQueryResults, pReserved);
|
||||||
|
};
|
||||||
|
|
||||||
|
void hook_network() {
|
||||||
|
hook("Ws2_32.dll", "connect", Fake_connect, (void**)&True_connect, 5);
|
||||||
|
hook("Iphlpapi.dll", "GetIfTable", FakeGetIfTable, (void**)&TrueGetIfTable, 5);
|
||||||
|
hook("Dnsapi.dll", "DnsQuery_A", FakeDnsQuery_A, (void**)&TrueDnsQuery_A, 5);
|
||||||
|
}
|
14
src/micetools/dll/network.h
Normal file
14
src/micetools/dll/network.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#include <Winsock2.h>
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <iphlpapi.h>
|
||||||
|
#include <windns.h>
|
||||||
|
|
||||||
|
|
||||||
|
static int(WINAPI* True_connect)(SOCKET s, const SOCKADDR* name, int namelen);
|
||||||
|
|
||||||
|
static DWORD(WINAPI* TrueGetIfTable)(PMIB_IFTABLE pIfTable, PULONG pdwSize, BOOL bOrder);
|
||||||
|
|
||||||
|
static DNS_STATUS(WINAPI* TrueDnsQuery_A)(PCSTR pszName, WORD wType, DWORD Options, PVOID pExtra,
|
||||||
|
PDNS_RECORDA* ppQueryResults, PVOID* pReserved);
|
||||||
|
|
||||||
|
void hook_network();
|
27
src/micetools/dll/processes.c
Normal file
27
src/micetools/dll/processes.c
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#include "processes.h"
|
||||||
|
|
||||||
|
#include "../lib/mice/mice.h"
|
||||||
|
|
||||||
|
const wchar_t* HOOK_BINARIES[] = {
|
||||||
|
L"app\\ALLNetProc.exe",
|
||||||
|
L"app\\CameraUploader.exe",
|
||||||
|
L"app\\GmSync.exe",
|
||||||
|
};
|
||||||
|
|
||||||
|
BOOL WINAPI FakeCreateProcessW(LPCWSTR lpApplicationName, LPWSTR lpCommandLine,
|
||||||
|
LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes,
|
||||||
|
BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment,
|
||||||
|
LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo,
|
||||||
|
LPPROCESS_INFORMATION lpProcessInformation) {
|
||||||
|
log_info("spawn", "CreateProcessW %ls %ls", lpApplicationName, lpCommandLine);
|
||||||
|
|
||||||
|
CHAR applicationName[MAX_PATH + 1];
|
||||||
|
WideCharToMultiByte(CP_ACP, 0, lpApplicationName, -1, applicationName, sizeof applicationName, NULL, NULL);
|
||||||
|
CHAR commandLine[MAX_PATH + 1];
|
||||||
|
WideCharToMultiByte(CP_ACP, 0, lpCommandLine, -1, commandLine, sizeof commandLine, NULL, NULL);
|
||||||
|
|
||||||
|
HANDLE child = start_and_inject(applicationName, commandLine, MICELIB);
|
||||||
|
return child != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void hook_processes() { hook("Kernel32.dll", "CreateProcessW", FakeCreateProcessW, (void**)&TrueCreateProcessW, 6); }
|
11
src/micetools/dll/processes.h
Normal file
11
src/micetools/dll/processes.h
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#include <Windows.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
static BOOL(WINAPI* TrueCreateProcessW)(LPCWSTR lpApplicationName, LPWSTR lpCommandLine,
|
||||||
|
LPSECURITY_ATTRIBUTES lpProcessAttributes,
|
||||||
|
LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles,
|
||||||
|
DWORD dwCreationFlags, LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory,
|
||||||
|
LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation);
|
||||||
|
|
||||||
|
void hook_processes();
|
@ -68,7 +68,7 @@ BOOL WINAPI FakeSetupDiGetDeviceInterfaceDetailA(HDEVINFO DeviceInfoSet, PSP_DEV
|
|||||||
FAKE_DEVICE* device = fake_devices;
|
FAKE_DEVICE* device = fake_devices;
|
||||||
while (device != NULL) {
|
while (device != NULL) {
|
||||||
if (device->handle == DeviceInfoSet && (ULONG_PTR)device->path == DeviceInterfaceData->Reserved) {
|
if (device->handle == DeviceInfoSet && (ULONG_PTR)device->path == DeviceInterfaceData->Reserved) {
|
||||||
log_info("setupapi", "Yoinked SetupDiGetDeviceInterfaceDetailA");
|
log_info("setupapi", "Intercepted SetupDiGetDeviceInterfaceDetailA");
|
||||||
|
|
||||||
const WCHAR* res = (WCHAR*)DeviceInterfaceData->Reserved;
|
const WCHAR* res = (WCHAR*)DeviceInterfaceData->Reserved;
|
||||||
int new_len = (wcslen(res) + 1) * (sizeof *res);
|
int new_len = (wcslen(res) + 1) * (sizeof *res);
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
#include <Windows.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
HANDLE start_and_inject(LPCSTR path, LPSTR cmdline, LPCSTR inject);
|
|
@ -1,4 +1,5 @@
|
|||||||
#include "locate.h"
|
#include "locate.h"
|
||||||
|
#include "../lib/mice/mice.h"
|
||||||
|
|
||||||
const char* KNOWN_GAMES[] = {
|
const char* KNOWN_GAMES[] = {
|
||||||
// Preferentially use a decrypted dump if present
|
// Preferentially use a decrypted dump if present
|
||||||
@ -6,14 +7,6 @@ const char* KNOWN_GAMES[] = {
|
|||||||
"maimai.exe",
|
"maimai.exe",
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef MICELIB
|
|
||||||
#ifdef MICE_WIN32
|
|
||||||
#define MICELIB "mice86.dll"
|
|
||||||
#else // MICE_WIN32
|
|
||||||
#define MICELIB "mice64.dll"
|
|
||||||
#endif // MICE_WIN32
|
|
||||||
#endif // MICELIB
|
|
||||||
|
|
||||||
bool locate_file(char* path, size_t len, const char* exe) {
|
bool locate_file(char* path, size_t len, const char* exe) {
|
||||||
WIN32_FIND_DATA fdFile;
|
WIN32_FIND_DATA fdFile;
|
||||||
HANDLE hFind = NULL;
|
HANDLE hFind = NULL;
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "../lib/mice/mice.h"
|
#include "../lib/mice/mice.h"
|
||||||
#include "exe.h"
|
|
||||||
#include "locate.h"
|
#include "locate.h"
|
||||||
|
|
||||||
const char* VERSION = "0.0-pre";
|
const char* VERSION = "0.0-pre";
|
||||||
|
@ -4,7 +4,6 @@ executable(
|
|||||||
win_subsystem: 'console',
|
win_subsystem: 'console',
|
||||||
sources: [
|
sources: [
|
||||||
'locate.c',
|
'locate.c',
|
||||||
'exe.c',
|
|
||||||
'main.c',
|
'main.c',
|
||||||
rc,
|
rc,
|
||||||
],
|
],
|
||||||
|
@ -5,9 +5,9 @@ WORD dmi_size = 0;
|
|||||||
size_t _dmi_max = 0;
|
size_t _dmi_max = 0;
|
||||||
|
|
||||||
DMI_BIOS deafult_dmi_bios = {
|
DMI_BIOS deafult_dmi_bios = {
|
||||||
.Type = 0x00,
|
.Head.Type = 0x00,
|
||||||
.Length = 0x12,
|
.Head.Length = 0x12,
|
||||||
.Handle = 0x0000,
|
.Head.Handle = 0x0000,
|
||||||
.Vendor = 0x00,
|
.Vendor = 0x00,
|
||||||
.Version = 0x00,
|
.Version = 0x00,
|
||||||
.StartSegment = 0x0000,
|
.StartSegment = 0x0000,
|
||||||
@ -17,9 +17,10 @@ DMI_BIOS deafult_dmi_bios = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
DMI_SYSTEM default_dmi_system = {
|
DMI_SYSTEM default_dmi_system = {
|
||||||
.Type = 0x01,
|
.Head.Type = 0x01,
|
||||||
.Length = 0x08,
|
.Head.Length = 0x08,
|
||||||
.Handle = 0x0000,
|
.Head.Handle = 0x0001,
|
||||||
|
// TODO: Are these used?
|
||||||
.Manufacturer = 0x00,
|
.Manufacturer = 0x00,
|
||||||
.ProductName = 0x00,
|
.ProductName = 0x00,
|
||||||
.Version = 0x00,
|
.Version = 0x00,
|
||||||
@ -27,84 +28,82 @@ DMI_SYSTEM default_dmi_system = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
DMI_STRING deafult_dmi_string = {
|
DMI_STRING deafult_dmi_string = {
|
||||||
.Type = 0x0b,
|
.Head.Type = 0x0b,
|
||||||
.Length = 0x05,
|
.Head.Length = 0x05,
|
||||||
.Handle = 0x0000,
|
.Head.Handle = 0x0002,
|
||||||
.NoStrings = 0x00,
|
.NoStrings = 0x00,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void dmi_init(void) {
|
static void dmi_init(void) {
|
||||||
if (dmi_table) free(dmi_table);
|
if (dmi_table) free(dmi_table);
|
||||||
dmi_table = (LPBYTE)malloc(0xff);
|
_dmi_max = 0xff;
|
||||||
dmi_size = 0;
|
dmi_table = (LPBYTE)malloc(_dmi_max);
|
||||||
_dmi_max = 1024;
|
memset(dmi_table, 0, _dmi_max);
|
||||||
|
dmi_size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dmi_append(void* data, size_t size) {
|
static void dmi_append(void* data, size_t size) {
|
||||||
if (!dmi_table) return;
|
if (!dmi_table) return;
|
||||||
while (dmi_size + (size + 1) >= _dmi_max) {
|
while (dmi_size + (size + 1) >= _dmi_max) {
|
||||||
LPBYTE new_table = (LPBYTE)realloc(dmi_table, _dmi_max += 0xff);
|
LPBYTE new_table = (LPBYTE)realloc(dmi_table, _dmi_max += 0xff);
|
||||||
if (!new_table) return;
|
if (!new_table) return;
|
||||||
dmi_table = new_table;
|
dmi_table = new_table;
|
||||||
}
|
}
|
||||||
memcpy(dmi_table + dmi_size, &data, size);
|
memcpy(dmi_table + dmi_size, data, size);
|
||||||
dmi_size += size;
|
dmi_size += size;
|
||||||
dmi_table[dmi_size++] = 0;
|
dmi_table[dmi_size++] = 0;
|
||||||
dmi_table[dmi_size++] = 0;
|
dmi_table[dmi_size++] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dmi_append_with_strings(void* data, size_t size, int num_strings, ...) {
|
static void dmi_append_with_strings(void* data, size_t size, int num_strings, ...) {
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, num_strings);
|
va_start(args, num_strings);
|
||||||
|
|
||||||
dmi_append(data, size);
|
dmi_append(data, size);
|
||||||
dmi_size -= 2;
|
dmi_size -= 2;
|
||||||
for (int i = 0; i < num_strings; i++) {
|
for (int i = 0; i < num_strings; i++) {
|
||||||
char* str = va_arg(args, char*);
|
char* str = va_arg(args, char*);
|
||||||
int len = strlen(str);
|
int len = strlen(str);
|
||||||
// #pragma warning(disable : 4996)
|
strcpy((char*)dmi_table + dmi_size, str);
|
||||||
strcpy((char*)dmi_table + dmi_size, str);
|
dmi_size += len + 1;
|
||||||
dmi_size += len + 1;
|
dmi_table[dmi_size - 1] = 0;
|
||||||
dmi_table[dmi_size - 1] = 0;
|
}
|
||||||
}
|
dmi_table[dmi_size++] = 0;
|
||||||
dmi_table[dmi_size++] = 0;
|
|
||||||
|
|
||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dmi_build_default() {
|
void dmi_build_default() {
|
||||||
dmi_init();
|
dmi_init();
|
||||||
dmi_append(&deafult_dmi_bios, sizeof deafult_dmi_bios);
|
dmi_append(&deafult_dmi_bios, sizeof deafult_dmi_bios);
|
||||||
// Platform AAM: Board type one of "Supermicro"(=1) or "Advantech"(=2)
|
// Platform AAM: Board type one of "Supermicro"(=1) or "Advantech"(=2)
|
||||||
// Platform AAL: Board type one of "NEC"(=0) or "AAL2"(=3)
|
// Platform AAL: Board type one of "NEC"(=0) or "AAL2"(=3)
|
||||||
|
|
||||||
dmi_append_with_strings(&default_dmi_system, sizeof default_dmi_system, 1, "Supermicro");
|
dmi_append_with_strings(&default_dmi_system, sizeof default_dmi_system, 1, "Supermicro");
|
||||||
|
|
||||||
deafult_dmi_string.NoStrings = 3;
|
deafult_dmi_string.NoStrings = 3;
|
||||||
|
|
||||||
dmi_append_with_strings(&deafult_dmi_string, sizeof deafult_dmi_string,
|
dmi_append_with_strings(&deafult_dmi_string, sizeof deafult_dmi_string,
|
||||||
// OEM strings:
|
// OEM strings:
|
||||||
// 0: ??
|
// 0: ??
|
||||||
// 1: ??
|
// 1: ??
|
||||||
// 2: Platform ID (AAL, AAM)
|
// 2: Platform ID (AAL, AAM)
|
||||||
// AAL = Nvidia drivers
|
// AAL = Nvidia drivers
|
||||||
// AAM = AMD drivers
|
// AAM = AMD drivers
|
||||||
// *** = No dedicated drivers
|
// *** = No dedicated drivers
|
||||||
// 3: ??
|
// 3: ??
|
||||||
// 4: Board type (AAL, NEC, AAL2, " ", AAM, Supermicro, Advantech)
|
// 4: Board type (AAL, NEC, AAL2, " ", AAM, Supermicro, Advantech)
|
||||||
// If present -> makes board = 4
|
// If present -> makes board = 4
|
||||||
// AAL = 4
|
// AAL = 4
|
||||||
// AAM = 4
|
// AAM = 4
|
||||||
// Supermicro = 4
|
// Supermicro = 4
|
||||||
// Advantech = 4
|
// Advantech = 4
|
||||||
5, ".", ".", "AAM", ".", "AAL"
|
5, ".", ".", "AAM", ".", "AAL");
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BYTE dmi_calc_checksum(const char* buf, int len) {
|
BYTE dmi_calc_checksum(const char* buf, int len) {
|
||||||
int sum = 0;
|
int sum = 0;
|
||||||
int a;
|
int a;
|
||||||
for (a = 0; a < len; a++)
|
for (a = 0; a < len; a++) sum += buf[a];
|
||||||
sum += buf[a];
|
return (BYTE)(sum == 0);
|
||||||
return (BYTE)(sum == 0);
|
|
||||||
}
|
}
|
@ -7,7 +7,14 @@ extern WORD dmi_size;
|
|||||||
// #define PACK(...) __pragma(pack(push, 1)) __VA_ARGS__ __pragma(pack(pop))
|
// #define PACK(...) __pragma(pack(push, 1)) __VA_ARGS__ __pragma(pack(pop))
|
||||||
|
|
||||||
#pragma pack(1)
|
#pragma pack(1)
|
||||||
typedef struct DMI_HEADER_ {
|
typedef struct {
|
||||||
|
BYTE Type;
|
||||||
|
BYTE Length;
|
||||||
|
WORD Handle;
|
||||||
|
} DMI_SECTION_HEADER;
|
||||||
|
|
||||||
|
#pragma pack(1)
|
||||||
|
typedef struct {
|
||||||
CHAR Signature[5];
|
CHAR Signature[5];
|
||||||
BYTE Checksum;
|
BYTE Checksum;
|
||||||
WORD StructLength;
|
WORD StructLength;
|
||||||
@ -18,10 +25,8 @@ typedef struct DMI_HEADER_ {
|
|||||||
} DMI_HEADER;
|
} DMI_HEADER;
|
||||||
|
|
||||||
#pragma pack(1)
|
#pragma pack(1)
|
||||||
typedef struct DMI_BIOS_ {
|
typedef struct {
|
||||||
BYTE Type;
|
DMI_SECTION_HEADER Head;
|
||||||
BYTE Length;
|
|
||||||
WORD Handle;
|
|
||||||
BYTE Vendor;
|
BYTE Vendor;
|
||||||
BYTE Version;
|
BYTE Version;
|
||||||
WORD StartSegment;
|
WORD StartSegment;
|
||||||
@ -31,10 +36,8 @@ typedef struct DMI_BIOS_ {
|
|||||||
} DMI_BIOS;
|
} DMI_BIOS;
|
||||||
|
|
||||||
#pragma pack(1)
|
#pragma pack(1)
|
||||||
typedef struct DMI_SYSTEM_ {
|
typedef struct {
|
||||||
BYTE Type;
|
DMI_SECTION_HEADER Head;
|
||||||
BYTE Length;
|
|
||||||
WORD Handle;
|
|
||||||
BYTE Manufacturer;
|
BYTE Manufacturer;
|
||||||
BYTE ProductName;
|
BYTE ProductName;
|
||||||
BYTE Version;
|
BYTE Version;
|
||||||
@ -42,17 +45,14 @@ typedef struct DMI_SYSTEM_ {
|
|||||||
} DMI_SYSTEM;
|
} DMI_SYSTEM;
|
||||||
|
|
||||||
#pragma pack(1)
|
#pragma pack(1)
|
||||||
typedef struct DMI_STRING_ {
|
typedef struct {
|
||||||
BYTE Type;
|
DMI_SECTION_HEADER Head;
|
||||||
BYTE Length;
|
|
||||||
WORD Handle;
|
|
||||||
BYTE NoStrings;
|
BYTE NoStrings;
|
||||||
} DMI_STRING;
|
} DMI_STRING;
|
||||||
|
|
||||||
static void dmi_init(void);
|
static void dmi_init(void);
|
||||||
static void dmi_append(void* data, size_t size);
|
static void dmi_append(void* data, size_t size);
|
||||||
static void dmi_append_with_strings(void* data, size_t size, int num_strings,
|
static void dmi_append_with_strings(void* data, size_t size, int num_strings, ...);
|
||||||
...);
|
|
||||||
|
|
||||||
void dmi_build_default(void);
|
void dmi_build_default(void);
|
||||||
BYTE dmi_calc_checksum(const char* buf, int len);
|
BYTE dmi_calc_checksum(const char* buf, int len);
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
subdir('util') # This is the only lib that should ever be link_with'd by another lib
|
subdir('util') # This is the only lib that should ever be link_with'd by another lib
|
||||||
subdir('am')
|
|
||||||
subdir('mice')
|
|
||||||
subdir('dmi')
|
|
||||||
subdir('json')
|
subdir('json')
|
||||||
|
subdir('am')
|
||||||
|
subdir('dmi')
|
||||||
|
subdir('mice')
|
||||||
|
|
||||||
fs = import('fs')
|
fs = import('fs')
|
||||||
# Handle the fact we aren't distributing the libpcp source
|
# Handle the fact we aren't distributing the libpcp source
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#include "exe.h"
|
#include "exe.h"
|
||||||
|
#include "log.h"
|
||||||
#include "../lib/mice/mice.h"
|
|
||||||
|
|
||||||
bool inject_debug_wait(HANDLE process) {
|
bool inject_debug_wait(HANDLE process) {
|
||||||
BOOL present;
|
BOOL present;
|
12
src/micetools/lib/mice/exe.h
Normal file
12
src/micetools/lib/mice/exe.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#include <Windows.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
HANDLE start_and_inject(LPCSTR path, LPSTR cmdline, LPCSTR inject);
|
||||||
|
|
||||||
|
#ifndef MICELIB
|
||||||
|
#ifdef MICE_WIN32
|
||||||
|
#define MICELIB "mice86.dll"
|
||||||
|
#else // MICE_WIN32
|
||||||
|
#define MICELIB "mice64.dll"
|
||||||
|
#endif // MICE_WIN32
|
||||||
|
#endif // MICELIB
|
@ -146,6 +146,46 @@ int log_error(const char* caller, const char* format, ...) {
|
|||||||
// return ret;
|
// return ret;
|
||||||
// };
|
// };
|
||||||
|
|
||||||
|
char* trim_string(char* string) {
|
||||||
|
size_t len = strlen(string) - 1;
|
||||||
|
|
||||||
|
DWORD oldProt;
|
||||||
|
while (len > 0 && (string[len] == '\n' || string[len] == '\r')) {
|
||||||
|
// TODO: Reassess this. Suspect it may be causing issues.
|
||||||
|
// Make sure we can write! This is a terrible hack, but it does work.
|
||||||
|
VirtualProtect(string + len, 1, PAGE_EXECUTE_READWRITE, &oldProt);
|
||||||
|
string[len--] = '\0';
|
||||||
|
VirtualProtect(string + len + 1, 1, oldProt, &oldProt);
|
||||||
|
}
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
|
||||||
|
HANDLE WINAPI FakeRegisterEventSourceA(LPCSTR lpUNCServerName, LPCSTR lpSourceName) { return (HANDLE)0xDEADBEEF; }
|
||||||
|
|
||||||
|
BOOL WINAPI FakeReportEventA(HANDLE hEventLog, WORD wType, WORD wCategory, DWORD dwEventID, PSID lpUserSid,
|
||||||
|
WORD wNumStrings, DWORD dwDataSize, LPCSTR* lpStrings, LPVOID lpRawData) {
|
||||||
|
switch (wType) {
|
||||||
|
case EVENTLOG_SUCCESS:
|
||||||
|
case EVENTLOG_AUDIT_SUCCESS:
|
||||||
|
for (int i = 0; i < wNumStrings; i++) log_misc("evtlog", trim_string((char*)lpStrings[i]));
|
||||||
|
break;
|
||||||
|
case EVENTLOG_AUDIT_FAILURE:
|
||||||
|
case EVENTLOG_ERROR_TYPE:
|
||||||
|
for (int i = 0; i < wNumStrings; i++) log_error("evtlog", trim_string((char*)lpStrings[i]));
|
||||||
|
break;
|
||||||
|
case EVENTLOG_WARNING_TYPE:
|
||||||
|
for (int i = 0; i < wNumStrings; i++) log_warning("evtlog", trim_string((char*)lpStrings[i]));
|
||||||
|
break;
|
||||||
|
case EVENTLOG_INFORMATION_TYPE:
|
||||||
|
default:
|
||||||
|
for (int i = 0; i < wNumStrings; i++) log_info("evtlog", trim_string((char*)lpStrings[i]));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
};
|
||||||
|
|
||||||
|
BOOL WINAPI FakeDeregisterEventSource(HANDLE hEventLog) { return TRUE; }
|
||||||
|
|
||||||
static VOID(WINAPI* TrueOutputDebugStringA)(LPCSTR lpOutputString);
|
static VOID(WINAPI* TrueOutputDebugStringA)(LPCSTR lpOutputString);
|
||||||
VOID WINAPI FakeOutputDebugStringA(LPCSTR lpOutputString) { log_info("debug", "%s", lpOutputString); }
|
VOID WINAPI FakeOutputDebugStringA(LPCSTR lpOutputString) { log_info("debug", "%s", lpOutputString); }
|
||||||
|
|
||||||
@ -165,4 +205,8 @@ void setup_logging() {
|
|||||||
|
|
||||||
if (LOG_FILE == NULL)
|
if (LOG_FILE == NULL)
|
||||||
LOG_FILE = CreateFileA("log.txt", GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL);
|
LOG_FILE = CreateFileA("log.txt", GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL);
|
||||||
|
|
||||||
|
hook("Advapi32.dll", "RegisterEventSourceA", FakeRegisterEventSourceA, &TrueRegisterEventSourceA);
|
||||||
|
hook("Advapi32.dll", "ReportEventA", FakeReportEventA, &TrueReportEventA);
|
||||||
|
hook("Advapi32.dll", "DeregisterEventSource", FakeDeregisterEventSource, &TrueDeregisterEventSource);
|
||||||
}
|
}
|
||||||
|
@ -3,11 +3,17 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
#define LOG_MISC
|
static HANDLE(WINAPI* TrueRegisterEventSourceA)(LPCSTR lpUNCServerName, LPCSTR lpSourceName);
|
||||||
|
static BOOL(WINAPI* TrueReportEventA)(HANDLE hEventLog, WORD wType, WORD wCategory, DWORD dwEventID, PSID lpUserSid,
|
||||||
|
WORD wNumStrings, DWORD dwDataSize, LPCSTR* lpStrings, LPVOID lpRawData);
|
||||||
|
static BOOL(WINAPI* TrueDeregisterEventSource)(HANDLE hEventLog);
|
||||||
|
|
||||||
|
// #define LOG_MISC
|
||||||
#define LOG_INFO
|
#define LOG_INFO
|
||||||
#define LOG_WARNING
|
#define LOG_WARNING
|
||||||
#define LOG_ERROR
|
#define LOG_ERROR
|
||||||
|
|
||||||
|
#define COMM_LOGGER "comm"
|
||||||
#define HOOKS_LOGGER "hooks"
|
#define HOOKS_LOGGER "hooks"
|
||||||
#define BOOT_LOGGER "boot"
|
#define BOOT_LOGGER "boot"
|
||||||
|
|
||||||
|
@ -3,5 +3,10 @@ mice_lib = static_library(
|
|||||||
sources: [
|
sources: [
|
||||||
'hook.c',
|
'hook.c',
|
||||||
'log.c',
|
'log.c',
|
||||||
|
'exe.c',
|
||||||
|
'patch.c',
|
||||||
],
|
],
|
||||||
|
link_with: [
|
||||||
|
json_lib,
|
||||||
|
]
|
||||||
)
|
)
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
#include "hook.h"
|
#include "hook.h"
|
||||||
#include "ioctl.h"
|
#include "ioctl.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "exe.h"
|
||||||
|
#include "patch.h"
|
||||||
|
224
src/micetools/lib/mice/patch.c
Normal file
224
src/micetools/lib/mice/patch.c
Normal file
@ -0,0 +1,224 @@
|
|||||||
|
#include "patch.h"
|
||||||
|
|
||||||
|
bool fetch(json_value* object, char* name, json_value** value) {
|
||||||
|
if (object->type != json_object) return false;
|
||||||
|
for (size_t j = 0; j < object->u.object.length; j++) {
|
||||||
|
json_object_entry* entry = &(object->u.object.values[j]);
|
||||||
|
if (strncmp(name, entry->name, entry->name_length) == 0) {
|
||||||
|
*value = entry->value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool fetch_string(json_value* object, char* name, char** value) {
|
||||||
|
json_value* fetched;
|
||||||
|
if (!fetch(object, name, &fetched)) return false;
|
||||||
|
if (fetched->type != json_string) return false;
|
||||||
|
*value = fetched->u.string.ptr;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool fetch_int(json_value* object, char* name, size_t* value) {
|
||||||
|
json_value* fetched;
|
||||||
|
if (!fetch(object, name, &fetched)) return false;
|
||||||
|
if (fetched->type != json_integer) return false;
|
||||||
|
*value = fetched->u.integer;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool fetch_bool(json_value* object, char* name, bool* value) {
|
||||||
|
json_value* fetched;
|
||||||
|
if (!fetch(object, name, &fetched)) return false;
|
||||||
|
if (fetched->type != json_boolean) return false;
|
||||||
|
*value = fetched->u.boolean;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
void free_patches(patches_t* patches) {
|
||||||
|
if (patches->nopatchsets == 0) return;
|
||||||
|
for (int i = patches->nopatchsets - 1; i >= 0; i--) {
|
||||||
|
if (patches->patchsets[i] != NULL) {
|
||||||
|
for (int j = 0; j < patches->patchsets[i]->nopatches; j++) {
|
||||||
|
if (patches->patchsets[i]->patches[j].from != NULL) free(patches->patchsets[i]->patches[j].from);
|
||||||
|
if (patches->patchsets[i]->patches[j].to != NULL) free(patches->patchsets[i]->patches[j].to);
|
||||||
|
}
|
||||||
|
free(patches->patchsets[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
patches->nopatchsets = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
json_value* load_json_from_file(char* path, char* error) {
|
||||||
|
FILE* fp = fopen(path, "r");
|
||||||
|
if (fp == NULL) {
|
||||||
|
if (error != NULL) sprintf(error, "Failed to open patch file");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek(fp, 0L, SEEK_END);
|
||||||
|
size_t sz = ftell(fp);
|
||||||
|
rewind(fp);
|
||||||
|
|
||||||
|
char* json_buf = (char*)malloc(sz);
|
||||||
|
if (json_buf == NULL) {
|
||||||
|
if (error != NULL) sprintf(error, "Failed to allocate file buffer");
|
||||||
|
fclose(fp);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (!(sz = fread(json_buf, 1, sz, fp))) {
|
||||||
|
if (error != NULL) sprintf(error, "Failed to read file");
|
||||||
|
fclose(fp);
|
||||||
|
return NULL;
|
||||||
|
};
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
json_settings settings = {0};
|
||||||
|
return json_parse_ex(&settings, json_buf, sz, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool parse_patches(patches_t* patches, json_value** set_json, int set_count, char* error) {
|
||||||
|
patches->nopatchsets = set_count;
|
||||||
|
patches->patchsets = (patchset_t**)malloc(set_count * sizeof(patchset_t*));
|
||||||
|
for (int i = 0; i < set_count; i++) patches->patchsets[i] = NULL;
|
||||||
|
|
||||||
|
error[0] = '\0';
|
||||||
|
for (int i = 0; i < set_count; i++) {
|
||||||
|
patchset_t* patchset = (patchset_t*)malloc(sizeof(patchset_t));
|
||||||
|
patches->patchsets[i] = patchset;
|
||||||
|
patchset->name = NULL;
|
||||||
|
patchset->description = NULL;
|
||||||
|
patchset->binary_name = NULL;
|
||||||
|
patchset->apply = false;
|
||||||
|
patchset->nopatches = 0;
|
||||||
|
|
||||||
|
char *name, *description, *binary_name;
|
||||||
|
if (!fetch_string(set_json[i], "name", &name)) {
|
||||||
|
snprintf(error, json_error_max, "'name' missing for patch %d", i);
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
if (!fetch_string(set_json[i], "description", &description)) {
|
||||||
|
snprintf(error, json_error_max, "'description' missing for patch %d (%s)", i, name);
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
if (!fetch_string(set_json[i], "binary_name", &binary_name)) binary_name = NULL;
|
||||||
|
|
||||||
|
bool apply;
|
||||||
|
if (!fetch_bool(set_json[i], "apply", &apply)) {
|
||||||
|
snprintf(error, json_error_max, "'apply' missing for patch %d (%s)", i, name);
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
json_value* set_patches;
|
||||||
|
if (!fetch(set_json[i], "patches", &set_patches) || set_patches->type != json_array) {
|
||||||
|
char* patches_file_path;
|
||||||
|
if (fetch_string(set_json[i], "patches_file", &patches_file_path)) {
|
||||||
|
char load_error[json_error_max];
|
||||||
|
set_patches = load_json_from_file(patches_file_path, load_error);
|
||||||
|
if (set_patches == NULL) {
|
||||||
|
log_warning("patcher", "Failed to load '%s': %s", patches_file_path, load_error);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (set_patches->type != json_array) {
|
||||||
|
log_warning("patcher", "Failed to load '%s': not an array", patches_file_path);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
snprintf(error, json_error_max, "Neither 'patches' nor 'patchs_file' in patch %d (%s)", i, name);
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int count = set_patches->u.array.length;
|
||||||
|
patchset = (patchset_t*)realloc(patchset, sizeof(patchset_t) + (sizeof(patch_t) * count));
|
||||||
|
patches->patchsets[i] = patchset;
|
||||||
|
|
||||||
|
patchset->name = name;
|
||||||
|
patchset->description = description;
|
||||||
|
patchset->binary_name = binary_name;
|
||||||
|
patchset->apply = apply;
|
||||||
|
patchset->nopatches = count;
|
||||||
|
memset(patchset->patches, 0, count * (sizeof(patch_t)));
|
||||||
|
|
||||||
|
for (int j = 0; j < count; j++) {
|
||||||
|
json_value* this_patch = set_patches->u.array.values[j];
|
||||||
|
size_t at;
|
||||||
|
char *from, *to;
|
||||||
|
if (!fetch_int(this_patch, "at", &at)) {
|
||||||
|
char* at_str;
|
||||||
|
if (!fetch_string(this_patch, "at", &at_str)) {
|
||||||
|
snprintf(error, json_error_max, "'at' missing for patch %s[%d]", name, j);
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strlen(at_str) > 8) {
|
||||||
|
snprintf(error, json_error_max, "invalid 'at' value for patch %s[%d]", name, j);
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
hex_to_bin(at_str, (void*)&at, 8);
|
||||||
|
at = _byteswap_ulong(at); // Endianess!
|
||||||
|
}
|
||||||
|
if (!fetch_string(this_patch, "from", &from)) {
|
||||||
|
snprintf(error, json_error_max, "'from' missing for patch %s[%d]", name, j);
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
if (!fetch_string(this_patch, "to", &to)) {
|
||||||
|
snprintf(error, json_error_max, "'to' missing for patch %s[%d]", name, j);
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* patch_name;
|
||||||
|
if (!fetch_string(this_patch, "name", &patch_name)) patch_name = NULL;
|
||||||
|
|
||||||
|
patchset->patches[j].name = patch_name;
|
||||||
|
patchset->patches[j].offset = at;
|
||||||
|
size_t size = strlen(from);
|
||||||
|
if (size != strlen(to)) {
|
||||||
|
snprintf(error, json_error_max, "'from' and 'to' lengths differ in patch %s[%d]", name, j);
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
if (size % 2 != 0) {
|
||||||
|
snprintf(error, json_error_max, "invalid hex string in patch %s[%d]", name, j);
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
char* bin_from = patchset->patches[j].from = (char*)malloc(size / 2);
|
||||||
|
char* bin_to = patchset->patches[j].to = (char*)malloc(size / 2);
|
||||||
|
if (!hex_to_bin(from, bin_from, size)) {
|
||||||
|
snprintf(error, json_error_max, "invalid hex string in patch %s[%d].from", name, j);
|
||||||
|
goto failed;
|
||||||
|
};
|
||||||
|
if (!hex_to_bin(to, bin_to, size)) {
|
||||||
|
snprintf(error, json_error_max, "invalid hex string in patch %s[%d].to", name, j);
|
||||||
|
goto failed;
|
||||||
|
};
|
||||||
|
|
||||||
|
patchset->patches[j].count = size / 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
failed:
|
||||||
|
free_patches(patches);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool load_patches(patches_t* patches, char* path, char* error) {
|
||||||
|
patches->nopatchsets = 0;
|
||||||
|
|
||||||
|
json_value* parsed = load_json_from_file(path, error);
|
||||||
|
if (parsed == NULL) return false;
|
||||||
|
|
||||||
|
int loaded_patches = 0;
|
||||||
|
json_value** patches_json;
|
||||||
|
if (parsed->type == json_array) {
|
||||||
|
loaded_patches = parsed->u.array.length;
|
||||||
|
patches_json = parsed->u.array.values;
|
||||||
|
} else if (parsed->type == json_object) {
|
||||||
|
loaded_patches = 1;
|
||||||
|
patches_json = &parsed;
|
||||||
|
} else {
|
||||||
|
sprintf(error, "Patch file format error");
|
||||||
|
json_value_free(parsed);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!parse_patches(patches, patches_json, loaded_patches, error)) return false;
|
||||||
|
return true;
|
||||||
|
}
|
39
src/micetools/lib/mice/patch.h
Normal file
39
src/micetools/lib/mice/patch.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "../json/json.h"
|
||||||
|
#include "../util/hex.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
size_t offset;
|
||||||
|
size_t count;
|
||||||
|
char* name;
|
||||||
|
unsigned char* from;
|
||||||
|
unsigned char* to;
|
||||||
|
} patch_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char* name;
|
||||||
|
char* description;
|
||||||
|
char* binary_name;
|
||||||
|
bool apply;
|
||||||
|
size_t nopatches;
|
||||||
|
patch_t patches[];
|
||||||
|
} patchset_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
size_t nopatchsets;
|
||||||
|
patchset_t** patchsets;
|
||||||
|
} patches_t;
|
||||||
|
|
||||||
|
// Internal JSON helpers
|
||||||
|
bool fetch(json_value* object, char* name, json_value** value);
|
||||||
|
bool fetch_string(json_value* object, char* name, char** value);
|
||||||
|
bool fetch_int(json_value* object, char* name, size_t* value);
|
||||||
|
bool fetch_bool(json_value* object, char* name, bool* value);
|
||||||
|
bool parse_patches(patches_t* patches, json_value** set_json, int set_count, char* error);
|
||||||
|
|
||||||
|
// Main two exports
|
||||||
|
void free_patches(patches_t* patches);
|
||||||
|
bool load_patches(patches_t* patches, char* path, char* error);
|
@ -1,167 +1,18 @@
|
|||||||
#include "../lib/json/json.h"
|
#include "../lib/mice/mice.h"
|
||||||
#include "../lib/util/hex.h"
|
|
||||||
#include "stdbool.h"
|
|
||||||
#include "stdio.h"
|
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
|
|
||||||
typedef struct {
|
void print_patches(patches_t* patches, char* filename) {
|
||||||
size_t offset;
|
|
||||||
size_t count;
|
|
||||||
unsigned char* from;
|
|
||||||
unsigned char* to;
|
|
||||||
} patch_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char* name;
|
|
||||||
char* description;
|
|
||||||
bool apply;
|
|
||||||
size_t nopatches;
|
|
||||||
patch_t patches[];
|
|
||||||
} patchset_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
size_t nopatchsets;
|
|
||||||
patchset_t** patchsets;
|
|
||||||
} patches_t;
|
|
||||||
|
|
||||||
bool fetch(json_value* object, char* name, json_value** value) {
|
|
||||||
if (object->type != json_object) return false;
|
|
||||||
for (size_t j = 0; j < object->u.object.length; j++) {
|
|
||||||
json_object_entry* entry = &(object->u.object.values[j]);
|
|
||||||
if (strncmp(name, entry->name, entry->name_length) == 0) {
|
|
||||||
*value = entry->value;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
bool fetch_string(json_value* object, char* name, char** value) {
|
|
||||||
json_value* fetched;
|
|
||||||
if (!fetch(object, name, &fetched)) return false;
|
|
||||||
if (fetched->type != json_string) return false;
|
|
||||||
*value = fetched->u.string.ptr;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
bool fetch_int(json_value* object, char* name, size_t* value) {
|
|
||||||
json_value* fetched;
|
|
||||||
if (!fetch(object, name, &fetched)) return false;
|
|
||||||
if (fetched->type != json_integer) return false;
|
|
||||||
*value = fetched->u.integer;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
bool fetch_bool(json_value* object, char* name, bool* value) {
|
|
||||||
json_value* fetched;
|
|
||||||
if (!fetch(object, name, &fetched)) return false;
|
|
||||||
if (fetched->type != json_boolean) return false;
|
|
||||||
*value = fetched->u.boolean;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
void free_patches(patches_t* patches) {
|
|
||||||
if (patches->nopatchsets == 0) return;
|
|
||||||
for (int i = patches->nopatchsets - 1; i >= 0; i--) {
|
|
||||||
if (patches->patchsets[i] != NULL) {
|
|
||||||
for (int j = 0; j < patches->patchsets[i]->nopatches; j++) {
|
|
||||||
if (patches->patchsets[i]->patches[j].from != NULL) free(patches->patchsets[i]->patches[j].from);
|
|
||||||
if (patches->patchsets[i]->patches[j].to != NULL) free(patches->patchsets[i]->patches[j].to);
|
|
||||||
}
|
|
||||||
free(patches->patchsets[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
patches->nopatchsets = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool parse_patches(patches_t* patches, json_value** set_json, int set_count, char* error) {
|
|
||||||
patches->nopatchsets = set_count;
|
|
||||||
patches->patchsets = (patchset_t**)malloc(set_count * sizeof(patchset_t*));
|
|
||||||
for (int i = 0; i < set_count; i++) patches->patchsets[i] = NULL;
|
|
||||||
|
|
||||||
error[0] = '\0';
|
|
||||||
for (int i = 0; i < set_count; i++) {
|
|
||||||
char *name, *description;
|
|
||||||
if (!fetch_string(set_json[i], "name", &name)) {
|
|
||||||
snprintf(error, json_error_max, "'name' missing for patch %d", i);
|
|
||||||
goto failed;
|
|
||||||
}
|
|
||||||
if (!fetch_string(set_json[i], "description", &description)) {
|
|
||||||
snprintf(error, json_error_max, "'description' missing for patch %d (%s)", i, name);
|
|
||||||
goto failed;
|
|
||||||
}
|
|
||||||
bool apply;
|
|
||||||
if (!fetch_bool(set_json[i], "apply", &apply)) {
|
|
||||||
snprintf(error, json_error_max, "'apply' missing for patch %d (%s)", i, name);
|
|
||||||
goto failed;
|
|
||||||
}
|
|
||||||
json_value* set_patches;
|
|
||||||
if (!fetch(set_json[i], "patches", &set_patches) || set_patches->type != json_array) {
|
|
||||||
snprintf(error, json_error_max, "'patches' missing for patch %d (%s)", i, name);
|
|
||||||
goto failed;
|
|
||||||
}
|
|
||||||
|
|
||||||
int count = set_patches->u.array.length;
|
|
||||||
patchset_t* patchset = (patchset_t*)malloc(sizeof(patchset_t) + (sizeof(patch_t) * count));
|
|
||||||
patches->patchsets[i] = patchset;
|
|
||||||
patchset->name = name;
|
|
||||||
patchset->apply = apply;
|
|
||||||
patchset->description = description;
|
|
||||||
patchset->nopatches = count;
|
|
||||||
|
|
||||||
for (int j = 0; j < count; j++) {
|
|
||||||
json_value* this_patch = set_patches->u.array.values[j];
|
|
||||||
size_t at;
|
|
||||||
char *from, *to;
|
|
||||||
if (!fetch_int(this_patch, "at", &at)) {
|
|
||||||
snprintf(error, json_error_max, "'at' missing for patch %s[%d]", name, j);
|
|
||||||
goto failed;
|
|
||||||
}
|
|
||||||
if (!fetch_string(this_patch, "from", &from)) {
|
|
||||||
snprintf(error, json_error_max, "'from' missing for patch %s[%d]", name, j);
|
|
||||||
goto failed;
|
|
||||||
}
|
|
||||||
if (!fetch_string(this_patch, "to", &to)) {
|
|
||||||
snprintf(error, json_error_max, "'to' missing for patch %s[%d]", name, j);
|
|
||||||
goto failed;
|
|
||||||
}
|
|
||||||
|
|
||||||
patchset->patches[j].offset = at;
|
|
||||||
size_t size = strlen(from);
|
|
||||||
if (size != strlen(to)) {
|
|
||||||
snprintf(error, json_error_max, "'from' and 'to' lengths differ in patch %s[%d]", name, j);
|
|
||||||
goto failed;
|
|
||||||
}
|
|
||||||
if (size % 2 != 0) {
|
|
||||||
snprintf(error, json_error_max, "invalid hex string in patch %s[%d]", name, j);
|
|
||||||
goto failed;
|
|
||||||
}
|
|
||||||
char* bin_from = patchset->patches[j].from = (char*)malloc(size / 2);
|
|
||||||
char* bin_to = patchset->patches[j].to = (char*)malloc(size / 2);
|
|
||||||
if (!hex_to_bin(from, bin_from, size)) {
|
|
||||||
snprintf(error, json_error_max, "invalid hex string in patch %s[%d].from", name, j);
|
|
||||||
goto failed;
|
|
||||||
};
|
|
||||||
if (!hex_to_bin(to, bin_to, size)) {
|
|
||||||
snprintf(error, json_error_max, "invalid hex string in patch %s[%d].to", name, j);
|
|
||||||
goto failed;
|
|
||||||
};
|
|
||||||
|
|
||||||
patchset->patches[j].count = size / 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
|
|
||||||
failed:
|
|
||||||
free_patches(patches);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_patches(patches_t* patches) {
|
|
||||||
for (int i = 0; i < patches->nopatchsets; i++) {
|
for (int i = 0; i < patches->nopatchsets; i++) {
|
||||||
patchset_t* patchset = patches->patchsets[i];
|
patchset_t* patchset = patches->patchsets[i];
|
||||||
|
|
||||||
printf("Patch: %s (%s)\n", patchset->name, patchset->apply ? "applied" : "unapplied");
|
bool skip = patchset->name != NULL && strcmp(patchset->name, filename) != 0;
|
||||||
|
|
||||||
|
printf("Patch: %s (%s)\n", patchset->name, skip ? "skipped" : patchset->apply ? "applied" : "unapplied");
|
||||||
printf("- %s\n", patchset->description);
|
printf("- %s\n", patchset->description);
|
||||||
for (int i = 0; i < patchset->nopatches; i++) {
|
if (!skip) {
|
||||||
printf(":: %d bytes at %08x\n", patchset->patches[i].count, patchset->patches[i].offset);
|
for (int i = 0; i < patchset->nopatches; i++) {
|
||||||
|
printf(":: %d bytes at %08x\n", patchset->patches[i].count, patchset->patches[i].offset);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
puts("======================");
|
puts("======================");
|
||||||
}
|
}
|
||||||
@ -179,6 +30,11 @@ void apply_patches(patches_t* patches, char* filename) {
|
|||||||
|
|
||||||
for (int i = 0; i < patches->nopatchsets; i++) {
|
for (int i = 0; i < patches->nopatchsets; i++) {
|
||||||
patchset_t* patchset = patches->patchsets[i];
|
patchset_t* patchset = patches->patchsets[i];
|
||||||
|
|
||||||
|
if (patchset->name != NULL && strcmp(patchset->name, filename) != 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
for (int j = 0; j < patchset->nopatches; j++) {
|
for (int j = 0; j < patchset->nopatches; j++) {
|
||||||
patch_t patch = patchset->patches[j];
|
patch_t patch = patchset->patches[j];
|
||||||
if (patch.offset + patch.count > sz) {
|
if (patch.offset + patch.count > sz) {
|
||||||
@ -239,65 +95,18 @@ int main(int argc, char** argv) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE* fp = fopen(argv[1], "r");
|
|
||||||
if (fp == NULL) {
|
|
||||||
fprintf(stderr, "Failed to open '%s' (%d)\n", argv[1], errno);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
fseek(fp, 0L, SEEK_END);
|
|
||||||
size_t sz = ftell(fp);
|
|
||||||
rewind(fp);
|
|
||||||
|
|
||||||
char* json_buf = (char*)malloc(sz);
|
|
||||||
if (json_buf == NULL) {
|
|
||||||
fprintf(stderr, "Failed to allocate %d bytes\n", sz, errno);
|
|
||||||
fclose(fp);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (!(sz = fread(json_buf, 1, sz, fp))) {
|
|
||||||
fprintf(stderr, "Failed to read from '%s' (%d)\n", argv[1], errno);
|
|
||||||
fclose(fp);
|
|
||||||
return -1;
|
|
||||||
};
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
json_settings settings = {0};
|
|
||||||
char error[json_error_max];
|
char error[json_error_max];
|
||||||
json_value* parsed = json_parse_ex(&settings, json_buf, sz, error);
|
|
||||||
|
|
||||||
if (parsed == NULL) {
|
|
||||||
fprintf(stderr, "Parse error: %s\n", error);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int loaded_patches = 0;
|
|
||||||
json_value** patches_json;
|
|
||||||
if (parsed->type == json_array) {
|
|
||||||
loaded_patches = parsed->u.array.length;
|
|
||||||
patches_json = parsed->u.array.values;
|
|
||||||
} else if (parsed->type == json_object) {
|
|
||||||
loaded_patches = 1;
|
|
||||||
patches_json = &parsed;
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "Patch file format error\n");
|
|
||||||
json_value_free(parsed);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
patches_t all_patches;
|
patches_t all_patches;
|
||||||
if (!parse_patches(&all_patches, patches_json, loaded_patches, error)) {
|
if (!load_patches(&all_patches, argv[1], error)) {
|
||||||
fprintf(stderr, "Patch file format error: %s\n", error);
|
fprintf(stderr, "%s", error);
|
||||||
return;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
puts("");
|
puts("");
|
||||||
puts("Loaded patches:");
|
puts("Loaded patches:");
|
||||||
puts("---------------");
|
puts("---------------");
|
||||||
print_patches(&all_patches);
|
print_patches(&all_patches, argv[2]);
|
||||||
|
|
||||||
apply_patches(&all_patches, argv[2]);
|
apply_patches(&all_patches, argv[2]);
|
||||||
|
|
||||||
free_patches(&all_patches);
|
free_patches(&all_patches);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,6 @@ micepatch = executable(
|
|||||||
],
|
],
|
||||||
link_with: [
|
link_with: [
|
||||||
mice_lib,
|
mice_lib,
|
||||||
json_lib,
|
|
||||||
],
|
],
|
||||||
link_args: [
|
link_args: [
|
||||||
'/MANIFEST:EMBED',
|
'/MANIFEST:EMBED',
|
||||||
|
93
src/patches/ALLNetProc.patch.json
Normal file
93
src/patches/ALLNetProc.patch.json
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_DONGLE",
|
||||||
|
"at": "004f48b0",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_PCP",
|
||||||
|
"at": "004f989c",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_EEPROM",
|
||||||
|
"at": "004f7d04",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_BACKUP",
|
||||||
|
"at": "004f7d08",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_RTC",
|
||||||
|
"at": "004f8118",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_GFETCHER",
|
||||||
|
"at": "004f96dc",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_NETWORK",
|
||||||
|
"at": "004f8338",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_MASTER",
|
||||||
|
"at": "004f88c0",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_HM",
|
||||||
|
"at": "004f88b0",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_SRAM",
|
||||||
|
"at": "004f8330",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_PLATFORM",
|
||||||
|
"at": "004f9728",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_ASSERTS (We use ALPB_LOG_LEVEL instead)",
|
||||||
|
"at": "004f9e7c",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ALPB_LOG_LEVEL (0=None, 1=Error, 2=Warning, 3=Most, 4=Debug)",
|
||||||
|
"at": "004e884c",
|
||||||
|
"from": "01000000",
|
||||||
|
"to": "0a000000",
|
||||||
|
"count": 4
|
||||||
|
}
|
||||||
|
]
|
98
src/patches/Game.patch.json
Normal file
98
src/patches/Game.patch.json
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"at": "008717a0",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"at": "00871728",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"at": "00871cd8",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"at": "00872660",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"at": "0087297c",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"at": "00872980",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"at": "00872988",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"at": "00873540",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"at": "00873538",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"at": "0087f890",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"at": "00882ce4",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"at": "00882cec",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"at": "00883018",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"at": "00886ff8",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"at": "0088b1b8",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"at": "0088b1c0",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
}
|
||||||
|
]
|
149
src/patches/maimai_dump_.patch.json
Normal file
149
src/patches/maimai_dump_.patch.json
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_SRAM",
|
||||||
|
"at": "00c8ab7c",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_CABINET_DL",
|
||||||
|
"at": "00f406f0",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_INSTALL",
|
||||||
|
"at": "00c88680",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_EEPROM",
|
||||||
|
"at": "00c8ab78",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_PLATFORM",
|
||||||
|
"at": "00c88608",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_STORAGE",
|
||||||
|
"at": "00c88dd0",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_PCP",
|
||||||
|
"at": "00ca25ec",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_HM",
|
||||||
|
"at": "00c96ed0",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_HTTP",
|
||||||
|
"at": "00f406ec",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_DIPSW",
|
||||||
|
"at": "00c89ca8",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_DONGLE",
|
||||||
|
"at": "00c96ed8",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_JVSP",
|
||||||
|
"at": "00c9a83c",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_NETWORK",
|
||||||
|
"at": "00c89730",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_JVST_THREAD",
|
||||||
|
"at": "00c9a440",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_JVS",
|
||||||
|
"at": "00c8ab80",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_MASTER",
|
||||||
|
"at": "00c89fc8",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_RTC",
|
||||||
|
"at": "00c88bb8",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_JVST_DRIVER",
|
||||||
|
"at": "00c9e420",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_BACKUP",
|
||||||
|
"at": "00c89320",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_HWRESET",
|
||||||
|
"at": "00c88bb4",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN",
|
||||||
|
"at": "00c830e8",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
}
|
||||||
|
]
|
16
src/patches/mxnetwork.patch.json
Normal file
16
src/patches/mxnetwork.patch.json
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_PCP",
|
||||||
|
"at": "004438e0",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_UTL",
|
||||||
|
"at": "004433f8",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
}
|
||||||
|
]
|
163
src/patches/mxsegaboot.patch.json
Normal file
163
src/patches/mxsegaboot.patch.json
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_JVS_DRIVER",
|
||||||
|
"at": "0054fcd8",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_DIPSW",
|
||||||
|
"at": "00538810",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_ATA",
|
||||||
|
"at": "0054afc8",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_DONGLE",
|
||||||
|
"at": "00544b78",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_EEPROM",
|
||||||
|
"at": "00536c98",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_GCATCHER",
|
||||||
|
"at": "00537834",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_GDELIVER",
|
||||||
|
"at": "00537d4c",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_GFETCHER",
|
||||||
|
"at": "0053828c",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_HWRESET",
|
||||||
|
"at": "00547fd0",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_PLATFORM",
|
||||||
|
"at": "00547fd8",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_HM",
|
||||||
|
"at": "00548268",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_BACKUP",
|
||||||
|
"at": "00536f30",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_CMOS",
|
||||||
|
"at": "00547fcc",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_INSTALL",
|
||||||
|
"at": "005382d8",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_JVS",
|
||||||
|
"at": "00538818",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_JVSP",
|
||||||
|
"at": "00544b68",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_MASTER",
|
||||||
|
"at": "0054b3d8",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_NETWORK",
|
||||||
|
"at": "00548280",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_RTC",
|
||||||
|
"at": "00548050",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_SRAM",
|
||||||
|
"at": "00536c94",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_STORAGE",
|
||||||
|
"at": "005487f8",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_SYS",
|
||||||
|
"at": "00536c90",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_PCPT",
|
||||||
|
"at": "00536c70",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
}
|
||||||
|
]
|
51
src/patches/patches.json
Normal file
51
src/patches/patches.json
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "maimai Finale logs",
|
||||||
|
"description": "Enable logging facilities",
|
||||||
|
"binary_name": "maimai_dump_.exe",
|
||||||
|
"apply": true,
|
||||||
|
"patches_file": "maimai_dump_.patch.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mxnetwork logs",
|
||||||
|
"description": "Enable logging facilities",
|
||||||
|
"binary_name": "mxnetwork.exe",
|
||||||
|
"apply": true,
|
||||||
|
"patches_file": "mxnetwork.patch.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "maimai 1.00 logs",
|
||||||
|
"description": "Enable logging facilities",
|
||||||
|
"binary_name": "Game.exe",
|
||||||
|
"apply": true,
|
||||||
|
"patches_file": "Game.patch.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ALLNetProc logs",
|
||||||
|
"description": "Enable logging facilities",
|
||||||
|
"binary_name": "ALLNetProc.exe",
|
||||||
|
"apply": true,
|
||||||
|
"patches_file": "ALLNetProc.patch.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ALLNetProc logs",
|
||||||
|
"description": "Enable logging facilities (alt filename)",
|
||||||
|
"binary_name": "ALLNetProc_win.exe",
|
||||||
|
"apply": true,
|
||||||
|
"patches_file": "ALLNetProc.patch.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mxsegaboot logs",
|
||||||
|
"description": "Enable logging facilities",
|
||||||
|
"binary_name": "mxsegaboot.exe",
|
||||||
|
"apply": true,
|
||||||
|
"patches_file": "mxsegaboot.patch.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mxsegaboot logs",
|
||||||
|
"description": "Enable logging facilities (alt filename)",
|
||||||
|
"binary_name": "ORIG_mxsegaboot.exe",
|
||||||
|
"apply": true,
|
||||||
|
"patches_file": "mxsegaboot.patch.json"
|
||||||
|
}
|
||||||
|
]
|
Loading…
Reference in New Issue
Block a user