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 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, 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; }
public uint Emulate(uint rva, uint[] args) { Initialize(args); reader.Position = peImage.RvaToOffset(rva); byte[] prolog, epilog; if (IsBytes(prolog1)) { prolog = prolog1; epilog = epilog1; } else if (IsBytes(prolog2)) { prolog = prolog2; epilog = epilog2; } else { throw new ApplicationException(string.Format("Missing prolog @ RVA {0:X8}", rva)); } reader.Position += prolog.Length; while (!IsBytes(epilog)) { Emulate(); } return(regs[0]); }
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 DecrypterBase(MyPEImage peImage, CodeHeader codeHeader) { this.peImage = peImage; this.codeHeader = codeHeader; var mdDir = peImage.Cor20Header.MetaData; endOfMetadata = peImage.RvaToOffset((uint)mdDir.VirtualAddress + mdDir.Size); }
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); }
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)); }
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); }
public bool Decrypt(MyPEImage peImage, ref DumpedMethods dumpedMethods) { dumpedMethods = new DumpedMethods(); bool decrypted = false; var methodDef = peImage.DotNetFile.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); }
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); }
DumpedMethods Decrypt_v17_r73404(MyPEImage peImage, byte[] fileData) { var dumpedMethods = new DumpedMethods(); 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); if (!IsEncryptedMethod(fileData, (int)bodyOffset)) { continue; } int key = BitConverter.ToInt32(fileData, (int)bodyOffset + 6); int mdOffs = BitConverter.ToInt32(fileData, (int)bodyOffset + 2) ^ key; int len = BitConverter.ToInt32(fileData, (int)bodyOffset + 11) ^ ~key; var codeData = DecryptMethodData_v17_r73404(methodsData, mdOffs + 2, (uint)key, len); var reader = ByteArrayDataReaderFactory.CreateReader(codeData); var mbHeader = MethodBodyParser.ParseMethodBody(ref reader, out dm.code, out dm.extraSections); if (reader.Position != reader.Length) { throw new ApplicationException("Invalid method data"); } peImage.UpdateMethodHeaderInfo(dm, mbHeader); dumpedMethods.Add(dm); } return(dumpedMethods); }
bool Decrypt_v14_r57884(MyPEImage peImage, byte[] fileData) { methodsData = DecryptMethodsData_v14_r57884(peImage, false); 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 rva = reader.ReadUInt32(); if (rva == 0) { continue; } writer.BaseStream.Position = peImage.RvaToOffset(rva); writer.Write(reader.ReadBytes(reader.ReadInt32())); } return(true); }
DumpedMethods Decrypt(MyPEImage peImage, byte[] fileData, DecryptMethodData decrypter) { var dumpedMethods = new DumpedMethods(); 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); if (!IsEncryptedMethod(fileData, (int)bodyOffset)) continue; int key = BitConverter.ToInt32(fileData, (int)bodyOffset + 6); int mdOffs = BitConverter.ToInt32(fileData, (int)bodyOffset + 2) ^ key; int len = BitConverter.ToInt32(fileData, (int)bodyOffset + 11) ^ ~key; int methodDataOffset = mdOffs + 2; uint[] methodData; byte[] codeData; decrypter.Decrypt(methodsData, methodDataOffset, (uint)key, len, out methodData, out codeData); dm.mhFlags = 0x03; int maxStack = (int)methodData[methodDataIndexes.maxStack]; dm.mhMaxStack = (ushort)maxStack; dm.mhLocalVarSigTok = methodData[methodDataIndexes.localVarSigTok]; if (dm.mhLocalVarSigTok != 0 && (dm.mhLocalVarSigTok >> 24) != 0x11) throw new ApplicationException("Invalid local var sig token"); int numExceptions = (int)methodData[methodDataIndexes.ehs]; uint options = methodData[methodDataIndexes.options]; int codeSize = (int)methodData[methodDataIndexes.codeSize]; var codeDataReader = MemoryImageStream.Create(codeData); if (decrypter.IsCodeFollowedByExtraSections(options)) { dm.code = codeDataReader.ReadBytes(codeSize); dm.extraSections = ReadExceptionHandlers(codeDataReader, numExceptions); } else { dm.extraSections = ReadExceptionHandlers(codeDataReader, numExceptions); dm.code = codeDataReader.ReadBytes(codeSize); } if (codeDataReader.Position != codeDataReader.Length) throw new ApplicationException("Invalid method data"); if (dm.extraSections != null) dm.mhFlags |= 8; dm.mhCodeSize = (uint)dm.code.Length; // Figure out if the original method was tiny or not. bool isTiny = dm.code.Length <= 0x3F && dm.mhLocalVarSigTok == 0 && dm.extraSections == null && dm.mhMaxStack == 8; if (isTiny) dm.mhFlags |= 0x10; // Set 'init locals' dm.mhFlags |= (ushort)(options & 0x10); // copy 'init locals' bit dumpedMethods.Add(dm); } return dumpedMethods; }
bool Decrypt_v14_r57884(MyPEImage peImage, byte[] fileData) { methodsData = DecryptMethodsData_v14_r57884(peImage, false); 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 rva = reader.ReadUInt32(); if (rva == 0) continue; writer.BaseStream.Position = peImage.RvaToOffset(rva); writer.Write(reader.ReadBytes(reader.ReadInt32())); } return true; }
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 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; }
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; }
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); }
DumpedMethods Decrypt(MyPEImage peImage, byte[] fileData, DecryptMethodData decrypter) { var dumpedMethods = new DumpedMethods(); 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); if (!IsEncryptedMethod(fileData, (int)bodyOffset)) { continue; } int key = BitConverter.ToInt32(fileData, (int)bodyOffset + 6); int mdOffs = BitConverter.ToInt32(fileData, (int)bodyOffset + 2) ^ key; int len = BitConverter.ToInt32(fileData, (int)bodyOffset + 11) ^ ~key; int methodDataOffset = mdOffs + 2; uint[] methodData; byte[] codeData; decrypter.Decrypt(methodsData, methodDataOffset, (uint)key, len, out methodData, out codeData); dm.mhFlags = 0x03; int maxStack = (int)methodData[methodDataIndexes.maxStack]; dm.mhMaxStack = (ushort)maxStack; dm.mhLocalVarSigTok = methodData[methodDataIndexes.localVarSigTok]; if (dm.mhLocalVarSigTok != 0 && dm.mhLocalVarSigTok >> 24 != 0x11) { throw new ApplicationException("Invalid local var sig token"); } int numExceptions = (int)methodData[methodDataIndexes.ehs]; uint options = methodData[methodDataIndexes.options]; int codeSize = (int)methodData[methodDataIndexes.codeSize]; var codeDataReader = MemoryImageStream.Create(codeData); if (decrypter.IsCodeFollowedByExtraSections(options)) { dm.code = codeDataReader.ReadBytes(codeSize); dm.extraSections = ReadExceptionHandlers(codeDataReader, numExceptions); } else { dm.extraSections = ReadExceptionHandlers(codeDataReader, numExceptions); dm.code = codeDataReader.ReadBytes(codeSize); } if (codeDataReader.Position != codeDataReader.Length) { throw new ApplicationException("Invalid method data"); } if (dm.extraSections != null) { dm.mhFlags |= 8; } dm.mhCodeSize = (uint)dm.code.Length; // Figure out if the original method was tiny or not. bool isTiny = dm.code.Length <= 0x3F && dm.mhLocalVarSigTok == 0 && dm.extraSections == null && dm.mhMaxStack == 8; if (isTiny) { dm.mhFlags |= 0x10; // Set 'init locals' } dm.mhFlags |= (ushort)(options & 0x10); // copy 'init locals' bit dumpedMethods.Add(dm); } return(dumpedMethods); }
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; }
List <CsHeaderVersion> GetCsHeaderVersions(uint codeHeaderOffset, MDTable methodDefTable) { if (sigType == SigType.Old) { return new List <CsHeaderVersion> { CsHeaderVersion.V10 } } ; if (!IsOldHeader(methodDefTable)) { return new List <CsHeaderVersion> { CsHeaderVersion.V52 } } ; if (csRtType.IsAtLeastVersion50()) { return new List <CsHeaderVersion> { CsHeaderVersion.V50 } } ; if (IsCsHeader40(codeHeaderOffset)) { return(new List <CsHeaderVersion> { CsHeaderVersion.V40, CsHeaderVersion.V30, }); } return(new List <CsHeaderVersion> { CsHeaderVersion.V45, CsHeaderVersion.V50, }); } bool IsCsHeader40(uint codeHeaderOffset) { try { uint offset = codeHeaderOffset + codeHeader.totalCodeSize + 0x28; uint prevCodeOffs = 0; for (int i = 0; i < (int)codeHeader.numMethods; i++, offset += 4) { uint codeOffs = peImage.OffsetReadUInt32(offset); if (prevCodeOffs != 0 && codeOffs != 0 && codeOffs < prevCodeOffs) { return(false); } if (codeOffs != 0) { prevCodeOffs = codeOffs; } } return(true); } catch (IOException) { return(false); } } bool IsOldHeader(MDTable methodDefTable) { if (methodDefTable.RowSize != codeHeader.methodDefElemSize) { return(true); } if ((uint)methodDefTable.StartOffset - peImage.RvaToOffset((uint)peImage.Cor20Header.MetaData.VirtualAddress) != codeHeader.methodDefTableOffset) { return(true); } return(false); } ICsHeader CreateCsHeader(CsHeaderVersion version) { switch (version) { case CsHeaderVersion.V30: return(new CsHeader30(this)); case CsHeaderVersion.V40: return(new CsHeader40(this)); case CsHeaderVersion.V45: return(new CsHeader45(this)); case CsHeaderVersion.V50: return(new CsHeader5(this, 0x28)); case CsHeaderVersion.V52: return(new CsHeader5(this, 0x30)); default: throw new ApplicationException("Unknown CS header"); } }
static uint GetCodeHeaderOffset(MyPEImage peImage) { return(peImage.RvaToOffset((uint)peImage.Cor20Header.MetaData.VirtualAddress + peImage.Cor20Header.MetaData.Size)); }
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); }
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; }
DumpedMethods Decrypt_v17_r73404(MyPEImage peImage, byte[] fileData) { var dumpedMethods = new DumpedMethods(); 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); if (!IsEncryptedMethod(fileData, (int)bodyOffset)) continue; int key = BitConverter.ToInt32(fileData, (int)bodyOffset + 6); int mdOffs = BitConverter.ToInt32(fileData, (int)bodyOffset + 2) ^ key; int len = BitConverter.ToInt32(fileData, (int)bodyOffset + 11) ^ ~key; var codeData = DecryptMethodData_v17_r73404(methodsData, mdOffs + 2, (uint)key, len); var reader = MemoryImageStream.Create(codeData); var mbHeader = MethodBodyParser.ParseMethodBody(reader, out dm.code, out dm.extraSections); if (reader.Position != reader.Length) throw new ApplicationException("Invalid method data"); peImage.UpdateMethodHeaderInfo(dm, mbHeader); dumpedMethods.Add(dm); } return dumpedMethods; }
static uint GetCodeHeaderOffset(MyPEImage peImage) { return peImage.RvaToOffset((uint)peImage.Cor20Header.MetaData.VirtualAddress + peImage.Cor20Header.MetaData.Size); }