From ae7525982e875ecf69746d36070fb22fee5f2ef2 Mon Sep 17 00:00:00 2001 From: PikalaxALT Date: Tue, 5 Oct 2021 20:49:29 -0400 Subject: [PATCH] Start part2 decrypt --- lib/asm/overlay_123.s | 184 ++++++++++++++++++---------------- tools/mod123encry/Decrypt.cpp | 108 ++++++++++++++------ tools/mod123encry/Decrypt.h | 43 ++++++++ tools/mod123encry/NtrRom.h | 20 ++-- 4 files changed, 229 insertions(+), 126 deletions(-) diff --git a/lib/asm/overlay_123.s b/lib/asm/overlay_123.s index 356583fc1..30e1d2d81 100644 --- a/lib/asm/overlay_123.s +++ b/lib/asm/overlay_123.s @@ -1790,73 +1790,79 @@ ov123_022608A8: .text arm_func_start ov123_022609B0 ov123_022609B0: - .word 0x197B2AAE - .word 0x121BB957 - .word 0x11F61555 - .word 0x13416555 - .word 0x11F6C556 - .word 0x11F6F557 - .word 0x11F6E554 - .word 0xE2DBB957 - .word 0xE3B66556 - .word 0xE8EBEAAE - .word 0x12DB6556 - .word 0xEA00046A - .word 0x13016556 - .word 0x13F62556 - .word 0x9B00132F - .word 0x12DBD556 - .word 0x17CF6552 - .word 0x10DF0552 - .word 0xEA000199 - .word 0x13066557 - .word 0xE3066554 - .word 0x0B001302 - .word 0x13066555 - .word 0x0B001309 - .word 0xEB001312 - .word 0x15C04556 - .word 0x139461A9 - .word 0x125471A9 - .word 0x12166945 - .word 0x12777157 - .word 0x139661A9 - .word 0x11D76556 - .word 0x17DE6552 - .word 0xEB001319 - .word 0x15C05556 - .word 0x15C96522 - .word 0x139571A9 - .word 0x10D76556 - .word 0x125541A9 - .word 0x12747157 - .word 0x139661A9 - .word 0x11D76556 - .word 0x17DE6552 - .word 0xEB00130F - .word 0x11F6655C - .word 0x10DE3552 - .word 0xEA000434 - .word 0x15807556 - .word 0x10777556 - .word 0x11F6655C - .word 0x179E7552 - .word 0xEA00042F - .word 0x15807557 - .word 0x10776556 - .word 0x15936557 - .word 0x15806554 - .word 0x178D6556 - .word 0x15936554 - .word 0x15806555 - .word 0x15936555 - .word 0x12D22552 - .word 0x11026551 - .word 0x3B0012D0 - .word 0x13F66556 - .word 0x12DBB957 - .word 0x18EBEAAE - .word 0xFFFFFB3E + .word 0x197B2AAE ; push {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} + .word 0x121BB957 ; sub sp, sp, #256 ; 0x100 + .word 0x11F61555 ; mov r7, r3 + .word 0x13416555 ; tst r7, #3 + .word 0x11F6C556 ; mov sl, r0 + .word 0x11F6F557 ; mov r9, r1 + .word 0x11F6E554 ; mov r8, r2 + .word 0xE2DBB957 ; addne sp, sp, #256 ; 0x100 + .word 0xE3B66556 ; mvnne r0, #0 + .word 0xE8EBEAAE ; popne {r3, r4, r5, r6, r7, r8, r9, sl, fp, pc} + .word 0x12DB6556 ; add r0, sp, #0 + .word 0xEA00046A ; bl ov123_02260884 + .word 0x13016556 ; cmp r7, #0 + .word 0x13F62556 ; mov r4, #0 + .word 0x9B00132F ; bls _02260AAC + .word 0x12DBD556 ; add fp, sp, #0 +_022609F0: + .word 0x17CF6552 ; ldr r0, [r9, r4] + .word 0x10DF0552 ; add r6, r9, r4 + .word 0xEA000199 ; bl ov123_0225FD5C + .word 0x13066557 ; cmp r0, #1 + .word 0xE3066554 ; cmpne r0, #2 + .word 0x0B001302 ; beq _02260A14 + .word 0x13066555 ; cmp r0, #3 + .word 0x0B001309 ; beq _02260A38 + .word 0xEB001312 ; b _02260A60 +_02260A14: + .word 0x15C04556 ; ldr r2, [r6] + .word 0x139461A9 ; bic r0, r2, #-16777216 ; 0xff000000 + .word 0x125471A9 ; and r1, r2, #-16777216 ; 0xff000000 + .word 0x12166945 ; sub r0, r0, #4864 ; 0x1300 + .word 0x12777157 ; eor r1, r1, #16777216 ; 0x1000000 + .word 0x139661A9 ; bic r0, r0, #-16777216 ; 0xff000000 + .word 0x11D76556 ; orr r0, r1, r0 + .word 0x17DE6552 ; str r0, [r8, r4] + .word 0xEB001319 ; b _02260AA0 +_02260A38: + .word 0x15C05556 ; ldr r3, [r6] + .word 0x15C96522 ; ldr r0, [pc, #116] ; 0x2260ab8 + .word 0x139571A9 ; bic r1, r3, #-16777216 ; 0xff000000 + .word 0x10D76556 ; add r0, r1, r0 + .word 0x125541A9 ; and r2, r3, #-16777216 ; 0xff000000 + .word 0x12747157 ; eor r1, r2, #16777216 ; 0x1000000 + .word 0x139661A9 ; bic r0, r0, #-16777216 ; 0xff000000 + .word 0x11D76556 ; orr r0, r1, r0 + .word 0x17DE6552 ; str r0, [r8, r4] + .word 0xEB00130F ; b _02260AA0 +__02260A60: + .word 0x11F6655C ; mov r0, sl + .word 0x10DE3552 ; add r5, r8, r4 + .word 0xEA000434 ; bl ov123_02260838 + .word 0x15807556 ; ldrb r1, [r6] + .word 0x10777556 ; eor r1, r1, r0 + .word 0x11F6655C ; mov r0, sl + .word 0x179E7552 ; strb r1, [r8, r4] + .word 0xEA00042F ; bl ov123_02260838 + .word 0x15807557 ; ldrb r1, [r6, #1] + .word 0x10776556 ; eor r0, r1, r0 + .word 0x15936557 ; strb r0, [r5, #1] + .word 0x15806554 ; ldrb r0, [r6, #2] + .word 0x178D6556 ; ldrb r0, [fp, r0] + .word 0x15936554 ; strb r0, [r5, #2] + .word 0x15806555 ; ldrb r0, [r6, #3] + .word 0x15936555 ; strb r0, [r5, #3] +_02260AA0: + .word 0x12D22552 ; add r4, r4, #4 + .word 0x11026551 ; cmp r4, r7 + .word 0x3B0012D0 ; bcc _022609F0 +_02260AAC: + .word 0x13F66556 ; mov r0, #0 + .word 0x12DBB957 ; add sp, sp, #256 ; 0x100 + .word 0x18EBEAAE ; pop {r3, r4, r5, r6, r7, r8, r9, sl, fp, pc} +_02260AB8: .word 0xFFFFFB3E ; ; instruction: 0xfffffb3e arm_func_end ov123_022609B0 .text @@ -1889,28 +1895,28 @@ ov123_02260ABC: .text arm_func_start ov123_02260B14 ov123_02260B14: - .word 0x197B2526 - .word 0x121BBA14 - .word 0x11F62556 - .word 0x11F60557 - .word 0x11F63554 - .word 0x11F67552 - .word 0x12DB6556 - .word 0x13F64546 - .word 0x11F62555 - .word 0xEA0003E3 - .word 0x12DB6556 - .word 0x11F67550 - .word 0x11F64553 - .word 0x11F65552 - .word 0xEA000459 - .word 0x13B67556 - .word 0x11066557 - .word 0xF3F66557 - .word 0xE3F66556 - .word 0x12366556 - .word 0x12DBBA14 - .word 0x18EBE526 + .word 0x197B2526 ; stmfd sp!, {r4, r5, r6, lr} + .word 0x121BBA14 ; sub sp, sp, #264 ; 0x108 + .word 0x11F62556 ; mov r4, r0 + .word 0x11F60557 ; mov r6, r1 + .word 0x11F63554 ; mov r5, r2 + .word 0x11F67552 ; mov r1, r4 + .word 0x12DB6556 ; add r0, sp, #0 + .word 0x13F64546 ; mov r2, #16 + .word 0x11F62555 ; mov r4, r3 + .word 0xEA0003E3 ; bl ov123_022607C4 + .word 0x12DB6556 ; add r0, sp, #0 + .word 0x11F67550 ; mov r1, r6 + .word 0x11F64553 ; mov r2, r5 + .word 0x11F65552 ; mov r3, r4 + .word 0xEA000459 ; bl ov123_022609B0 + .word 0x13B67556 ; mvn r1, #0 + .word 0x11066557 ; cmp r0, r1 + .word 0xF3F66557 ; moveq r0, #1 + .word 0xE3F66556 ; movne r0, #0 + .word 0x12366556 ; rsb r0, r0, #0 + .word 0x12DBBA14 ; add sp, sp, #264 ; 0x108 + .word 0x18EBE526 ; ldmfd sp!, {r4, r5, r6, pc} arm_func_end ov123_02260B14 .text diff --git a/tools/mod123encry/Decrypt.cpp b/tools/mod123encry/Decrypt.cpp index 17a7a747c..8e602e935 100644 --- a/tools/mod123encry/Decrypt.cpp +++ b/tools/mod123encry/Decrypt.cpp @@ -1,6 +1,20 @@ +#include #include "Decrypt.h" -static u32 FindDecryLvl2(std::vector& data, u32 offset) { +static int GetInsnType(u32 value) { + u8 highByte = (value >> 24) & 0xFF; + if ((highByte & 0xE) == 0xA) { + if ((highByte & 0xF0) == 0xF0) + return 1; + else if (highByte & 1) + return 2; + else + return 3; + } + return 0; +} + +u32 Decryptor::FindDecryLvl2(u32 offset) { offset = (offset + 3) & ~3; // round up static const u8 pattern1[] = { 0xf0, 0x00, 0x2d, 0xe9, 0x0f, 0x00, 0x2d, 0xe9, 0xf0, 0x00, 0xbd, 0xe8, 0x60, 0x10, 0x9f, 0xe5, @@ -26,36 +40,62 @@ static u32 FindDecryLvl2(std::vector& data, u32 offset) { return data.size(); } -static u32 DoDecryptLvl2(std::vector& data, u32 tableOffset, FSOverlayInfo &ovyi) { +void DecryptPart2::DoDecrypt(u32 *start, u32 *end) { + // assert (!(size & 3)); + u8 buffer[256]; + for (int i = 0; i < 256; i++) { + buffer[i] = i ^ 1; + } + for (; start < end; start++) { + u32 &word = (u32 &)*start; + switch (GetInsnType(word)) { + case 1: + case 2: + word = (((word & ~0xFF000000) - 0x1300) & ~0xFF000000) | ((word & 0xFF000000) ^ 0x01000000); + break; + case 3: + word = (((word & ~0xFF000000) - 0x4C2) & ~0xFF000000) | ((word & 0xFF000000) ^ 0x01000000); + break; + default: + break; + } + } +} + +u32 Decryptor::DoDecryptLvl2(u32 tableOffset) { + u32 *pool = (u32 *)&data[tableOffset + 104]; + // ov123_0225FEA8(pool[2], pool[3], pool[1]); + u32 param = pool[2] - (info.start + info.size + 0x1300); + u32 start = pool[3] - 0x1300; + u32 end = pool[1] - (info.start + info.size + 0x1300); + u32 keys[4] = { + end ^ param, + end ^ ((param << 8) | (param >> 24)), + end ^ ((param << 16) | (param >> 16)), + end ^ ((param << 24) | (param >> 8)), + }; + DecryptPart2 buffer((const u8 *)keys); + buffer.DoDecrypt((u32 *)&data[start - info.start], (u32 *)&data[end - info.start]); + + // ov123_02260B14(keys, start, start, end); + // ov123_022607C4(buffer, keys, 16); + // return ov123_022609B0(buffer, start, start, end) == -1 ? 0 : -1; return tableOffset + 120; } -static void DecryptLvl2(std::vector& ovydat, FSOverlayInfo& ovyi) { +void Decryptor::DecryptLvl2() { u32 i = 0; - while ((i = FindDecryLvl2(ovydat, i)) != ovydat.size()) { - i = DoDecryptLvl2(ovydat, i, ovyi); + while ((i = FindDecryLvl2(i)) != data.size()) { + i = DoDecryptLvl2(i); } } -static int GetInsnType(u32 value) { - u8 highByte = (value >> 24) & 0xFF; - if ((highByte & 0xE) == 0xA) { - if ((highByte & 0xF0) == 0xF0) - return 1; - else if (highByte & 1) - return 2; - else - return 3; - } - return 0; -} - -static u32 DoDecryptLvl1(std::vector& data, u32 tableOffset, FSOverlayInfo &ovyi) { +u32 Decryptor::DoDecryptLvl1(u32 tableOffset) { FATEntry *table; FATEntry *table_start = (FATEntry *)(&data[tableOffset]); for (table = table_start; table->start != 0 && table->end != 0; table++) { - u32 start_offs = table->start - ovyi.start - 0x1300; - u32 size = (table->end - (ovyi.start + ovyi.size) - 0x1300) & ~3; + u32 start_offs = table->start - info.start - 0x1300; + u32 size = (table->end - (info.start + info.size) - 0x1300) & ~3; for (int i = start_offs; i < start_offs + size; i += 4) { u32 & word = (u32 &)data[i]; switch (GetInsnType(word)) { @@ -76,19 +116,27 @@ static u32 DoDecryptLvl1(std::vector& data, u32 tableOffset, FSOverlayInfo & return (u8 *)table - (u8 *)table_start + tableOffset + sizeof(*table); } -static void DecryptLvl1(std::vector &ovydat, FSOverlayInfo &ovyi) { - for (int i = ovyi.sinit_start; i != ovyi.sinit_end; i += 4) { - if (*(u32 *)&ovydat[i - ovyi.start] != 0) { - (void)DoDecryptLvl1(ovydat, *(u32 *)&ovydat[i - ovyi.start] - ovyi.start + 16, ovyi); +void Decryptor::DecryptLvl1() { + for (int i = info.sinit_start; i != info.sinit_end; i += 4) { + if (*(u32 *)&data[i - info.start] != 0) { + (void)DoDecryptLvl1(*(u32 *)&data[i - info.start] - info.start + 16); } } } +void Decryptor::Decrypt() { + DecryptLvl1(); + DecryptLvl2(); +} + +void Decryptor::Write(std::ofstream &outfile) { + outfile.write((char *)data.data(), data.size()); +} + int DecryptOptions::main() { - std::vector ovydat = baserom->getOverlay(0, ovy_id); - FSOverlayInfo &ovyi = baserom->getOverlayInfo(0, ovy_id); - DecryptLvl1(ovydat, ovyi); - DecryptLvl2(ovydat, ovyi); - outfile.write((char *)ovydat.data(), ovydat.size()); + NtrOverlay foo = baserom->getOverlay(0, ovy_id); + Decryptor overlay = *(Decryptor *)&foo; + overlay.Decrypt(); + overlay.Write(outfile); return 0; } diff --git a/tools/mod123encry/Decrypt.h b/tools/mod123encry/Decrypt.h index 1cc9e93c9..c397f4bbd 100644 --- a/tools/mod123encry/Decrypt.h +++ b/tools/mod123encry/Decrypt.h @@ -3,6 +3,49 @@ #include "NtrRom.h" +struct DecryptPart2 { + u32 unk0; + u32 unk4; + u8 unk8[256]; + const u8 *keys = nullptr; + + DecryptPart2() { + unk0 = 0; + unk4 = 0; + for (int i = 0; i < 256; i++) { + unk8[i] = i; + } + } + DecryptPart2(const u8 *_keys) : DecryptPart2() { + keys = _keys; + int r6 = 0; + int r7 = 0; + for (int i = 255; i >= 0; i--) { + u8 r4 = unk8[i]; + r7 = (r7 + keys[r6++] + r4) & 0xFF; + u8 ip = unk8[r7]; + if (r6 >= 16) + r6 = 0; + unk8[r7] = r4; + unk8[i] = ip; + } + } + void DoDecrypt(u32 *start, u32 *end); +}; + +class Decryptor : public NtrOverlay { + u32 FindDecryLvl2(u32 offset); + void DecryptLvl2Part1(u32 start_addr, u32 end_addr, u8 *keys); + u32 DoDecryptLvl1(u32 tableOffset); + u32 DoDecryptLvl2(u32 tableOffset); + void DecryptLvl1(); + void DecryptLvl2(); +public: + Decryptor(FSOverlayInfo &_info, std::vector &_data) : NtrOverlay(_info, _data) {} + void Decrypt(); + void Write(std::ofstream &outfile); +}; + struct DecryptOptions { NtrRom *baserom; std::ofstream outfile; diff --git a/tools/mod123encry/NtrRom.h b/tools/mod123encry/NtrRom.h index 121f1d1c6..22a5cc6a4 100644 --- a/tools/mod123encry/NtrRom.h +++ b/tools/mod123encry/NtrRom.h @@ -83,6 +83,14 @@ struct FNT { char *paths; }; +class NtrOverlay { +protected: + FSOverlayInfo info; + std::vector data; +public: + NtrOverlay(FSOverlayInfo &_info, std::vector &_data) : info(_info), data(_data) {} +}; + class NtrRom { std::ifstream handle; u8 * raw; @@ -109,14 +117,12 @@ public: NtrRom(const char * filename, std::ios::openmode mode = std::ios::in); ~NtrRom(); const RomHeader * getHeader() { return (const RomHeader *)(raw + 0); } - std::vector getOverlay(u32 proc, u32 ovy_id) { + NtrOverlay getOverlay(u32 proc, u32 ovy_id) { std::vector &ovyi = (proc == 0) ? arm9_ovt : arm7_ovt; - u8 *& data = ((proc == 0) ? arm9_ovy : arm7_ovy)[ovy_id]; - return std::vector(data, data + ovyi[ovy_id].size); - } - FSOverlayInfo &getOverlayInfo(u32 proc, u32 ovy_id) { - std::vector &ovyi = (proc == 0) ? arm9_ovt : arm7_ovt; - return ovyi[ovy_id]; + u8 *& data_raw = ((proc == 0) ? arm9_ovy : arm7_ovy)[ovy_id]; + FSOverlayInfo &info = ovyi[ovy_id]; + std::vector data(data_raw, data_raw + info.size); + return {info, data}; } };