public MethodInfos(MainType mainType, PeImage peImage, PeHeader peHeader, McKey mcKey) { this.mainType = mainType; this.peImage = peImage; this.peHeader = peHeader; this.mcKey = mcKey; structSize = getStructSize(mcKey); uint methodInfosRva = peHeader.getRva2(0x0FF8, mcKey.readUInt32(0x005A)); uint encryptedDataRva = peHeader.getRva2(0x0FF0, mcKey.readUInt32(0x0046)); methodInfosOffset = peImage.rvaToOffset(methodInfosRva); encryptedDataOffset = peImage.rvaToOffset(encryptedDataRva); }
static uint getOldCodeHeaderOffset(PeImage peImage) { var sect = getLastOf(peImage, sections); if (sect == null || sect.virtualSize < 0x100) { return(0); } return(peImage.rvaToOffset(sect.virtualAddress + sect.virtualSize - 0x100)); }
int getStartOffset(PeImage 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 MethodInfos(MainType mainType, PeImage peImage, PeHeader peHeader, McKey mcKey) { this.mainType = mainType; this.peImage = peImage; this.peHeader = peHeader; this.mcKey = mcKey; decryptHandlersV1 = new Decrypt[] { decrypt1a, decrypt4a, decrypt2a, decrypt3a, decrypt5, decrypt6, decrypt7 }; decryptHandlersV2 = new Decrypt[] { decrypt3a, decrypt2a, decrypt1a, decrypt4a, decrypt5, decrypt6, decrypt7 }; decryptHandlersV3 = new Decrypt[] { decrypt1a, decrypt2a, decrypt3a, decrypt4a, decrypt5, decrypt6, decrypt7 }; decryptHandlersV4 = new Decrypt[] { decrypt2a, decrypt1a, decrypt3a, decrypt4a, decrypt5, decrypt6, decrypt7 }; decryptHandlersV5a = new Decrypt[] { decrypt4a, decrypt2a, decrypt3a, decrypt1a, decrypt5, decrypt6, decrypt7 }; decryptHandlersV5b = new Decrypt[] { decrypt4b, decrypt2b, decrypt3b, decrypt1b, decrypt6, decrypt7, decrypt5 }; decryptHandlersV5c = new Decrypt[] { decrypt4c, decrypt2c, decrypt3c, decrypt1c, decrypt6, decrypt7, decrypt5 }; 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); }
DumpedMethods createDumpedMethods(PeImage peImage, byte[] fileData, byte[] methodsData) { var dumpedMethods = new DumpedMethods(); var methodsDataReader = new BinaryReader(new MemoryStream(methodsData)); var fileDataReader = new BinaryReader(new MemoryStream(fileData)); var metadataTables = peImage.Cor20Header.createMetadataTables(); var methodDef = metadataTables.getMetadataType(MetadataIndex.iMethodDef); uint methodDefOffset = methodDef.fileOffset; for (int i = 0; i < methodDef.rows; i++, methodDefOffset += methodDef.totalSize) { uint bodyRva = peImage.offsetReadUInt32(methodDefOffset); if (bodyRva == 0) { continue; } uint bodyOffset = peImage.rvaToOffset(bodyRva); var dm = new DumpedMethod(); dm.token = (uint)(0x06000001 + i); dm.mdImplFlags = peImage.offsetReadUInt16(methodDefOffset + (uint)methodDef.fields[1].offset); dm.mdFlags = peImage.offsetReadUInt16(methodDefOffset + (uint)methodDef.fields[2].offset); dm.mdName = peImage.offsetRead(methodDefOffset + (uint)methodDef.fields[3].offset, methodDef.fields[3].size); dm.mdSignature = peImage.offsetRead(methodDefOffset + (uint)methodDef.fields[4].offset, methodDef.fields[4].size); dm.mdParamList = peImage.offsetRead(methodDefOffset + (uint)methodDef.fields[5].offset, methodDef.fields[5].size); 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.BaseStream.Position = codeOffset; if (!decrypter.decrypt(fileDataReader, dm)) { continue; } dumpedMethods.add(dm); } return(dumpedMethods); }
DumpedMethods decryptMethods() { var dumpedMethods = new DumpedMethods(); var methodInfos = new MethodInfos(mainType, peImage, peHeader, mcKey); methodInfos.initializeInfos(); var metadataTables = peImage.Cor20Header.createMetadataTables(); var methodDef = metadataTables.getMetadataType(MetadataIndex.iMethodDef); uint methodDefOffset = methodDef.fileOffset; for (int i = 0; i < methodDef.rows; i++, methodDefOffset += methodDef.totalSize) { uint bodyRva = peImage.offsetReadUInt32(methodDefOffset); if (bodyRva == 0) { continue; } var info = methodInfos.lookup(bodyRva); if (info == null) { continue; } uint bodyOffset = peImage.rvaToOffset(bodyRva); ushort magic = peImage.offsetReadUInt16(bodyOffset); if (magic != 0xFFF3) { continue; } var dm = new DumpedMethod(); dm.token = (uint)(0x06000001 + i); dm.mdImplFlags = peImage.offsetReadUInt16(methodDefOffset + (uint)methodDef.fields[1].offset); dm.mdFlags = peImage.offsetReadUInt16(methodDefOffset + (uint)methodDef.fields[2].offset); dm.mdName = peImage.offsetRead(methodDefOffset + (uint)methodDef.fields[3].offset, methodDef.fields[3].size); dm.mdSignature = peImage.offsetRead(methodDefOffset + (uint)methodDef.fields[4].offset, methodDef.fields[4].size); dm.mdParamList = peImage.offsetRead(methodDefOffset + (uint)methodDef.fields[5].offset, methodDef.fields[5].size); var reader = new BinaryReader(new MemoryStream(info.body)); byte b = reader.ReadByte(); if ((b & 3) == 2) { dm.mhFlags = 2; dm.mhMaxStack = 8; dm.mhCodeSize = (uint)(b >> 2); dm.mhLocalVarSigTok = 0; } else { reader.BaseStream.Position--; dm.mhFlags = reader.ReadUInt16(); dm.mhMaxStack = reader.ReadUInt16(); dm.mhCodeSize = reader.ReadUInt32(); dm.mhLocalVarSigTok = reader.ReadUInt32(); uint codeOffset = (uint)(dm.mhFlags >> 12) * 4; reader.BaseStream.Position += codeOffset - 12; } dm.code = reader.ReadBytes((int)dm.mhCodeSize); if ((dm.mhFlags & 8) != 0) { reader.BaseStream.Position = (reader.BaseStream.Position + 3) & ~3; dm.extraSections = reader.ReadBytes((int)(reader.BaseStream.Length - reader.BaseStream.Position)); } dumpedMethods.add(dm); } return(dumpedMethods); }
public bool decrypt(PeImage peImage, ref DumpedMethods dumpedMethods) { dumpedMethods = new DumpedMethods(); bool decrypted = false; var metadataTables = peImage.Cor20Header.createMetadataTables(); var methodDef = metadataTables.getMetadataType(MetadataIndex.iMethodDef); uint methodDefOffset = methodDef.fileOffset; for (int i = 0; i < methodDef.rows; i++, methodDefOffset += methodDef.totalSize) { uint bodyRva = peImage.offsetReadUInt32(methodDefOffset); if (bodyRva == 0) { continue; } uint bodyOffset = peImage.rvaToOffset(bodyRva); var dm = new DumpedMethod(); dm.token = (uint)(0x06000001 + i); byte[] code, extraSections; peImage.Reader.BaseStream.Position = bodyOffset; var mbHeader = MethodBodyParser.parseMethodBody(peImage.Reader, out code, out extraSections); if (code.Length < 6 || code[0] != 0x2A || code[1] != 0x2A) { continue; } dm.code = code; dm.extraSections = extraSections; int seed = BitConverter.ToInt32(code, 2); Array.Copy(newCodeHeader, code, newCodeHeader.Length); if (seed == 0) { decrypt(code); } else { decrypt(code, seed); } dm.mdImplFlags = peImage.offsetReadUInt16(methodDefOffset + (uint)methodDef.fields[1].offset); dm.mdFlags = peImage.offsetReadUInt16(methodDefOffset + (uint)methodDef.fields[2].offset); dm.mdName = peImage.offsetRead(methodDefOffset + (uint)methodDef.fields[3].offset, methodDef.fields[3].size); dm.mdSignature = peImage.offsetRead(methodDefOffset + (uint)methodDef.fields[4].offset, methodDef.fields[4].size); dm.mdParamList = peImage.offsetRead(methodDefOffset + (uint)methodDef.fields[5].offset, methodDef.fields[5].size); dm.mhFlags = mbHeader.flags; dm.mhMaxStack = mbHeader.maxStack; dm.mhCodeSize = (uint)dm.code.Length; dm.mhLocalVarSigTok = mbHeader.localVarSigTok; dumpedMethods.add(dm); decrypted = true; } return(decrypted); }
public DecrypterBase(PeImage peImage, CodeHeader codeHeader) { this.peImage = peImage; this.codeHeader = codeHeader; endOfMetadata = peImage.rvaToOffset(peImage.Cor20Header.metadataDirectory.virtualAddress + peImage.Cor20Header.metadataDirectory.size); }
static uint getCodeHeaderOffset(PeImage peImage) { return(peImage.rvaToOffset(peImage.Cor20Header.metadataDirectory.virtualAddress + peImage.Cor20Header.metadataDirectory.size)); }
List <CsHeaderVersion> getCsHeaderVersions(uint codeHeaderOffset, MetadataType 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(MetadataType methodDefTable) { if (methodDefTable.totalSize != codeHeader.methodDefElemSize) { return(true); } if (methodDefTable.fileOffset - peImage.rvaToOffset(peImage.Cor20Header.metadataDirectory.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"); } }
public bool decrypt2(ref DumpedMethods dumpedMethods) { uint offset = peImage.rvaToOffset(peImage.Cor20Header.metadataDirectory.virtualAddress + peImage.Cor20Header.metadataDirectory.size); if (!readCodeHeader(offset)) { return(false); } var metadataTables = peImage.Cor20Header.createMetadataTables(); var methodDefTable = metadataTables.getMetadataType(MetadataIndex.iMethodDef); if (methodDefTable.totalSize != codeHeader.methodDefElemSize) { return(false); } var methodInfos = getMethodInfos(offset + 0x30 + codeHeader.totalCodeSize); offset = methodDefTable.fileOffset - methodDefTable.totalSize; foreach (var methodInfo in methodInfos) { offset += methodDefTable.totalSize; if (methodInfo.flags == 0 || methodInfo.codeOffs == 0) { continue; } uint rva = peImage.offsetReadUInt32(offset); peImage.writeUint16(rva, (ushort)methodInfo.flags); peImage.writeUint32(rva + 8, methodInfo.localVarSigTok); } dumpedMethods = new DumpedMethods(); offset = methodDefTable.fileOffset; for (int i = 0; i < methodInfos.Count; i++, offset += methodDefTable.totalSize) { var methodInfo = methodInfos[i]; if (methodInfo.codeOffs == 0) { continue; } var dm = new DumpedMethod(); dm.token = 0x06000001 + (uint)i; uint rva = peImage.offsetReadUInt32(offset); dm.mdImplFlags = peImage.offsetReadUInt16(offset + (uint)methodDefTable.fields[1].offset); dm.mdFlags = peImage.offsetReadUInt16(offset + (uint)methodDefTable.fields[2].offset); dm.mdName = peImage.offsetRead(offset + (uint)methodDefTable.fields[3].offset, methodDefTable.fields[3].size); dm.mdSignature = peImage.offsetRead(offset + (uint)methodDefTable.fields[4].offset, methodDefTable.fields[4].size); dm.mdParamList = peImage.offsetRead(offset + (uint)methodDefTable.fields[5].offset, methodDefTable.fields[5].size); dm.code = decrypter.decrypt(methodInfo); if ((peImage.readByte(rva) & 3) == 2) { dm.mhFlags = 2; dm.mhMaxStack = 8; dm.mhCodeSize = (uint)dm.code.Length; dm.mhLocalVarSigTok = 0; } else { dm.mhFlags = peImage.readUInt16(rva); dm.mhMaxStack = peImage.readUInt16(rva + 2); dm.mhCodeSize = (uint)dm.code.Length; dm.mhLocalVarSigTok = peImage.readUInt32(rva + 8); } dumpedMethods.add(dm); } return(true); }