Martmath / ILInjectionandSample

18 stars 10 forks source link

BadImageFormatException when using it injected #3

Open Jarrekstar opened 7 years ago

Jarrekstar commented 7 years ago

Hi,

I have a test WinForms application built in .Net 4.5/Release config. The assembly I inject into it is also built against .Net 4.5 in release config. Now I have no problems getting types from the host winforms app, I can even do the example in the sample app where number 1 and 2 gets compared and the < operator gets changed to >.

Both my methods are static and public. When I try to modify the method by completely exchanging it with another one with the same signature/name/etc except having the compare operator reversed, I get a BadImageFormatException when invoking the method (the InjectionHelper.UpdateILCodes throws no errors whatsoever). This scenario works without problems in the sample application.

Can you give me some hints/tips/insight on how I could fix this?

Thanks in advance, Jarrekstar

Martmath commented 7 years ago

Hi. If you send a sample project with the error to martmath0@gmail.com, i will try to watch it this\next week.

Jarrekstar commented 7 years ago

Hi,

Thanks for the quick reply! I've attached the projects. Basically you just have to run FormsTarget.exe, press the button if you want to see that the default method works fine, then start the Loader which will inject the assembly with the modified method into the target. When you press the button again, you should get the exception.

IL_Code_Injection_Test.zip

Thanks a lot in advance, Jarrekstar

Martmath commented 7 years ago

Hi, sorry I don't know the inner workings .net but as I understand, the problem is in metadatatokens (mdt in next texts). I explored an example of the methods, but for fields and types, I think everything is similar (there are a few differences for “static strings”). Link with your assembly (asbl next text) is not enough for using your code in another application. You need at least one direct calling of injected method (don’t sure about field or type) your asbl from being modified asbl. So your method will get a new mdt in another asbl. It differs from the mdt used in native asbl or, for example, in the code generated by CsharpCodeProvider. MetadataToken property every time return direct mdt, so I used my RealTokens class instead MetadataToken. I don’t see the way for using this class in another asbl –only deep searching in methods code by using some about “Assembly.GetTypes()[0].GetMethods()[0].GetMethodBody().GetILAsByteArray()”. But if u found how add tokens without direct calling/referencing, it is interesting for me too. But...if reflection (System.Type.GetType(), System.Type.GetMethod(), System.Reflection.MethodBase.Invoke ()) has been used in another assembly, you can try to call a method without tokens. To do this:

  1. Note that the call will be longer (20 bytes or 21 for not Public / Instance vs. 5 bytes) –So your il code should be shorter, or you have to use the other longer method in another asbl for copy and changing code. After calling this method you should return the original code.
  2. For type and method names is necessary to find a method with two input string parameters (full count and type of another input parameters are not famous. Use null / Default (type) for them in invoking method which we change) ... or object type + using call .ToString () inside our il code instead string type.
  3. One string input and two string class variable can help u, instread of second item.

As u see, u have many "if" for using this way and u can use only native data (types/methods/static string) without problems. You can go another way. Call methods other asbl from your asbl. So you can easily use reflection or arrange batch loading (calling) of the other asbl methods through t4 + reflection, for example. But it is necessary to understand the need to replace everything mdt, when refactoring other asbl method. Also you will get big problems with UI - will have really regenerate it from scratch. Also wish to see the profit of using CsharpCodeProvider and add both assembly to ReferencedAssemblies.

Jarrekstar commented 7 years ago

Hi,

Thanks for your great answer! I'll look into adding/replacing those tokens without direct calling/referencing. I'll get back at you if I find anything useful :)

Thanks again!

On 19 February 2017 at 18:03, Martmath notifications@github.com wrote:

Hi, sorry I don't know the inner workings .net but as I understand, the problem is in metadatatokens (mdt in next texts). I explored an example of the methods, but for fields and types, I think everything is similar (there are a few differences for “static strings”). Link with your assembly (asbl next text) is not enough for using your code in another application. You need at least one direct calling of injected method (don’t sure about field or type) your asbl from being modified asbl. So your method will get a new mdt in another asbl. It differs from the mdt used in native asbl or, for example, in the code generated by CsharpCodeProvider. MetadataToken property every time return direct mdt, so I used my RealTokens class instead MetadataToken. I don’t see the way for using this class in another asbl –only deep searching in methods code by using some about “Assembly.GetTypes()[0].GetMethods()[0].GetMethodBody().GetILAsByteArray()”. But if u found how add tokens without direct calling/referencing, it is interesting for me too. But...if reflection (System.Type.GetType(), System.Type.GetMethod(), System.Reflection.MethodBase.Invoke ()) has been used in another assembly, you can try to call a method without tokens. To do this:

  1. Note that the call will be longer (20 bytes or 21 for not Public / Instance vs. 5 bytes) –So your il code should be shorter, or you have to use the other longer method in another asbl for copy and changing code. After calling this method you should return the original code.
  2. For type and method names is necessary to find a method with two input string parameters (full count and type of another input parameters are not famous. Use null / Default (type) for them in invoking method which we change) ... or object type + using call .ToString () inside our il code instead string type.
  3. One string input and two string class variable can help u, instread of second item. As u see, u have many "if" for using this way and u can use only native data (types/methods/static string) without problems. You can go another way. Call methods other asbl from your asbl. So you can easily use reflection or arrange batch loading (calling) of the other asbl methods through t4 + reflection, for example. But it is necessary to understand the need to replace everything mdt, when refactoring other asbl method. Also you will get big problems with UI - will have really regenerate it from scratch. Also wish to see the profit of using CsharpCodeProvider and add both assembly to ReferencedAssemblies.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/Martmath/ILInjectionandSample/issues/3#issuecomment-280932241, or mute the thread https://github.com/notifications/unsubscribe-auth/AAdS9pxrsrOeq3Ot_bNX68VPELUMuC8xks5reHXHgaJpZM4L2rTW .