paavohtl's blog

Bypassing early 2000s copy protection for software preservation

AKA: Sidestepping copy protection with Masa Mainio

There was a Swedish series of children’s somewhat educational video games called Mulle Meck, known in other languages with similarly alliterative names like Masa Mainio, Gary Gadget and Willy Werkel. The franchise consists of five games about designing and building things, plus naturally a personal organiser / calendar application. Four of the five games were localised & released in Finnish, and they were wildly popular between the late 90s and early-to-mid 2000s. Like many other people of my vintage I played and greatly enjoyed them at the time. For me the games were primitive yet effective gateway drugs to more complex engineering-y games year later like Garry’s Mod and Kerbal Space Program. The simple gameplay was supported by lovely hand-drawn art and quirky fully voice acted dialogue.

None of the games are on sale anymore, and since a lot of people (at least here in Finland) played them in schools or public libraries there are not too many physical copies around. Luckily all of the games are preserved on archive.org.

The first two games (about building cars and boats respectively) are quite easy to run even on Windows 10 with the help of a few compatibility settings. The third game (about planes) is more difficult to run because it uses an ancient version of Direct3D, and I remember it being fiddly to run even when it was new. However, it is by far the worst of the series (don’t @ me) and can be ran with the help of a virtual machine if nothing else.

The fourth game — about building houses, of course — was released in 2002 (2003 in Finland) and is somewhat more difficult to run on modern systems. While it is technology-wise quite similar to the first two games, from the preservation point of view it includes an unfortunate addition: DRM.

UnsafeDisc

I mounted a backup disc image of the game, and tried to run the installer on my Windows 10 computer. Absolutely nothing happened. Why?

The CD of Bygg hus med Mulle Meck incorporates a disc copy protection scheme known as SafeDisc V2, which was very common in games of the era. Last time I encountered was while backing up my CD copy of The Lord of the Rings: The Return of The King for PC.

SafeDisc v2 is easy to recognise: the root folder of the disc includes the files 00000001.TMP, 00000001.TMP and SECDRV.SYS. When I opened setup.exe in a hex editor I was easily able to find the magic string that identifies the exe as being SafeDisc v2 protected.

SafeDisc header in setup.exe, in hex editor

SafeDisc was implemented using a system driver, which ironically caused it to become a major source of security vulnerabilities. Because of this Windows 10 dropped support for the DRM scheme in 2015, alongside the more widely known and despised SecuROM software. While this was the right move from the security POV, the result is that about a decade’s worth of games are no longer playable on Windows 10, at least when installing from an original CD or DVD.

There are ways to bypass the DRM, even on Windows 10. These include re-enabling the possibly vulnerable DRM driver (no thanks), installing a no-CD patch (I’m not aware of one for this game) or getting a digital copy of the game (which as previously stated does not exist). However, it turns out there is a relatively easy way to bypass the DRM in the case of this game.

We don’t need no stinking installers

Remember a couple of paragraphs ago when I said that the SafeDisc signature is in setup.exe? This gave me an idea: what if SafeDisc is only used for the installer, and not the game itself? So by bypassing the installer, we could run the game without having to care about the DRM.

To test the theory, I needed to extract all of the necessary game files from the CD. This was both simpler and more complicated than I expected. The installer was created using InstallShield 6.1. The game data is stored in two archives on the disc: data1.cab and data2.cab. I’ve done this a couple of times before using Universal Extractor 2, an excellent tool for extracting literally hundreds of different binary archive formats. However it did not work completely for the game: I was able to extract the first archive, but I got some undescriptive error messages when trying to extract the second. Not being in a mood to delve to the source code to figure out why, I spent an hour or two looking for alternative tools.

I was ultimately able to extract the files using unshield, which I built from source in WSL / Ubuntu as Windows binaries were not available. Extracting both .cab files resulted in the following folder full of folders:

Program_Executable_Files
_Engine_Engine_Files
_Engine_Kernel_Placeholder
_Engine_Log_Services
_Engine_Log_Services_Placeholder
_Engine_ScriptEngine
_Engine_SelfRegistering
_Support_Finnish_Files
_Support_Finnish_OS_Independent_Files
_Support_Finnish_String_Tables
_Support_Language_Independent_OS_Independent_Files
_Support_Non-SelfRegistering

The only thing we need from here is the contents of Program_Executable_Files, as all the other stuff is only used by the installer framework as far as I can tell. I copied the contents to a new folder called assembled. I also copied the Movies folder from the root of the CD to the same directory, which contains basically the vast majority of the game content.

And ta-da! We have successfully bypassed the installer, and entirely sidestepped the DRM.

Something extra

Well, somewhat successfully. We can now run MulleHus.exe, which results in an exciting black screen, followed by an even more exciting message in Swedish:

Error message about the game not being installed correctly

…which roughly translates to:

The program is not installed correctly. Please run the installer again.

So what did we do wrong? Time to break out the big boy tools. I started poking at the game executable in Ghidra and a hex editor, and I was able to locate the message as a part of a script which sets some variables.

set errNotInstalled = "Programmet är inte korrekt installerat. Kör installationsprogrammet igen."

The same section contains other interesting stuff, such as the following:

criticalFileCD = "Help\MulleHusHelp.htm"
criticalFileHD = "Data\Data.cst"

This will be important later.

Curiously, the message was trivial to find in the hex editor yet Ghidra did not show it at all — the Ghidra listing ended before the section where the string was supposed to be. Understanding why requires one more diversion.

