MDK 2 [Engine:Omen]

Upload your cheat tables here (No requests)
Post Reply
User avatar
SunBeam
Administration
Administration
Posts: 4703
Joined: Sun Feb 04, 2018 7:16 pm
Reputation: 4287

MDK 2 [Engine:Omen]

Post by SunBeam »

[ 10 Sep 21 - First Release ]

Image

Game Name: MDK 2
Game Vendor: GOG
Game Process: mdk2Main.exe
Game Version: 1.003
Game File Size: 768 KB


[ Context ]


Hello, folks. I've recently started looking at old games from my childhood, simply because at the time I was just enjoying playing them rather than checking out what's "under the hood". So I've had a nice time digging up/out whatever the internet apparently either doesn't have anymore or it never had. Doing searches for cheats, trainers, etc. for these games will return very little to no results, I guess mostly because no one gives a rat's ass about them anymore. Well, not everyone :) That being said, let's proceed.


[ Cheats ]


Scouring the Internet for some references I found several cheats being listed out [Link].

Then I wanted to learn a bit where these came from, how they're stored in the game's data, are they strings [?], are they some functions [?] Then I noticed in the actual game disclaimer there's mentioning of the word "Lua" :)

Image

The cheats mentioned 2 paragraphs above are to be typed into a console which you can open via the Tilde (`~) key:

Image

Several considerations:
  • If the key doesn't work for you and you're on some non-QWERTY keyboard, then please follow this and add EN ad you secondary keyboard language: [Link]. You can then use Alt + Shift key combination to switch between keyboard languages back and forth.
  • You will notice YOU CANNOT PASTE text in the console. Which is very annoying. This led to what follows.
  • I believe the console can only process 1-liner commands. Since you cannot paste more text, I doubt anyone would want to write a Lua function from start to end with no 'new line' rows. I have not tried this, as it wouldn't make sense. Why am I mentioning Lua functions you will discover a bit later :)

[ Background ]


That being said.. and learning that the game's Engine is called Omen and it's a LUA Engine, I was curious to know WHICH Lua version were they using. The game was developed in 2000, so Lua wasn't that very far ahead. I then looked up the referenced strings in the binary and found out there's a "Lua 3.1" reference :) So boom, there we go.

Then I said to myself: "I wanna find the source code for Lua 3.1 and/or DLL binaries built with the SAME Visual Studio C++ version the game uses (VC++ 8)". Old shit again, right? Chances of me finding stuff like that were very slim. Well.. I did find the source code for Lua 3.1 at [Link]. Note that it's a .tar.gz containing a .tar. So you'll have to double-extract it (I will also attach it to this page at the bottom, so we keep back-ups). From that I was only interested in the src folder, seeing there's nothing to be used in the bin folder. You'll learn in a bit why the source code was SUPER useful :)

Then.. "alright, I have the source code.. but I also want to find a binary.. if possible, one built with same VC++ 8 as the game's". I couldn't find a 3.1, but I did find a 3.2 at [Link], built with VC++ 7 though. Useful, in absence of anything else. Also linking it at the bottom.

Lastly, "cool, I have these, but since we're talking about Lua, isn't the game supposed to be running some Lua scripts? where are these?". I then saw there are a bunch of ZIP files in the game's folder, then \MDK 2\data\ path:

Image

So I tried to extract them, only to learn BioWare used some proprietary compression (PKImploding). But hey, at least there's a tool that can extract them - PKZIP - which I could download from [Link]. More information on the subject can be read at this location: [Link] (you will notice I will be referencing this forum several times more).

PKZIP helped me unpack what I was interested in and found quite a bunch of nice .lua scripts in those ZIPs (you can see the folders extracted in the screenshot above). The scripts helped me understand a bit how the game's Engine works, as well as this topic: [Link]. So I want to take a quick stop and thank that dude there -- Egor305 -- for all the nice and juicy information he's pulled out from the game back in 2014.

With all of the above in mind I was able to map 80% of the Lua functions in the game's binary (using both the source code and the 3.2 DLL to guide myself by; how: by searching for string references from the mdk2Main.exe into the source code and the 3.2 DLL's referenced strings; nothing magic about it, just plain logic). So this is how my executable looks like now:

Image

Like in the MDK topic on this forum, you will find the .dd32 database at the bottom, so you can inspect and use it to your heart's content.


[ Running Lua Scripts ]


As per the topic I mentioned above - [Link] - there is mentioning of a Lua function which, if ran in the game's Lua context, could allow the user to SPAWN various objects. The code, transcribed, looks like this:

Code: Select all

function make(type)
b=mdkGetPlayerGob()
g=mdkCreateObjectLua("",type,scene)
QuatYDir(g.position,b.orientation)
VectorMul(g.position,6)
VectorAdd(g.position,b.position)
end
On the same forum page, a bit down, you also get an explanation of how the function works (lines are commented).

So.. how the hell do we run this, considering we can't PASTE an entire block of text in the existing console? The answer came through studying a bit how the game loads up its .lua files and executes them. And that happens here:

Image

The function is called "dofile" internally, but you can see it's a C wrapper calls-in Lua functions. Reading through [Link], I understand that it's good practice to wrap the Lua calls with a lua_beginblock/lua_endblock pair:

Image

Then we have the main exec, so to speak, in the form of lua_dobuffer, doing this:

Image

Hey, a lot of information in the documentation that helps connect the dots. Don't you think? :P


[ Cheat Table ]


With that in mind and with some guidance/tips from my good ol' pal Zanzer -- thanks, by the way! -- I was able to design this CE UDF:

Image

Download:

mdk2Main.CT
(10.94 KiB) Downloaded 106 times

Open CE, target mdk2Main.exe, then open the table. When asked if you want to run the Lua code, click YES. To open the UDF head to Table menu in main CE GUI, then UDF1, then Restore and show. Make sure to drag it outside CE's main window - left or right - as it will get placed behind the main CE GUI when you alt-tab to another process.

The code behind it does the following:

Code: Select all

COMMAND_COUNT = 0

function UDF1_InputKeyUp(sender, key)
  if isKeyPressed(VK_SHIFT) then
    if key == VK_RETURN then
      local text = sender.Lines.Text
      if text and #text > 0 then
        text = trim(text)
        UDF1.Log.Append('* ' .. string.format( "%03X", COMMAND_COUNT ) .. ' *\r\n')
        UDF1.Log.Append(text .. '\r\n')
        --text = text:gsub( "\r\n", "\n" )
        writeString( getAddressSafe( "_buff" ), text )
        writeBytes( getAddressSafe( "_buff" ) + #text, 0 )
        writeInteger( getAddressSafe( "_size" ), #text )
        executeCodeEx( 0, nil, getAddressSafe( "_exec" ) )
        sender.Lines.Text = nil
        COMMAND_COUNT = COMMAND_COUNT + 1
      end
    end
  end
  return key
end

function UDF1_ClearClick(sender)
  strings_clear(memo_getLines(UDF1_Log))
  COMMAND_COUNT = 0
end

function trim(s)
  return s:find'^%s*$' and '' or s:match'^%s*(.*%S)'
end

local gameModule = getAddressSafe( process )
local offset = 0x500
local _name = gameModule + offset + 0x00
unregisterSymbol( "_name" )
registerSymbol( "_name", _name, true )
writeString( _name, 'script' )
writeBytes( _name + 0x6, 0, 0 )
local _size = gameModule + offset + 0x08
unregisterSymbol( "_size" )
registerSymbol( "_size", _size, true )
local _exec = gameModule + offset + 0x10
fullAccess( _exec, 0x1000 - offset )
unregisterSymbol( "_exec" )
registerSymbol( "_exec", _exec, true )
local _buff = gameModule + offset + 0x40
unregisterSymbol( "_buff" )
registerSymbol( "_buff", _buff, true )

local lua_beginblock = gameModule + 0x43F50
unregisterSymbol( "_lua_beginblock" )
registerSymbol( "_lua_beginblock", lua_beginblock, true )
local lua_dobuffer = gameModule + 0x46100
unregisterSymbol( "_lua_dobuffer" )
registerSymbol( "_lua_dobuffer", lua_dobuffer, true )
local lua_endblock = gameModule + 0x43FA0
unregisterSymbol( "_lua_endblock" )
registerSymbol( "_lua_endblock", lua_endblock, true )

local _wrapper = [[

  _exec:
  push ebp
  mov ebp,esp
  call _lua_beginblock
  push _name
  push [_size]
  push _buff
  call _lua_dobuffer
  add esp,C
  call _lua_endblock
  mov esp,ebp
  pop ebp
  ret

]]

result, disableinfo = autoAssemble( _wrapper )
And now the explanation:
  • There are 2 memo boxes and a button
  • Your text goes into the bottom memo, the white one, called Input. It accepts multi-line, hence why we're doing it like this and not through the game's console (where you would have to type everything in 1 line/row).
  • Once you type your stuff and are ready to send it to the game's Lua, you will press Shift+Enter key combination.
  • The function UDF1_InputKeyUp OnKeyUp event handles input coming from the form and when it detects Shift+Enter have been pressed, it does 2 things: outputs the text to the top memo, the purplish one called Log -- AND -- executes your text in the game Lua's context.
  • the Clear button will clean the Log memo and reset an internal variable to 0 (COMMAND_COUNT). This variable is used to keep track of how many commands/functions/scripts you've type in (just a quirk, not that important). The clean-up is done via function UDF1_ClearClick OnClick event.
  • What's being executed in the game's Lua context is done through local _wrapper, which is an assembled piece of code in the PE header of mdk2Main.exe. How it's executed: through executeCodeEx( 0, nil, getAddressSafe( "_exec" ) ) in UDF1_InputKeyUp function.
All you need to know is you type stuff in the Input box, hit Shift+Enter and the Log box is showing you what you've sent to the game's Lua to execute :)

So.. with that in mind, you can now copy this..

Code: Select all

function make(type)
b=mdkGetPlayerGob()
g=mdkCreateObjectLua("",type,scene)
QuatYDir(g.position,b.orientation)
VectorMul(g.position,6)
VectorAdd(g.position,b.position)
end
..paste it in the Input box of that UDF, hit Shift+Enter and you'll see the game lagging for 0.5-1s in the background (if it's running windowed). Then go back in-game, press Tilde (`~) key and now, since you have the make function compiled and registered internally in the game's Lua engine, you can now type in:

