Author Topic: String Hack  (Read 4345 times)

0 Members and 1 Guest are viewing this topic.

Offline AGKorson

String Hack
« on: August 15, 2019, 07:47:21 PM »
Sierra was notorious for not including error checks and buffer overflow checks in AGI. Even simple mistakes in source code can result in situations that cause unexpected results and crashing AGI.

But this can actually be used to your advantage to do some really cool advanced coding to 'hack' the interpreter on the fly from within your AGI game.

The key lies in the set.string(str sA, msg mB) command. It's no surprise that AGI does not validate the string number A; it will write the value of mB wherever sA points to. This means that using values larger than 23 will let you overwrite program memory. Of course, this usually crashes AGI, but if you know what's in those areas past the string table and you are careful, you can modify the underlying code to make the interpreter do what you want.

One area that is easy to manipulate is the command function offset table; it is located in memory around the spot where strings '26' through '43' would be. Each command function table entry consists of a two byte offset followed by a byte that tells how many arguments, and another byte with a bit field to tell what kind of argument (number or variable). The only value that AGI uses is the offset; the argument info is not used so you don't need to worry about overwriting those two bytes. By writing a string value that replaces just the two bytes of the offset of the command you want to hijack, you can easily redirect those commands to anywhere in program memory.

To take advantage of this, you can use the set.string command to add bytes anywhere in memory to create a new function, then change the offset in the command table.

I've attached a logic file that you can add to a test game to see this work first hand. A couple of important things to keep in mind:

  • the code will only compile in WinAGI 1.2.5 or later; other compilers cannot handle creating logics that have messages with special characters (less than 0x20 or greater than 0x7F)
  • this will ONLY work on the original DOS interpeter; if you try to run this in NAGI, SCUMMVM or any other non-Sierra interpreter it will not work
  • the code is VERY MUCH version specific; do not try to run this with any interpreter other than v2.917. Each version has slightly different address values for internal functions and data storage
  • the set.string command has two quirks to it that you need to be aware of; first of all, you can't write a string longer than 40 characters; if you try, AGI will truncate the string at 39 characters and add a single null character (0x00) to the end; secondly, if the string is less than 40 characters, AGI adds TWO null characters to the end; this makes it a bit trickier to create custom functions (the sample code shows an easy workaround to both of these limitations)
  • all string copying gets terminated when a null character (0x00) is found; to create custom functions that have zeros in it, you need to use a series of strings that work backwards, which lets you then control where the null characters show up (the sample code demonstrates this)

If you want to see this in action, create a sample game, setting it's version to 2.917. Find a copy of Sierra's AGI files from that version to run your game in a DOSBox setting. Then import the StringHack.lgc logic into your game, and call it from logic 0 just before calling the game setup logic.

The demo does four things:

  • it replaces the init.disk command with a function that prints the value of string s9
  • it replaces the set.string command with a modified version that is not limited to 40 characters, and also does not add extra null characters
  • it modifies the message displayed when you quit the game
  • it modifies the command so you can set your game ID without causing AGI to quit (save a game to see it in action)

There really is no limit to what you could do with this hack. The set.string command only lets you modify code following the string table, but you could easily create a bootstrap function there that then lets you modify code anywhere in program memory. You could then completely modify AGI on the fly. Two examples I can think of that this could be useful for would be the AGIMOUSE and the AGIPAL hacks; a single logic, run once at game load up could include all the code needed without needing a special interpeter!

If you have questions about the details on how this works, let me know, I'd be happy to explain the whole thing in more depth. And if you create any hacks that you think others might be interested, it'd be nice to share your code so others can use it too.

Happy hacking!

Offline Collector

Re: String Hack
« Reply #1 on: August 15, 2019, 08:50:09 PM »
Might be nice to add to the Wiki, too.
KQII Remake Pic

Offline OmerMor

Re: String Hack
« Reply #2 on: August 16, 2019, 05:04:20 PM »
That's really cool! Nice work!

SMF 2.0.19 | SMF © 2021, Simple Machines
Simple Audio Video Embedder

Page created in 0.035 seconds with 21 queries.