The Mulle Meck games were not implemented in C or C++ like most games of the era, but rather using Macromedia Shockwave 8, which at the time was a common choice for new and fancy CD-based games and multimedia software like interactive encyclopaedias. It was also a popular browser plugin for web games (like Habbo Hotel) around the turn of the millennium, but eventually lost to Flash which was also owned by Macromedia (and later Adobe).

So, the game executable is not really the game. Rather it is the standard Shockwave player executable (Macromedia Projector) presumably compiled by Macromedia, and the game data is simply appended to the end of the file. Ghidra only shows what is in the executable part of the file, which is why it doesn’t find the strings above. Therefore the error message is very likely produced by a script in the Shockwave part of the game, and not any special code in the executable. I could probably hunt down a copy of Macromedia Director (the tool used to create Shockwave applications) and some tools to unpack the files, but I decided to continue working on the game executable instead.

I ran the game again, but this time I used Ghidra 10’s new integrated debugger. I saw that the game loaded some libraries which I did not expect it to, which lead me to discover Shockwave’s Xtras system. Normally Shockwave applications are somewhat limited in terms of capabilities, but Xtras allow the runtime to be extended with native code in order to for example call operating system APIs or make web requests. The game directory contains an Xtras folder, with plenty of stuff:

Amplitude.x32
Animated GIF Asset.x32
Animated GIF Options.x32
Budapi.x32
DirectOS.x32
DirectSound.x32
FileIo.x32
Font Asset.x32
Font Xtra.x32
INetURL.x32
keypoll.x32
MacroMix.x32
Mix Services.x32
NetFile.x32
NetLingo.x32
PMatic.x32
QT3Asset.x32
QuickTime Agent.x32
Sound Control.x32
Sound Import Export.x32
SWADCmpr.x32
Text Asset.x32
TextXtra.x32
vList.x32

Despite the file extension .x32 these are actually just plain old .dll files, which the game executable loads dynamically. By going through module imports and setting some breakpoints I was able to verify that game uses the libraries to do things like file IO and registry access.

Breakthrough

I was unable to make further process with Ghidra, so I decided to use another tool: Sysinternals Process Monitor (Procmon). It is an invaluable tool when you want to figure out what a program is really doing, as it essentially logs most WinApi calls made by every currently running application. I use it somewhat frequently to check if some slow-running program has frozen or is actually doing something.

I attached Procmon and ran the game again, which gave me thousands of events to scroll through.

A screenshot of Procmon’s UI

This immediately revealed some interesting things about the game. The player creates a temporary folder (AppData\Local\Temp\TempFolder.aaa) and extracts some DLL files to it. The folder is destroyed when the game exits. Between the two sequences of events, the game performs the check(s) to validate the installation, and then shows an error message if it detects any problems. After some scrolling, I found what was wrong.

A screenshot of registry reading events in Procmon

A stack trace from one of the registry events

Bingo! The game reads the Windows registry key HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\MulleHus.exe, and shows the error message if the key does not exist. Procmon also produced a stack trace for the event which confirms that the key is read by code in the DirectOS.x32 Xtra. The keys under App Paths are used by Windows’ Application Registration system which is normally used to associate file types and protocols with programs, but looks like this game uses it to detect that the game has been properly installed with the installer. After creating the key (containing the path of the executable) and the Path subkey (which points to the working directory) the game can now be run successfully!

The game’s splash screen

An error about missing QuickTime installation

There is one more wärning båx about QuickTime 5 not being installed, but that only means you can’t watch a 2-minute intro video. The game continues running normally after closing the message.

Now do it without the CD!

We’ve now reached the original goal, but there’s one more thing to do: to run the game without the (virtual) CD. This turned out to be really simple. I unmounted the image and started the game, which produced this error message:

A screenshot of the game asking for the CD

I had an another look at the events I recorded earlier after running the game successfully for the first time.

10.16.11,6061719	MulleHus.exe	26396	QueryOpen	D:\Help\MulleHusHelp.htm	PATH NOT FOUND	
10.16.11,6062203	MulleHus.exe	26396	QueryOpen	E:\Help\MulleHusHelp.htm	PATH NOT FOUND	
10.16.11,6062606	MulleHus.exe	26396	QueryOpen	F:\Help\MulleHusHelp.htm	PATH NOT FOUND	
10.16.11,6063213	MulleHus.exe	26396	CreateFile	G:\Help\MulleHusHelp.htm	PATH NOT FOUND	Desired Access: Read Attributes, Disposition: Open, Options: Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a
10.16.11,6064747	MulleHus.exe	26396	CreateFile	V:\Help\MulleHusHelp.htm	SUCCESS	Desired Access: Read Attributes, Disposition: Open, Options: Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a, OpenResult: Opened
10.16.11,6065008	MulleHus.exe	26396	QueryBasicInformationFile	V:\Help\MULLEHUSHELP.HTM	SUCCESS	CreationTime: 5.6.2003 14.56.10, LastAccessTime: 1.1.1601 2.00.00, LastWriteTime: 5.6.2003 14.56.10, ChangeTime: 5.6.2003 14.56.10, FileAttributes: R
10.16.11,6065062	MulleHus.exe	26396	CloseFile	V:\Help\MULLEHUSHELP.HTM	SUCCESS	

The game loops through all of my drives (both hard drives and virtual CD drives) looking for the file \Help\MulleHusHelp.htm, which we saw previously as a string in the game executable. And you might be able to guess that by copying the file from the CD to a corresponding folder on any hard drive the game thinks that the CD is in the drive. We’ve now bypassed the second and final form of primitive copy protection!

Conclusions

Software is not made of magic. Installers are mostly useless. DRM is terrible for software preservation. Ghidra is great, but not for every purpose. Procmon is excellent as long as your mouse has a free-scrolling wheel.