Code: Select all

make(num OR string)
And press enter and an object is going to be spawned in front of the player, 6 units away.

The num OR string in the above code wrapper has to be changed to the values listed in this topic: [Link].

For example, if I am playing as Kurt and I want to spawn a Super Chain Gun object, I would hit Tilde (`~) key and type in:

Code: Select all

make(356)
-- OR --

Code: Select all

make(OBJ_SUPERCHAINGUN)
While the string form may work for Kurt and Max, you may notice sometimes it doesn't for Doc. For example, when I tried make(OBJ_BAGETTE), it errored out asking a numerical form for the arg in the function. So I executed make(360) instead and that worked :) I think Egor350 has a typo in that post.

And here's an example of a spawned SUPERCHAINGUNs:

Image

To close the console once hitting Enter, press ESC key. Yes, it will bring up the game menu, but you can hit ESC again to resume the game.


[ Others ]


I've mapped a few things in my executable and below you can download the .dd32 file to be used with x32dbg (it's the x86 debugger that's part of the [Link]). Inside this file you will find a shit ton of comments and labels to assist in your craving to study the game's executable :P

Download:

mdk2Main.exe.dd32.zip
(4.26 KiB) Downloaded 50 times

What to do with it:
  • get x64dbg downloaded and unzip it to a folder of your choice (e.g.: C:\x64dbg\)
  • head to \x32\db folder (e.g.: C:\x64dbg\x32\db\) and place the .dd32 file in the ZIP there
  • open mdk2Main.exe in x32dbg and check the comments/labels
Image

Image

Image

Also attached the mdk2Main.exe for reference/backup/archiving purposes, just in case the GOG.com version updates (doubt it would):

mdk2Main.exe.zip
(326.91 KiB) Downloaded 47 times

As usual, enjoy!

BR,
Sun

P.S.: Next-up -- Giants: Citizen Kabuto.

How to use this cheat table?
  1. Install Cheat Engine
  2. Double-click the .CT file in order to open it.
  3. Click the PC icon in Cheat Engine in order to select the game process.
  4. Keep the list.
  5. Activate the trainer options by checking boxes or setting values from 0 to 1
Attachments
lua-3.2_dll_vc7.zip
(30.28 KiB) Downloaded 47 times
lua-3.1_src.zip
(140.09 KiB) Downloaded 33 times

TMG HK
What is cheating?
What is cheating?
Posts: 1
Joined: Thu Nov 04, 2021 12:35 pm
Reputation: 0

Re: MDK 2 [Engine:Omen]

Post by TMG HK »

Good work! That's was very interesting.

TurboSosiska
What is cheating?
What is cheating?
Posts: 3
Joined: Sat Apr 02, 2022 6:19 pm
Reputation: 0

Re: MDK 2 [Engine:Omen]

Post by TurboSosiska »

Please reply to DM, I have an IDA project for mdk 2 (not full, but all lua functions prefixed with mdk, ch, om are mapped)

User avatar
SunBeam
Administration
Administration
Posts: 4703
Joined: Sun Feb 04, 2018 7:16 pm
Reputation: 4287

Re: MDK 2 [Engine:Omen]

Post by SunBeam »

TurboSosiska wrote:
Tue Apr 05, 2022 12:39 am
Please reply to DM, I have an IDA project for mdk 2 (not full, but all lua functions prefixed with mdk, ch, om are mapped)
Hi there. Have replied. Don't have any interest in studying the game or Engine more than what I've already posted. I considered having exposed quite a lot to let you "mod" and play the game to your liking. I don't see any value in reverse-engineering Omen, unless you plan to make use of its internals for some personal projects. In which case, it's all up to you to get there. Or find another person interested in doing this.

Sorry.

P.S.: Just in case you'd consider this in your next reply: no, I am not interested in doing this even if you proposed payment.

TurboSosiska
What is cheating?
What is cheating?
Posts: 3
Joined: Sat Apr 02, 2022 6:19 pm
Reputation: 0

Re: MDK 2 [Engine:Omen]

Post by TurboSosiska »

SunBeam wrote:
Tue Apr 05, 2022 8:45 am
TurboSosiska wrote:
Tue Apr 05, 2022 12:39 am
Please reply to DM, I have an IDA project for mdk 2 (not full, but all lua functions prefixed with mdk, ch, om are mapped)
Hi there. Have replied. Don't have any interest in studying the game or Engine more than what I've already posted. I considered having exposed quite a lot to let you "mod" and play the game to your liking. I don't see any value in reverse-engineering Omen, unless you plan to make use of its internals for some personal projects. In which case, it's all up to you to get there. Or find another person interested in doing this.

Sorry.

P.S.: Just in case you'd consider this in your next reply: no, I am not interested in doing this even if you proposed payment.
Alright, I understand that, have a good day. The last thing I want to ask you for is an advice on how to try to reverse-engineer Omen in a more efficient way, if you know of course. Maybe some IDA plugins or something like that?

User avatar
SunBeam
Administration
Administration
Posts: 4703
Joined: Sun Feb 04, 2018 7:16 pm
Reputation: 4287

Re: MDK 2 [Engine:Omen]

Post by SunBeam »

There are no plugins that will convert the game to some source-code form that's usable to the point of click-and-compile. You'll have to upgrade your skills, learn reverse-engineering and how the flow of ASM code works. Advice: learn ASM; compile a simple MSVC program, with debug symbols, then open that program of yours in a debugger (like x64dbg) and compare what you see there with the source-code. Just so you get comfortable matching C++ code to its ASM-compiled form. Note that we're talking x86 here (MDK2 is Intel x86), so don't compile an x64 program.

Best of luck!

P.S.: I mentioned a link in the "[ Running Lua Scripts ]" of this topic. Maybe start from there. I usually pick-up breadcrumbs along the way and I piece them together to my needs. You have to really define what your aim is, making it very particular, then slowly generalizing.

TurboSosiska
What is cheating?
What is cheating?
Posts: 3
Joined: Sat Apr 02, 2022 6:19 pm
Reputation: 0

Re: MDK 2 [Engine:Omen]

Post by TurboSosiska »

Thank you very much!!!

Post Reply

Who is online

Users browsing this forum: AhrefsBot, Audience3339, badboi888, Bing [Bot], Cloover, darshangkolhe, Google Adsense [Bot], hobeone, iamthame, Jer, KittyKat, LionZero, oliv, Shizuka, Sirlefou, Starscar, Vasily, ZoanChrome