public bool Decrypt(MyPEImage peImage, byte[] fileData, ref DumpedMethods dumpedMethods) { if (initMethod == null) { return(false); } switch (version) { case ConfuserVersion.v17_r73404: return(Decrypt_v17_r73404(peImage, fileData, ref dumpedMethods)); case ConfuserVersion.v17_r73430: return(Decrypt_v17_r73404(peImage, fileData, ref dumpedMethods)); case ConfuserVersion.v17_r73477: return(Decrypt_v17_r73477(peImage, fileData, ref dumpedMethods)); case ConfuserVersion.v17_r73479: return(Decrypt_v17_r73479(peImage, fileData, ref dumpedMethods)); case ConfuserVersion.v17_r74021: return(Decrypt_v17_r73479(peImage, fileData, ref dumpedMethods)); case ConfuserVersion.v18_r75257: return(Decrypt_v17_r73479(peImage, fileData, ref dumpedMethods)); case ConfuserVersion.v18_r75288: return(Decrypt_v17_r73479(peImage, fileData, ref dumpedMethods)); case ConfuserVersion.v18_r75291: return(Decrypt_v17_r73479(peImage, fileData, ref dumpedMethods)); case ConfuserVersion.v18_r75402: return(Decrypt_v18_r75402(peImage, fileData, ref dumpedMethods)); case ConfuserVersion.v19_r75725: return(Decrypt_v18_r75402(peImage, fileData, ref dumpedMethods)); default: throw new ApplicationException("Unknown version"); } }
static EncryptionVersion GetHeaderOffsetAndVersion(MyPEImage peImage, out uint headerOffset) { headerOffset = 0; var version = GetVersion(peImage, headerOffset); if (version != EncryptionVersion.Unknown) { return(version); } var section = peImage.FindSection(".rsrc"); if (section != null) { version = GetHeaderOffsetAndVersion(section, peImage, out headerOffset); if (version != EncryptionVersion.Unknown) { return(version); } } foreach (var section2 in peImage.Sections) { version = GetHeaderOffsetAndVersion(section2, peImage, out headerOffset); if (version != EncryptionVersion.Unknown) { return(version); } } return(EncryptionVersion.Unknown); }
static void patchDwords(MyPEImage peImage, IBinaryReader reader, int count) { for (int i = 0; i < count; i++) { uint rva = reader.ReadUInt32(); uint data = reader.ReadUInt32(); peImage.dotNetSafeWrite(rva, BitConverter.GetBytes(data)); } }
public PeHeader(MainType mainType, MyPEImage peImage) { version = GetHeaderOffsetAndVersion(peImage, out uint headerOffset); headerData = peImage.OffsetReadBytes(headerOffset, 0x1000); // MC uses 4-byte xorKey, 2 Hex for 1 Byte GuessXorKey(false, peImage, 4); switch (version) { case EncryptionVersion.V1: case EncryptionVersion.V2: case EncryptionVersion.V3: case EncryptionVersion.V4: case EncryptionVersion.V5: default: xorKey = 0x7ABF931; break; case EncryptionVersion.V6: xorKey = 0x7ABA931; break; case EncryptionVersion.V7: xorKey = 0x8ABA931; break; case EncryptionVersion.V8: if (CheckMcKeyRva(peImage, 0x99BA9A13)) break; if (CheckMcKeyRva(peImage, 0x18ABA931)) break; if (CheckMcKeyRva(peImage, 0x18ABA933)) break; break; } }
public PeHeader(MainType mainType, MyPEImage peImage) { uint headerOffset; version = GetHeaderOffsetAndVersion(peImage, out headerOffset); headerData = peImage.OffsetReadBytes(headerOffset, 0x1000); switch (version) { case EncryptionVersion.V1: case EncryptionVersion.V2: case EncryptionVersion.V3: case EncryptionVersion.V4: case EncryptionVersion.V5: default: xorKey = 0x7ABF931; break; case EncryptionVersion.V6: xorKey = 0x7ABA931; break; case EncryptionVersion.V7: xorKey = 0x8ABA931; break; case EncryptionVersion.V8: if (CheckMcKeyRva(peImage, 0x99BA9A13)) break; if (CheckMcKeyRva(peImage, 0x18ABA931)) break; if (CheckMcKeyRva(peImage, 0x18ABA933)) break; break; } }
protected byte[] DecryptMethodsData_v16_r71742(MyPEImage peImage, uint encryptedHeaderOffset) { uint mdRva = peImage.OptionalHeader.CheckSum ^ (uint)key0; if ((RVA)mdRva != peImage.Cor20Header.Metadata.VirtualAddress) { throw new ApplicationException("Invalid metadata rva"); } var reader = peImage.Reader; reader.Position = encryptedHeaderOffset; ulong checkSum = reader.ReadUInt64() ^ lkey0; reader.ReadInt32(); // strong name RVA reader.ReadInt32(); // strong name len var iv = reader.ReadBytes(reader.ReadInt32() ^ (int)key2); var encrypted = reader.ReadBytes(reader.ReadInt32() ^ (int)key3); var streamsBuffer = GetStreamsBuffer(peImage); if (checkSum != CalcChecksum(streamsBuffer)) { throw new ApplicationException("Invalid checksum. File has been modified."); } var decrypted = Decrypt(encrypted, iv, streamsBuffer); if (BitConverter.ToInt16(decrypted, 0) != 0x6FD6) { throw new ApplicationException("Invalid magic"); } return(decrypted); }
public byte[] Unpack() { byte[] data = null; MyPEImage myPeImage = null; try { myPeImage = new MyPEImage(peImage); data = Unpack2(myPeImage); } catch { } finally { if (myPeImage != null) { myPeImage.Dispose(); } } if (data != null) { return(data); } if (shouldUnpack) { Logger.w("Could not unpack file: {0}", peImage.FileName ?? "(unknown filename)"); } return(null); }
public bool Decrypt(MyPEImage peImage, ref DumpedMethods dumpedMethods) { dumpedMethods = new DumpedMethods(); bool decrypted = false; var methodDef = peImage.MetaData.TablesStream.MethodTable; for (uint rid = 1; rid <= methodDef.Rows; rid++) { var dm = new DumpedMethod(); peImage.ReadMethodTableRowTo(dm, rid); if (dm.mdRVA == 0) continue; uint bodyOffset = peImage.RvaToOffset(dm.mdRVA); peImage.Reader.Position = bodyOffset; var mbHeader = MethodBodyParser.ParseMethodBody(peImage.Reader, out dm.code, out dm.extraSections); peImage.UpdateMethodHeaderInfo(dm, mbHeader); if (dm.code.Length < 6 || dm.code[0] != 0x2A || dm.code[1] != 0x2A) continue; int seed = BitConverter.ToInt32(dm.code, 2); Array.Copy(newCodeHeader, dm.code, newCodeHeader.Length); if (seed == 0) Decrypt(dm.code); else Decrypt(dm.code, seed); dumpedMethods.Add(dm); decrypted = true; } return decrypted; }
bool DecryptImage_v14_r58004(MyPEImage peImage, byte[] fileData) { var reader = new BinaryReader(new MemoryStream(methodsData)); reader.ReadInt16(); // sig var writer = new BinaryWriter(new MemoryStream(fileData)); int numInfos = reader.ReadInt32(); for (int i = 0; i < numInfos; i++) { uint offs = reader.ReadUInt32() ^ key4; if (offs == 0) { continue; } uint rva = reader.ReadUInt32() ^ key4; if (peImage.RvaToOffset(rva) != offs) { throw new ApplicationException("Invalid offs & rva"); } writer.BaseStream.Position = peImage.RvaToOffset(rva); writer.Write(reader.ReadBytes(reader.ReadInt32())); } return(true); }
public bool Decrypt(byte[] fileData, ref DumpedMethods dumpedMethods) { if (decrypter == null) { return(false); } using (var peImage = new MyPEImage(fileData)) { if (peImage.Sections.Count <= 0) { return(false); } var methodsData = FindMethodsData(peImage, fileData); if (methodsData == null) { return(false); } decrypter.Initialize(methodsData); dumpedMethods = CreateDumpedMethods(peImage, fileData, methodsData); if (dumpedMethods == null) { return(false); } } return(true); }
bool DecryptImage_v16_r71742(MyPEImage peImage, byte[] fileData) { var reader = new BinaryReader(new MemoryStream(methodsData)); reader.ReadInt16(); // sig int numInfos = reader.ReadInt32(); for (int i = 0; i < numInfos; i++) { uint offs = reader.ReadUInt32() ^ key4; if (offs == 0) { continue; } uint rva = reader.ReadUInt32() ^ key5; if (peImage.RvaToOffset(rva) != offs) { throw new ApplicationException("Invalid offs & rva"); } int len = reader.ReadInt32(); for (int j = 0; j < len; j++) { fileData[offs + j] = reader.ReadByte(); } } return(true); }
public bool Decrypt(MyPEImage peImage, byte[] fileData) { if (initMethod == null) { return(false); } switch (version) { case ConfuserVersion.v14_r57884: return(Decrypt_v14_r57884(peImage, fileData)); case ConfuserVersion.v14_r58004: return(Decrypt_v14_r58004(peImage, fileData)); case ConfuserVersion.v14_r58564: return(Decrypt_v14_r58004(peImage, fileData)); case ConfuserVersion.v14_r58852: return(Decrypt_v14_r58004(peImage, fileData)); case ConfuserVersion.v15_r59014: return(Decrypt_v15_r59014(peImage, fileData)); case ConfuserVersion.v16_r71742: return(Decrypt_v16_r71742(peImage, fileData)); case ConfuserVersion.v17_r72989: return(Decrypt_v16_r71742(peImage, fileData)); case ConfuserVersion.v17_r73605: return(Decrypt_v17_r73605(peImage, fileData)); case ConfuserVersion.v18_r75288: return(Decrypt_v17_r73605(peImage, fileData)); case ConfuserVersion.v19_r75725: return(Decrypt_v17_r73605(peImage, fileData)); default: throw new ApplicationException("Unknown version"); } }
public DecrypterInfo(MainType mainType, byte[] fileData) { this.mainType = mainType; this.peImage = new MyPEImage(fileData); this.peHeader = new PeHeader(mainType, peImage); this.mcKey = new McKey(peImage, peHeader); this.fileData = fileData; }
bool CheckMcKeyRva(MyPEImage peImage, uint newXorKey) { xorKey = newXorKey; uint rva = GetMcKeyRva(); return((rva & 0xFFF) == 0 && peImage.FindSection((RVA)rva) != null); }
bool FindNativeCode(byte[] moduleBytes) { var bytes = moduleBytes != null ? moduleBytes : DeobUtils.ReadModule(module); using (var peImage = new MyPEImage(bytes)) return(foundSig = MethodsDecrypter.Detect(peImage)); }
static EncryptionVersion getHeaderOffsetAndVersion(MyPEImage peImage, out uint headerOffset) { headerOffset = 0; var version = getVersion(peImage, headerOffset); if (version != EncryptionVersion.Unknown) { return(version); } var section = peImage.findSection(".rsrc"); if (section == null) { return(EncryptionVersion.Unknown); } headerOffset = section.PointerToRawData; uint end = section.PointerToRawData + section.SizeOfRawData - 0x1000 + 1; while (headerOffset < end) { version = getVersion(peImage, headerOffset); if (version != EncryptionVersion.Unknown) { return(version); } headerOffset++; } return(EncryptionVersion.Unknown); }
byte[] Unpack2(MyPEImage peImage) { shouldUnpack = false; uint headerOffset = (uint)peImage.Length - 12; uint offsetEncryptedAssembly = CheckOffset(peImage, peImage.OffsetReadUInt32(headerOffset)); uint ezencryptionLibLength = peImage.OffsetReadUInt32(headerOffset + 4); uint iniFileLength = peImage.OffsetReadUInt32(headerOffset + 8); uint offsetClrVersionNumber = checked (offsetEncryptedAssembly - 12); uint iniFileOffset = checked (headerOffset - iniFileLength); uint ezencryptionLibOffset = checked (iniFileOffset - ezencryptionLibLength); uint clrVerMajor = peImage.OffsetReadUInt32(offsetClrVersionNumber); uint clrVerMinor = peImage.OffsetReadUInt32(offsetClrVersionNumber + 4); uint clrVerBuild = peImage.OffsetReadUInt32(offsetClrVersionNumber + 8); if (clrVerMajor <= 0 || clrVerMajor >= 20 || clrVerMinor >= 20 || clrVerBuild >= 1000000) { return(null); } var settings = new IniFile(Decompress2(peImage.OffsetReadBytes(iniFileOffset, (int)iniFileLength))); sizes = GetSizes(settings["General_App_Satellite_Assemblies_Sizes"]); if (sizes == null || sizes.Length <= 1) { return(null); } shouldUnpack = true; if (sizes[0] != offsetEncryptedAssembly) { return(null); } filenames = settings["General_App_Satellite_Assemblies"].Split('|'); if (sizes.Length - 1 != filenames.Length) { return(null); } byte[] ezencryptionLibData = Decompress1(peImage.OffsetReadBytes(ezencryptionLibOffset, (int)ezencryptionLibLength)); var ezencryptionLibModule = ModuleDefMD.Load(ezencryptionLibData); var decrypter = new ApplicationModeDecrypter(ezencryptionLibModule); if (!decrypter.Detected) { return(null); } var mainAssembly = UnpackEmbeddedFile(peImage, 0, decrypter); decrypter.MemoryPatcher.Patch(mainAssembly.data); for (int i = 1; i < filenames.Length; i++) { satelliteAssemblies.Add(UnpackEmbeddedFile(peImage, i, decrypter)); } ClearDllBit(mainAssembly.data); return(mainAssembly.data); }
public ProDecrypter(MyPEImage peImage, CodeHeader codeHeader) : base(peImage, codeHeader) { for (int i = 0; i < 4; i++) { key[i] = ReadUInt32_be(codeHeader.decryptionKey, i * 4); } }
public DecrypterInfo(MainType mainType, byte[] fileData) { this.mainType = mainType; peImage = new MyPEImage(fileData); peHeader = new PeHeader(mainType, peImage); mcKey = new McKey(peImage, peHeader); this.fileData = fileData; }
void FreePEImage() { if (peImage != null) { peImage.Dispose(); } peImage = null; }
public DecrypterBase(MyPEImage peImage, CodeHeader codeHeader) { this.peImage = peImage; this.codeHeader = codeHeader; var mdDir = peImage.Cor20Header.MetaData; endOfMetadata = peImage.RvaToOffset((uint)mdDir.VirtualAddress + mdDir.Size); }
uint CheckOffset(MyPEImage peImage, uint offset) { if (offset >= peImage.Length) { throw new Exception(); } return(offset); }
public McKey(MyPEImage peImage, PeHeader peHeader) { this.peHeader = peHeader; try { this.data = peImage.ReadBytes(peHeader.GetMcKeyRva(), 0x2000); } catch (IOException) { this.data = peImage.ReadBytes(peHeader.GetMcKeyRva(), 0x1000); } }
public void Dispose() { if (peImage != null) { peImage.Dispose(); } peImage = null; reader = null; }
public void patch(byte[] peImageData) { using (var peImage = new MyPEImage(peImageData)) { foreach (var info in patchInfos) { for (int i = 0; i < info.offsets.Length; i++) peImage.dotNetSafeWriteOffset((uint)info.offsets[i], BitConverter.GetBytes(info.values[i])); } } }
DumpedMethods CreateDumpedMethods(MyPEImage peImage, byte[] fileData, byte[] methodsData) { var dumpedMethods = new DumpedMethods(); var methodsDataReader = MemoryImageStream.Create(methodsData); var fileDataReader = MemoryImageStream.Create(fileData); var methodDef = peImage.MetaData.TablesStream.MethodTable; for (uint rid = 1; rid <= methodDef.Rows; rid++) { var dm = new DumpedMethod(); peImage.ReadMethodTableRowTo(dm, rid); if (dm.mdRVA == 0) { continue; } uint bodyOffset = peImage.RvaToOffset(dm.mdRVA); byte b = peImage.OffsetReadByte(bodyOffset); uint codeOffset; if ((b & 3) == 2) { if (b != 2) { continue; // not zero byte code size } dm.mhFlags = 2; dm.mhMaxStack = 8; dm.mhLocalVarSigTok = 0; codeOffset = bodyOffset + 1; } else { if (peImage.OffsetReadUInt32(bodyOffset + 4) != 0) { continue; // not zero byte code size } dm.mhFlags = peImage.OffsetReadUInt16(bodyOffset); dm.mhMaxStack = peImage.OffsetReadUInt16(bodyOffset + 2); dm.mhLocalVarSigTok = peImage.OffsetReadUInt32(bodyOffset + 8); codeOffset = bodyOffset + (uint)(dm.mhFlags >> 12) * 4; } fileDataReader.Position = codeOffset; if (!decrypter.Decrypt(fileDataReader, dm)) { continue; } dumpedMethods.Add(dm); } return(dumpedMethods); }
byte[] FindMethodsData(MyPEImage peImage, byte[] fileData) { var section = peImage.Sections[0]; var reader = MemoryImageStream.Create(fileData); const int RVA_EXECUTIVE_OFFSET = 1 * 4; const int ENC_CODE_OFFSET = 6 * 4; int lastOffset = Math.Min(fileData.Length, (int)(section.PointerToRawData + section.SizeOfRawData)); for (int offset = GetStartOffset(peImage); offset < lastOffset;) { offset = FindSig(fileData, offset, lastOffset, initializeMethodEnd); if (offset < 0) { return(null); } offset += initializeMethodEnd.Length; short retImm16 = BitConverter.ToInt16(fileData, offset); if (retImm16 != 0x0C && retImm16 != 0x10) { continue; } offset += 2; if (offset + ENC_CODE_OFFSET + 4 > lastOffset) { return(null); } // rva is 0 when the assembly has been embedded uint rva = BitConverter.ToUInt32(fileData, offset + RVA_EXECUTIVE_OFFSET); if (rva != 0 && mainType.Rvas.IndexOf(rva) < 0) { continue; } int relOffs = BitConverter.ToInt32(fileData, offset + ENC_CODE_OFFSET); if (relOffs <= 0 || relOffs >= section.SizeOfRawData) { continue; } reader.Position = section.PointerToRawData + relOffs; int size = (int)reader.ReadCompressedUInt32(); int endOffset = relOffs + size; if (endOffset < relOffs || endOffset > section.SizeOfRawData) { continue; } return(reader.ReadBytes(size)); } return(null); }
static void ClearDllBit(byte[] peImageData) { using (var mainPeImage = new MyPEImage(peImageData)) { uint characteristicsOffset = (uint)mainPeImage.PEImage.ImageNTHeaders.FileHeader.StartOffset + 18; ushort characteristics = mainPeImage.OffsetReadUInt16(characteristicsOffset); characteristics &= 0xDFFF; characteristics |= 2; mainPeImage.OffsetWriteUInt16(characteristicsOffset, characteristics); } }
bool Decrypt_v18_r75402(MyPEImage peImage, byte[] fileData, ref DumpedMethods dumpedMethods) { if (peImage.OptionalHeader.CheckSum == 0) { return(false); } methodsData = DecryptMethodsData_v17_r73404(peImage); dumpedMethods = Decrypt_v18_r75402(peImage, fileData); return(dumpedMethods != null); }
public McKey(MyPEImage peImage, PeHeader peHeader) { try { data = peImage.ReadBytes(peHeader.GetMcKeyRva(), 0x2000); } catch (Exception ex) when(ex is IOException || ex is ArgumentException) { data = peImage.ReadBytes(peHeader.GetMcKeyRva(), 0x1000); } }
public McKey(MyPEImage peImage, PeHeader peHeader) { //this.peHeader = peHeader; try { this.data = peImage.ReadBytes(peHeader.GetMcKeyRva(), 0x2000); } catch (IOException) { this.data = peImage.ReadBytes(peHeader.GetMcKeyRva(), 0x1000); } }
bool Decrypt_v17_r73605(MyPEImage peImage, byte[] fileData) { if (peImage.OptionalHeader.CheckSum == 0) { return(false); } methodsData = DecryptMethodsData_v17_r73404(peImage); return(DecryptImage_v16_r71742(peImage, fileData)); }
static uint GetOldCodeHeaderOffset(MyPEImage peImage) { var sect = GetLastOf(peImage, sections); if (sect == null || sect.VirtualSize < 0x100) { return(0); } return(peImage.RvaToOffset((uint)sect.VirtualAddress + sect.VirtualSize - 0x100)); }
public bool Patch(byte[] peData) { try { using (var peImage = new MyPEImage(peData)) return(Patch2(peImage)); } catch { Logger.w("Could not patch the file"); return(false); } }
public void Patch(byte[] peImageData) { using (var peImage = new MyPEImage(peImageData)) { foreach (var info in patchInfos) { for (int i = 0; i < info.offsets.Length; i++) { peImage.DotNetSafeWriteOffset((uint)info.offsets[i], BitConverter.GetBytes(info.values[i])); } } } }
public MethodInfos(ModuleDef module, MainType mainType, MyPEImage peImage, PeHeader peHeader, McKey mcKey) { this.module = module; this.mainType = mainType; this.peImage = peImage; this.peHeader = peHeader; this.mcKey = mcKey; structSize = GetStructSize(mcKey); uint methodInfosRva = peHeader.GetRva(0x0FF8, mcKey.ReadUInt32(0x005A)); uint encryptedDataRva = peHeader.GetRva(0x0FF0, mcKey.ReadUInt32(0x0046)); methodInfosOffset = peImage.RvaToOffset(methodInfosRva); encryptedDataOffset = peImage.RvaToOffset(encryptedDataRva); }
public bool Decrypt(MyPEImage peImage, byte[] fileData, ref DumpedMethods dumpedMethods) { if (initMethod == null) return false; switch (version) { case ConfuserVersion.v17_r73404: return Decrypt_v17_r73404(peImage, fileData, ref dumpedMethods); case ConfuserVersion.v17_r73430: return Decrypt_v17_r73404(peImage, fileData, ref dumpedMethods); case ConfuserVersion.v17_r73477: return Decrypt_v17_r73477(peImage, fileData, ref dumpedMethods); case ConfuserVersion.v17_r73479: return Decrypt_v17_r73479(peImage, fileData, ref dumpedMethods); case ConfuserVersion.v17_r74021: return Decrypt_v17_r73479(peImage, fileData, ref dumpedMethods); case ConfuserVersion.v18_r75257: return Decrypt_v17_r73479(peImage, fileData, ref dumpedMethods); case ConfuserVersion.v18_r75288: return Decrypt_v17_r73479(peImage, fileData, ref dumpedMethods); case ConfuserVersion.v18_r75291: return Decrypt_v17_r73479(peImage, fileData, ref dumpedMethods); case ConfuserVersion.v18_r75402: return Decrypt_v18_r75402(peImage, fileData, ref dumpedMethods); case ConfuserVersion.v19_r75725: return Decrypt_v18_r75402(peImage, fileData, ref dumpedMethods); default: throw new ApplicationException("Unknown version"); } }
public override bool GetDecryptedModule(int count, ref byte[] newFileData, ref DumpedMethods dumpedMethods) { if (count != 0) return false; fileData = ModuleBytes ?? DeobUtils.ReadModule(module); peImage = new MyPEImage(fileData); if (!options.DecryptMethods) return false; var tokenToNativeCode = new Dictionary<uint,byte[]>(); if (!methodsDecrypter.Decrypt(peImage, DeobfuscatedFile, ref dumpedMethods, tokenToNativeCode, unpackedNativeFile)) return false; newFileData = fileData; return true; }
bool DecryptImage_v16_r71742(MyPEImage peImage, byte[] fileData) { var reader = new BinaryReader(new MemoryStream(methodsData)); reader.ReadInt16(); // sig int numInfos = reader.ReadInt32(); for (int i = 0; i < numInfos; i++) { uint offs = reader.ReadUInt32() ^ key4; if (offs == 0) continue; uint rva = reader.ReadUInt32() ^ key5; if (peImage.RvaToOffset(rva) != offs) throw new ApplicationException("Invalid offs & rva"); int len = reader.ReadInt32(); for (int j = 0; j < len; j++) fileData[offs + j] = reader.ReadByte(); } return true; }
public byte[] Unpack() { byte[] data = null; MyPEImage myPeImage = null; try { myPeImage = new MyPEImage(peImage); data = Unpack2(myPeImage); } catch { } finally { if (myPeImage != null) myPeImage.Dispose(); } if (data != null) return data; if (shouldUnpack) Logger.w("Could not unpack file: {0}", peImage.FileName ?? "(unknown filename)"); return null; }
void FreePEImage() { if (peImage != null) peImage.Dispose(); peImage = null; }
byte[] DecryptMethodsData_v14_r57884(MyPEImage peImage, bool hasStrongNameInfo) { var reader = peImage.Reader; reader.Position = 0; var md5SumData = reader.ReadBytes((int)peImage.OptionalHeader.CheckSum ^ (int)key0); int csOffs = (int)peImage.OptionalHeader.StartOffset + 0x40; Array.Clear(md5SumData, csOffs, 4); var md5Sum = DeobUtils.Md5Sum(md5SumData); ulong checkSum = reader.ReadUInt64() ^ lkey0; if (hasStrongNameInfo) { int sn = reader.ReadInt32(); int snLen = reader.ReadInt32(); if (sn != 0) { if (peImage.RvaToOffset((uint)peImage.Cor20Header.StrongNameSignature.VirtualAddress) != sn || peImage.Cor20Header.StrongNameSignature.Size != snLen) throw new ApplicationException("Invalid sn and snLen"); Array.Clear(md5SumData, sn, snLen); } } if (checkSum != CalcChecksum(md5SumData)) throw new ApplicationException("Invalid checksum. File has been modified."); var iv = reader.ReadBytes(reader.ReadInt32() ^ (int)key2); var encrypted = reader.ReadBytes(reader.ReadInt32() ^ (int)key3); var decrypted = Decrypt(encrypted, iv, md5SumData); if (BitConverter.ToInt16(decrypted, 0) != 0x6FD6) throw new ApplicationException("Invalid magic"); return decrypted; }
public bool Decrypt(MyPEImage peImage, ISimpleDeobfuscator simpleDeobfuscator, ref DumpedMethods dumpedMethods, Dictionary<uint, byte[]> tokenToNativeCode, bool unpackedNativeFile) { if (encryptedResource.Method == null) return false; encryptedResource.Initialize(simpleDeobfuscator); if (!encryptedResource.FoundResource) return false; var methodsData = encryptedResource.Decrypt(); bool hooksJitter = FindDnrCompileMethod(encryptedResource.Method.DeclaringType) != null; xorKey = GetXorKey(); XorEncrypt(methodsData); var methodsDataReader = MemoryImageStream.Create(methodsData); int patchCount = methodsDataReader.ReadInt32(); int mode = methodsDataReader.ReadInt32(); int tmp = methodsDataReader.ReadInt32(); methodsDataReader.Position -= 4; if ((tmp & 0xFF000000) == 0x06000000) { // It's method token + rva. DNR 3.7.0.3 (and earlier?) - 3.9.0.1 methodsDataReader.Position += 8L * patchCount; patchCount = methodsDataReader.ReadInt32(); mode = methodsDataReader.ReadInt32(); PatchDwords(peImage, methodsDataReader, patchCount); while (methodsDataReader.Position < methodsData.Length - 1) { uint token = methodsDataReader.ReadUInt32(); int numDwords = methodsDataReader.ReadInt32(); PatchDwords(peImage, methodsDataReader, numDwords / 2); } } else if (!hooksJitter || mode == 1) { // DNR 3.9.8.0, 4.0+ PatchDwords(peImage, methodsDataReader, patchCount); bool oldCode = !IsNewer45Decryption(encryptedResource.Method); while (methodsDataReader.Position < methodsData.Length - 1) { uint rva = methodsDataReader.ReadUInt32(); int size; if (oldCode) { methodsDataReader.ReadUInt32(); // token, unknown, or index size = methodsDataReader.ReadInt32(); } else size = methodsDataReader.ReadInt32() * 4; var newData = methodsDataReader.ReadBytes(size); if (unpackedNativeFile) peImage.DotNetSafeWriteOffset(rva, newData); else peImage.DotNetSafeWrite(rva, newData); } } else { // DNR 4.0+ (jitter is hooked) var methodDef = peImage.MetaData.TablesStream.MethodTable; var rvaToIndex = new Dictionary<uint, int>((int)methodDef.Rows); uint offset = (uint)methodDef.StartOffset; for (int i = 0; i < methodDef.Rows; i++) { uint rva = peImage.OffsetReadUInt32(offset); offset += methodDef.RowSize; if (rva == 0) continue; if ((peImage.ReadByte(rva) & 3) == 2) rva++; else rva += (uint)(4 * (peImage.ReadByte(rva + 1) >> 4)); rvaToIndex[rva] = i; } PatchDwords(peImage, methodsDataReader, patchCount); int count = methodsDataReader.ReadInt32(); dumpedMethods = new DumpedMethods(); while (methodsDataReader.Position < methodsData.Length - 1) { uint rva = methodsDataReader.ReadUInt32(); uint index = methodsDataReader.ReadUInt32(); bool isNativeCode = index >= 0x70000000; int size = methodsDataReader.ReadInt32(); var methodData = methodsDataReader.ReadBytes(size); int methodIndex; if (!rvaToIndex.TryGetValue(rva, out methodIndex)) { Logger.w("Could not find method having code RVA {0:X8}", rva); continue; } uint methodToken = 0x06000001 + (uint)methodIndex; if (isNativeCode) { totalEncryptedNativeMethods++; if (tokenToNativeCode != null) tokenToNativeCode[methodToken] = methodData; // Convert return true / false methods. The others are converted to // throw 0xDEADCODE. if (DeobUtils.IsCode(nativeLdci4, methodData)) { uint val = BitConverter.ToUInt32(methodData, 4); // ldc.i4 XXXXXXXXh / ret methodData = new byte[] { 0x20, 0, 0, 0, 0, 0x2A }; methodData[1] = (byte)val; methodData[2] = (byte)(val >> 8); methodData[3] = (byte)(val >> 16); methodData[4] = (byte)(val >> 24); } else if (DeobUtils.IsCode(nativeLdci4_0, methodData)) { // ldc.i4.0 / ret methodData = new byte[] { 0x16, 0x2A }; } else { tokenToNativeMethod[methodToken] = methodData; // ldc.i4 0xDEADCODE / conv.u4 / throw methodData = new byte[] { 0x20, 0xDE, 0xC0, 0xAD, 0xDE, 0x6D, 0x7A }; } } var dm = new DumpedMethod(); peImage.ReadMethodTableRowTo(dm, MDToken.ToRID(methodToken)); dm.code = methodData; var codeReader = peImage.Reader; codeReader.Position = peImage.RvaToOffset(dm.mdRVA); byte[] code; var mbHeader = MethodBodyParser.ParseMethodBody(codeReader, out code, out dm.extraSections); peImage.UpdateMethodHeaderInfo(dm, mbHeader); dumpedMethods.Add(dm); } } return true; }
bool Decrypt_v16_r71742(MyPEImage peImage, byte[] fileData) { methodsData = DecryptMethodsData_v16_r71742(peImage, GetEncryptedHeaderOffset_v16_r71742(peImage.Sections)); return DecryptImage_v16_r71742(peImage, fileData); }
bool DecryptImage_v14_r58004(MyPEImage peImage, byte[] fileData) { var reader = new BinaryReader(new MemoryStream(methodsData)); reader.ReadInt16(); // sig var writer = new BinaryWriter(new MemoryStream(fileData)); int numInfos = reader.ReadInt32(); for (int i = 0; i < numInfos; i++) { uint offs = reader.ReadUInt32() ^ key4; if (offs == 0) continue; uint rva = reader.ReadUInt32() ^ key4; if (peImage.RvaToOffset(rva) != offs) throw new ApplicationException("Invalid offs & rva"); writer.BaseStream.Position = peImage.RvaToOffset(rva); writer.Write(reader.ReadBytes(reader.ReadInt32())); } return true; }
public bool Decrypt(byte[] fileData, ref DumpedMethods dumpedMethods) { if (decrypter == null) return false; using (var peImage = new MyPEImage(fileData)) { if (peImage.Sections.Count <= 0) return false; var methodsData = FindMethodsData(peImage, fileData); if (methodsData == null) return false; decrypter.Initialize(methodsData); dumpedMethods = CreateDumpedMethods(peImage, fileData, methodsData); if (dumpedMethods == null) return false; } return true; }
bool Decrypt_v17_r73605(MyPEImage peImage, byte[] fileData) { if (peImage.OptionalHeader.CheckSum == 0) return false; methodsData = DecryptMethodsData_v17_r73404(peImage); return DecryptImage_v16_r71742(peImage, fileData); }
DumpedMethods CreateDumpedMethods(MyPEImage peImage, byte[] fileData, byte[] methodsData) { var dumpedMethods = new DumpedMethods(); var methodsDataReader = MemoryImageStream.Create(methodsData); var fileDataReader = MemoryImageStream.Create(fileData); var methodDef = peImage.MetaData.TablesStream.MethodTable; for (uint rid = 1; rid <= methodDef.Rows; rid++) { var dm = new DumpedMethod(); peImage.ReadMethodTableRowTo(dm, rid); if (dm.mdRVA == 0) continue; uint bodyOffset = peImage.RvaToOffset(dm.mdRVA); byte b = peImage.OffsetReadByte(bodyOffset); uint codeOffset; if ((b & 3) == 2) { if (b != 2) continue; // not zero byte code size dm.mhFlags = 2; dm.mhMaxStack = 8; dm.mhLocalVarSigTok = 0; codeOffset = bodyOffset + 1; } else { if (peImage.OffsetReadUInt32(bodyOffset + 4) != 0) continue; // not zero byte code size dm.mhFlags = peImage.OffsetReadUInt16(bodyOffset); dm.mhMaxStack = peImage.OffsetReadUInt16(bodyOffset + 2); dm.mhLocalVarSigTok = peImage.OffsetReadUInt32(bodyOffset + 8); codeOffset = bodyOffset + (uint)(dm.mhFlags >> 12) * 4; } fileDataReader.Position = codeOffset; if (!decrypter.Decrypt(fileDataReader, dm)) continue; dumpedMethods.Add(dm); } return dumpedMethods; }
public NativeImageUnpacker(IPEImage peImage) { this.peImage = new MyPEImage(peImage); }
byte[] FindMethodsData(MyPEImage peImage, byte[] fileData) { var section = peImage.Sections[0]; var reader = MemoryImageStream.Create(fileData); const int RVA_EXECUTIVE_OFFSET = 1 * 4; const int ENC_CODE_OFFSET = 6 * 4; int lastOffset = Math.Min(fileData.Length, (int)(section.PointerToRawData + section.SizeOfRawData)); for (int offset = GetStartOffset(peImage); offset < lastOffset; ) { offset = FindSig(fileData, offset, lastOffset, initializeMethodEnd); if (offset < 0) return null; offset += initializeMethodEnd.Length; short retImm16 = BitConverter.ToInt16(fileData, offset); if (retImm16 != 0x0C && retImm16 != 0x10) continue; offset += 2; if (offset + ENC_CODE_OFFSET + 4 > lastOffset) return null; // rva is 0 when the assembly has been embedded uint rva = BitConverter.ToUInt32(fileData, offset + RVA_EXECUTIVE_OFFSET); if (rva != 0 && mainType.Rvas.IndexOf(rva) < 0) continue; int relOffs = BitConverter.ToInt32(fileData, offset + ENC_CODE_OFFSET); if (relOffs <= 0 || relOffs >= section.SizeOfRawData) continue; reader.Position = section.PointerToRawData + relOffs; int size = (int)reader.ReadCompressedUInt32(); int endOffset = relOffs + size; if (endOffset < relOffs || endOffset > section.SizeOfRawData) continue; return reader.ReadBytes(size); } return null; }
public override bool GetDecryptedModule(int count, ref byte[] newFileData, ref DumpedMethods dumpedMethods) { if (count != 0 || version == Version.Unknown) return false; byte[] fileData = ModuleBytes ?? DeobUtils.ReadModule(module); byte[] decompressed; using (var peImage = new MyPEImage(fileData)) { var section = peImage.Sections[peImage.Sections.Count - 1]; var offset = section.PointerToRawData; offset += 16; byte[] compressed; int compressedLen; switch (version) { case Version.V0x: compressedLen = fileData.Length - (int)offset; compressed = peImage.OffsetReadBytes(offset, compressedLen); decompressed = Lzmat.DecompressOld(compressed); if (decompressed == null) throw new ApplicationException("LZMAT decompression failed"); break; case Version.V1x_217: case Version.V218: if (peImage.PEImage.ImageNTHeaders.FileHeader.Machine == Machine.AMD64 && version == Version.V218) offset = section.PointerToRawData + section.VirtualSize; int decompressedLen = (int)peImage.OffsetReadUInt32(offset); compressedLen = fileData.Length - (int)offset - 4; compressed = peImage.OffsetReadBytes(offset + 4, compressedLen); decompressed = new byte[decompressedLen]; uint decompressedLen2; if (Lzmat.Decompress(decompressed, out decompressedLen2, compressed) != LzmatStatus.OK) throw new ApplicationException("LZMAT decompression failed"); break; default: throw new ApplicationException("Unknown MPRESS version"); } } newFileData = decompressed; return true; }
int GetStartOffset(MyPEImage peImage) { int minOffset = int.MaxValue; foreach (var rva in mainType.Rvas) { int rvaOffs = (int)peImage.RvaToOffset((uint)rva); if (rvaOffs < minOffset) minOffset = rvaOffs; } return minOffset == int.MaxValue ? 0 : minOffset; }
bool decryptModule(ref byte[] newFileData, ref DumpedMethods dumpedMethods) { if (!methodsDecrypter.Detected) return false; byte[] fileData = ModuleBytes ?? DeobUtils.readModule(module); using (var peImage = new MyPEImage(fileData)) { if (!methodsDecrypter.decrypt(peImage, ref dumpedMethods)) return false; } newFileData = fileData; return true; }
byte[] Unpack2(MyPEImage peImage) { shouldUnpack = false; uint headerOffset = (uint)peImage.Length - 12; uint offsetEncryptedAssembly = CheckOffset(peImage, peImage.OffsetReadUInt32(headerOffset)); uint ezencryptionLibLength = peImage.OffsetReadUInt32(headerOffset + 4); uint iniFileLength = peImage.OffsetReadUInt32(headerOffset + 8); uint offsetClrVersionNumber = checked(offsetEncryptedAssembly - 12); uint iniFileOffset = checked(headerOffset - iniFileLength); uint ezencryptionLibOffset = checked(iniFileOffset - ezencryptionLibLength); uint clrVerMajor = peImage.OffsetReadUInt32(offsetClrVersionNumber); uint clrVerMinor = peImage.OffsetReadUInt32(offsetClrVersionNumber + 4); uint clrVerBuild = peImage.OffsetReadUInt32(offsetClrVersionNumber + 8); if (clrVerMajor <= 0 || clrVerMajor >= 20 || clrVerMinor >= 20 || clrVerBuild >= 1000000) return null; var settings = new IniFile(Decompress2(peImage.OffsetReadBytes(iniFileOffset, (int)iniFileLength))); sizes = GetSizes(settings["General_App_Satellite_Assemblies_Sizes"]); if (sizes == null || sizes.Length <= 1) return null; shouldUnpack = true; if (sizes[0] != offsetEncryptedAssembly) return null; filenames = settings["General_App_Satellite_Assemblies"].Split('|'); if (sizes.Length - 1 != filenames.Length) return null; byte[] ezencryptionLibData = Decompress1(peImage.OffsetReadBytes(ezencryptionLibOffset, (int)ezencryptionLibLength)); var ezencryptionLibModule = ModuleDefMD.Load(ezencryptionLibData); var decrypter = new ApplicationModeDecrypter(ezencryptionLibModule); if (!decrypter.Detected) return null; var mainAssembly = UnpackEmbeddedFile(peImage, 0, decrypter); decrypter.MemoryPatcher.Patch(mainAssembly.data); for (int i = 1; i < filenames.Length; i++) satelliteAssemblies.Add(UnpackEmbeddedFile(peImage, i, decrypter)); ClearDllBit(mainAssembly.data); return mainAssembly.data; }
bool Decrypt_v15_r59014(MyPEImage peImage, byte[] fileData) { methodsData = DecryptMethodsData_v14_r57884(peImage, true); return DecryptImage_v14_r58004(peImage, fileData); }
public override bool GetDecryptedModule(int count, ref byte[] newFileData, ref DumpedMethods dumpedMethods) { if (count != 0 || !options.DecryptMethods) return false; byte[] fileData = ModuleBytes ?? DeobUtils.ReadModule(module); using (var peImage = new MyPEImage(fileData)) { if (!new MethodsDecrypter().Decrypt(peImage, module, cliSecureRtType, ref dumpedMethods)) { Logger.v("Methods aren't encrypted or invalid signature"); return false; } } newFileData = fileData; return true; }
UnpackedFile UnpackEmbeddedFile(MyPEImage peImage, int index, ApplicationModeDecrypter decrypter) { uint offset = 0; for (int i = 0; i < index + 1; i++) offset += sizes[i]; string filename = Win32Path.GetFileName(filenames[index]); var data = peImage.OffsetReadBytes(offset, (int)sizes[index + 1]); data = DeobUtils.AesDecrypt(data, decrypter.AssemblyKey, decrypter.AssemblyIv); data = Decompress(data); return new UnpackedFile(filename, data); }
uint CheckOffset(MyPEImage peImage, uint offset) { if (offset >= peImage.Length) throw new Exception(); return offset; }
static void PatchDwords(MyPEImage peImage, IBinaryReader reader, int count) { for (int i = 0; i < count; i++) { uint rva = reader.ReadUInt32(); uint data = reader.ReadUInt32(); peImage.DotNetSafeWrite(rva, BitConverter.GetBytes(data)); } }