2011-12-29 15:22:41 +08:00
|
|
|
|
/*
|
2012-01-10 06:02:47 +08:00
|
|
|
|
Copyright (C) 2011-2012 de4dot@gmail.com
|
2011-12-29 15:22:41 +08:00
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
using System.Collections.Generic;
|
2012-01-24 22:14:57 +08:00
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Security.Cryptography;
|
2012-12-20 09:06:09 +08:00
|
|
|
|
using dnlib.DotNet;
|
|
|
|
|
using dnlib.DotNet.Emit;
|
2011-12-29 15:22:41 +08:00
|
|
|
|
using de4dot.blocks;
|
|
|
|
|
|
|
|
|
|
namespace de4dot.code.deobfuscators {
|
|
|
|
|
class InitializedDataCreator {
|
2012-11-01 18:28:09 +08:00
|
|
|
|
ModuleDef module;
|
|
|
|
|
Dictionary<long, TypeDef> sizeToArrayType = new Dictionary<long, TypeDef>();
|
|
|
|
|
TypeDef ourType;
|
|
|
|
|
TypeDefOrRefSig valueType;
|
2011-12-29 15:22:41 +08:00
|
|
|
|
int unique = 0;
|
2012-11-01 18:28:09 +08:00
|
|
|
|
MemberRef initializeArrayMethod;
|
2012-01-03 22:25:25 +08:00
|
|
|
|
|
2012-11-01 18:28:09 +08:00
|
|
|
|
public MemberRef InitializeArrayMethod {
|
2012-01-03 22:25:25 +08:00
|
|
|
|
get { return createInitializeArrayMethod(); }
|
|
|
|
|
}
|
2011-12-29 15:22:41 +08:00
|
|
|
|
|
2012-11-01 18:28:09 +08:00
|
|
|
|
public InitializedDataCreator(ModuleDef module) {
|
2011-12-29 15:22:41 +08:00
|
|
|
|
this.module = module;
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-01 18:28:09 +08:00
|
|
|
|
MemberRef createInitializeArrayMethod() {
|
2012-01-03 22:25:25 +08:00
|
|
|
|
if (initializeArrayMethod == null) {
|
2012-11-22 16:14:51 +08:00
|
|
|
|
var runtimeHelpersType = DotNetUtils.findOrCreateTypeRef(module, module.CorLibTypes.AssemblyRef, "System.Runtime.CompilerServices", "RuntimeHelpers", false);
|
|
|
|
|
var systemArrayType = DotNetUtils.findOrCreateTypeRef(module, module.CorLibTypes.AssemblyRef, "System", "Array", false);
|
|
|
|
|
var runtimeFieldHandleType = DotNetUtils.findOrCreateTypeRef(module, module.CorLibTypes.AssemblyRef, "System", "RuntimeFieldHandle", true);
|
2012-11-01 18:28:09 +08:00
|
|
|
|
var methodSig = MethodSig.CreateStatic(module.CorLibTypes.Void, systemArrayType, runtimeFieldHandleType);
|
|
|
|
|
initializeArrayMethod = module.UpdateRowId(new MemberRefUser(module, "InitializeArray", methodSig, runtimeHelpersType.TypeDefOrRef));
|
2012-01-03 22:25:25 +08:00
|
|
|
|
}
|
|
|
|
|
return initializeArrayMethod;
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-01 18:28:09 +08:00
|
|
|
|
public void addInitializeArrayCode(Block block, int start, int numToRemove, ITypeDefOrRef elementType, byte[] data) {
|
2012-01-03 22:25:25 +08:00
|
|
|
|
int index = start;
|
2012-11-01 18:28:09 +08:00
|
|
|
|
block.replace(index++, numToRemove, Instruction.CreateLdcI4(data.Length / elementType.ToTypeSig().ElementType.GetPrimitiveSize()));
|
2012-12-16 07:03:56 +08:00
|
|
|
|
block.insert(index++, OpCodes.Newarr.ToInstruction(elementType));
|
|
|
|
|
block.insert(index++, OpCodes.Dup.ToInstruction());
|
|
|
|
|
block.insert(index++, OpCodes.Ldtoken.ToInstruction((IField)create(data)));
|
|
|
|
|
block.insert(index++, OpCodes.Call.ToInstruction((IMethod)InitializeArrayMethod));
|
2012-01-03 22:25:25 +08:00
|
|
|
|
}
|
|
|
|
|
|
2011-12-29 15:22:41 +08:00
|
|
|
|
void createOurType() {
|
|
|
|
|
if (ourType != null)
|
|
|
|
|
return;
|
|
|
|
|
|
2012-11-01 18:28:09 +08:00
|
|
|
|
ourType = new TypeDefUser("", string.Format("<PrivateImplementationDetails>{0}", getModuleId()), module.CorLibTypes.Object.TypeDefOrRef);
|
2012-11-17 06:50:52 +08:00
|
|
|
|
ourType.Attributes = TypeAttributes.NotPublic | TypeAttributes.AutoLayout |
|
2012-11-01 18:28:09 +08:00
|
|
|
|
TypeAttributes.Class | TypeAttributes.AnsiClass;
|
|
|
|
|
module.UpdateRowId(ourType);
|
2011-12-29 15:22:41 +08:00
|
|
|
|
module.Types.Add(ourType);
|
|
|
|
|
}
|
|
|
|
|
|
2012-01-24 22:14:57 +08:00
|
|
|
|
object getModuleId() {
|
|
|
|
|
var memoryStream = new MemoryStream();
|
|
|
|
|
var writer = new BinaryWriter(memoryStream);
|
|
|
|
|
if (module.Assembly != null)
|
2012-11-01 18:28:09 +08:00
|
|
|
|
writer.Write(module.Assembly.FullName);
|
|
|
|
|
writer.Write((module.Mvid ?? Guid.Empty).ToByteArray());
|
2012-01-24 22:14:57 +08:00
|
|
|
|
var hash = new SHA1Managed().ComputeHash(memoryStream.GetBuffer());
|
|
|
|
|
var guid = new Guid(BitConverter.ToInt32(hash, 0),
|
|
|
|
|
BitConverter.ToInt16(hash, 4),
|
|
|
|
|
BitConverter.ToInt16(hash, 6),
|
|
|
|
|
hash[8], hash[9], hash[10], hash[11],
|
|
|
|
|
hash[12], hash[13], hash[14], hash[15]);
|
|
|
|
|
return guid.ToString("B");
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-01 18:28:09 +08:00
|
|
|
|
TypeDef getArrayType(long size) {
|
2011-12-29 15:22:41 +08:00
|
|
|
|
createOurType();
|
|
|
|
|
|
2012-11-01 18:28:09 +08:00
|
|
|
|
TypeDef arrayType;
|
2011-12-29 15:22:41 +08:00
|
|
|
|
if (sizeToArrayType.TryGetValue(size, out arrayType))
|
|
|
|
|
return arrayType;
|
|
|
|
|
|
|
|
|
|
if (valueType == null)
|
2012-11-22 16:14:51 +08:00
|
|
|
|
valueType = DotNetUtils.findOrCreateTypeRef(module, module.CorLibTypes.AssemblyRef, "System", "ValueType", false);
|
2012-11-01 18:28:09 +08:00
|
|
|
|
arrayType = new TypeDefUser("", string.Format("__StaticArrayInitTypeSize={0}", size), valueType.TypeDefOrRef);
|
|
|
|
|
module.UpdateRowId(arrayType);
|
2012-11-17 06:50:52 +08:00
|
|
|
|
arrayType.Attributes = TypeAttributes.NestedPrivate | TypeAttributes.ExplicitLayout |
|
2012-11-01 18:28:09 +08:00
|
|
|
|
TypeAttributes.Class | TypeAttributes.Sealed | TypeAttributes.AnsiClass;
|
2011-12-29 15:22:41 +08:00
|
|
|
|
ourType.NestedTypes.Add(arrayType);
|
|
|
|
|
sizeToArrayType[size] = arrayType;
|
2012-11-01 18:28:09 +08:00
|
|
|
|
arrayType.ClassLayout = new ClassLayoutUser(1, (uint)size);
|
2011-12-29 15:22:41 +08:00
|
|
|
|
return arrayType;
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-01 18:28:09 +08:00
|
|
|
|
public FieldDef create(byte[] data) {
|
2011-12-29 15:22:41 +08:00
|
|
|
|
var arrayType = getArrayType(data.LongLength);
|
2012-11-01 18:28:09 +08:00
|
|
|
|
var fieldSig = new FieldSig(new ValueTypeSig(arrayType));
|
2011-12-29 15:22:41 +08:00
|
|
|
|
var attrs = FieldAttributes.Assembly | FieldAttributes.Static;
|
2012-11-01 18:28:09 +08:00
|
|
|
|
var field = new FieldDefUser(string.Format("field_{0}", unique++), fieldSig, attrs);
|
|
|
|
|
module.UpdateRowId(field);
|
|
|
|
|
field.HasFieldRVA = true;
|
2011-12-29 15:22:41 +08:00
|
|
|
|
ourType.Fields.Add(field);
|
|
|
|
|
var iv = new byte[data.Length];
|
|
|
|
|
Array.Copy(data, iv, data.Length);
|
|
|
|
|
field.InitialValue = iv;
|
|
|
|
|
return field;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|