private void CreateSection(ModuleWriter writer) { // move some PE parts to separate section to prevent it from being hashed var peSection = new PESection("", 0x60000020); bool moved = false; uint alignment; if (writer.StrongNameSignature != null) { alignment = writer.TextSection.Remove(writer.StrongNameSignature).Value; peSection.Add(writer.StrongNameSignature, alignment); moved = true; } if (writer.ImportAddressTable != null) { alignment = writer.TextSection.Remove(writer.ImportAddressTable).Value; peSection.Add(writer.ImportAddressTable, alignment); moved = true; } if (writer.StartupStub != null) { alignment = writer.TextSection.Remove(writer.StartupStub).Value; peSection.Add(writer.StartupStub, alignment); moved = true; } if (moved) writer.Sections.Add(peSection); // create section var nameBuffer = new byte[8]; nameBuffer[0] = (byte)(name1 >> 0); nameBuffer[1] = (byte)(name1 >> 8); nameBuffer[2] = (byte)(name1 >> 16); nameBuffer[3] = (byte)(name1 >> 24); nameBuffer[4] = (byte)(name2 >> 0); nameBuffer[5] = (byte)(name2 >> 8); nameBuffer[6] = (byte)(name2 >> 16); nameBuffer[7] = (byte)(name2 >> 24); var newSection = new PESection(Encoding.ASCII.GetString(nameBuffer), 0xE0000040); writer.Sections.Insert(random.NextInt32(writer.Sections.Count), newSection); // random padding at beginning to prevent revealing hash key newSection.Add(new ByteArrayChunk(random.NextBytes(0x10)), 0x10); // create index var bodyIndex = new JITBodyIndex(methods.Select(method => writer.MetaData.GetToken(method).Raw)); newSection.Add(bodyIndex, 0x10); // move initialization away from module initializer cctorRepl.Body = cctor.Body; cctor.Body = new CilBody(); cctor.Body.Instructions.Add(Instruction.Create(OpCodes.Call, initMethod)); cctor.Body.Instructions.Add(Instruction.Create(OpCodes.Call, cctorRepl)); cctor.Body.Instructions.Add(Instruction.Create(OpCodes.Ret)); // save methods foreach (MethodDef method in methods.WithProgress(context.Logger)) { if (!method.HasBody) continue; MDToken token = writer.MetaData.GetToken(method); var jitBody = new JITMethodBody(); var bodyWriter = new JITMethodBodyWriter(writer.MetaData, method.Body, jitBody, random.NextUInt32(), writer.MetaData.KeepOldMaxStack || method.Body.KeepOldMaxStack); bodyWriter.Write(); jitBody.Serialize(token.Raw, key, fieldLayout); bodyIndex.Add(token.Raw, jitBody); method.Body = NopBody; writer.MetaData.TablesHeap.MethodTable[token.Rid].ImplFlags |= (ushort)MethodImplAttributes.NoInlining; context.CheckCancellation(); } bodyIndex.PopulateSection(newSection); // padding to prevent bad size due to shift division newSection.Add(new ByteArrayChunk(new byte[4]), 4); }
private void EncryptSection(ModuleWriter writer) { Stream stream = writer.DestinationStream; var reader = new BinaryReader(writer.DestinationStream); stream.Position = 0x3C; stream.Position = reader.ReadUInt32(); stream.Position += 6; ushort sections = reader.ReadUInt16(); stream.Position += 0xc; ushort optSize = reader.ReadUInt16(); stream.Position += 2 + optSize; uint encLoc = 0, encSize = 0; for (int i = 0; i < sections; i++) { uint nameHash = reader.ReadUInt32() * reader.ReadUInt32(); stream.Position += 8; if (nameHash == name1 * name2) { encSize = reader.ReadUInt32(); encLoc = reader.ReadUInt32(); } else if (nameHash != 0) { uint sectSize = reader.ReadUInt32(); uint sectLoc = reader.ReadUInt32(); Hash(stream, reader, sectLoc, sectSize); } stream.Position += 16; } uint[] key = DeriveKey(); encSize >>= 2; stream.Position = encLoc; var result = new uint[encSize]; for (uint i = 0; i < encSize; i++) { uint data = reader.ReadUInt32(); result[i] = data ^ key[i & 0xf]; key[i & 0xf] = (key[i & 0xf] ^ data) + 0x3dbb2819; } var byteResult = new byte[encSize << 2]; Buffer.BlockCopy(result, 0, byteResult, 0, byteResult.Length); stream.Position = encLoc; stream.Write(byteResult, 0, byteResult.Length); }
private void CreateSections(ModuleWriter writer) { var nameBuffer = new byte[8]; nameBuffer[0] = (byte)(name1 >> 0); nameBuffer[1] = (byte)(name1 >> 8); nameBuffer[2] = (byte)(name1 >> 16); nameBuffer[3] = (byte)(name1 >> 24); nameBuffer[4] = (byte)(name2 >> 0); nameBuffer[5] = (byte)(name2 >> 8); nameBuffer[6] = (byte)(name2 >> 16); nameBuffer[7] = (byte)(name2 >> 24); var newSection = new PESection(Encoding.ASCII.GetString(nameBuffer), 0xE0000040); writer.Sections.Insert(0, newSection); // insert first to ensure proper RVA uint alignment; alignment = writer.TextSection.Remove(writer.MetaData).Value; writer.TextSection.Add(writer.MetaData, alignment); alignment = writer.TextSection.Remove(writer.NetResources).Value; writer.TextSection.Add(writer.NetResources, alignment); alignment = writer.TextSection.Remove(writer.Constants).Value; newSection.Add(writer.Constants, alignment); // move some PE parts to separate section to prevent it from being hashed var peSection = new PESection("", 0x60000020); bool moved = false; if (writer.StrongNameSignature != null) { alignment = writer.TextSection.Remove(writer.StrongNameSignature).Value; peSection.Add(writer.StrongNameSignature, alignment); moved = true; } if (writer.ImportAddressTable != null) { alignment = writer.TextSection.Remove(writer.ImportAddressTable).Value; peSection.Add(writer.ImportAddressTable, alignment); moved = true; } if (writer.StartupStub != null) { alignment = writer.TextSection.Remove(writer.StartupStub).Value; peSection.Add(writer.StartupStub, alignment); moved = true; } if (moved) writer.Sections.Add(peSection); // move encrypted methods var encryptedChunk = new MethodBodyChunks(writer.TheOptions.ShareMethodBodies); newSection.Add(encryptedChunk, 4); foreach (MethodDef method in methods) { if (!method.HasBody) continue; MethodBody body = writer.MetaData.GetMethodBody(method); bool ok = writer.MethodBodies.Remove(body); encryptedChunk.Add(body); } // padding to prevent bad size due to shift division newSection.Add(new ByteArrayChunk(new byte[4]), 4); }