-1

Alright so i am pretty new to really anything in memory execution. I usually just write the bytes from the embedded resource into the file on the hard drive but for the program i am making for a work project it cannot write the exe to the disk.

So i took the code from Load a .NET assembly from the application's resources and run It from memory, but without terminating the main/host application I modified the code a little bit in what i would think would work for running it with an argument and it does nothing but crash, not really listing any crash details though besides the windows error reporting. here is the code:

 Dim ass As Assembly = Assembly.Load(My.Resources.bbinst)
            Dim method As MethodInfo = ass.EntryPoint
            Dim parametersArray As Object() = New Object() {"/q /SERIAL=xxx-xxx"}

            If (method IsNot Nothing) Then
                Dim instance As Object = ass.CreateInstance(method.Name)
                method.Invoke(instance, parametersArray)
                If (instance IsNot Nothing) AndAlso (instance.GetType().GetInterfaces.Contains(GetType(IDisposable))) Then
                    DirectCast(instance, IDisposable).Dispose()
                End If
                instance = Nothing
                method = Nothing
                ass = Nothing

            Else
                Throw New EntryPointNotFoundException("Entrypoint not found in the specified resource. Are you sure it is a .NET assembly?")
            End If

bbinst is the exe name that is embedded as bbinst.exe The parametersArray is the argument i want to run which i converted from a C# sample i found else where.

Can someone help me as to why the program just crashes and error reporting pops up second after, i'm not to good as debugging. I also tried to run it without the arguments and it as well crashed the same way.

Any help is awesome, sometimes i have these random projects at work i don't know why they give me lol

  • Which program is crashing? The host or the embedded one? If the former, start your application from Visual Studio so its debugger gets attached. – Visual Vincent Jul 07 '17 at 19:28
  • I'm not sure, it doesn't give a .net run time error just the windows error reporting. when i close the error window it closes the whole program. I don't know if this helps but in process explorer/process hacker it doesn't show the second exe as being loaded/started. I'll have to redo the code on the program to attach it to the visual studio debugger in a few hours. – Paintballer4lfe Jul 07 '17 at 19:44
  • Why do you have to _redo_ the code in order to run it though VS? If you coded it in there you should just have to open up the project and press F5. -- Also, even if the error dialog isn't very informative you can still check the Windows Event Viewer (`eventvwr.msc`) for a more specific error. Look for an item that says either `Application Error` or `.NET Runtime Error`. – Visual Vincent Jul 07 '17 at 22:14
  • because it's at the bottom a large list of code it executes prior to getting to this step. i'm just going to comment it out and run it in VS, idk why i forgot about even viewer to, i'll check it tomorrow. – Paintballer4lfe Jul 10 '17 at 12:45
  • How about just creating a new project and trying it there at first? That way you can see if the code works at all or if it's something related to that specific project of yours. – Visual Vincent Jul 10 '17 at 12:53
  • Alright so i am getting this error from the .NET application not the embeded exe: Faulting application name: sysmon-test.exe, version: 4.3.0.1542, time stamp: 0x595fc379 Faulting module name: KERNELBASE.dll, version: 6.1.7601.23807, time stamp: 0x5915f98e Exception code: 0xe0434352 That is from event viewer – Paintballer4lfe Jul 13 '17 at 16:26
  • This is the error details from the VS debugger which i don't really know how to debug to be honest. https://i.gyazo.com/e32bdc3783ea79ccc31cf5c219db68e9.png – Paintballer4lfe Jul 13 '17 at 16:41
  • Well you're in luck! There is no need to debug it! I've added an answer explaining the problem. :) – Visual Vincent Jul 13 '17 at 17:17

2 Answers2

0

A BadImageFormatException is thrown either when you attempt to load an assembly of the wrong bitness, or when you try to load an assembly that cannot be read, run or compiled by the current runtime.

Regarding bitness: 32-bit (x86) applications cannot load 64-bit code, and 64-bit (x64) applications cannot load 32-bit code. It's that simple.

As for not being able to read, run or compile the assembly: If the assembly that you're trying to load was programmed in a completely different language (more precisely: a language without .NET support) then it would also cause the above exception to be thrown.

