Category Archives: Helpful Tips

Installing Mono on CentOS 6.x

Since yum does not include a default mono package / repo, installing it has become a fairly annoying task.

Here are some steps to get Mono installed on CentOS 6.x (I am using 6.5 as of this post):

  • Create a new repo entry under /etc/yum.repos.d/ named mono.repo
  • Enter the below into the file with your favorite editor:

[home_tpokorra_mono]
name=mono and monodevelop (CentOS_CentOS-6)
type=rpm-md
baseurl=http://download.opensuse.org/repositories/home:/tpokorra:/mono/CentOS_CentOS-6/
gpgcheck=1
gpgkey=http://download.opensuse.org/repositories/home:/tpokorra:/mono/CentOS_CentOS-6/repodata/repomd.xml.key
enabled=1

  • Next install all of the mono packages needed via: yum install mono*-opt
  • (Optional) In some cases you will need to register the format yourself, use the following to do so:

‘:CLR:M::MZ::/usr/local/bin/mono:’ > /proc/sys/fs/binfmt_misc/register

  • Next to always have mono in the path variable we can add it to .bashrc
    • To do this, open ~/.bashrc in your favorite editor and add the following line to it:

export PATH=/opt/mono/bin:$PATH

  • Lastly you can either restart the machine to make the path take effect, or you can execute the following to do it:

export PATH=/opt/mono/bin:$PATH

  • Done! Mono should now be working 🙂
  • You can use mono –version to output the version information.

Thanks to my friend devnull for piecing together these parts in helping me get Mono working. 🙂

Misc Tutorials I’ve Recently Written

Here are some various articles/tutorials I’ve written in the past ~2 years:

C# Loader Hooking With Mono.Cecil
Click Here!

Terraria 1.1.2 – Decompiling / Recompiling
Click Here!

Creating Packet Editor / Proxy In C#
Click Here!

TSGE – Terraria Save Game Editor
Click Here!

Terraria 1.1.2 – Dumping Data and Textures
Click Here!

Terraria 1.1.2 – Collector Edition Bunny
Click Here!

XNA Hooking Through Reflection / Reference
Click Here!

ISS Maintenance Mode Easily With URL Rewrite

I needed to take down one of my sites a bit ago and was looking for a method to keep it up, just not to the outside world. Sadly, all the methods I found where based around using ASP.NET’s trick with the known app_offline.htm page. In my situation, this didn’t help since I’m not using any web app on my site.

The few rewrite rules I found were also a bit overkill and didn’t really fit my needs.
I didn’t want to make a custom page, didn’t want to make another website to fake the page, etc.
So tinkering with a custom rule condition I was able to get what I wanted done.

Here is how I can locally still access the website, while all remote requests are rejected:

In IIS Manager choose your desired site to put into maintenance mode.

  • Choose URL Rewrite from the modules list for the site. (Be sure to set this on the base dir of the site to block all requests for the entire site.)
  • Add a new rule by right-clicking on the inbound rules.
  • Choose ‘Request Blocking’ from the selection of choices.
  • On the rule properties popup, fill out as follows:
    • Block access based on: URL Path
    • Block request that: Matches the Pattern
    • Pattern (URL Path): *
    • Using: Wildcards
    • How to block: Send an HTTP 403 Response
  • Next, click ok to add the rule.
  • Double-click the newly added rule to open the Edit Inbound Rule panel for the specific rule.
  • Under conditions, click add.
  • Fill out the condition properties as follow:
    • Condition input: {REMOTE_HOST}
    • Check if input string: Does Not Match the Pattern
    • Pattern: ::1
    • Ignore case: true
  • Click ok and you’re all set.

The site should now be blocked from remote requests that are not from the remote host ‘::1’ which according to the logs is used when the local server attempts to request pages from itself.

Hope this helps someone else with a similar issue. 🙂

Visual Studio 2012 – Windows XP Targeting

Warning:

The information in this post is not recommended to be followed!
This is simply an observation I made a while ago when debugging a user problem for a project I work on called Ashita.

This issue is no longer a problem with Visual Studio 2012 Update 1!

The Problem

After upgrading Ashita to Visual Studio 2012, we had noticed that some users were complaining that our application no longer worked on their system. This resulted in me investigating and finding out the issue was only happening to users on Windows XP. I tossed Windows XP onto a virtual machine to replicate the issue and sure enough our app would not work on the VM.

