Showcase of fully functional Beef DLL

Beef DLL Creation & Research

Beef language is still in heavy development. Anything can change at any time in Beef language and thus this document may not be valid anymore!

Content

Requirements 

  • Latest BeefIDE (nightly)
  • DebugView++

About Beef

Beef is an open source performance-oriented compiled programming language. Basically it's C language with C# like syntax. OOP paradigm also can be used for developing applications since in Beef you can create custom reference types (Objects) and combine it with polymorphism. Reflection is also possible. Its quite fast and its fun to work with. More info can be found here -> https://www.beeflang.org/

Beef DLL and DllMain

So first we need to create DLL project in Beef IDE. Go to File -> New -> New Project and choose Dynamic Library.

Now we need to add new class called Program. Like this:

namespace DLLResearch
{
	public static class Program
	{
	}
}

So... Normally when you are creating DLL (for example in C/++) you define DllMain method which is gonna be called when a process is going to try and load our library using, for example, LoadLibrary function from Win32 API. However, this is not possible in Beef since DllMain is already handled by Beef Runtime.

So what we gonna do now? 🤔 It turns out that the solution is very simple. Only thing we need to do is write a public static constructor and deconstructor for class Program.

using System.Diagnostics;
using System;
namespace DLLResearch
{
        [AlwaysInclude] // <- We need this to include our class in DLL, Normally you dont need this
	public static class Program
	{
		public static this() // <- This will gets called when our library gets loaded
		{
			Debug.WriteLine("Hello From Beef DLL :3");
		}

		public static ~this() // <- This will gets called when our library gets unloaded
		{
			Debug.WriteLine("See ya next time my friend :)");
		}
	}
}

So lets compile it and inject it into some process. I am gonna use notepad.
As you can see, when we inject our library into notepad we can see this in DebugView++.

DebugView++ Output: Printed message from static contructor

Our constructor get called and we printed first message. So lets try to unload our library and see what happens. 

DebugView++ Output: Printed message from static decontructor

Looks like our deconstructor gets called.

Note: Our deconstructor also gets called when process, where our library is loaded, gonna exit.

Exporting methods

So what if we want to export some methods from our DLL? Well... Thats a really simple task. Just write your method and throw ExportAttribute on it like this:

[Export]
public static int32 MyAmazingMethod(int32 a, int32 b)
{
    return a + b;
}

This will export your method using Beef style mangling. Ez ... 

Exported method using Beef-style mangling

But what if you want to use your exported method in some app using C-style API? Then you need to add CLinkAttribute. That will export your method using C-style mangling.

[Export, CLink]
public static int32 MyAmazingMethod(int32 a, int32 b)
{
    return a + b;
}
Exported method using C-style mangling

See? It's that easy! 

In case we need C++ mangling we can use LinkNameAttribute. You can use this attribute to specify link name for importing methods from another library or to specify mangling style for exported method. Actually you don't need CLinkAttribute at all. You can use LinkName(.C) instead!

[Export, LinkName(.CPP)]
public static int32 MyAmazingMethod(int32 a, int32 b)
{
    return a + b;
}
Exported method using C++ style mangling

As you can see, calling convention __cdecl is used by default. If you want to change that, you need to use CallingConventionAttribute. For example, this is how we export our method using __stdcall calling convention ...

[Export, LinkName(.CPP), CallingConvention(.Stdcall)]
public static int32 MyAmazingMethod(int32 a, int32 b)
{
    return a + b;
}

Note: That works only when we are targeting x86 platform

How to work with threads

WARNING!  Due to a bug in previous version of Beef, this works only in version 0.42.6 (Nightly 09/02/2020) and newer!

So ... what if we want to use threads? How can we start a thread on DLL loading and how can we terminate thread on DLL unloading? We also need to make sure that the process, where our DLL is loaded, will exit gracefully.

Lets add one thread called myThread and initialize it, so it will run our method called ThreadMethod.

using System.Diagnostics;
using System;
using System.Threading;
namespace DLLResearch
{
	[AlwaysInclude]
	public static class Program
	{
		public static Thread myThread = new Thread(new () => ThreadMethod());

		public static this()
		{
			Debug.WriteLine("Hello From Beef DLL :3");
		}

		public static ~this()
		{
			Debug.WriteLine("See ya next time my friend :)");
		}

		public static void ThreadMethod()
		{
			//...
		}
	}
}

Right now, it will just initialize new thread and nothing else. Let's say that we want our thread periodically print some message. Our ThreadMethod will gonna look like this:

public static void ThreadMethod()
{
    Debug.WriteLine("ThreadMethod started.");
    var i = 0; 
    while(true)
    {
        Debug.WriteLine("Hello from Beef DLL. Counter: {}", i++);
        Thread.Sleep(500); // Wait 500 ms
    }
    Debug.WriteLine("ThreadMethod ended.");
}

But this code has one big problem. In this case, our DLL will not be unloaded from a process, because ThreadMethod will never end! We need some form of signalization that will notify our thread that we want to exit. How we are gonna do that? Simply declare new static boolean called exit. And replace while(true) with while(!exit). That's it!

Last thing we need to do is start myThread inside contructor and terminate it in decontructor:

using System.Diagnostics;
using System;
using System.Threading;
namespace DLLResearch
{
	[AlwaysInclude] // <- We need this to include our class
	public static class Program
	{
		public static Thread myThread = new Thread(new () => ThreadMethod());
		public static bool exit = false;

		// This will gets called when our library gets loaded
		public static this() 
		{
			myThread.Start(); // <- Start our thread
			Debug.WriteLine("Hello From Beef DLL :3");
		}

		// This will gets called when our library gets unloaded
		public static ~this() 
		{
			exit = true; // Notify we want to exit
			myThread.Join(500); // Wait max 500 ms for thread to finish
			
			Debug.WriteLine("See ya next time my friend :)");
		}

		public static void ThreadMethod()
		{
			Debug.WriteLine("ThreadMethod started.");
			var i = 0; 
			while(!exit)
			{
				Debug.WriteLine("Hello from Beef DLL. Counter: {}", i++);
				Thread.Sleep(500); // Wait 500 ms
			}
			Debug.WriteLine("ThreadMethod ended.");
		}
	}
}

Compile it and inject your DLL into some process (notepad in my case) and after some time unload it.

DebugView++ Output: Output from DLL

And it works! Working on DLL using Beef is fun and really simple. Next time i am gonna try to create simple plugin system for DLLs made in Beef. 

This article was updated on September 3, 2020

Admin

I am a developer and i am in love with C/C#/Beef. I am focused on developing apps for Desktop (UI/CLI) and developing firmware for MCUs using ARM CPU from STM32 and Espressif. I am currently trying to master reverse engineering etc.

Comments