3

As the title says the deserialization fail after protecting my application with themida with the following exception :

Unable to generate a temporary class (result=1). error CS0009: Metadata file 'c:\Path\to\protected.exe' could not be opened -- 'An attempt was made to load a program with an incorrect format. '

Here's the code I'm using for the deserialization (It works when the exe is not protected):

MyClass myClass;
try
{
    using (var stream = new MemoryStream(Data))
    {
        var serializer = new XmlSerializer(typeof(ComSec.MyClass));
        myClass = serializer.Deserialize(stream) as MyClass;
    }
}
catch (Exception e)
{
    return null;
}

Weird thing is that the code + themida protection works fine on my machine but it fails on the VM and on a co-worker's machine

I'm using (same config as my co-worker) :

  • VS2012 Professional
  • Windows 7 x64 Ultimate
  • Themida 2.1.2.0 x86 (With .Net support)

The VM is a fresh install of Windows 7 x86.

Late4Work
  • 71
  • 5
  • Sounds like a question for Themida. Maybe there is an attribute to tell it to ignore your DTOs... – Marc Gravell Sep 29 '12 at 10:40
  • However! The incorrect format exception often relates to x86 vs x64. The machines that work/fail - is it possible you're x64 and they're x86? – Marc Gravell Sep 29 '12 at 10:41
  • I compiled the project to run as a x86 process even on x64 machines. The VM machine is x86 and the co-worker's machine is x64 and it doesn't work on both except on mine which is a Win7 x64. – Late4Work Sep 29 '12 at 12:55
  • how do i get reputaiton to answer my question ? I solved the problem. – Late4Work Sep 29 '12 at 13:31
  • 1
    If you've solved it, then perhaps post the solution *as an answer* – Marc Gravell Sep 29 '12 at 13:40
  • How ? I can't unless I wait 8 hours. anyway, by using the serializable attribute and binary formatter I was able to serialize/deserialize without problems. thank you – Late4Work Sep 29 '12 at 14:16
  • I suspect that could be a dangerous choice. BinaryFormatter is notoriously version intolerant to start with, but an obfuacator can make things even worse, since a common trick is to generate different names each build. Be very careful to test that approach, in particular moving between versions. I personally wouldn't use BinaryFormattet for anything except exchanging data between two AppDomain instances in one process via remoting. I certainly wouldn't use BinaryFormatter for storage. – Marc Gravell Sep 29 '12 at 17:45
  • @MarcGravell What would be a better way to do this ? DataContract (with naming the DataMemebers) ? BTW I'm just using this to save the object to disk then read it back. Sorry if I'm asking too much. – Late4Work Sep 30 '12 at 07:52
  • Yes, DataContractSerializer would be reliable (w/ named members and contracts). XmlSerializer *should* work - sounds like an internal glitch. I'd actuallly be interested to know if protobuf-net works in your scenario, but if DCS works it should suffice. Don't use NetDataContractSerializer here - that has the same issues as BinaryFormatter. – Marc Gravell Sep 30 '12 at 10:01

2 Answers2

4

I ended up using the DataContract attribute and using a DataContractSerializer to Serialize and deserialize the object (It works now everywhere and with/without the protection ).

My research:

[DataContract(Name = "TestClass")]
public class TestClass
{
    [DataMember(Name = "Name")]
    public string Name { get; set; }
    [DataMember(Name = "Age")]
    public int Age { get; set; }
}

Serialization/Deserialization :

var serializer = new DataContractSerializer(typeof(TestClass));

using (var stream = new MemoryStream())
{
    serializer.WriteObject(stream, this);
    File.WriteAllBytes("TestClass.xml", stream.ToArray());
}

TestClass o = null;
using (var stream = new MemoryStream(File.ReadAllBytes("TestClass.xml")))
{
    o = serializer.ReadObject(stream) as TestClass;
}
Late4Work
  • 71
  • 5
0

I experienced this issue as well and the proposed answer worked fine. The original problem was due to file access permissions. Just adding this information so other people understand why DataContract works (from https://stackoverflow.com/a/10340155/1111380):

DataContractSerializer, NetDataContractSerializer and DataContractJsonSerializer do NOT require disk space and do NOT emit assemblies to disk. Instead, they generate IL on the fly (in memory) and use it during subsequent serialization episodes to do serialization and deserialization all within the AppDomain they're operating in. However, XmlSerializer does require disk space and explains the error (path to the file could not be opened/access).

Community
  • 1
  • 1
user1111380
  • 551
  • 2
  • 6
  • 17