Cracking ARSENAL2 Extended Power (game)

TL;DR [you lazy script kiddie]
Go to how to apply the ARSENAL 2 crack and cheats section.

Goal

The ARSENAL2 game

I have an old game on my airgaped Windows XP station that I use for offline gaming (yes, XP, because, it's air gaped so no internet connection at all, no wifi, and backups of the disk so indeed, this is XP, but this is safer than a lot of modern OSes connected to the internet!). This game is called "ARSENAL 2, Extended Power" made by Eric Mathiault and its demo (v2.H) can be downloaded from http://www.tacticalsoft.com/ .

This is an old strategy game, kind of Command & Conquer like.
I had a licence for this game, but, it got revoked a long while ago so nowadays, I only have the demo version. This demo version has some limitations: you can only play for 20-30 minutes (while finishing a game session requires something like 1 hour), you cannot get a higher military than "Sergeant", you cannot play online, you cannot save a game, edit a map, and so on.

So the goal is to crack this game to be able to finish a game session (overpassing the time limit).

Legality?

Is it legal? I guess so: I never signed any user agreement stating I cannot take a look at the game's executable code, or its game data, nor stating that this article cannot be written. Also, the demo says itself "This demo must be shared!" so, I'm sharing this demo here, along with some extra technical infos. I'm not gonna forge fake licences (tho, it can certainly be done), I'm not gonna reshare a licence I have (I already paid this game and got a licence a decade ago or so), and I'm not responsible of any usage anyone may do with these infos.

Presenting of the game

So when you download the demo from official source (or from my local copy if you want to), and extract it, you get two files: a very light "arsen2go.exe" executable, and a "arsenal2.adf" (Arsenal Data File I guess).

arsen2go.exe and arsenal2.adf files in explorer
The base files

When you start the exe, you get a welcome simple screen, stating it's a demo. So let's play it.

ARSENAL 2 welcome screen with a play the demo button
The welcome screen

Once started, you have a "loading" screen, which I guess "extracts" somehow the data from the adf file (note that this adf file is not a simple renamed zip file, but this is for later on)

Black screen showing Init WHATEVER.... loadings progress bars
The loading screen in game

And you're inside the game.

In-game screen with a menu to create your game character
You can now create a character in the game menu

Once you have a character, you can play the game

In-game screen showing the game map and units
You can play the demo

And after a while (20 to 30 minutes), the game stops, because it's a "demo".

Game screen fading out
Game stops after 20-30 minutes

Why a "20-30 minutes" limit, instead of a plain raw fixed limit? I'm unsure, but I guess it's to frustrate players more, so they cannot think like "I must win before 25 minutes, else game stops!"

Overpassing the time limit

So how can we overpass this limit? Let's try with ollydbg that I already used here for cracking a software for my company . At this point, I expected the game assembly code to contain something like if (current_timer_in_game > random_value_or_so) then quit_game()

Trying OllyDbg

Let's start Ollydbg (that you can download from http://www.ollydbg.de/odbg110.zip (which I also provide here, note that v2 exists so you may try the one you wish), and run the "arsen2go.exe" file from here.

Ollydbg windows showing the popup to open the executable you want to debug
Opening the arsen2go.exe from ollydbg

After hitting "play" (=continue debug) I got the welcome screen...

ARSENAL 2 welcome screen with a play the demo button
The welcome screen shown up again

And started the game

Black screen showing Init WHATEVER.... loadings progress bars
The loading screen again

But weirdly, ollydbg shown nothing during game execution... Why? Well, it's easy to find: kill the game using the task manager, and look and the game's folder: you'll see that another executable named "arsenal2_game.exe" appeared!

The game directory showing new files
Files appeared, and mainly, an exe file!

When trying to run arsenal2_game.exe directly, the exe will actually delete itself, and run arsenal2go.exe instead.

So, this means that this arsen2go.exe executable contains only the welcome screen, and it generates the game's executable arsenal2_game.exe on the fly. If you quit the game normally, without killing the process, then you won't notice this "temporary" exe, which seems to be deleted once the game is closed...
And when you run the arsen2go.exe file again, the generated exe disappear!

The welcome screen and the game's folder in background
Welcome screen "cleans" the game folder by removing exes
Finding the deletion code

Opening the arsen2go.exe again in ollydbg, I looked for the strings in the assembly code, looking for the generated executable's name

Ollydbg menu to search for strings in the assembly code
Let's look for "arsenal2_game.exe" in "arsen2go.exe"

I then found the deletion code at 0x40503B offset.

View of ollydbg and the assembly code of the file deletion
This is the deletion code

I added a breakpoint at this offset (press F2), created a fake (empty) file named "arsenal2_game.exe" in the game's folder, and run the arsen2go.exe program again to check if these op codes actually deletes the fake exe file.

The game's folder with fake exe and the assembly code in background
The execution was stuck on the breakpoint...
The game's folder no longer having the fake exe and the assembly code in background
... and the fake exe got deleted right after the CALL instruction

When reverse-engineering programs, always emit an hypothesis about its way of working, and try to confirm it with a test: this will make your understanding of a program way more stronger and reliable.

As you can see, this exe is not the only one that seems to be deleted: an "arsenal2_launch.exe" and an "arsenal2_restore.exe" seems to also be wipped out. I guess the restore one is used when you call the helpdesk or so, but the launcher? Well, let's assume it's created and deleted right away!
To confirm that, I opened the exe using CR-Hexact, which is a neat hex editing software that locks the files it opens. By locking them, I expected to make the windows-API file deletion fails.

I then run the arsen2go.exe file, hit "Play demo" button, and... poof, back to windows, but this time, with 2 executables: arsenal2_game.exe and arsenal2_launcher.exe, along with a "trace.trc" file that seems to be a debugging log file

CR-Hexact software window with the executables (and a trace file) opened
Use Cr-Hexact to lock the exe files

I tried taking a look at the arsenal2_launch.exe in ollydbg too, and I saw that it has references to both the arsen2go.exe file (the welcome screen) and the arsenal2_game.exe (the actual game exe).

Ollydbg assembly view of the arsenal2_launch.exe on-the-fly file
That exe file had references to the other two exes
Sum it up: the exes process

Okay, so, what do we have so far?
arsen2go.exe removes arsenal2_launch.exe and arsenal2_game.exe if present, then when hitting "play demo" button, it generates (if you dig into ollydbg code, you'll see it's actually extracted from the adf file) the arsenal2_launch.exe and runs it.
arsenal2_launch.exe checks that it was run by arsen2go.exe (and not directly by the user, if so, it stops and runs arsen2go.exe instead which will remove the other exes), deletes itself, reextract arsen2go.exe from the adf and overwrites it, and then generates and runs the arsenal2_game.exe
Last, this arsenal2_game.exe checks it was not directly run by user (if so, it runs arsen2go.exe), and if so, lets you play the game.

Diagram of which exe deletes who and such
The 3-exes mess
Boy, you're a useless mess...

I'm actually unsure about who deletes who exactly, but sure thing: this is a crappy useless mess.
If you wonder why things are run this way, I can tell you this is a dumb attempt to make the game "uncrackable". Suppose you have a crack for any of the exes, then, it would be deleted right away and recreated so, game is not crackable right?

Wrong.
It still is, you only need to remove the deletion codes from the three executables. It's very fairly doable but it made me think about one thing: if I crack things this way, not only it's gonna be boring as hell, but it would have to be re-done if a new version comes out (ok, it's an old game, so very few chance a new version would be out, but anyway... plus I was working on the v2.CC version at this time, and saw later on that version v2.H was out since a decade or so, hence, there indeed was an update I missed). So I tried another way.

Do not attempt such thing to make game "uncrackable", because, first, it won't work (see above or below) and second, anti-virus of "normal/regular" users/players can consider this as a "malicious behavior" and block your game, frustrating legitimate users. Not to mention that if the game's folder is in Windows 7's "Program Files" directory, then you would require the admin rights to delete exes, which is a crappy security issue for a game.

Another way: Cheat Engine

So, the main point here is I don't care about the exes and the complete useless mess developers made here. I'm caring about the running game. So I turned to an alternative way of thinking: instead of tampering the saved exes like I did last time, I will instead tamper the memory of the running game, to make it do what I want.
For this, I use Cheat Engine , which allows to fairly easily alter running program's memory (often, for cheating, but here, we'll crack game with it instead). Note that this might raise alerts from "anti-cheating" systems like Punkbuster or so, but I don't care since I don't have them. Also, Cheat Engine tampers with other processes data so your anti-virus might complain about it and requires you to whitelist/allow this software first (this airgaped offline Windows XP has no anti-virus so this wasn't a problem either)

Hooking the time limit

After installing and running Cheat Engine, let's run the game again (please ignore that I switched to French meanwhile) and try to bypass the 20-30 minutes limit that I highlighted in black

Cheat engine window, and the welcome screen window
Let's run the game again

Once the game is running (after all the messy exes thing that we actually don't care about), let's go back to Cheat Engine (alt+tab) and open the arsenal game process (because I don't care about the welcome screen and such, I only care about the running game process)

Cheat engine window showing the process selection
Select the game's process
Train yourself firt

As a training, I won't rush to the time limit. Instead, I'll try to cheat the game, and change, say, the amount of ressources (oil, in the top-center of the screen) I have from 20.000 to 80.000 or whatever. This would proof that I can tamper with the game's memory.

The game map showing the ressources you have
I have 20.000 oil: let's train to make it 80.000

For that, let's look for a 32bits integer exact value of 20000, only in the arsenal2_game.exe memory (this exe loads some DLLs, including "Crypto32.dll" from Windows which seems to confirm that the ADF file is encrypted with a secret key and decrypted on the fly)

Cheat engine window and the search form to look for specific memory values
Search 20000 value in memory, to tamper with it

Ouch, that's a lot of values!

Cheat engine window and the 33 corresponding values
Lots of match!

It's okay: actually, there are several resources in this game (3), and several players (8), so you may end up with a lot of 20.000 values. This shown me that the memory of the game contains a lot of stuff, even for such a small game. So let's play a bit, and try to narrow results.

The game view, after 1min 29 of playing, showing ressources quantities have changed
I play, and now, I have less oil (19000)

Since I have a new value to look for, let's search, in the previous search matches, a value that would now be "19000", the amount of oil I now have. You may use the search form, and change "20000" to "19000" then hit "next scan", but here, the hit was super obvious, so I didn't re-scanned

Cheat engine memory values, where you see the changes in real time
Only 1 value out of the 33 matches was exactly 19000

So I double clicked the value, which added it to the below "cheat table" list of memory addresses, and I changed to value to "0".

Cheat engine memory values, with the addresses you selected at the bottom
let's change the value at 0x4cd75c to 0

And poof! No more oil in game!

The game view showing the I have 0 oil resource now
I lost all my oil in game

And if I change it to 80000

Cheat Engine view, where the value of the memory address was changed to 80000
Changing to 80000

And bam! Lots of oil!

The game view showing the I have 80000 oil resource now
I now have oil again!

If you want to edit a memory value on the fly, use Ctrl+E instead of double-clic.
If you check the left box on the address list table, cheat engine will "freeze" this memory value by resetting it to (say) 80000 every 100ms or so, making the value "look to be frozen at 80000".

Looking for the timer

Ok, now, I know how to tamper with the game's memory, and it works perfectly well. Let's try to block the timer now, on the upper left, so that it will never reach 20 minutes and so (I hope), will never makes the game end.
The time was at "28 seconds" in the previous screen (where I paused the game, so timer doesn't change while I look for it).

Cheat engine view, searching for the 28 (seconds) of the timer, showing 7 hits
Searching for the "28s" timer

Ok, I have multiple hits, I know what to do according to above training. So back to game, un-pause; wait a bit, and pause again

The game view showing a 2 min 30 seconds timer
Timer is now 30 seconds

Back (alt+tab or windows key) to Cheat Engine, let's look for "30" and...

Cheat engine new scan results for value 30, showing no hit
... no result found
Reconsider from blue perspective

Ok, let's think the blue team (= developers team) way now: I'm a game developer, I have a timer to store in my code, would I really use a 32 bits integer? Actually, no. Timer is 0-60 for seconds and minutes, so, I only need 1 byte. But 1 byte is hard to manipulate, so, I would probably use a short integer (2 bytes). Let's go back in game, unpause, wait, and pause:

The game view showing a 2 min 31 seconds timer
Timer is now 31 seconds

And search for value "31" but this time (see the search form on the right), it would be a 2 bytes integer (note that Cheat Engine seems to consider all integers as unsigned, but allows to search indifferently for signed or unsigned value; so searching -1 8int is same as searching 255 8int).

Cheat engine new scan results for value 31, showing one single hit
Paf, 1 single hit!

Ok, looks good, but you know the drill: back to game, unpause it, and let's leave it unpaused now

Game view showing the game is running and is now at 2 min 34 s
Back to game, let's leave it running

And in cheat engine, I now see that the value is incrementing every second (it's now 47)

Cheat engine view showing that current memory value at 0x4ce39a is 47
I found the memory address of the seconds in the timer

Note that the addresses are "arsenal2_game.exe+CE39A", meaning the adress is relative to the 1st byte of memory of this process. On the right, you see that the memory range for arsenal2_game.exe process itself (so, not its DLLs) is 0x400000..0x4df000 so all addresses can either be refered to as "arsenal2_game.exe+CE39A" or "0x400000+CE39A = 0x4CE39A"

Search the hours and minutes

Right clicking the memory address, you can select "view memory region". From there, you'll see (in real time) the game's memory around block 0x4ce39a, which is the memory address of the seconds in the timer.

Cheat engine view showing the memory region, which real time changes highlighted in red
Timer's memory region

Being used to reading byte codes (eheh, I love saying this, it makes me feel like "you're always looking at the Matrix encoded?" ) I can see that 0x4ce39a holds a short 16int with the seconds, next is a short 16 bits integers with minutes, and next is another 16bits integers for hours.

So let's now add these 3 shorts to the memory addresses list ("Add address manually on the right", and don't forget to select "2 bytes" as the integer type). Then, check the box on the left so these values are locked to 0 4 7 (0 hours, 4 minutes, 7 seconds).

Cheat engine view showing the three added addresses in the memory table
The values of the timer are locked in Cheat Engine...

And you'll see in game that the timer is frozen!

Game view showing the timer stuck at 4minutes and 7 seconds, even if you're playing
... and the game thinks it stays at 4'07s

Wow. We did it? Hum, I would have to play up to 30 minutes to know, so let's attempt something: if the timer makes the game stop once reaching 20-30 mins, then if I set it at 40 minutes, the game should immediatly stop. Let's try: back to Cheat Engine, change "4" at 0x4ce39c to 40 (16bits int), uncheck the box so the timer increases normally again, and back to game...

Game view showing the timer is now at 40 minutes and 7 seconds, and increments
... and the game doesn't stop

So, at this point, I kind of knew freezing the displayed timer does not work. I still gave it a shot, and 20 minutes after, the game stopped like usual... So this is not working either

You may think "Why the f--- do you show us ways that do not work?", well, easy: I want you to know how a cracking session works. It's not straight forward, it's full of tries and fails, and it's by failing that you'll understand how a game works, and be able to crack it in the end.
So bear with me until it works.

Looking for another timer

So this means something else makes the game stop after a while. There is some kind of "another timer" somewhere in the memory, which is not the displayed timer, and that the game uses to say "stop, you've played enough".
So I started a new game, and searched for a 4 bits integer (because timestamps are often 32bits int) with unknown initial value.

Cheat engine view showing the search form for an unknown initial 32bits integer value
Let's search the hidden timer...

I then got back to the game, unpaused it, and let it run. Back into Cheat Engine, I looked for "next scan", with "increased value", since I'm searching for a 32bits integer that increments (probably regularly) along the game's playing...

Cheat engine view showing the search results for incremented values
"Next scan"ing for "increased value"...

I kept scanning until I got one (actually, two) values, at 0x4d7a00 and 0x4d9e70 (both 32 bits int):

Cheat engine view showing the search results (two) for incremented values
One of these two values must be the game's hidden timer!

So, same, I added both addresses to the table, and froze them to their current value

Cheat engine view showing the addresses table with frozen values
Freeze these values should make the game continue forever

But back into the game, the music was frozen too! The game was working well, but sound was stuck, meaning one of the two values is used for sound sampling. So, I unfroze one of the value, and music continued normally. I let the other value frozen, hopping it will allow me to bypass the time limit...

Game view showing the game stopped after 29 minutes and 54 seconds of playing
... and fail! The game ended after 30 minutes of playing

The decrementing timer

Ok, I was slightly disappointed, but back to blue team thinking: I need to implement a time limit in a game, and that time must vary randomly between 20 and 30 minutes. How can I do that, if not relying on the game's timer, or an increasing timer?
Well, what about defining a value randomly at the game's start, decrement it regularly during the game, and stop the game once this value reaches 0?
That sounds fairly doable and simpler than an incrementing timer! So, let's do the same as above, start a new game map, scanning for "unknown initial value", and looking for a "decreased" value on every "next scan".

Cheat Engine view, showing 28 values that are decreasing
I got multiple hits, so, I kept doing "next scan" every 2 seconds

I didn't know how "fast" the value was decreasing: maybe every ms, or every second, or it could have been every minute! Hence I run "next scan" every 2 seconds or so, to be sure the value had enough real time to be decreased by at least 1.

Cheat Engine view, showing 8 values that are decreasing
8 hits found after a while

At this point, knowing the game, I knew the first 7 values are ressources (which, yes, decrease at the game's start because you're consumming them), but, what the h--l can this 0x4ce3b8 value be?! It's not a ressoruce value (too weird to be), so, maybe it's my timer? Let's keep on playing the game, collecting some resources to have my resources quantity increase, and see...

Cheat Engine view, showing 1 single value that is still decreasing
I got 1 single hit!

Okay! After playing enough to have a viable economy and increasing resources in-game, I only had 1 single value that keeps decreasing along time... so, I could try freezing it, and see if games continue? But, again, it requires 20-30 minutes to check, so, very time-costy. So what if, instead, I set this value to a lower one? If I'm guessing right, the game should stop within few seconds of playing, instead of 20-30 minutes. Let's try!

Cheat Engine view, showing the address 0x4ce3b8 in the table, and setting its value to 1209
Change 31209 to only 1209, and expect game to stop within seconds

And yes! The game stopped after few more seconds of playing: I did the change at about the 6th minute, and game faded out at 6'18s

In game view, game is stopping (fade out) at 6 minutes 18s instead of the 20+ minutes limit
Game stopped! It's the first time I'm happy to see this!

Once game was stopped (and went back to its in-game main menu), I headed back to Cheat Engine, and saw the value skyrocketed to more than 4 billions, meaning that yes, it's a 32bits integer decresing timer stored at 0x4ce3b8 that makes the game stop!

Cheat Engine view, showing the address 0x4ce3b8 value is now 4294967252
After the game is finished, the value change again
Random address?

Last thing to check was if the timer remains at the same place on every game's boot. So, I shut down the game, shut down the computer, even unplugged the power, and rebooted everything up. I then started the game, started cheat engine, opened the game process again, and looked at the 0x4ce3b8 address: the timer was still here! I froze it (to about 50000) and was able to play for more than an hour and finish another game session.
Time limit was cracked!

Conclusion

So, to crack ARSENAL2 Extended Power's time limit, all you have to do is download Cheat Engine, download the v2.H of the demo game, run the game, open cheat engine, open the arsenal game process, add the 0x4ce3b8 address in the table as a 4 bytes integer, and freeze (check the box on the left) its value to, say, 100000

Bonus stages

Unlocking the military grades

My goal was fulfilled, but, then, I saw something weird: I cannot go higher than "Sergent" military grade.

In game view showing my stats, being Sergent with 49999 points
I'm stuck at 49999 points?!

Ok, seems like another limitation of the demo: your points are blocked to 49999. Let's look for this value in the memory, and raise it up.

Cheat Engine view, searching for 49999 32 bits int value
One single match for 49999 in Cheat Engine

Found at 0x4d9378. But, wait, 1 single hit? That's not expected! I expected to found 2 hits: my current score (49999) and the limited score constant (49999 too)! Let's change this value anyway to 800k

In game view showing my stats, being Sergent with now 800000 points
Ok, this 0x4d9378 address stores my curent score

Well, this is my score (so I could cheat it too btw), not the limit. I could search for 50000 (because, maybe, it's not a ≤ limit but only a < limit). But I had another idea in mind first: I said "the limited score constant", and on the search form, I had checked "Writable"! So Cheat Engine is looking for the 49999 in the writable memory only, while constants are read only values. So let's scan again, with greyed "Writable" checkbox (meaning "I don't care whether it's writable or not)

Cheat Engine view, showing the scan for writable and non writable memory value of 49999
Re-scanning with "writable: I don't care" option

Cheat Engine view, showing no result for the 49999 value
... and nothing again!

Huh, still nothing (because my score is no longer 49999 but 800000, so my score is expected to not appear at all here). Ok, see the option option "Fast Scan"? Maybe I need a "full scan" instead of a fast one, so, let's uncheck this and rescan

Cheat Engine view, showing the scan for writable and non writable memory value of 49999 without fast scan
"Writable: i don't care" + "no fast scan" shown 1 single hit!

Boom! Feels like I found you, constant! Let's try now to understand why it needed a full scan, instead of fast scan. Right click the address, and "show memory region", to see what's going on here.

Cheat Engine view of the memory nearby 0x46869b address
Memory nearby the constant address

Oooh, do you see what's written above the memory view (which is the bottom part of the window) for this 0x46869b offset? It says "Protect: Execute/Read Only". This constant is part of executable code. So, maybe, it's actually part of the assembly (executable) code of the program? Let's right click the top-half of the view, where assembly code is, and "go to adress", then tipe "x46869b"

Cheat Engine view of the 'go to address' in the assembly code window
Search the assembly code at the 0x46869b address we found

And boom!

Cheat Engine view of the assembly code nearby address 0x46869b
The assembly code is a PUSH instruction with the 49999 constant

The assembly code at this memory region (which is read only and executable) contains some jumps, and a PUSH 0000C34F instruction, which is 49999. We needed a "full scan" because our constant was not residing at an address that was a multiple of 32 bits, which is what is expected by a "Fast Scan, 4 [bytes] alignment".

If you cannot find your value in Cheat Engine, uncheck "Fast Scan", grey out "Writable" and "Executable", and/or try different data types like 1/2/4 bytes integers.

Altering assembly code using Cheat Engine

Now, how do I change this constant? I could alter the assembly code, replacing the instructions with some NOP (no-operation, hence "do nothing" bytes) to bypass the jumps, reassemble the program, and so I'll get the constant cracked. Wait. No. I cannot do that, because exes are deleted all around. So I need to alter this constant while the game is running, using Cheat Engine's memory tampering capacities instead. Well, let's do that: the constant I want to change is a 32 bits integer that resides at 0x46869b so I'll "add address manually" to the table, set its value to (say) 0x7fffffff and we should be good.

Cheat Engine view of the table addresses, the assembly code and the memory view
The assembly code changed because of the 0x46869b value I set

Notice that this processor uses little endian: PUSH 0x7FFFFFFF becomes 0x68 0xFFFFFF7F bytecode, same in the memory view.

Now, the assembly code, which is the in-memory view of the executable, looks nice: there is still a limit to points you may have, but it's 0x7fffffff which is the same value than at +x686a1 address. I think that this "super high" value is the one used when you have the licence, and the old "49999" one was the used when you don't, hence the "je +x686a1" instruction before (to tell between "you have licence" and "you have not"). From a blue team (developer) perspective, this is a simple way of having 1 single process (=always have a limits to points) with 2 different values (=50k without a licence, 2G with a licence).

Note that this jump is taken if the "test byte ptr +cd5ca,40" is true, which made me think "hey, this is where the 'you have the licence' boolean is stored", but I couldn't actually exploit that.

Let's now go back to the game. Remember I still have 800.000 points, right? So, let's construct houses, demolish them to have a negative score (so my score changes), and see if it's still blocked to 49999 or not

In game view showing houses being constructed
Let's make houses in game...

In game view showing houses having been destroyed
... and destroy them to have a negative score of -530 (see top left)

In game view showing the game session is about to be quit
... now, quit this game map so that score is "added" to mine

In game view showing the game ended, and I had lost 530 points
... ok, seems like I indeed got a -530 score for this session

In game view showing that I got a promotion to 'Lieutenant Colonel'
... and I got a higher grade than Sergent!
(because I cheated to have 800k points first)

In game view showing my current score of 799470
... and indeed, my player's profile was 800k-530

In order to have unlocked score and grade, you must alter the 0x46869b address to be 0x7fffffff
This also shows that Cheat Engine can alter not only any program's data in memory, but also any program's assembly code, thanks to computers being Turing machines: code and data and on the same memory band, and you can change it in any way you want.

Unlocking the map editor

Can I dig any deeper to unlock this demo game? Yes. In the main menu, you have a "map editor", which requires the licence

In game view showing that the map editor requires the licence
"The licence is required for the Map Editor"

When I digged into assembly code, both in Ollydbg and Cheat Engine, I saw that the licence seems to be able to "expire" at some date, meaning that the licence data should hold a "timestamp" stating until when it's valid.

Cheat Engine memory view showing some strings with 'expir' word
The licence seems to "expire" on some circunstances
(this is what the strings in memory view mean)

So, in order to make the game consider I have a valid licence and unlock the map editor, I'm looking for a "timestamp" being a 32 bits integers. Its value, now, should probably be "0" meaning "you don't have a licence at all", and I'll try to raise it to a value higher than current date. So let's search for 32bits ints value of 0.

Cheat Engine search result for 32 bits int value of 0
9566 hits, that's a lot!

So I played the game again, and kept on scanning for "0" values. Clicking around in the menus, playing game sessions, etc should not change the licence's status, so, I was "next scan"-ing for a "exact value" of still being "0"...

Cheat Engine search result for 32 bits int value of 0 scan after scan
After few minutes, I still have 8523 results

Ok, that's a lot still, and I'm lazy to think more. So, I'll brute force this: I'll select a large range of memory values, say all the +B#### values, and force the "0" to be "2000000000" which is a timestamp that has not expired yet. So select the range, Ctrl+E, and set a 2G value.

Cheat Engine view showing you can change a whole range of values in one shot
Changing bunch of values in one shot

This didn't work: game was still showing "Cette DEMO doit être copiée et distribuée LIBREMENT" at the bottom left, meaning "This DEMO must be shared ALL AROUND", so basically, I didn't unlocked the licence by tampering with +B#### range.

In game view showing this didn't worked
Range +B#### did not work

So I repeated this with next range +C####, then +D#### etc. Game crashed sometimes, so I narrowed some ranges to +C0###..+C8### which did not crash, skipped the +C9###..+CA### which crashes, and kept on trying. Probably not the smartest way of doing, but at some point after 5 minutes of tries, I saw this:

In game view showing the game licence has EXPIRED
Bottom left message changed!

Brute force like this might be tried, but if I had not result after 10 minutes or so of attempts, then I would have searched for a smarter way to find the licence expiration timestamp memory address.

The message was now "Licence has EXPIRED"! So I reverted some ranges to 0, then back to 2G, etc, until I found 3 addresses: 0x4cea0c 0x4cea30 and 0x4ce69c. Altering the first to 2G shows "EXPIRED Licence", second shown "Passport valid until some_date to" (without anything after the "to") meaning I could play the game online (if this computer was connected to the internet, so, since it's not, this is useless to me)

In game view showing that the 'passport is valid' until a certain date
Tampering 0x4cea30 value allows you to get the online passport

The last 0x4CE69C 32int address shown "Licence granted to " when set to 2G, without a name after the "to" again. Why no name after "to"? Because the name is probably a string somewhere else in the memory (and I couldn't find where it was stored), which is all "zeros". So, no name. But licence seems valid now...

In game view showing that the 'licence is valid'
Tampering 0x4ce69c value allows you to get the licence

If you noticed it, the current computer date is "January 1 2002", in the top right corner. This is because I "unplug" the computer from the wall after having played games, and the motherboard's BIOS date gets reset (I'm lazy to change its depleated battery).

In game view showing I tried to open the map editor
Let's see if this last change unlocked the map editor...

In game view showing the map editor's agreement
... and I got the next step
(abusive agreement saying "all maps you'll do are belong to Tactical Soft's")

In game view showing the map editor first screen
... if you accept it, you get to the editor

In game view showing the actual map editor
... and then, you can alter your map!

So, changing the value of "0" at 0x4ce69c to "2000000000", which is a non expired timestamp (after 2002), works!
Let's also try if I can load a game, or save it, which is forbidden when you don't have the licence. First, I revert the value to 0, and try to load a game.

In game view showing that you cannot load a game if you don't own the licence
Loading fails: I don't have the licence

It fails as expected (I don't have the licence). Now, let's change value to 2G again and test:

In game view showing that I can now load a game
After changing value to 2G, I can load a game

In game view while playing, on a map, showing I cannot save game without licence
Changing to 0 again and trying to save a current game: forbidden

In game view showing that I can now save a game
After changing value to 2G again: save is allowed

Funnily, even with the unlocked licence, I still have this "you can buy the licence right now!" screen when ending a game session.

In game view suggesting me to buy the licence, even if it seems I already have one
Even with unlocked licence, I still have this "buy licence" screen

This means I hadn't fully cracked the licence, so I still need to tamper the assembly code for unlocking the max points I can have, and to tamper the memory to unlock the game duration: hooking the licence timestamp like I did in this section is not enough to unlock everything.

This also means that another data somewhere in the memory (taken from the licence file) is used to fully unlock the game, but I couldn't find it, so I kept the timestamps addresses to unlock save and editor, and I kept the PUSH constant and in-game decreasing timer addresses to unlock the rest of the game.

Automatization

Last bonus: so far, I need to set the addresses values manually. It's a pain, as I now have several ones: the int32 time limit at 0x4CE3B8, the int32 points limit at 0x46869B, the int32 passport expiration timestamp at 0x4CEA30, and the int32 licence expiration timestamp at 0x4CE69C.
This can be made automatic by using "Table" menu in Cheat Engine, then "Show Cheat Table Lua Script"

Cheat Engine view showing where the 'LUA Script' menu is
Open the LUA script

Did you notice the extra fields? "Time left" was the address of the time limit integer in the v2.CC version of the game (I actually cracked the time limit on this version first, and then saw a newer v2.H existed, to I redid the process with this v2.H version, which was fairly easy once you know "look for Writable non-Executable 32bits integer address that decrese along the game playing").
The "Licence infos" is not an address fields: it's a header, for easier reading.
The "Nb de points" is the number of points my character has, I collected and kept this when looking for the 49999 constant

And just write your script here.

Cheat Engine view showing my LUA script
Write the LUA script for automation

I made it simple: 1st call is supposed to hide Cheat Engine windows (but this doesn't work, it's displayed anyway so, nevermind it!).
Then, I wait 27 seconds, which is enough to start the welcome screen, hit "play" button, and get into the game.
Then, I bind the Cheat Engine process to the "arsenal2_game.exe" process, which is the game's process name.
Then, I get the addresses (which are luckily all static addresses!) for each of the 4 values to tamper (the description is an arbitrary text I wrote in the addresses table description for each address)
Last, I set the values to arbitrary things (1.6G for timestamps, and 2G for points limit) and freeze the values so they won't change during game (the most important one being the "time left" value but freezing them all is fine too).

Save this. Now, to play the game, the only thing to do is double click the Cheat Engine saved file, say "Yes, run LUA script" (you might check 'Always' to not be prompted again).

Cheat Engine view asking if you want to run the LUA script
Run the LUA script with Cheat Engine by simply double-clicking the file

The Welcome screen
Then run arsenal2go.exe and hit "Play demo"

The main menu in game
Once in game, wait a bit for the 27s timer to end

Cheat Engine window pops out, with everything configured
Cheat Engine pops, all configured (notice the red cross on frozen values)

In game view showing the licence has been granted to you
And you'll see in game that the licence is unlocked!

What remains now?

So, I cracked this game. What now?
First, never expect to make a thick client "uncrackable". It will always be. Protect the data instead: if I attempted to play the game online, I must be forbidden to join the online servers, because the server must hold and check the licence, using some sort of login.
If the program requires no online data, then it will be crackable, no matter what, so don't waste time and risk/bring bugs to "avoid" this.

Next steps I could try would be (someday maybe) to find where the licenced name is, so I don't have "Licence granted to [EMPTY STRING HERE]". Or I could try to break the adf file format, and extract the game resources. This file is certainly simply "encrypted" in some way, maybe with a simple XOR or so. In the assembly code and the game's process memory, you'll actually see a lot of file names like "tektonfortress.apf" or "sprites/tree.pcx", which makes me think the program access the adf file like it would access a zip. Or, last, I could actually try to crack the three exes for good (you may download them here if you want to try) but that sounds uselessly complex.

Summary for the lazy

Process the following way:
  1. Download Cheat Engine
  2. Download ARSENAL2 Extended Power v2.H
  3. Download my LUA script for Cheat Engine
  4. Install Cheat Engine
  5. Extract ARSENAL in a directory
  6. Extract the LUA script in that directory too
  7. Double-click to run the LUA script saying "Yes, Always" when CE asks "do you want to run LUA script?"
  8. Run the game
  9. Hit "play demo"
  10. Wait for CE to pop out
  11. Go back to game and see it's now "licenced to"
  12. Play unlimited game
  13. You may contact me on Twitter if needed

All the ressources

A lot of scams exists for "cracking" this game, so, if you believe none of my links, you can make the LUA script yourself, it's written below. The Cheat table is also given, so you can grab the addresses by yourself (I've added some interesting addresses too if you're curious). All links above are official links, so no virus and no malware.
Note that my airgaped Windows is fully offline, and its current date is often January 2002, so the timestamp values suggested here might have to be increased depending on when you're reading this article.

hideAllCEWindows() sleep(27000) openProcess("arsenal2_game.exe") local addr = getAddressList() local tleft = addr.getMemoryRecordByDescription("Time left new version") local passp = addr.getMemoryRecordByDescription("Passport expiration timestamp") local liclock = addr.getMemoryRecordByDescription("Unlock licence timestamp") local maxpts = addr.getMemoryRecordByDescription("Max allowed points") tleft.Active = true tleft.Value = "1610612736" passp.Active = true passp.Value = "1610612736" liclock.Active = true liclock.Value = "1610612736" maxpts.Active = true maxpts.Value = "2147483647"
My LUA Script

Address Type Description Suggested value
0x4C0E70 32int Time left for the v2.cc version Freeze this to 100000, ONLY for the v2.CC (old version)
0x4CE3B8 32int Time left for the v2.H version (latest one) Freeze this to 100000
0x4CEA0C 32int Allows you to make your licence expired Leave it to 0
0x4CEA30 32int Passport expiration timestamp Freeze this to 1610612736 (or whatever suits you)
0x4CE69C 32int Licence expiration timestamp Freeze this to 1610612736 (or whatever suits you)
0x4D9378 32int Number of points your character has Set to whatever you want, it's useless to freeze
My character is named "Derg", I don't know if this influences the address position
0x4D937C 16int Character's reputation Negative is bad reputation, positive is good, from -20k to +20k
0x4D9380 8int
(3 times)
Reputation, Ego and other character's infos Each value seems to be 0-8 ranged or so
0x4D9370 8int Your nation's color Seems 0-8 ranged too
0x4D9374 8int Your current military grade Seems useless to tamper: just increase your points, play, get some score (positive or not) and quit to have your promotion
0x46869B 32int Max points you can have Freeze to 2147483647 so you won't be stuck to "Sergent" grade
Cheat engine table with interesting addresses

Tips for crackers

Last, some tips when cracking games or softwares
  1. Focus on your goal, not on means
    And achieve it the simplest way you can, hence why I was falling back from OllyDbg to Cheat Engine (way easier to tamper with real time game memory rather than the stored exes)
  2. Always write notes
    You don't want to spend hours searching where something is located in the memory, and then loose everything because your memory tampering crashed the game/program, so have a piece of paper and note stuff along your cracking journey
  3. Be lazy, but not too much
    Don't be afraid to tamper with large bunch of memory data if it's the easiest and fastest way, but don't try to tamper with every byte because you're too lazy to understand/guess how the code works
  4. Be also smart
    Understand the underlying code, or at least, principles of implementation. And if something doesn't seem to work the way you guessed, make other guesses