Your method of executing an embedded application will only work with assemblies that were coded in a .NET language (C#, VB.NET, F#, C++/CLR, etc.). This is because that doesn't only run the application, it tries to load it like a .NET app linked to an Assembly, and/or AppDomain, class so that you can have some control over it and invoke methods inside it.

Your issue: My bet that your problem is caused by your embedded application not being of the same bitness as the host. Make sure both applications are compiled either as x86, x64 or AnyCPU.

However if it turns out that your embedded program isn't even written in a .NET language then that is the cause of your problem. That code of yours can only run .NET programs/DLLs.

Visual Vincent
  • 18,045
  • 5
  • 28
  • 75
  • hmm well the program i'm loading is apparently both x86 and x64 and the program i'm coding has the Any CPU platform selected, should i try and run this only as x86? – Paintballer4lfe Jul 13 '17 at 19:39
  • i changed the platform to x86 and recieved the same error but in a .net runtime error rather then in event viewer (same error in VS debugger as well) EDIT/UPDATE: i tried both x86 and x64 platforms, same error everytime in VS debugger – Paintballer4lfe Jul 13 '17 at 20:19
  • @Paintballer4lfe : The main program (the program you're coding) must target _**the very same**_ platform (bitness) as the one you're loading. Thus, if the one _you're coding_ targets x86, then the one _you're loading_ must also target x86. -- Likewise if the one _you're coding_ targets AnyCPU, then the one _you're loading_ must also target AnyCPU. (and so on) – Visual Vincent Jul 13 '17 at 20:47
  • @Paintballer4lfe : By the way, the program that _you're loading_ (the embedded one), in what _**programming language**_ was it written? And did you write the program? – Visual Vincent Jul 13 '17 at 20:49
  • @Paintballer4lfe : I updated my answer with another probable cause of your problem. I didn't thought it would be that since I assumed that your embedded program was written in a .NET language, but if that's not so then what I've added to my answer is the actual cause of your problem. – Visual Vincent Jul 13 '17 at 21:07
  • ooo my bad i guess i should have said at the beginning of this, the embedded program is native,written in c++. I know you can still run it in memory .NET running native BUT i don't know if i can use this same code or something like it to do so. – Paintballer4lfe Jul 13 '17 at 21:10
  • @Paintballer4lfe : As I just added to my answer: you cannot. That code of yours can **only** run other .NET assemblies. Native C++ (ex. C++/Win32) can only be loaded using native Win32 methods that you P/Invoke (Platform Invoke). – Visual Vincent Jul 13 '17 at 21:13
  • @Paintballer4lfe : When you mentioned that the embedded app was (or could be) x86 or x64 (but not AnyCPU) I figured that we might not be dealing with a .NET app here. – Visual Vincent Jul 13 '17 at 21:17
  • @Paintballer4lfe : [**This question and its highest rated answer**](https://stackoverflow.com/q/305203/3740093) describes how you can create _a separate process_ from memory. It would require you to P/Invoke all those calls _**or**_ make a C++ DLL wrapper where you only P/Invoke _**it**_ from VB.NET. -- If you don't want to start it as a separate process the other answers have some suggestions as well. – Visual Vincent Jul 13 '17 at 21:23
  • hmm i've never done this before lol i'll try some of the snippets out, i was wondering why it wasn't working lol. I'n unsure what route i should go using a DLL or not but i guess i'll try em both. – Paintballer4lfe Jul 17 '17 at 15:51
  • @Paintballer4lfe : The good thing with making a C++ wrapper DLL is that you will only have to P/Invoke _**one**_ function in VB.NET. Then that function takes care of the rest of the C++ calls necessary to load an application into memory. – Visual Vincent Jul 17 '17 at 23:16
  • Sorry to drag this on but i found a snippet that seems like it should work but it errors when i execute, Here is the pastebn with the error on the bottom: [https://pastebin.com/BrahtRdR](https://pastebin.com/BrahtRdR) Could you give me a link to a decent write up for DLL wrapper in vb.net? i've never done it before. – Paintballer4lfe Jul 18 '17 at 15:54
  • @Paintballer4lfe : You get the error because you literally throw it in the `CreateProcess()` method: `Throw New NotImplementedException()`. The method is incomplete, there's no code in it. -- What wrapper do you mean you are looking for? I don't know of any specific one. – Visual Vincent Jul 18 '17 at 16:03
  • @Paintballer4lfe : If it was the C++ wrapper you meant you basically just create a C++ DLL project and write a function which does all the C++ calls for you. The declaration could for example look like: `void __declspec(dllexport) __stdcall ExecuteInMemory(unsigned char* bytes)`, though it is too complicated to be able to give you any details in the comments. – Visual Vincent Jul 18 '17 at 16:42
  • O god i'm in over my head lol, can you point me towards a better example of the code i am trying to use in VB.NET? i found all these samples but it seems most of them are nothing but errors and i can't quite understand how it functions. – Paintballer4lfe Jul 20 '17 at 14:06
  • @Paintballer4lfe : This isn't something I've done before, but I managed to find this answer: https://stackoverflow.com/a/9233591/3740093 -- If you create a C# Class Library (DLL) project and reference that in your VB.NET app you should be able to use it. – Visual Vincent Jul 20 '17 at 14:30
  • @Paintballer4lfe : Though you'd have to remove `unsafe` from `public unsafe class` and then wrap the code _**inside**_ `Run()` in an `unsafe { ...code here... }` block. – Visual Vincent Jul 20 '17 at 14:33
  • o boy lol i tried to convert it but the fixed (byte* p = &IMAGE_SECTION_HEADER[0]) code doesn't see to easily transfer over lol, i feel like i'm very overmy head right now lol – Paintballer4lfe Jul 20 '17 at 17:39
  • So i found a different way of doing it. Using RunPE, even though it has a bad rep since people use it for malware commonly i can actually legit use the code not abuse it. I'm unsing RunPE and i have everything good but now i'm getting a Variable is used before it has been assigned a value when i do: Dim RunPE as RunPE 'RunPE is the Class name RunPE.Run(Application.ExecutablePath, "/q /SERIAL=xxx-xxx", My.Resources.bbinst) – Paintballer4lfe Jul 20 '17 at 19:56
  • @Paintballer4lfe : But you _**cannot**_ convert the code, I edited the comment because you must take that approach and put it in a C# DLL. VB.NET doesn't support `fixed`, `unsafe` nor pointers (`byte*`). – Visual Vincent Jul 21 '17 at 09:50
  • @Paintballer4lfe : As for the error, `Dim RunPE As RunPE` creates a variable, but you never assign anything to it nor create a new instance. The variable is empty. To create an instance use the [**`New` keyword**](https://learn.microsoft.com/en-us/dotnet/visual-basic/language-reference/operators/new-operator): `Dim RunPE As New RunPE`. – Visual Vincent Jul 21 '17 at 09:54
  • Yeah i found that out not long after i put that comment lol, now i have to start understanding how the arguments work LOL, what a pain. – Paintballer4lfe Jul 24 '17 at 12:44
0

You can invoke the EntryPoint by loading it in the assembly :

 Public Shared Sub RunSearch(ByVal pPath As String, ByVal pText As String)
    'Get assembly
    Dim assembly As Reflection.Assembly = Reflection.Assembly.GetExecutingAssembly()

    'Get the resource stream
    Dim resourceStream As Stream = assembly.GetManifestResourceStream("path.executable name")

    If resourceStream Is Nothing Then
         MsgBox("Unexisting Path","Error")
    End If

    'Read the raw bytes of the resource
    Dim resourcesBuffer(CInt(resourceStream.Length) - 1) As Byte

    resourceStream.Read(resourcesBuffer, 0, resourcesBuffer.Length)
    resourceStream.Close()

    'Load the assembly
    Dim exeAssembly As Reflection.Assembly = Reflection.Assembly.Load(resourcesBuffer)
    Dim args() As String = {pPath, pText}
    Dim parameters = New Object() {args}
    Try
        exeAssembly.EntryPoint.Invoke(Nothing, parameters)
    Catch
        MsgBox("Error during assembly executing","Error")
    End Try
End Sub
Ale865
  • 116
  • 9