Jump to content
Moopler Closing Read more... ×
Sign in to follow this  

.NET How to make a trainer in .NET (VB or C#, using C++), Part 1

Recommended Posts

This tutorial will show you the basics of making a trainer in .NET.
The reason we will also require C++ is to create a loader for the trainer.
It’s also possible to use the Unmanaged Exports library by Robert Giesecke, but this requires a DLL injector capable of calling a function inside the process, beside that it’s also quite tricky to keep the build settings correct, plainly said, it’s not made for the purpose of making inject-able DLL’s.

Credits are appreciated, but are not mandatory


It’s also possible to use other .NET languages but this tutorial will only cover C# and VB.

  • Visual Studio. (this tutorial is written based on 2012, so it might differ)
  • Basic knowledge of C# or VB.
  • Basic knowledge of how hacks work.


Step 1, making the C++ loader
The first thing we will do is to create a basic DLL in C++ which will load our .NET DLL.
This is done quite easily, in Visual Studio on the toolbar (left top) you go File -> New -> Project (or ctrl+shift+n), then under Visual C++ you select a Win32 project, you can rename “Win32Project1” to whatever you want (this will be the name of you DLL).

After pressing “OK” it will ask you to set the “Application Settings”, in this case check DLL and “Empty Project” and press “Finish”.
You should now see something similar to this under "Solution Explorer":

Where “NetLoader” will be the name you gave your project.
The next thing you should do is right click the folder called “Source Files” -> Add -> New Item and add a new C++ File (.cpp) named MainDLL.
Now you should see an empty file, in there you paste the following code.

  1. #include <windows.h>
  2. #pragma once
  3. using namespace System::Windows::Forms;
  4. using namespace NetBot; //Replace "NetBot" with the name of your .NET project
  6. DWORD WINAPI Start ( LPVOID lpParam )
  7. {
  8.     Application::EnableVisualStyles();
  9.     Application::SetCompatibleTextRenderingDefault(false);
  10.     Application::Run(gcnew NetBot::MainForm); //Replace "NetBot" with the name of your .NET project
  11.     Application::Exit();
  12.     return 0;
  13. }
  15. #pragma unmanaged
  16. BOOL WINAPI DllMain ( __in ::HMODULE hModule, __in ::DWORD dwReason, __in __reserved ::LPVOID lpvReserved )
  17. {
  18.     ::HANDLE hThread = NULL;
  20.     if ( dwReason == DLL_PROCESS_ATTACH )
  21.     {
  22.         if (( hThread = ::CreateThread(NULL0&Start, hModule, 0NULL) ) == NULL )
  23.         {
  24.             return FALSE;
  25.         }
  26.         if ( ::CloseHandle(hThread) == FALSE ) { }
  27.     }
  28.     return TRUE;
  29. }

This code will contain some errors as the project is not using the .NET framework yet, so the next thing we will do is enabling this.
In the solution explorer you will need to right click you project and select "Properties", in the left top you will see "Configuration", select "All Configuration".
On your right you should see a bunch of settings, one of them is "Common Language Runtime Support" which is set to "No Common Language Runtime Support", this should be set to "Common Language Runtime Support (/clr)".

By default the target framework will be set to 4.0, which it quite wierd as the latest version is 4.5
The best thing for us would be to manually set the framework to 4.5, which is slightly tricky but will prevent errors later on (this can be skipped if you use 4.0 instead of 4.5 on your .NET project).
In your solution explorer right click your project and select "Unload Project" now it should be grayed out and you right click it again and select "Edit *.vcxproj", now you will see a XML which is the base of your project.


<PropertyGroup Label="Globals">






    <Reference Include="System" />
    <Reference Include="System.Data" />
    <Reference Include="System.Drawing" />
    <Reference Include="System.Windows.Forms" />
    <Reference Include="System.Xml" />

Now right click your project again and select "Reload Project".

There should be still 3 errors left because it cannot find "NetBot", this will be replaced with your .NET project name later on.


Step 2, making the .NET project

Now we will create the .NET project which will be the base of your trainer, like I have mentioned before this can be any language you prefer though I will only handle C# and VB.In your solution explorer right click your Solution, thus not your project, and go Add -> New Project then select a "Class Library" in the language you prefer.In my case I named it "NetBot", assuming you will name this differently you will need to change "NetBot" inside MainDLL.cpp to whatever you name this project. (This also creates a Class1.vb or .cs, you can remove that)

After you created the .NET project we will go back to the properties of our C++ project (Right click -> Properties) now in the navigation on the left we will go to "Common Properties" and press the button "Add Reference" a window will pop up and you will be able to select your .NET project under "Solution", it should look like this.


Now select your project and press "OK".

There should still be some errors left as we did not add a form to our .NET project yet, so that is what we will do next.Right click you .NET project -> Add -> Windows Form and name it "MainForm". (note if you choice a different name you will have to change the name in MainDLL.cpp)Now if you try to build you solution the should be no errors left, if there are, please make a post on this thread.You should also be able to inject the loader into any executable now, though you will have to place both DLLs inside the executable folder.


Step 3, Adding simple hacks

What is a trainer without hacks? you are right, nothing.Though the thing most people do not know is that hacks are just simple changing a few bytes in the memory.

To keep this thread a little bit inside the MapleStory tracks I will use the following hack as example.

//Long Blink Godmode
00EA21EA: //7E ? 8B ? E8 ? ? ? ? 8B ? 83 [1st Result]
db EB 09
00EA2253: //Address of 2nd SUB below
db 83 CE 90

db 7E 21
db 83 EF 1E

The first thing we will do is create a new class named "Hacks", right click Project -> Add -> Class.And then change the code to this, (note: in C# only replace the code of "class Hacks")


  • internal static class Hacks
  • {
  •     internal static void BlinkGodMode(bool enable)
  •     {
  •     }
  • }


  1. Friend NotInheritable Class Hacks
  2.     Friend Shared Sub BlinkGodMode(enable As Boolean)
  3.     End Sub
  4. End Class

Using this code we can call the function from everywhere inside the .NET project, e.g.


  1. Hacks.BlinkGodMode(true); //Enables the hack
  2. Hacks.BlinkGodMode(false); //Disables the hack


  1. Hacks.BlinkGodMode(True) 'Enables the hack
  2. Hacks.BlinkGodMode(False) 'Disables the hack

But as its still an empty function it will not active anything, thus we need something to write to the memory, the .NET framework has default support for writing into a program its memory, which is good as we basically will inject our project inside the application causing it to share its memory.
But as an unsafe context is quite complicated (and does not appear to exist in VB) we will use the Marshal class instead, which basically is a class containing the unsafe functionality we want to use to write into the memory and its also quite easy to use.
To use the Marshal class we must first add a reference to it inside our Hacks class, which can be done as following;


  1. using System.Runtime.InteropServices;


  1. Imports System.Runtime.InteropServices

Which needs to be added on the first line of the class (file)

As you can see the "Long Blink Godmode" is a very simple hack which changes a total of 5 bytes on 2 addresses.
So the thing we should do first is declaring the addresses (pointers) in our code, we will use the IntPtr class for this and it can be used like this;


  1. IntPtr Address1 = new IntPtr(0x00EA21EA);
  2. IntPtr Address2 = new IntPtr(0x00EA2253);


  1. Dim Address1 As IntPtr = New IntPtr(&HEA21EA)
  2. Dim Address2 As IntPtr = New IntPtr(&HEA2253)

After that we need a simple if statement for enabling and disabling the hack, here I will just assume everybody knows how to write one using "enable".
So the next thing todo is declaring the bytes to write which enable the hack or disable the hack, if we look back the the "Long Blink Godmode" script we see the enable bytes are "EB 09" and "83 CE 90" and the disable bytes are "7E 21" and "83 EF 1E".
To write these bytes to the memory we will use the Marshal.Copy() function, the finished code should look similar to this;


  1. internal static void BlinkGodMode(bool enable)
  2. {
  3.     IntPtr Address1 = new IntPtr(0x00EA21EA);
  4.     IntPtr Address2 = new IntPtr(0x00EA2253);
  5.     if (enable)
  6.     {
  7.         byte[] Bytes1 = new byte[] { 0xEB, 0x09 };
  8.         byte[] Bytes2 = new byte[] { 0x83, 0xCE, 0x90 };
  9.         Marshal.Copy(Bytes1, 0, Address1, Bytes1.Length);
  10.         Marshal.Copy(Bytes2, 0, Address2, Bytes2.Length);
  11.     }
  12.     else
  13.     {
  14.         byte[] Bytes1 = new byte[] { 0x7E, 0x21 };
  15.         byte[] Bytes2 = new byte[] { 0x83, 0xEF, 0x1E };
  16.         Marshal.Copy(Bytes1, 0, Address1, Bytes1.Length);
  17.         Marshal.Copy(Bytes2, 0, Address2, Bytes2.Length);
  18.     }
  19. }


  1. Friend Shared Sub BlinkGodMode(enable As Boolean)
  2.     Dim Address1 As IntPtr = New IntPtr(&HEA21EA)
  3.     Dim Address2 As IntPtr = New IntPtr(&HEA2253)
  4.     If enable Then
  5.         Dim Bytes1 As Byte() = New Byte() {&HEB, &H9}
  6.         Dim Bytes2 As Byte() = New Byte() {&H83, &HCE, &H90}
  7.         Marshal.Copy(Bytes1, 0, Address1, Bytes1.Length)
  8.         Marshal.Copy(Bytes2, 0, Address2, Bytes2.Length)
  9.     Else
  10.         Dim Bytes1 As Byte() = New Byte() {&H7E, &H21}
  11.         Dim Bytes2 As Byte() = New Byte() {&H83, &HEF, &H1E}
  12.         Marshal.Copy(Bytes1, 0, Address1, Bytes1.Length)
  13.         Marshal.Copy(Bytes2, 0, Address2, Bytes2.Length)
  14.     End If
  15. End Sub

And this is the end of the tutorial, I hope you enjoyed it.
Part 2 about using codecaves is coming soon.

Edited by Yaminike
  • Like 9

Share this post

Link to post

i managed to inject the DLL using UnmagaedExports and everything was great until i started to copy the value to the address,

i got the following exception.


Share this post

Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this