124 lines
4.1 KiB
C#
124 lines
4.1 KiB
C#
|
/*
|
|||
|
Copyright (C) 2011-2012 de4dot@gmail.com
|
|||
|
|
|||
|
This file is part of de4dot.
|
|||
|
|
|||
|
de4dot is free software: you can redistribute it and/or modify
|
|||
|
it under the terms of the GNU General Public License as published by
|
|||
|
the Free Software Foundation, either version 3 of the License, or
|
|||
|
(at your option) any later version.
|
|||
|
|
|||
|
de4dot is distributed in the hope that it will be useful,
|
|||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|||
|
GNU General Public License for more details.
|
|||
|
|
|||
|
You should have received a copy of the GNU General Public License
|
|||
|
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
|||
|
*/
|
|||
|
|
|||
|
using System;
|
|||
|
|
|||
|
namespace de4dot.code.deobfuscators.MaxtoCode {
|
|||
|
class Decrypter6 {
|
|||
|
readonly uint[] key;
|
|||
|
readonly byte[] gen1 = new byte[0x100];
|
|||
|
readonly byte[] gen2 = new byte[0x100];
|
|||
|
readonly byte[] gen3 = new byte[0x100];
|
|||
|
readonly byte[] gen4 = new byte[0x100];
|
|||
|
static readonly byte[] d1 = new byte[16] { 14, 4, 13, 21, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7 };
|
|||
|
static readonly byte[] d2 = new byte[16] { 15, 1, 8, 14, 6, 11, 3, 4, 30, 7, 2, 13, 12, 0, 5, 10 };
|
|||
|
static readonly byte[] d3 = new byte[16] { 10, 0, 9, 14, 6, 3, 15, 5, 23, 13, 12, 7, 11, 4, 2, 8 };
|
|||
|
static readonly byte[] d4 = new byte[16] { 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15 };
|
|||
|
static readonly byte[] d5 = new byte[16] { 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9 };
|
|||
|
static readonly byte[] d6 = new byte[16] { 12, 1, 10, 15, 9, 2, 6, 8, 2, 13, 3, 4, 14, 7, 5, 11 };
|
|||
|
static readonly byte[] d7 = new byte[16] { 4, 11, 12, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1 };
|
|||
|
static readonly byte[] d8 = new byte[16] { 13, 2, 8, 14, 6, 7, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7 };
|
|||
|
|
|||
|
public static byte[] decrypt(byte[] key, byte[] encrypted) {
|
|||
|
return new Decrypter6(key).decrypt(encrypted);
|
|||
|
}
|
|||
|
|
|||
|
Decrypter6(byte[] key) {
|
|||
|
if (key.Length != 32)
|
|||
|
throw new ArgumentException("Invalid key size", "key");
|
|||
|
this.key = new uint[8];
|
|||
|
Buffer.BlockCopy(key, 0, this.key, 0, key.Length);
|
|||
|
initialize();
|
|||
|
}
|
|||
|
|
|||
|
byte[] decrypt(byte[] encrypted) {
|
|||
|
if ((encrypted.Length & 7) != 0)
|
|||
|
throw new ArgumentException("Invalid data length", "encrypted");
|
|||
|
var decrypted = new byte[encrypted.Length];
|
|||
|
|
|||
|
int count = decrypted.Length / 8;
|
|||
|
for (int i = 0; i < count; i++) {
|
|||
|
uint x, y;
|
|||
|
decrypt(BitConverter.ToUInt32(encrypted, i * 8), BitConverter.ToUInt32(encrypted, i * 8 + 4), out x, out y);
|
|||
|
for (int j = 1; j < 100; j++)
|
|||
|
decrypt(x, y, out x, out y);
|
|||
|
writeUInt32(decrypted, i * 8, x);
|
|||
|
writeUInt32(decrypted, i * 8 + 4, y);
|
|||
|
}
|
|||
|
|
|||
|
return decrypted;
|
|||
|
}
|
|||
|
|
|||
|
static void writeUInt32(byte[] data, int index, uint value) {
|
|||
|
data[index] = (byte)value;
|
|||
|
data[index + 1] = (byte)(value >> 8);
|
|||
|
data[index + 2] = (byte)(value >> 16);
|
|||
|
data[index + 3] = (byte)(value >> 24);
|
|||
|
}
|
|||
|
|
|||
|
void initialize() {
|
|||
|
for (int i = 0; i < 0x100; i++) {
|
|||
|
gen1[i] = (byte)((d1[i / 16] << 4) | d2[i & 0x0F]);
|
|||
|
gen2[i] = (byte)((d3[i / 16] << 4) | d4[i & 0x0F]);
|
|||
|
gen3[i] = (byte)((d5[i / 16] << 4) | d6[i & 0x0F]);
|
|||
|
gen4[i] = (byte)((d7[i / 16] << 4) | d8[i & 0x0F]);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void decrypt(uint i0, uint i1, out uint o0, out uint o1) {
|
|||
|
uint x = i0;
|
|||
|
uint y = decrypt(x + key[0]);
|
|||
|
y ^= i1;
|
|||
|
x ^= decrypt(y + key[1]);
|
|||
|
y ^= decrypt(x + key[2]);
|
|||
|
x ^= decrypt(y + key[3]);
|
|||
|
y ^= decrypt(x + key[4]);
|
|||
|
x ^= decrypt(y + key[5]);
|
|||
|
y ^= decrypt(x + key[6]);
|
|||
|
x ^= decrypt(y + key[7]);
|
|||
|
|
|||
|
for (int i = 0; i < 3; i++) {
|
|||
|
y ^= decrypt(x + key[7]);
|
|||
|
x ^= decrypt(y + key[6]);
|
|||
|
y ^= decrypt(x + key[5]);
|
|||
|
x ^= decrypt(y + key[4]);
|
|||
|
y ^= decrypt(x + key[3]);
|
|||
|
x ^= decrypt(y + key[2]);
|
|||
|
y ^= decrypt(x + key[1]);
|
|||
|
x ^= decrypt(y + key[0]);
|
|||
|
}
|
|||
|
|
|||
|
o0 = y;
|
|||
|
o1 = x;
|
|||
|
}
|
|||
|
|
|||
|
uint decrypt(uint val) {
|
|||
|
uint x = (uint)((gen1[(byte)(val >> 24)] << 24) |
|
|||
|
(gen2[(byte)(val >> 16)] << 16) |
|
|||
|
(gen3[(byte)(val >> 8)] << 8) |
|
|||
|
gen4[(byte)val]);
|
|||
|
return ror(x, 21);
|
|||
|
}
|
|||
|
|
|||
|
static uint ror(uint val, int n) {
|
|||
|
return (val << (32 - n)) + (val >> n);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|