Further investigation proved that Visual Studio 2012 (stock) did not support Windows XP machines. After many complaints to Microsoft from developers, though, Microsoft released Update 1 to VS2012 which included the toolset option to target Windows XP machines when compiling. (Read here: http://blogs.msdn.com/b/vcblog/archive/2012/10/08/10357555.aspx)

However at the time of this issue, we did not have access to Update 1 yet so finding a work-around was needed. Upon attempting to load our application, I would get the following error:
“Ashita Boot.exe is not a valid Win32 application.”

Knowing that the application works fine on all other versions of Windows after WinXP we knew this was a fluke of an error that had no real merit. I compared the files of a VS2010 compile and VS2012 compile and noticed, mainly, that in the file header there were two main things that peeked my interest:
– MajorOperatingSystemVersion
– MajorSubsystemVersion

While compiling in Visual Studio 2012, these are set to the value 0x06
While compiling in Visual Studio 2010, these are set to the value 0x04

So the first step was to set these to 0x04 in the newer binary. Afterward I was greeted with another error saying that an import was not found for ‘GetTickCount64’. Given that the Windows XP machine does not have this API, I had to also edit the import table to target ‘GetTickCount’ instead of the 64bit version.

Afterward this fixed our application and made it work for those users temporarily.

Tool I used to apply the file fixes: (CFF Explorer)
http://www.ntcore.com/exsuite.php

Native CLR Hosting (With separate AppDomains per-module.)

Notice: All error handling / checking has been stripped from the code to make things as basic and easy to understand. Majority of the calls made in the below code are to COM objects which use HRESULT returns. Always check your returns before continuing to help prevent crashes!

One of the biggest, I consider, issues with .NET and plugins is that you can’t truly unload a managed module without fully shutting down the application domain it is ran within. Things linger in memory and the garbage collection only does so much. In C/C++ the simple FreeLibrary handles this but we don’t have that luxury in C#. Instead, the easiest way to truly get unloading plugins is by loading each one into it’s own AppDomain.

Doing this with the use of ‘mixed’ code is simple and documented, however doing this in pure native C++ is not. It involves working with the COM interfaces of the CLR and such which does not have much documentation, and after a certain pointer, there is none. There also is a lack of examples showing how to do it online / open source. For someone like me, I personally enjoy both .NET (C#) and C/C++, however, I enjoy them being separate. I do not like VC++, the look and feel of the code is just wrong to me. I do not use it, and do not plan to use it. (This is my opinion, I’m sure yours will differ, that’s not the point of this post.)

Anyway, getting into the code. To start, this article will be based around how I implemented things, and what for. So a little back story. I work on a project that is an injected hook into a popular MMORPG. The purpose of this hook is to extend the ability of the game to make it better enjoyable to play. The focus is not cheating related, but the project does not limit what the users can do with the plugin interface that is exposed. The project is fully coded in C++ and the extension SDK exposes a collection of interfaces that the users can use to interact with the core hook. This is done by the hook loading plugins and passing a core object pointer to them which is casted to the core interface object.

With this I created an extension for our hook called ‘Bootstrap’. The purpose of this extension is to load the CLR into the process as well as creating new appdomains for each C# extension that it loads. I wanted to ensure that these plugins can be fully unloaded during runtime because being an MMO, the game does take up it’s own amount of resources and such. Keeping things clean and limited help out a lot.

So we have:

Hook <- -> Bootstrap Extension <- -> Managed Extension(s)

When Bootstrap first starts, we want to ensure we load the CLR runtime first and immediately.
I do that with the following little bit of code:

// Bind to the given runtime..
ICorRuntimeHost* lpRuntimeHost = NULL;
CorBindToRuntimeEx( L"v4.0.30319", L"wks", 0, CLSID_CorRuntimeHost, IID_PPV_ARGS( &lpRuntimeHost ) );

// Attempt to start the runtime..
lpRuntimeHost->Start();

Next, when a managed plugin is requested to start, Bootstrap will do some minor checking to ensure the file exists and such. Once it ensures the plugins not already loaded and it exists on disk, it will attempt to load it.

The next step is to load this plugin into its own AppDomain. For starters, I wrote a simple wrapper to hold the important interfaces that this plugin created when being loaded like this:

struct managedplugin_t
{
    std::wstring                m_PluginName;
    std::wstring                m_PluginPath;

    CComPtr<IUnknown>           m_AppDomainSetupUnknown;
    CComQIPtr<IAppDomainSetup>  m_AppDomainSetup;

    CComPtr<IUnknown>           m_AppDomainUnknown;
    CComPtr<_AppDomain>         m_AppDomain;

    CComPtr<_Assembly>          m_AppAssembly;
    CComVariant                 m_AppVariant;
    
    CComPtr<IAshitaExtension>   m_AppInstance;

    bool                        m_IsDirect3DReady;

    managedplugin_t()
    {
        this->m_PluginName              = L"";
        this->m_PluginPath              = L"";
        this->m_AppDomainSetupUnknown   = NULL;
        this->m_AppDomainUnknown        = NULL;
        this->m_AppDomain               = NULL;
        this->m_AppAssembly             = NULL;
        this->m_AppVariant              = NULL;
        this->m_AppInstance             = NULL;
        this->m_IsDirect3DReady         = false;
    }
};

Next, the first step is to create a new AppDomain. We want to create a DomainSetup object first to set some properties for the domain, such as where it will resolve its assemblies from and such. Afterward we create the domain with this new setup information:

// Create a new AppDomain setup object for the new domain..
this->m_RuntimeHost->CreateDomainSetup( &plugin->m_AppDomainSetupUnknown );

// Fill some basic structure info about this domain..
plugin->m_AppDomainSetup = plugin->m_AppDomainSetupUnknown;
plugin->m_AppDomainSetup->put_ApplicationBase( CComBSTR( this->m_PluginBasePath.c_str() ) );
plugin->m_AppDomainSetup->put_ShadowCopyFiles( CComBSTR( "true" ) );
plugin->m_AppDomainSetup->put_ApplicationName( CComBSTR( pluginName.c_str() ) );

// Create the new AppDomain..
this->m_RuntimeHost->CreateDomainEx( pluginName.c_str(), plugin->m_AppDomainSetupUnknown, NULL, &plugin->m_AppDomainUnknown );

// Obtain the actual AppDomain object..
plugin->m_AppDomainUnknown->QueryInterface( __uuidof( mscorlib::_AppDomain ), (void**)&plugin->m_AppDomain );

Now we want to load the plugin file into this AppDomain. My method was to have users create their plugins a specific way. Each plugin is loaded by its name, and then it must use a public class named ‘Main’ that inherits my C# implementation of our IAshitaExtension base class. This way I can forward all the C++ plugin calls to the C# plugins. So we load the plugin now like this:

// Load the plugin module into the AppDomain..
plugin->m_AppDomain->Load_2( CComBSTR( mainInterface.c_str() ), &plugin->m_AppAssembly );

// Create instaoce of the 'Main' class object..
plugin->m_AppAssembly->CreateInstance_2( CComBSTR( mainInterface.append( L".Main" ).c_str() ), true, &plugin->m_AppVariant );

// Obtain instance of our base class from this newly created instance..
plugin->m_AppVariant.punkVal->QueryInterface( __uuidof( IAshitaExtension ), (void**)&plugin->m_AppInstance );

One major thing to note here. For some reason CreateInstance_2 does not return properly. If it fails to create an instance of the given object, it will still return S_OK. You need to check the VARIANT object it returns and ensure it is valid. You can do this by checking it like:

if (plugin->m_AppVariant.vt == VT_EMPTY || plugin->m_AppVariant.vt == VT_ERROR)
{
    /** Object is invalid.. **/
}

Next is understanding the relationship between C++ and C# in our extensions. As I said above, the C# extensions inherit a managed base class, which looks like this:

namespace ManagedExample
{
    public class Main : AshitaBase
    {
        public override bool Load(IntPtr ashitaCore)
        {
        }
    }
}

The way this works is that AshitaBase is actually an abstract class.
This class inherits a base COM exposed interface, which in turn these look like this:

[ComVisible(true)]
[Guid("7805E68A-A028-433C-BB73-38D34D7208C5")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IAshitaExtension
{
    [ComVisible(true)]
    [return: MarshalAs(UnmanagedType.I1)]
    bool Load(IntPtr ashitaCore);
}

public abstract class AshitaBase : IAshitaExtension
{
        public virtual bool Load(IntPtr ashitaCore)
        {
            return false;
        }
}

I had to use a COM exposed interface like this in order to be able to call things easily on the C++ side. With it setup like this, and with the above C++ code, we can now tell the C# plugin we loaded to call it’s Load function like this:

bool bReturn = false;
plugin->m_AppInstance->Load( (long)this->m_AshitaCore, (unsigned char*)&bReturn );

And there we have it, CLR hosting in pure native C++ 🙂

There are some things with this that I am still trying to figure out, such as adding an UnhandledException handler to each AppDomain but I am unsure how to properly call the m_AppDomain->add_UnhandledException function at this time.

Feel free to leave comments, suggestions, etc. Hope this helps someone in the future.

Some minor things I forgot to mention, here are the includes and other definitions needed for this stuff:

#pragma comment( lib, "mscoree.lib" )
#include <mscoree.h>

#include <atlbase.h>
#include <atlsafe.h>
#include <metahost.h>

#import "mscorlib.tlb" raw_interfaces_only

// Import of my managed base class information..
#import "../../build/Extensions/Managed/AshitaAPI.tlb" no_namespace named_guids raw_interfaces_only