Findus bei den Mucklas
Intro
So long time ago me and my brother Kyle.. Oh wait
Long time ago I played this game “Findus bei den Mucklas” from the “Petterson and Findus” series. So to relive this nostalgia trip I decided some time ago to play it again. The problem: You can’t find shit in this economy for this game. After some searching I found the game but it didn’t start or something like that.
Fast forward to last week: I was cleaning some files and found the game lying on my hard drive. Okay why didn’t it work? Maybe we’ll find some new informations online. I found some posts but most we’re saying that you have to emulate Windows 2000/XP and then forward the hard drive - which would require one to buy a copy, which isn’t sold anymore…
If you just want to know how I got it to play, go to the end
Part 2: Betrayal
So I downloaded a XP iso from archive.org and installed it there. Using WinCDEmu I could mount the .img and install the game. After starting it, a promising logo showed up and destroyed my excitement by throwing a error: “Disc Error !”. Well what happened? Maybe some copy protection shittery? The internet didn’t answer. Well then let’s jump into Ghidra and look ourself.
We know that it’s a MessageBox, so let’s look for mentions of that:
switch(reasonID) {
case 2:
uID = 0x3ea;
break;
case 3:
bVar1 = true;
uID = 0x3eb;
break;
default:
uID = 0x3ec;
break;
case 6:
case 7:
uID = 0x3e9;
}
LoadStringA(instance,1000,local_120,0x20);
LoadStringA(instance,uID,(LPSTR)local_100,0xff);
iVar2 = MessageBoxA((HWND)0x0,(LPCSTR)local_100,local_120,bVar1 | 0x10);
One mention and it looks good. So LoadString, meaning the error is in the resources?
STRINGTABLE
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
{
1000, "Application Error"
1001, "This application cannot start as it cannot create needed files. There may not be enough free disk space."
1002, "This application cannot run, as it could not find the shared library MSVCRT.DLL."
1003, "This application requires the Shockwave 8 Player, which is not installed. Click OK to download it."
1004, "This application cannot run."
}
That’s weird… No mention of the disc error. Where is the MessageBox called (Functions already named)?
if (iVar2 == 0) {
iVar2 = 7;
}
else {
iVar2 = LoadMSVCRTModule(&local_20);
if (iVar2 == 0) {
iVar2 = LoadProjDllModule(&module,&local_1c);
if (iVar2 == 0) {
pFVar3 = GetProcAddress(module,s_ProjectorMain_2000806c);
if (pFVar3 == (FARPROC)0x0) {
iVar2 = 4;
}
else {
local_18 = 1;
local_14 = 0x18;
if (DVar1 != 0) {
local_10 = &LAB_200015f0;
local_c = DVar1;
}
local_8 = DAT_20008ab0;
local_4 = local_1c;
iVar4 = (*pFVar3)(mainHandle,param_2,param_3,param_4,&local_18);
}
}
}
}
...
MessageBoxExitReason((HINSTANCE)mainHandle,iVar2);
Okay so it wants to call a exported function from a module. And then complains about missing stuff… Looking through the rest of entry I didn’t find anything interesting. So maybe the check is done in this proj.dll:ProjectorMain? Well that file doesn’t exist next to the executable and google doesn’t say much. But what I see the shockwave player popping up. Does that mean the game has to do something with shockwave (which was similar to flash)?
It actually works?
Well yes. The game was made with Macromedia Director 8 Shockwave Studio (which is also written in the) and is basically just a glorified Shockwave player. This link told me that projectors just point into the starting direction and let Shockwave do the rest. So the real juice is in the other files, but they aren’t swf (which is flash) or filetypes I know.
In P3media
I found the files like intro.dxr
and credits.dxr
. So how does one play those? This archive.org link has some example projectors that are apparently packed with the Director Installer. Using the 8.5 projector I could just select any file and start it! Ignoring the script errors which it threw out by the minute, I could play some simple game, but they were out of context and I wanted the full game…
So what file does the real projector start? Clicking through some files I found intro.dxr
, which played the intro… and threw out a “Disc Error !”. Found you bitch.
Deep dive
On my travels through the interwebs I found this decompiler. But I thought “meh I don’t know these file types”. Well now I know better. Building it on a linux vm and dumping the intro file got me this “lingo” code in a few files. Here the interesting parts:
on exitFrame
if soundBusy(2) = 1 then
go(the frame)
else
go("slut")
end if
end
Uh good start? what does this even mean…
on exitFrame
go(1, "pofintro")
end
So a label?
on exitFrame me
KollaCopyProt()
end
Is this swedish? Kolla is maybe call? But CopyProt() sounds good. Where is it though… In the inconspiciously named file Cast Interne BehaviorScript Call Copy-X CD protection DLL (OPTGRAPH.DLL).lingo
I found the real stuff:
on exitFrame me
if the platform contains "Mac" then
nothing()
else
if Ok = 0 then
alert("Disc Error !")
avslutaSpelet()
else
if getReturnVal(me) <> 26079537 then
alert("Disc Error !")
avslutaSpelet()
end if
end if
end if
end
...
on init me
errstring = "Error setting up initdisplay function call: "
if serialNumber <> "demo" then
GLURegister("R100-71-82650534")
end if
initDisplaySetup = new(xtra("glu32"))
if not objectp(initDisplaySetup) then
Ok = 0
errstring = errstring & "no instance of Glu32"
else
dllpath = the applicationPath & "Optgraph.dll"
err = GLUNew(initDisplaySetup, dllpath, "initdisplay", "L", "V", 0, 0)
if err <> 0 then
Ok = 0
errstring = errstring & GLUGetErrorString(initDisplaySetup, err)
end if
end if
end
I found the Glu32.x32
in the Xtras
folder and the description (in a string) says “Calls Win32 DLL Functions”. Okay so it calls initdisplay
in Optgraph.dll
and changes Ok
if it fails (and thereby causing the “Disc Error !” prompt). There are a few other mentions of Ok in the file but let’s hope it depends on the stuff in optgraph.dll
cause I know how to change those files… But we could just check with a debugger if that dll gets called right? But that would require me to work in my shitty xp vm or run the game on my host.
Running the game on my host throws another error cause I don’t have the cd inserted. The error message is saved in Pettson3.ini
, but where the fuck does the code to call that come from? Ghidra shows no mention of that file in the main executable. Detect It Easy (used to look for packers and other stuff) does show it in a “overlay”, which is apparently data attached the back of the executable.
Note: At this point I also found out that you can just run the pfointro.dxr
and thereby bypass the intro check, but I wanted to bypass the check completely as I didn’t know if using another projector made any problems.
Overlay Unpacking
The overlay starts with the magic bytes 10JPQ
which is apparently attributed to the “Adveractive Installer”, which I have no idea what is. Maybe this is also a false positive?
Okay this Overlay has in the first hundred bytes this
MZ..........ÿÿ..
¸.......@.......
................
............è...
..º..´.Í!¸.LÍ!Th
is program canno
t be run in DOS
mode....$.......
...
So that’s a PE beginning… We can export the overlay with PE Tree (yes there are probably easier ways) and then remove the first few bytes to get a PE. Put it into ghidra and bam, we have code. The new file exports ProjectorMain
and still no mention of Pettson3.ini
in the strings. This looks like the proj.dll. So another overlay? I did this a few times and i got these files: proj.dll
, dirapi.dll
, iml.dll
, msvcrt.dll
The problem started with the fifth overlay:
NB10....Ú4g6....
E:\8337\vc98\sel
f\bin\x86\msvcrt
.pdb.XFIRfB..LPP
Apami........}!"
.@..............
.pamm...........
.....ÿÿÿÿÿÿÿÿÿÿÿ
ÿXFIRfB..Q!"....
...
So it starts with NB10
, which I don’t know. XFIR
is interesting though, because the .dxr
files all started with RIFX
. The decompiler also looks for mmap
or imap
, which would overlap with pamm
and pami
. But what happened here? Maybe it needs other endianness to make parsing easier during runtime?
Finding the cd check
Googling (more like duckduckgoing) a bit lead me to this unpacker (thanks to this SO answer) which dropped a kicker_010928_1153.dir
for me, which contains the exact thing I unpacked like 5 times before. But this one also starts with XFIR
. But wait .dir
? Didn’t the decompiler say that it also supports those? A quick decompile later and I got 2 new lingo files. Here are the interesting parts:
...
driveletter = checkpccdrompath()
if not voidp(driveletter) then
...
else
alert(string(ini.alertmessage)) -- Alerts us here
quit()
end if
...
on checkpccdrompath
seperator = the last char in the applicationPath
drivelista = ["d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]
Retvar = VOID
repeat with Drive in drivelista
iscdrom = baDiskInfo(Drive, "type")
if iscdrom = "CD-ROM" then
path = Drive & ":" & seperator & "p3media"
if checkoncd(path) then
Retvar = Drive
else
end if
return Retvar
end if
end repeat
end
on checkoncd path
fileList = getfilesinfolder(path)
iscd = 0
if fileList.getOne("intro.dxr") or fileList.getOne("intro.dir") then
iscd = 1
end if
return iscd
end
(For Windows) It basically checks if a CD-ROM exists which has a intro.dxr
or intro.dir
in the p3media
folder. I don’t think it even calls that intro file.
Outlook
Now we have 2 paths we can go down:
- Just use another Projector and run the game through that (may have problems)
- Remove/bypass the Copy protection from
optgraph.dll
and maybe the cd check in the executable so you can run it from anywhere
I decided to go with the 1st route cause I’m lazy. I uploaded the img file here. You can run it with the Projector I linked above or through Flashpoint. The resolution is only 640x480 but I haven’t found a way yet to make it bigger.