Injector4k is a DLL injector for Kotlin/Native applications, built with Kotlin/Native.
"Hold up, why do we need yet another DLL injector? There are so many of them!" - you might say, and you'd be right. See not your average injector for an explanation.
Note
Currently, Injector4k only works with 32-bit (x86) Windows programs, but you can run it on 64-bit Windows just fine.
It can be used for messing around with the original versions of retro games from circa 2005, like
Grand Theft Auto: San Andreas
orWorld of Warcraft: The Burning Crusade
, as most of them have 32-bit executables.
Below you will find everything you need to know to get you started with Kotlin DLL injections.
You should begin with acquiring or producing a compatible Kotlin/Native DLL.
If you already have one, you can skip to GUI or Library sections.
If you would like to take Injector4k for a spin first, you can download an example DLL from the Releases page. Once
the example DLL is injected, it will sleep for 10 seconds, and then create a harmless "Hello World" pop-up window -
similar to JavaScript's alert()
. You can find the source code
here.
If you would like to produce your own .dll
, you can use dll-example as a starting point, or follow
the Kotlin/Native as a dynamic library tutorial on
kotlinlang.org.
The most important part is to export your entry-point function with @CName
:
@CName("kotlinDllMain")
fun kotlinDllMain() {
// logic
}
Beware that the bitness of the DLL you produce must be the same as the program you want to inject it into. So if you
want to inject some code into a 32-bit game, like GTA: SA, you will have to use the mingwX86
target.
Injector4k comes with a basic graphical user interface for injecting arbitrary DLLs:
You can download the latest version from the Releases page.
Note
Depending on the program you're going to be injecting into, you should choose between
x86
andx64
versions of injector4k. Selecting the wrong version will not damage your computer, but it will fail with obscure errors during the injection.
Injector4k can also be embedded into your own program:
import me.beresnev.injector.Injector
import me.beresnev.injector.logger.PrintlnLogger
Injector(injectorLogger = PrintlnLogger).inject(
executablePath = "D:\\GTASA\\GTA_SA.EXE",
dllPath = "C:\\Users\\Cargeh\\Desktop\\kotlin_dll_x86.dll",
mainFunctionName = "kotlinDllMain",
)
Note
Injector4k artifacts haven't been published yet, but they will be available by April 30th.
Some tips and tricks to ease the development of your DLLs:
- When in doubt, google for C++ solutions, and adapt them to Kotlin. The Windows API mapping that comes built-in with Kotlin/Native is pretty much one to one, so it should not be difficult.
- When not sure how to call some Windows API from Kotlin/Native, use GitHub Advanced Search. Odds are, someone has already done it.
- Once your DLL is injected into a process, first thing you'll notice is the absence of feedback - you will not know
what it's doing and if it's even being executed, or if it failed with an error. The DLL can, of course, spin up a
GUI of its own, or write logs to a common file, but you can simply use the
OutputDebugStringW
win-api function for println debugging. You will be able to see the messages you output in your DLL in the
DebugView utility application. Write strings
with a prefix like
[MyDll]
to filter out the noise from other programs. - Many popular games have been reverse engineered, so most likely there's a forum or a wiki out there that contains various memory and function addresses, as well as more specific instructions. To find simple value addresses, use Cheat Engine. To do serious reverse engineering, use IDA.
Unfortunately, most traditional DLL injectors rely on the injected DLL implementing a special
DllMain function, which you cannot produce with
Kotlin/Native as it does not support adding the required WINAPI
(__stdcall
) calling convention.
You can write an intermediate DLL wrapper in C++: you first inject the wrapper, and then the wrapper calls your Kotlin/Native code - it'll work. But who wants to be dealing with C++ when you don't have to?
Thankfully, you can use Injector4k to perform an organic, 100% pure, Kotlin DLL injection, all the way from the injector to the injected code.
Currently, Injector4k is in public Beta - it works, but with some limitations and inconveniences.
Here's what needs to be done for the 1.0 Stable release:
- Support 64-bit Windows programs.
- Publish the injector as a library.
- Add more documentation and technical details for both the problem and the solution.
- Create a GitHub template for starting out with writing DLLs.
- Add GitHub action workflows.