4

I want to start a C# console application by loading it from a byte array.

If I write the application to disk and start the program manually, it starts, which means that the bytes were read correctly.

I tried various snippets that I found online, for example:

Assembly a = Assembly.Load(programma);
MethodInfo method = a.EntryPoint;
if (method != null)
{
    object o = a.CreateInstance(method.Name);
    method.Invoke(o, null);
}

or:

public static Thread RunFromMemory(byte[] bytes)
{
    var thread = new Thread(new ThreadStart(() =>
    {
        var assembly = Assembly.Load(bytes);
        MethodInfo method = assembly.EntryPoint;
        if (method != null)
        {
            method.Invoke(null, null);
        }
    }));

    thread.SetApartmentState(ApartmentState.STA);
    thread.Start();

    return thread;
}

These two code examples work with a WinForms application, but not with a console application.

CarenRose
  • 1,266
  • 1
  • 12
  • 24
  • What do you mean that it doesn't work? Do you get an Exception? Does nothing happen? – Broots Waymb Dec 27 '18 at 18:35
  • 2
    If you want Windows to start a new process, which is what you need to do to open a separate console app, those bytes must exist on disk, and not just in memory. – Joel Coehoorn Dec 27 '18 at 18:37
  • 1
    What do you mean by "visual application c#" on the last line? Winforms? – NTDLS Dec 27 '18 at 18:37
  • *not with those console applications* correct because if you start them, you need to provide the visual stdin/stdout for them to run *within* your application. Starting a thread does not start a new independent process. – Erik Philips Dec 27 '18 at 18:40
  • @Broots Waymb I do not get any exceptions, the process remains active indefinitely – the gamer x Dec 27 '18 at 18:44
  • @NTDLS yes with ***Winforms*** the code that i sent up works – the gamer x Dec 27 '18 at 18:45
  • @JoelCoehoorn that is the classic method and works I know as said in the post if I write on the disk I can start the program correctly, I need to start it from memory without going through the disk – the gamer x Dec 27 '18 at 18:49
  • What version of the framework are you using? Can you check if the windows form is different from the console? – Kim Lage Dec 27 '18 at 18:50
  • The WinForms solution you showed **does not start a new application.** It just shows another form in a new thread within the same process. If you want to get a console app started from within a winforms apps, that will require a new process, and the only way to do that is to put the bytes on disk. – Joel Coehoorn Dec 27 '18 at 18:50
  • The way you're doing it at the moment is not actually running it as a separate program. You're just executing its code under the same process, same AppDomain and within the same memory. The application you are "executing" has access to all the same resources the process it's being launched from has. Basically it's almost the same as if you had a .dll referenced and called its Main method. – Imantas Dec 27 '18 at 18:52
  • @KimLage I'm using 4.6.1 from both solutions. I try to boot from a console application, a console application saved in a byte array – the gamer x Dec 27 '18 at 19:02
  • @JoelCoehoorn I want to run another console app saved in a byte array from a console app – the gamer x Dec 27 '18 at 19:03
  • @Imantas in theory it should call the method ever – the gamer x Dec 27 '18 at 19:04
  • Then you have to save it to disk first. There's no other way. – Joel Coehoorn Dec 27 '18 at 19:09
  • @thegamerx as pointed by Joel Coehoom what you doing in the methods you've shown is that its executing the code from the first aplication context. So you need to allocate the memory necessary before invoking it: try this solution: https://stackoverflow.com/a/959144/1504359 – Kim Lage Dec 27 '18 at 19:43
  • @KimLage I tried adding my bytes to the bodybuilder (I'm not sure how I should use that script), so I get the exception: "System.BadImageFormatException" otherwise if instead of the bodybuilder I use my byte array directly, the process remains suspended – the gamer x Dec 27 '18 at 20:01
  • Well, lets take a step back than... This is called dll or code injection. Its when you get an already compiled code to inside your already running program. Is often used to make cracks and cheats for games. I think if you are not familiar with that aproach I would try something different, since it can became quite confusing when working in that lower level. Do you have the code for the second application? can you inject from code instead of a compiled solution? that would make everything easier... – Kim Lage Dec 27 '18 at 20:44
  • you could just compile it at execution time and call your second application methods like it belongs from the first... – Kim Lage Dec 27 '18 at 20:45
  • another thing that would help to investigate the problem is knowing a little better what are you trying to inject. Is it a .exe console? Dll? is there anyother file included in your second application? like a app.config or dll? – Kim Lage Dec 27 '18 at 20:47

1 Answers1

1

You acquire the bytes for your program, then you can load up an Assembly from these bytes using Assembly.Load, find the EntryPoint, and invoke it.

private static void RunBytes(byte[] bytes)
{    
    Assembly exeAssembly = Assembly.Load(bytes);
    var entryPoint = exeAssembly.EntryPoint;
    var parms = exeAssembly?.CreateInstance(entryPoint.Name);
    entryPoint?.Invoke(parms, null);
}

Alternatively you can write the bytes to disk first and then try to use Assembly.LoadFrom instead.

Shashank Shekhar
  • 3,958
  • 2
  • 40
  • 52
Tore Aurstad
  • 3,189
  • 1
  • 27
  • 22