Range checks added
This commit is contained in:
parent
fd80294bf2
commit
ca4685cc42
@ -45,6 +45,7 @@ typedef struct CheatProcessInfo {
|
|||||||
|
|
||||||
typedef struct CheatDescription {
|
typedef struct CheatDescription {
|
||||||
u32 active;
|
u32 active;
|
||||||
|
u32 valid;
|
||||||
u32 keyActivated;
|
u32 keyActivated;
|
||||||
u32 keyCombo;
|
u32 keyCombo;
|
||||||
char name[40];
|
char name[40];
|
||||||
@ -52,6 +53,10 @@ typedef struct CheatDescription {
|
|||||||
u64 codes[0];
|
u64 codes[0];
|
||||||
} CheatDescription;
|
} CheatDescription;
|
||||||
|
|
||||||
|
u32 codeStartAddress, heapStartAddress;
|
||||||
|
u32 codeTotalSize, heapTotalSize;
|
||||||
|
|
||||||
|
|
||||||
CheatDescription* cheats[1024] = { 0 };
|
CheatDescription* cheats[1024] = { 0 };
|
||||||
u8 cheatFileBuffer[16384] = { 0 };
|
u8 cheatFileBuffer[16384] = { 0 };
|
||||||
u32 cheatFilePos = 0;
|
u32 cheatFilePos = 0;
|
||||||
@ -112,14 +117,36 @@ u64 cheatTitleInfo = -1ULL;
|
|||||||
|
|
||||||
char failureReason[64];
|
char failureReason[64];
|
||||||
|
|
||||||
void Cheat_write8(u32 offset, u8 value) {
|
bool Cheat_isValidAddress(u32 address) {
|
||||||
*((u8*) (cheat_state.offset + offset)) = value;
|
if (codeStartAddress <= address && address <= codeStartAddress + codeTotalSize) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (heapStartAddress <= address && address <= heapStartAddress + heapTotalSize) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
void Cheat_write16(u32 offset, u16 value) {
|
|
||||||
*((u16*) (cheat_state.offset + offset)) = value;
|
bool Cheat_write8(u32 offset, u8 value) {
|
||||||
|
if (Cheat_isValidAddress(cheat_state.offset + offset)) {
|
||||||
|
*((u8*) (cheat_state.offset + offset)) = value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
void Cheat_write32(u32 offset, u32 value) {
|
bool Cheat_write16(u32 offset, u16 value) {
|
||||||
*((u32*) (cheat_state.offset + offset)) = value;
|
if (Cheat_isValidAddress(cheat_state.offset + offset)) {
|
||||||
|
*((u16*) (cheat_state.offset + offset)) = value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool Cheat_write32(u32 offset, u32 value) {
|
||||||
|
if (Cheat_isValidAddress(cheat_state.offset + offset)) {
|
||||||
|
*((u32*) (cheat_state.offset + offset)) = value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 Cheat_read8(u32 offset) {
|
u8 Cheat_read8(u32 offset) {
|
||||||
@ -147,7 +174,7 @@ u8 Cheat_getNextTypeE(const CheatDescription* cheat) {
|
|||||||
>> (typeEMapping[cheat_state.typeEIdx])) & 0xFF);
|
>> (typeEMapping[cheat_state.typeEIdx])) & 0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cheat_applyCheat(const CheatDescription* const cheat) {
|
u32 Cheat_applyCheat(const CheatDescription* const cheat) {
|
||||||
cheat_state.index = 0;
|
cheat_state.index = 0;
|
||||||
cheat_state.offset = 0;
|
cheat_state.offset = 0;
|
||||||
cheat_state.data = 0;
|
cheat_state.data = 0;
|
||||||
@ -166,7 +193,7 @@ void Cheat_applyCheat(const CheatDescription* const cheat) {
|
|||||||
u32 arg1 = (u32) ((cheat->codes[cheat_state.index])
|
u32 arg1 = (u32) ((cheat->codes[cheat_state.index])
|
||||||
& 0x00000000FFFFFFFFULL);
|
& 0x00000000FFFFFFFFULL);
|
||||||
if (arg0 == 0 && arg1 == 0) {
|
if (arg0 == 0 && arg1 == 0) {
|
||||||
goto end_main_loop;
|
return 0;
|
||||||
}
|
}
|
||||||
u32 code = ((arg0 >> 28) & 0x0F);
|
u32 code = ((arg0 >> 28) & 0x0F);
|
||||||
u32 subcode = ((arg0 >> 24) & 0x0F);
|
u32 subcode = ((arg0 >> 24) & 0x0F);
|
||||||
@ -177,7 +204,7 @@ void Cheat_applyCheat(const CheatDescription* const cheat) {
|
|||||||
// Format: 0XXXXXXX YYYYYYYY
|
// Format: 0XXXXXXX YYYYYYYY
|
||||||
// Description: 32bit write of YYYYYYYY to 0XXXXXXX.
|
// Description: 32bit write of YYYYYYYY to 0XXXXXXX.
|
||||||
if (!skipExecution) {
|
if (!skipExecution) {
|
||||||
Cheat_write32((arg0 & 0x0FFFFFFF), arg1);
|
if (!Cheat_write32((arg0 & 0x0FFFFFFF), arg1)) return 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x1:
|
case 0x1:
|
||||||
@ -185,7 +212,7 @@ void Cheat_applyCheat(const CheatDescription* const cheat) {
|
|||||||
// Format: 1XXXXXXX 0000YYYY
|
// Format: 1XXXXXXX 0000YYYY
|
||||||
// Description: 16bit write of YYYY to 0XXXXXXX.
|
// Description: 16bit write of YYYY to 0XXXXXXX.
|
||||||
if (!skipExecution) {
|
if (!skipExecution) {
|
||||||
Cheat_write16((arg0 & 0x0FFFFFFF), (u16) (arg1 & 0xFFFF));
|
if (!Cheat_write16((arg0 & 0x0FFFFFFF), (u16) (arg1 & 0xFFFF))) return 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x2:
|
case 0x2:
|
||||||
@ -193,7 +220,7 @@ void Cheat_applyCheat(const CheatDescription* const cheat) {
|
|||||||
// Format: 2XXXXXXX 000000YY
|
// Format: 2XXXXXXX 000000YY
|
||||||
// Description: 8bit write of YY to 0XXXXXXX.
|
// Description: 8bit write of YY to 0XXXXXXX.
|
||||||
if (!skipExecution) {
|
if (!skipExecution) {
|
||||||
Cheat_write8((arg0 & 0x0FFFFFFF), (u8) (arg1 & 0xFF));
|
if (!Cheat_write8((arg0 & 0x0FFFFFFF), (u8) (arg1 & 0xFF))) return 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x3:
|
case 0x3:
|
||||||
@ -537,7 +564,7 @@ void Cheat_applyCheat(const CheatDescription* const cheat) {
|
|||||||
// Note: used with the C, D3, and D9 types.
|
// Note: used with the C, D3, and D9 types.
|
||||||
// Example: D3000000 023D6B28
|
// Example: D3000000 023D6B28
|
||||||
if (!skipExecution) {
|
if (!skipExecution) {
|
||||||
Cheat_write32(arg1, cheat_state.data);
|
if (!Cheat_write32(arg1, cheat_state.data)) return 0;
|
||||||
cheat_state.offset += 4;
|
cheat_state.offset += 4;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -549,7 +576,7 @@ void Cheat_applyCheat(const CheatDescription* const cheat) {
|
|||||||
// Note: used with the C, D3, and DA types.
|
// Note: used with the C, D3, and DA types.
|
||||||
// Example: D7000000 023D6B28
|
// Example: D7000000 023D6B28
|
||||||
if (!skipExecution) {
|
if (!skipExecution) {
|
||||||
Cheat_write16(arg1, (u16) (cheat_state.data & 0xFFFF));
|
if (!Cheat_write16(arg1, (u16) (cheat_state.data & 0xFFFF))) return 0;
|
||||||
cheat_state.offset += 2;
|
cheat_state.offset += 2;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -561,7 +588,7 @@ void Cheat_applyCheat(const CheatDescription* const cheat) {
|
|||||||
// Note: used with the C, D3, and DB types.
|
// Note: used with the C, D3, and DB types.
|
||||||
// Example: D8000000 023D6B28
|
// Example: D8000000 023D6B28
|
||||||
if (!skipExecution) {
|
if (!skipExecution) {
|
||||||
Cheat_write8(arg1, (u8) (cheat_state.data & 0xFF));
|
if (!Cheat_write8(arg1, (u8) (cheat_state.data & 0xFF))) return 0;
|
||||||
cheat_state.offset += 1;
|
cheat_state.offset += 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -625,7 +652,7 @@ void Cheat_applyCheat(const CheatDescription* const cheat) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
goto end_main_loop;
|
return 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0xE:
|
case 0xE:
|
||||||
@ -644,18 +671,18 @@ void Cheat_applyCheat(const CheatDescription* const cheat) {
|
|||||||
for (u32 i = 0; i < count; i++) {
|
for (u32 i = 0; i < count; i++) {
|
||||||
u8 byte = Cheat_getNextTypeE(cheat);
|
u8 byte = Cheat_getNextTypeE(cheat);
|
||||||
if (!skipExecution) {
|
if (!skipExecution) {
|
||||||
Cheat_write8(beginOffset + i, byte);
|
if (!Cheat_write8(beginOffset + i, byte)) return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cheat_state.index = cheat_state.typeELine;
|
cheat_state.index = cheat_state.typeELine;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
goto end_main_loop;
|
return 0;
|
||||||
}
|
}
|
||||||
cheat_state.index++;
|
cheat_state.index++;
|
||||||
}
|
}
|
||||||
end_main_loop: ;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Cheat_mapMemoryAndApplyCheat(u32 pid, CheatDescription* const cheat) {
|
Result Cheat_mapMemoryAndApplyCheat(u32 pid, CheatDescription* const cheat) {
|
||||||
@ -664,9 +691,7 @@ Result Cheat_mapMemoryAndApplyCheat(u32 pid, CheatDescription* const cheat) {
|
|||||||
res = svcOpenProcess(&processHandle, pid);
|
res = svcOpenProcess(&processHandle, pid);
|
||||||
if (R_SUCCEEDED(res)) {
|
if (R_SUCCEEDED(res)) {
|
||||||
|
|
||||||
u32 codeStartAddress, heapStartAddress;
|
|
||||||
u32 codeDestAddress, heapDestAddress;
|
u32 codeDestAddress, heapDestAddress;
|
||||||
u32 codeTotalSize, heapTotalSize;
|
|
||||||
|
|
||||||
s64 textStartAddress, textTotalRoundedSize, rodataTotalRoundedSize,
|
s64 textStartAddress, textTotalRoundedSize, rodataTotalRoundedSize,
|
||||||
dataTotalRoundedSize;
|
dataTotalRoundedSize;
|
||||||
@ -694,7 +719,7 @@ Result Cheat_mapMemoryAndApplyCheat(u32 pid, CheatDescription* const cheat) {
|
|||||||
heapStartAddress, heapTotalSize);
|
heapStartAddress, heapTotalSize);
|
||||||
|
|
||||||
if (R_SUCCEEDED(codeRes | heapRes)) {
|
if (R_SUCCEEDED(codeRes | heapRes)) {
|
||||||
Cheat_applyCheat(cheat);
|
cheat->valid = Cheat_applyCheat(cheat);
|
||||||
|
|
||||||
if (R_SUCCEEDED(codeRes))
|
if (R_SUCCEEDED(codeRes))
|
||||||
svcUnmapProcessMemoryEx(processHandle, codeDestAddress,
|
svcUnmapProcessMemoryEx(processHandle, codeDestAddress,
|
||||||
@ -742,6 +767,7 @@ CheatDescription* Cheat_allocCheat() {
|
|||||||
+ sizeof(u64) * (prev->codesCount));
|
+ sizeof(u64) * (prev->codesCount));
|
||||||
}
|
}
|
||||||
cheat->active = 0;
|
cheat->active = 0;
|
||||||
|
cheat->valid = 1;
|
||||||
cheat->codesCount = 0;
|
cheat->codesCount = 0;
|
||||||
cheat->keyActivated = 0;
|
cheat->keyActivated = 0;
|
||||||
cheat->keyCombo = 0;
|
cheat->keyCombo = 0;
|
||||||
@ -919,53 +945,6 @@ void Cheat_loadCheatsIntoMemory(u64 titleId) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadCheatsIntoMemoryBin(u64 titleId) {
|
|
||||||
cheatCount = 0;
|
|
||||||
cheatTitleInfo = titleId;
|
|
||||||
hasKeyActivated = 0;
|
|
||||||
|
|
||||||
char path[] = "/luma/titles/0000000000000000/cheats.bin";
|
|
||||||
Cheat_progIdToStr(path + 28, titleId);
|
|
||||||
|
|
||||||
IFile file;
|
|
||||||
|
|
||||||
if (!Cheat_openLumaFile(&file, path))
|
|
||||||
return;
|
|
||||||
|
|
||||||
u8 buffer[8];
|
|
||||||
u64 total;
|
|
||||||
|
|
||||||
IFile_Read(&file, &total, buffer, 1);
|
|
||||||
u8 cc = buffer[0];
|
|
||||||
for (u8 i = 0; i < cc; i++) {
|
|
||||||
CheatDescription* cheat = Cheat_allocCheat();
|
|
||||||
cheat->active = 0;
|
|
||||||
IFile_Read(&file, &total, buffer, 1);
|
|
||||||
u8 nameLen = buffer[0];
|
|
||||||
IFile_Read(&file, &total, cheat->name, nameLen);
|
|
||||||
cheat->name[nameLen] = '\0';
|
|
||||||
IFile_Read(&file, &total, buffer, 1);
|
|
||||||
u8 codeCount = buffer[0];
|
|
||||||
cheat->codesCount = 0;
|
|
||||||
cheat->keyActivated = 0;
|
|
||||||
cheat->keyCombo = 0;
|
|
||||||
for (u8 j = 0; j < codeCount; j++) {
|
|
||||||
IFile_Read(&file, &total, buffer, 8);
|
|
||||||
u64 tmp = buffer[0];
|
|
||||||
for (u8 k = 1; k < 8; k++) {
|
|
||||||
tmp = (tmp << 8) + buffer[k];
|
|
||||||
}
|
|
||||||
Cheat_addCode(cheat, tmp);
|
|
||||||
if (((tmp >> 32) & 0xFFFFFFFF) == 0xDD000000) {
|
|
||||||
cheat->keyCombo |= (tmp & 0xFFF);
|
|
||||||
cheat->keyActivated = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IFile_Close(&file);
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 Cheat_GetCurrentPID(u64* titleId) {
|
u32 Cheat_GetCurrentPID(u64* titleId) {
|
||||||
s32 processAmount = Cheats_FetchProcessInfo();
|
s32 processAmount = Cheats_FetchProcessInfo();
|
||||||
|
|
||||||
@ -1071,7 +1050,7 @@ void RosalinaMenu_Cheats(void) {
|
|||||||
const char * keyAct = (cheats[j]->keyActivated ? "*" : " ");
|
const char * keyAct = (cheats[j]->keyActivated ? "*" : " ");
|
||||||
sprintf(buf, "%s%s%s", checkbox, keyAct, cheats[j]->name);
|
sprintf(buf, "%s%s%s", checkbox, keyAct, cheats[j]->name);
|
||||||
|
|
||||||
Draw_DrawString(30, 30 + i * SPACING_Y, COLOR_WHITE, buf);
|
Draw_DrawString(30, 30 + i * SPACING_Y, cheats[j]->valid ? COLOR_WHITE : COLOR_RED, buf);
|
||||||
Draw_DrawCharacter(10, 30 + i * SPACING_Y, COLOR_TITLE,
|
Draw_DrawCharacter(10, 30 + i * SPACING_Y, COLOR_TITLE,
|
||||||
j == selected ? '>' : ' ');
|
j == selected ? '>' : ' ');
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user