1+ #pragma once
2+ #include < iostream>
3+ #include < fstream>
4+
5+ namespace Line__Crypt
6+ {
7+ static int lwz (int offset, int src)
8+ {
9+ return _byteswap_ulong (*reinterpret_cast <int *>(src + offset));
10+ }
11+
12+ static int lwbrx (int offset, int src)
13+ {
14+ return *reinterpret_cast <int *>(src + offset);
15+ }
16+
17+ static void stw (int val, unsigned int offset, unsigned int des)
18+ {
19+ *reinterpret_cast <int *>(des + offset) = _byteswap_ulong (val);
20+ }
21+
22+ static int mulhwu (unsigned int val1, unsigned int val2)
23+ {
24+ long long result = (long long )val1 * (long long )val2;
25+ result >>= 32 ;
26+ return (int )result;
27+ }
28+
29+ static int rlwinm (int src, int shift, int maskBeg, int maskEnd)
30+ { // inspired by rygorous' example
31+ int maskBegBin = 0xffffffff >> maskBeg;
32+ int maskEndBin = 0xffffffff << (31 - maskEnd);
33+ int bitMask = (maskBeg <= maskEnd) ? maskBegBin & maskEndBin : maskBegBin | maskEndBin;
34+
35+ return ((src << shift) | (src >> ((32 - shift) & 31 ))) & bitMask;
36+ }
37+
38+
39+ static int LoadEncrypted (std::wstring& filePath, void ** out)
40+ {
41+ std::ifstream file;
42+ file.open (filePath, std::ios::binary | std::ios::in);
43+
44+ if (!file.is_open ())
45+ {
46+ return 0 ;
47+ }
48+
49+ file.seekg (0 , std::ios::end);
50+ uint64_t size = file.tellg ();
51+ file.seekg (0 , std::ios::beg);
52+ uint64_t sizeWithPadding = (size % 0x20 == 0 ) ? size : size + 0x20 ;
53+
54+ *out = calloc (1 , sizeWithPadding);
55+
56+ if (!file.read ((char *)*out, size))
57+ {
58+ return 0 ;
59+ }
60+
61+ file.close ();
62+ return size;
63+ }
64+
65+ static void Decrypt (void * file, uint32_t fileSize)
66+ {
67+ // prepare key values and parameters
68+ int key0 = 0x000cd8f3 ;
69+ int key1 = 0x9b36bb94 ;
70+ int key2 = 0xaf8910be ;
71+ int salt = 0 ;
72+ int fileSizeExtended = (fileSize + 0x1f ) & ~0 ; // filesize next multiple of 0x20
73+ int fileLocation = reinterpret_cast <int >(file);
74+ int r8 = rlwinm (fileSizeExtended, 30 , 2 , 31 );
75+ int cryptedWords = 0 ;
76+ int r11 = 0 ;
77+ int r12 = 0 ;
78+ int r3 = r8 - 1 ;
79+ int rwLocation = fileLocation;
80+ r3 = rlwinm (r3, 29 , 3 , 31 );
81+
82+ for (int i = r3; i > 0 ; --i)
83+ {
84+ // decrypting 1st 4 bytes of 0x20 bytes block
85+ int keyProd = key2 * key1; // mullw r10, r31, r5 ;r10 = 2c8c77d8
86+ salt = 0x180a ; // li r4, 0x180a; r4 = 0000180a
87+ r3 = lwz (0 , rwLocation); // lwz r3, 0(r7); load(first) 4 bytes of encrypted file
88+ int r29 = keyProd + key0; // addc r29, r10, r0; r29 = 2c9950cb(0x2c8c77d8 + 0x000cd8f3)
89+ r3 ^= r29; // xor r3, r3, r29; xor 4 bytes of file with r29(0x2c9950cb).r3 = 0x0bd80f00
90+ stw (r3, 0 , rwLocation); // stw r3, 0(r7); store xored 4 bytes where they originated from
91+
92+ // decrypting 2nd 4 bytes of 0x20 bytes block
93+ r12 = mulhwu (key2, key1); // mulhwu r12, r31, r5; r12 = 0x6a6d84ab (af8910be * 9b36bb94)
94+ int val = lwz (4 , rwLocation); // lwz r10, 4(r7); load next 4 encrypted bytes.r10 = 0x4e63f64f
95+ r3 = 0 ; // mullw r3, r6, r5; r3 = 0 (0 * 0x9b36bb94)
96+ r11 = mulhwu (r29, key1); // mulhwu r11, r29, r5; r11 = 0x1b0a5cef (0x2c9950cb * 0x>9b36bb94)
97+ int r26 = r12; // add r26, r12, r3; r26 = 6a6d84ab(0x6a6d84ab + 0x00000000)
98+ int r27 = key2 * salt; // mullw r27, r31, r4; r27 = 0xb4ec776c (af8910be, 0000180a)
99+ r12 = r11; // add r12, r11, r3; r12 = 0x1b0a5cef (1b0a5cef, 00000000)
100+ r26 += r27; // add r26, r26, r27; r26 = 1f59fc17(6a6d84ab, b4ec776c)
101+ r11 = r29 * salt; // mullw r11, r29, r4; r11 = 1d902fee(2c9950cb, 0000180a)
102+ r27 = r29 * key1; // mullw r27, r29, r5; r27 = ba78fe5c(2c9950cb, 9b36bb94)
103+ r12 += r11; // add r12, r12, r11; r12 = 389a8cdd(1b0a5cef, 1d902fee)
104+ r29 = r27 + key0; // addc r29, r27, r0; r29 = ba85d74f(ba78fe5c, 000cd8f3)
105+ r12 = r29 * key1; // mullw r12, r29, r5; r12 = d9512eac(ba85d74f, 9b36bb94)
106+ val ^= r29; // xor r10, r10, r29; r10 = f4e62100(4E63F64F(loaded from file), ba85d74f)
107+ stw (val, 4 , rwLocation); // stw r10, 4(r7); store xored 4 bytes where they originated from
108+
109+ // decrypting 3rd 4 bytes of 0x20 bytes block
110+ val = lwz (8 , rwLocation); // lwz r10, 8(r7); load next 4 encrypted bytes.r10 = 0x73b3f79e
111+ key2 = r12 + key0; // addc r31, r12, r0; r31 = d95e079f(d9512eac, 000cd8f3)
112+ r11 = mulhwu (r29, key1); // mulhwu r11, r29, r5; r11 = 7116ea43(ba85d74f, 9b36bb94)
113+ val ^= key2; // xor r10, r10, r31; r10 = aaedf001(73b3f79e, d95e079f)
114+ stw (val, 8 , rwLocation); // stw r10, 8(r7); store xored 4 bytes where they originated from
115+
116+ // decrypting 4th 4 bytes of 0x20 bytes block
117+ val = lwz (0xC , rwLocation); // lwz r10, 0xc(r7); load next 4 encrypted bytes.r10 = 0xdc7c7732
118+ r12 = r29 * salt; // mullw r12, r29, r4; r12 = d569d116(ba85d74f, 0000180a)
119+ r27 = r11; // add r27, r11, r3; r27 = 7116ea43(7116ea43, 00000000)
120+ r12 = key2 * key1; // mullw r12, r31, r5; r12 = 3a778cec(d95e079f, 9b36bb94)
121+ r29 = r12 + key0; // addc r29, r12, r0; r29 = 3a8465df(3a778cec, 000cd8f3)
122+ r11 = mulhwu (key2, key1); // mulhwu r11, r31, r5; r11 = 83ca67b8(d95e079f, 9b36bb94)
123+ val ^= r29; // xor r10, r10, r29; r10 e6f812ed = (dc7c7732, 3a8465df)
124+ stw (val, 0xC , rwLocation); // stw r10, 0xc(r7); store xored 4 bytes where they originated from
125+
126+ // decrypting 5th 4 bytes of 0x20 bytes block
127+ val = lwz (0x10 , rwLocation); // lwz r10, 0x10(r7); load next 4 encrypted bytes.r10 = 0xfd47482b //ERROR?????????????
128+ r12 = key2 * salt; // mullw r12, r31, r4; r12 = 4e633436 (d95e079f, 0000180a)
129+ r27 = r11; // add r27, r11, r3; r27 = 83ca67b8(83ca67b8, 00000000)
130+ r12 = r29 * key1; // mullw r12, r29, r5; r12 = 0cfec9ec(3a8465df, 9b36bb94)
131+ key2 = r12 + key0; // addc r31, r12, r0; r31 = 0d0ba2df(0cfec9ec, 000cd8f3)
132+ r11 = mulhwu (r29, key1); // mulhwu r11, r29, r5; r11 = 237aac7c(3a8465df, 9b36bb94)
133+ val ^= key2; // xor r10, r10, r31; r10 = f04ceaf4(fd47482b, 0d0ba2df)
134+ stw (val, 0x10 , rwLocation); // stw r10, 0x10(r7); store xored 4 bytes where they originated from
135+
136+ // decrypting 6th 4 bytes of 0x20 bytes block
137+ val = lwz (0x14 , rwLocation); // lwz r10, 0x14(r7); load next 4 encrypted bytes.r10 = 0x4a370b2f
138+ r12 = r29 * salt; // mullw r12, r29, r4; r12 = b2b8e2b6(3a8465df, 0000180a)
139+ r27 = r11; // add r27, r11, r3; r27 = 237aac7c(237aac7c, 00000000)
140+ r12 = key2 * key1; // mullw r12, r31, r5; r12 = 6abd0dec(0d0ba2df, 9b36bb94)
141+ r27 = r12 + key0; // addc r27, r12, r0; r27 = 6ac9e6df(6abd0dec, 000cd8f3)
142+ r11 = mulhwu (key2, key1); // mulhwu r11, r31, r5; r11 = 07e8d5a0(0d0ba2df, 9b36bb94)
143+ val ^= r27; // xor r10, r10, r27; r10 = 20feedf0(4a370b2f, 6ac9e6df)
144+ stw (val, 0x14 , rwLocation); // stw r10, 0x14(r7); store xored 4 bytes where they originated from
145+
146+ // decrypting 7th 4 bytes of 0x20 bytes block
147+ val = lwz (0x18 , rwLocation); // lwz r10, 0x18(r7); load next 4 encrypted bytes.r10 = 0xf3753e21
148+ r12 = key2 * salt; // mullw r12, r31, r4; r12 = 99b944b6(0d0ba2df, 0000180a)
149+ r29 = r11; // add r29, r11, r3; r29 = 07e8d5a0(07e8d5a0, 00000000)
150+ r12 = r27 * key1; // mullw r12, r27, r5; r12 = f0685dec(6ac9e6df, 9b36bb94)
151+ r29 = r12 + key0; // addc r29, r12, r0; r29 = f07536df(f0685dec, 000cd8f3)
152+ r11 = mulhwu (r27, key1); // mulhwu r11, r27, r5; r11 = 40bf139e(6ac9e6df, 9b36bb94)
153+ val ^= r29; // xor r10, r10, r29; r10 = 030008fe(f3753e21, f07536df)
154+ stw (val, 0x18 , rwLocation); // stw r10, 0x18(r7); store xored 4 bytes where they originated from
155+
156+ // decrypting 8th 4 bytes of 0x20 bytes block
157+ val = lwz (0x1C , rwLocation); // lwz r10, 0x1c(r7); load next 4 encrypted bytes.r10 = 0x9eef6df4
158+ r12 = r27 * salt; // mullw r12, r27, r4; r12 = 1987ecb6(6ac9e6df, 0000180a)
159+ key2 = r11; // add r31, r11, r3; r31 = 40bf139e(40bf139e, 00000000)
160+ r12 += key2; // add r12, r31, r12; r12 = 5a470054(40bf139e, 1987ecb6)
161+ r11 = mulhwu (r29, key1); // mulhwu r11, r29, r5; r11 = 91ca6123(f07536df, 9b36bb94)
162+ r12 = r29 * key1; // mullw r12, r29, r5; r12 = 3ae29dec(f07536df, 9b36bb94)
163+ r11 += r3; // add r11, r11, r3; r11 = 91ca6123(91ca6123, 00000000)
164+ key2 = r12 + key0; // addc r31, r12, r0; r31 = 3aef76df(3ae29dec, 000cd8f3)
165+ r3 = val ^ key2; // xor r3, r10, r31; r3 = a4001b2b(9eef6df4, 3aef76df)
166+ stw (r3, 0x1C , rwLocation); // stw r3, 0x1c(r7); store xored 4 bytes where they originated from
167+
168+ // prepare salt and rwLocation for next iteration
169+ salt *= r29; // mullw r4, r29, r4; r4 = 61b90cb6(f07536df, 0000180a)
170+ rwLocation += 0x20 ; // addi r7, r7, 0x20; increment r7 for next read / write sector of encrypted file.r7 = 8145caa0
171+ r3 = r11 + salt; // add r3, r11, r4; r3 = f3836dd9(91ca6123, 61b90cb6)
172+ cryptedWords += 8 ; // addi r9, r9, 8; (r9 = 8) 0 + 8
173+ }
174+
175+ if (cryptedWords >= r8)
176+ return ;
177+
178+ // set parameters for last block processing
179+ r3 = 0x9b370000 ;
180+ int r4 = rlwinm (cryptedWords, 2 , 0 , 29 ); // slwi r4, r9, 2; rlwinm r4, r9, 2, 0, 29 (3fffffff). (r9 = 0003f600), r4 = 000fd800
181+ r11 = r3, (short )0xbb94 ; // addi r11, r3, 0xbb94; r11 = 9b36bb94
182+ r3 = 0x000d0000 ; // lis r3, 0xd; r3 = 000d0000
183+ int r0 = r8 - cryptedWords; // subf r0, r9, r8; r0 = 00000008 (0003f600, 0003f608)
184+ rwLocation = fileLocation + r4; // add r26, r28, r4; 8155a280(8145ca80, 000fd800). address of last bytes
185+ r3 += (short )0xd8f3 ; // addi r3, r3, 0xd8f3; 000cd8f3
186+ salt = 0x180a ; // li r10, 0x180a; 0000180a
187+
188+ // crypt last block
189+ for (int i = r0; i > 0 ; --i)
190+ {
191+ r4 = mulhwu (key2, r11); // mulhwu r4, r31, r11; r4 = 7cdc9f97(cdf076df, 9b36bb94)
192+ r0 = lwz (0 , rwLocation); // lwz r0, 0(r26); load first remaining undecrypted word.r0 = 5f20c231
193+ int r7 = key2 * r11; // mullw r7, r31, r11; r7 = cde39dec(cdf076df, 9b36bb94)
194+ int r5 = r4; // add r5, r4, r6; r5 = 7cdc9f97(7cdc9f97, 00000000)
195+ r4 = key2, salt; // mullw r4, r31, r10; r4 = 96898cb6(cdf076df, 0000180a)
196+ key2 = r7 + r3; // addc r31, r7, r3; 31 = cdf076df(cde39dec, 000cd8f3)
197+ r0 ^= key2; // xor r0, r0, r31; r0 = 92d0b4ee(5f20c231, cdf076df)
198+ stw (r0, 0 , rwLocation); // stw r0, 0(r26); store xored 4 bytes where they originated from
199+ rwLocation += 4 ; // addi r26, r26, 4; increment r26 pointer for next read / write
200+ r0 = r5 + r4; // add r0, r5, r4; r0 = 13662c4d(7cdc9f97, 96898cb6)
201+ } // bdnz 0x360; go to; label_loopDecryptFileEnd.loop ends after 3 more writes(might be unused).same value written for 00 (df cdf076df cdf076df cdf076df)
202+
203+ return ;
204+ }
205+
206+ static bool SaveBinary (std::wstring& filePath, void * data, uint64_t size)
207+ {
208+ std::ofstream file (filePath, std::ios::binary);
209+ if (!file)
210+ return false ;
211+
212+ file.write ((char *)data, size);
213+ file.close ();
214+ return true ;
215+ }
216+ }
0 commit comments