Switched from mapping target process memory to svcReadProcessMemory & svcWriteProcessMemory functions.
This commit is contained in:
parent
1de27c54f1
commit
c5c8dca14c
@ -55,9 +55,6 @@ typedef struct CheatDescription
|
||||
u64 codes[0];
|
||||
} CheatDescription;
|
||||
|
||||
u32 codeStartAddress, heapStartAddress;
|
||||
u32 codeTotalSize, heapTotalSize;
|
||||
|
||||
CheatDescription* cheats[1024] = { 0 };
|
||||
u8 cheatFileBuffer[16384] = { 0 };
|
||||
u32 cheatFilePos = 0;
|
||||
@ -118,75 +115,81 @@ u64 cheatTitleInfo = -1ULL;
|
||||
|
||||
char failureReason[64];
|
||||
|
||||
static bool Cheat_IsValidAddress(u32 address, u32 size)
|
||||
static bool Cheat_IsValidAddress(const Handle processHandle, u32 address, u32 size)
|
||||
{
|
||||
if (codeStartAddress > 0 && codeStartAddress <= address && address <= codeStartAddress + codeTotalSize - size)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (heapStartAddress > 0 && heapStartAddress <= address && address <= heapStartAddress + heapTotalSize - size)
|
||||
{
|
||||
MemInfo info;
|
||||
PageInfo out;
|
||||
|
||||
Result res = svcQueryDebugProcessMemory(&info, &out, processHandle, address);
|
||||
if (R_SUCCEEDED(res) && info.state != MEMSTATE_FREE && info.base_addr > 0 && info.base_addr <= address && address <= info.base_addr + info.size - size) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool Cheat_Write8(u32 offset, u8 value)
|
||||
static u32 ReadWriteBuffer32 = 0;
|
||||
static u16 ReadWriteBuffer16 = 0;
|
||||
static u8 ReadWriteBuffer8 = 0;
|
||||
|
||||
static bool Cheat_Write8(const Handle processHandle, u32 offset, u8 value)
|
||||
{
|
||||
if (Cheat_IsValidAddress(cheat_state.offset + offset, 1))
|
||||
if (Cheat_IsValidAddress(processHandle, cheat_state.offset + offset, 1))
|
||||
{
|
||||
*((u8*) (cheat_state.offset + offset)) = value;
|
||||
return true;
|
||||
*((u8*) (&ReadWriteBuffer8)) = value;
|
||||
return R_SUCCEEDED(svcWriteProcessMemory(processHandle, &ReadWriteBuffer8, cheat_state.offset + offset, 1));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool Cheat_Write16(u32 offset, u16 value)
|
||||
static bool Cheat_Write16(const Handle processHandle, u32 offset, u16 value)
|
||||
{
|
||||
if (Cheat_IsValidAddress(cheat_state.offset + offset, 2))
|
||||
if (Cheat_IsValidAddress(processHandle, cheat_state.offset + offset, 2))
|
||||
{
|
||||
*((u16*) (cheat_state.offset + offset)) = value;
|
||||
return true;
|
||||
*((u16*) (&ReadWriteBuffer16)) = value;
|
||||
return R_SUCCEEDED(svcWriteProcessMemory(processHandle, &ReadWriteBuffer16, cheat_state.offset + offset, 2));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool Cheat_Write32(u32 offset, u32 value)
|
||||
static bool Cheat_Write32(const Handle processHandle, u32 offset, u32 value)
|
||||
{
|
||||
if (Cheat_IsValidAddress(cheat_state.offset + offset, 4))
|
||||
if (Cheat_IsValidAddress(processHandle, cheat_state.offset + offset, 4))
|
||||
{
|
||||
*((u32*) (cheat_state.offset + offset)) = value;
|
||||
return true;
|
||||
*((u32*) (&ReadWriteBuffer32)) = value;
|
||||
return R_SUCCEEDED(svcWriteProcessMemory(processHandle, &ReadWriteBuffer32, cheat_state.offset + offset, 4));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool Cheat_Read8(u32 offset, u8* retValue)
|
||||
static bool Cheat_Read8(const Handle processHandle, u32 offset, u8* retValue)
|
||||
{
|
||||
if (Cheat_IsValidAddress(cheat_state.offset + offset, 1))
|
||||
if (Cheat_IsValidAddress(processHandle, cheat_state.offset + offset, 1))
|
||||
{
|
||||
*retValue = *((u8*) (cheat_state.offset + offset));
|
||||
return true;
|
||||
Result res = svcReadProcessMemory(&ReadWriteBuffer8, processHandle, cheat_state.offset + offset, 1);
|
||||
*retValue = *((u8*) (&ReadWriteBuffer8));
|
||||
return R_SUCCEEDED(res);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool Cheat_Read16(u32 offset, u16* retValue)
|
||||
static bool Cheat_Read16(const Handle processHandle, u32 offset, u16* retValue)
|
||||
{
|
||||
if (Cheat_IsValidAddress(cheat_state.offset + offset, 2))
|
||||
if (Cheat_IsValidAddress(processHandle, cheat_state.offset + offset, 2))
|
||||
{
|
||||
*retValue = *((u16*) (cheat_state.offset + offset));
|
||||
return true;
|
||||
Result res = svcReadProcessMemory(&ReadWriteBuffer16, processHandle, cheat_state.offset + offset, 2);
|
||||
*retValue = *((u16*) (&ReadWriteBuffer16));
|
||||
return R_SUCCEEDED(res);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool Cheat_Read32(u32 offset, u32* retValue)
|
||||
static bool Cheat_Read32(const Handle processHandle, u32 offset, u32* retValue)
|
||||
{
|
||||
if (Cheat_IsValidAddress(cheat_state.offset + offset, 4))
|
||||
if (Cheat_IsValidAddress(processHandle, cheat_state.offset + offset, 4))
|
||||
{
|
||||
*retValue = *((u32*) (cheat_state.offset + offset));
|
||||
return true;
|
||||
Result res = svcReadProcessMemory(&ReadWriteBuffer32, processHandle, cheat_state.offset + offset, 4);
|
||||
*retValue = *((u32*) (&ReadWriteBuffer32));
|
||||
return R_SUCCEEDED(res);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -208,7 +211,7 @@ static u8 Cheat_GetNextTypeE(const CheatDescription* cheat)
|
||||
return (u8) ((cheat->codes[cheat_state.typeELine] >> (typeEMapping[cheat_state.typeEIdx])) & 0xFF);
|
||||
}
|
||||
|
||||
static u32 Cheat_ApplyCheat(const CheatDescription* const cheat)
|
||||
static u32 Cheat_ApplyCheat(const Handle processHandle, const CheatDescription* const cheat)
|
||||
{
|
||||
cheat_state.index = 0;
|
||||
cheat_state.offset = 0;
|
||||
@ -241,7 +244,7 @@ static u32 Cheat_ApplyCheat(const CheatDescription* const cheat)
|
||||
// Description: 32bit write of YYYYYYYY to 0XXXXXXX.
|
||||
if (!skipExecution)
|
||||
{
|
||||
if (!Cheat_Write32((arg0 & 0x0FFFFFFF), arg1)) return 0;
|
||||
if (!Cheat_Write32(processHandle, (arg0 & 0x0FFFFFFF), arg1)) return 0;
|
||||
}
|
||||
break;
|
||||
case 0x1:
|
||||
@ -250,7 +253,7 @@ static u32 Cheat_ApplyCheat(const CheatDescription* const cheat)
|
||||
// Description: 16bit write of YYYY to 0XXXXXXX.
|
||||
if (!skipExecution)
|
||||
{
|
||||
if (!Cheat_Write16((arg0 & 0x0FFFFFFF), (u16) (arg1 & 0xFFFF))) return 0;
|
||||
if (!Cheat_Write16(processHandle, (arg0 & 0x0FFFFFFF), (u16) (arg1 & 0xFFFF))) return 0;
|
||||
}
|
||||
break;
|
||||
case 0x2:
|
||||
@ -259,7 +262,7 @@ static u32 Cheat_ApplyCheat(const CheatDescription* const cheat)
|
||||
// Description: 8bit write of YY to 0XXXXXXX.
|
||||
if (!skipExecution)
|
||||
{
|
||||
if (!Cheat_Write8((arg0 & 0x0FFFFFFF), (u8) (arg1 & 0xFF))) return 0;
|
||||
if (!Cheat_Write8(processHandle, (arg0 & 0x0FFFFFFF), (u8) (arg1 & 0xFF))) return 0;
|
||||
}
|
||||
break;
|
||||
case 0x3:
|
||||
@ -271,7 +274,7 @@ static u32 Cheat_ApplyCheat(const CheatDescription* const cheat)
|
||||
{
|
||||
u32 newSkip;
|
||||
u32 value = 0;
|
||||
if (!Cheat_Read32(arg0 & 0x0FFFFFFF, &value)) return 0;
|
||||
if (!Cheat_Read32(processHandle, arg0 & 0x0FFFFFFF, &value)) return 0;
|
||||
if (value < arg1)
|
||||
{
|
||||
newSkip = 0;
|
||||
@ -295,7 +298,7 @@ static u32 Cheat_ApplyCheat(const CheatDescription* const cheat)
|
||||
{
|
||||
u32 newSkip;
|
||||
u32 value = 0;
|
||||
if (!Cheat_Read32(arg0 & 0x0FFFFFFF, &value)) return 0;
|
||||
if (!Cheat_Read32(processHandle, arg0 & 0x0FFFFFFF, &value)) return 0;
|
||||
if (value > arg1)
|
||||
{
|
||||
newSkip = 0;
|
||||
@ -319,7 +322,7 @@ static u32 Cheat_ApplyCheat(const CheatDescription* const cheat)
|
||||
{
|
||||
u32 newSkip;
|
||||
u32 value = 0;
|
||||
if (!Cheat_Read32(arg0 & 0x0FFFFFFF, &value)) return 0;
|
||||
if (!Cheat_Read32(processHandle, arg0 & 0x0FFFFFFF, &value)) return 0;
|
||||
if (value == arg1)
|
||||
{
|
||||
newSkip = 0;
|
||||
@ -343,7 +346,7 @@ static u32 Cheat_ApplyCheat(const CheatDescription* const cheat)
|
||||
{
|
||||
u32 newSkip;
|
||||
u32 value = 0;
|
||||
if (!Cheat_Read32(arg0 & 0x0FFFFFFF, &value)) return 0;
|
||||
if (!Cheat_Read32(processHandle, arg0 & 0x0FFFFFFF, &value)) return 0;
|
||||
if (value != arg1)
|
||||
{
|
||||
newSkip = 0;
|
||||
@ -368,7 +371,7 @@ static u32 Cheat_ApplyCheat(const CheatDescription* const cheat)
|
||||
u32 newSkip;
|
||||
u16 mask = (u16) ((arg1 >> 16) & 0xFFFF);
|
||||
u16 value = 0;
|
||||
if (!Cheat_Read16(arg0 & 0x0FFFFFFF, &value)) return 0;
|
||||
if (!Cheat_Read16(processHandle, arg0 & 0x0FFFFFFF, &value)) return 0;
|
||||
if ((value & (~mask)) < (arg1 & 0xFFFF))
|
||||
{
|
||||
newSkip = 0;
|
||||
@ -393,7 +396,7 @@ static u32 Cheat_ApplyCheat(const CheatDescription* const cheat)
|
||||
u32 newSkip;
|
||||
u16 mask = (u16) ((arg1 >> 16) & 0xFFFF);
|
||||
u16 value = 0;
|
||||
if (!Cheat_Read16(arg0 & 0x0FFFFFFF, &value)) return 0;
|
||||
if (!Cheat_Read16(processHandle, arg0 & 0x0FFFFFFF, &value)) return 0;
|
||||
if ((value & (~mask)) > (arg1 & 0xFFFF))
|
||||
{
|
||||
newSkip = 0;
|
||||
@ -418,7 +421,7 @@ static u32 Cheat_ApplyCheat(const CheatDescription* const cheat)
|
||||
u32 newSkip;
|
||||
u16 mask = (u16) ((arg1 >> 16) & 0xFFFF);
|
||||
u16 value = 0;
|
||||
if (!Cheat_Read16(arg0 & 0x0FFFFFFF, &value)) return 0;
|
||||
if (!Cheat_Read16(processHandle, arg0 & 0x0FFFFFFF, &value)) return 0;
|
||||
if ((value & (~mask)) == (arg1 & 0xFFFF))
|
||||
{
|
||||
newSkip = 0;
|
||||
@ -443,7 +446,7 @@ static u32 Cheat_ApplyCheat(const CheatDescription* const cheat)
|
||||
u32 newSkip;
|
||||
u16 mask = (u16) ((arg1 >> 16) & 0xFFFF);
|
||||
u16 value = 0;
|
||||
if (!Cheat_Read16(arg0 & 0x0FFFFFFF, &value)) return 0;
|
||||
if (!Cheat_Read16(processHandle, arg0 & 0x0FFFFFFF, &value)) return 0;
|
||||
if ((value & (~mask)) != (arg1 & 0xFFFF))
|
||||
{
|
||||
newSkip = 0;
|
||||
@ -659,7 +662,7 @@ static u32 Cheat_ApplyCheat(const CheatDescription* const cheat)
|
||||
// Example: D3000000 023D6B28
|
||||
if (!skipExecution)
|
||||
{
|
||||
if (!Cheat_Write32(arg1, cheat_state.data)) return 0;
|
||||
if (!Cheat_Write32(processHandle, arg1, cheat_state.data)) return 0;
|
||||
cheat_state.offset += 4;
|
||||
}
|
||||
break;
|
||||
@ -672,7 +675,7 @@ static u32 Cheat_ApplyCheat(const CheatDescription* const cheat)
|
||||
// Example: D7000000 023D6B28
|
||||
if (!skipExecution)
|
||||
{
|
||||
if (!Cheat_Write16(arg1, (u16) (cheat_state.data & 0xFFFF))) return 0;
|
||||
if (!Cheat_Write16(processHandle, arg1, (u16) (cheat_state.data & 0xFFFF))) return 0;
|
||||
cheat_state.offset += 2;
|
||||
}
|
||||
break;
|
||||
@ -685,7 +688,7 @@ static u32 Cheat_ApplyCheat(const CheatDescription* const cheat)
|
||||
// Example: D8000000 023D6B28
|
||||
if (!skipExecution)
|
||||
{
|
||||
if (!Cheat_Write8(arg1, (u8) (cheat_state.data & 0xFF))) return 0;
|
||||
if (!Cheat_Write8(processHandle, arg1, (u8) (cheat_state.data & 0xFF))) return 0;
|
||||
cheat_state.offset += 1;
|
||||
}
|
||||
break;
|
||||
@ -699,7 +702,7 @@ static u32 Cheat_ApplyCheat(const CheatDescription* const cheat)
|
||||
if (!skipExecution)
|
||||
{
|
||||
u32 value = 0;
|
||||
if (!Cheat_Read32(arg1, &value)) return 0;
|
||||
if (!Cheat_Read32(processHandle, arg1, &value)) return 0;
|
||||
cheat_state.data = value;
|
||||
}
|
||||
break;
|
||||
@ -713,7 +716,7 @@ static u32 Cheat_ApplyCheat(const CheatDescription* const cheat)
|
||||
if (!skipExecution)
|
||||
{
|
||||
u16 value = 0;
|
||||
if (!Cheat_Read16(arg1, &value)) return 0;
|
||||
if (!Cheat_Read16(processHandle, arg1, &value)) return 0;
|
||||
cheat_state.data = value;
|
||||
}
|
||||
break;
|
||||
@ -727,7 +730,7 @@ static u32 Cheat_ApplyCheat(const CheatDescription* const cheat)
|
||||
if (!skipExecution)
|
||||
{
|
||||
u8 value = 0;
|
||||
if (!Cheat_Read8(arg1, &value)) return 0;
|
||||
if (!Cheat_Read8(processHandle, arg1, &value)) return 0;
|
||||
cheat_state.data = value;
|
||||
}
|
||||
break;
|
||||
@ -783,7 +786,7 @@ static u32 Cheat_ApplyCheat(const CheatDescription* const cheat)
|
||||
u8 byte = Cheat_GetNextTypeE(cheat);
|
||||
if (!skipExecution)
|
||||
{
|
||||
if (!Cheat_Write8(beginOffset + i, byte)) return 0;
|
||||
if (!Cheat_Write8(processHandle, beginOffset + i, byte)) return 0;
|
||||
}
|
||||
}
|
||||
cheat_state.index = cheat_state.typeELine;
|
||||
@ -797,66 +800,45 @@ static u32 Cheat_ApplyCheat(const CheatDescription* const cheat)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void Cheat_EatEvents(Handle debug)
|
||||
{
|
||||
DebugEventInfo info;
|
||||
Result r;
|
||||
|
||||
while(true)
|
||||
{
|
||||
if((r = svcGetProcessDebugEvent(&info, debug)) != 0)
|
||||
{
|
||||
if(r == (s32)(0xd8402009))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
svcContinueDebugEvent(debug, 3);
|
||||
}
|
||||
}
|
||||
|
||||
static Result Cheat_MapMemoryAndApplyCheat(u32 pid, CheatDescription* const cheat)
|
||||
{
|
||||
Handle processHandle;
|
||||
Handle debugHandle;
|
||||
Result res;
|
||||
res = svcOpenProcess(&processHandle, pid);
|
||||
if (R_SUCCEEDED(res))
|
||||
{
|
||||
|
||||
u32 codeDestAddress, heapDestAddress;
|
||||
|
||||
s64 textStartAddress, textTotalRoundedSize, rodataTotalRoundedSize, dataTotalRoundedSize;
|
||||
|
||||
svcGetProcessInfo(&textTotalRoundedSize, processHandle, 0x10002);
|
||||
svcGetProcessInfo(&rodataTotalRoundedSize, processHandle, 0x10003);
|
||||
svcGetProcessInfo(&dataTotalRoundedSize, processHandle, 0x10004);
|
||||
|
||||
svcGetProcessInfo(&textStartAddress, processHandle, 0x10005);
|
||||
|
||||
codeTotalSize = (u32) (textTotalRoundedSize + rodataTotalRoundedSize + dataTotalRoundedSize);
|
||||
codeDestAddress = codeStartAddress = (u32) textStartAddress; //should be 0x00100000
|
||||
|
||||
MemInfo info;
|
||||
PageInfo out;
|
||||
|
||||
heapDestAddress = heapStartAddress = 0x08000000;
|
||||
svcQueryProcessMemory(&info, &out, processHandle, heapStartAddress);
|
||||
heapTotalSize = info.size;
|
||||
|
||||
Result codeRes = svcMapProcessMemoryEx(processHandle, codeDestAddress, codeStartAddress, codeTotalSize);
|
||||
if (R_FAILED(codeRes))
|
||||
res = svcDebugActiveProcess(&debugHandle, pid);
|
||||
if (R_SUCCEEDED(res))
|
||||
{
|
||||
codeStartAddress = codeTotalSize = 0;
|
||||
}
|
||||
Cheat_EatEvents(debugHandle);
|
||||
cheat->valid = Cheat_ApplyCheat(debugHandle, cheat);
|
||||
|
||||
Result heapRes = svcMapProcessMemoryEx(processHandle, heapDestAddress, heapStartAddress, heapTotalSize);
|
||||
if (R_FAILED(heapRes))
|
||||
{
|
||||
heapStartAddress = heapTotalSize = 0;
|
||||
}
|
||||
|
||||
if (R_SUCCEEDED(codeRes) || R_SUCCEEDED(heapRes))
|
||||
{
|
||||
cheat->valid = Cheat_ApplyCheat(cheat);
|
||||
|
||||
if (R_SUCCEEDED(codeRes))
|
||||
{
|
||||
svcUnmapProcessMemoryEx(processHandle, codeDestAddress, codeTotalSize);
|
||||
}
|
||||
if (R_SUCCEEDED(heapRes))
|
||||
{
|
||||
svcUnmapProcessMemoryEx(processHandle, heapDestAddress, heapTotalSize);
|
||||
}
|
||||
svcCloseHandle(debugHandle);
|
||||
svcCloseHandle(processHandle);
|
||||
cheat->active = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
svcCloseHandle(processHandle);
|
||||
sprintf(failureReason, "Can not map any memory");
|
||||
return codeRes;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -1073,8 +1055,12 @@ static void Cheat_LoadCheatsIntoMemory(u64 titleId)
|
||||
Cheat_AddCode(cheat, tmp);
|
||||
if (((tmp >> 32) & 0xFFFFFFFF) == 0xDD000000)
|
||||
{
|
||||
cheat->keyCombo |= (tmp & 0xFFF);
|
||||
cheat->keyActivated = 1;
|
||||
if (tmp & 0xFFFFFFFF)
|
||||
{
|
||||
// Not empty key code
|
||||
cheat->keyCombo |= (tmp & 0xFFF);
|
||||
cheat->keyActivated = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user