• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

fail project

Status
Not open for further replies.
Level 5
Joined
Jun 16, 2004
Messages
108
Originally I posted this elsewhere, but figured I would put it here too. An out of date tool that might be able to be useful to someone.



I wrote a simple jass debugger for fun. But first I will mention some important things:

- this will only work on game version 1.28.2
- you should not play online with this tool running, as it modifies memory and can get you banned
- the tool will try to disconnect you if you are in a multiplayer game, so do not use it online
- the tool is quite unstable, and can crash / fail at several points of use


A beginner's guide to failing successfully:
- download and extract the archive
- verify you can run fail.exe in the /fail directory; if you are missing dependencies you may need whatever runtime matches VS 2017
- copy your common.j and Blizzard.j files into the /fail/script directory.
- start the game in windowed mode (you should really only try using this tool in windowed mode)
- make sure you are not online (ideally be at the main menu screen)
- run EMS.exe as an admin
- in the ems console that pops up, type in "start" (without quotation marks) and then press enter
- if it all works out, the ems console should start spitting out a bunch of text and wc3 should still be running properly; if things do not work out, wc3 will probably crash - and you may need to kill the process (war3.exe) in your task manager (try running the game again if it fails - and kill the War3.exe task if it says it cannot initialize).
- the bottom few lines in the ems console should mention something about debugutility loading
- now start fail.exe
- type the game process ID (find it in your task manager) into the text box in the test window in the bottom right pane, then press enter
- press F9 to resume the game after attaching
- the log window in the bottom left of fail.exe should have a "test print lua call" message, and the status bar at the bottom left should say "RUNNING"
- now try running your map in single player or in LAN (alone)
- once you are in game and past the loading screen, try pressing Alt-G (or generate symbols in the debug menu) while fail.exe is focused; only do this once
- at this point fail.exe will attempt to recompile the map script (hope you are not using any common.ai functionality); if it succeeds then the ems console should mention replacing functions; if it fails, the log window in fail.exe should mention what it failed to do
- if you reached this far, everything should be setup to fully use the debugger's functionality


Some other things to try after doing the above steps...

Viewing a function's code:
- open the symbol list viewer (Alt-F, or find the option in the debug menu)
- narrow the search using the search text box at the top if desired; search works by separating the search field into words (words are separated by spaces); each word must be part of the symbol name for it to match; search is case insensitive if all search terms are lower case
- double click a symbol you want to view; this should put it in the symbol viewer in the center
- optionally, you may press Alt-B in the symbol viewer to show the "assembly" of the function

Setting a breakpoint:
- do the "Viewing a function's code" steps, then select a line in the symbol viewer
- press F2 to set the breakpoint (or find the option in the debug menu); this will put a red dot in the margin of the line
- the next time that line is executed, the game should pause and the debugger will show a yellow arrow on the line with the breakpoint
- from there you can step through the code using F10 and F11 (step over / step in)

Modifying a function at runtime:
- do the "Viewing a function's code" steps, then press Alt-S
- when the editor window pops up, press Alt-C while it has focus
- modify the function to your liking (note that you cannot change the parameters and return type)
- press Alt-B to compile and put it in the game
- note: each time functions are replaced, some memory is "leaked," and only reclaimed after playing through another game and quitting that game

Travel up the stack when at a breakpoint:
- do the "Setting a breakpoint" steps, then when you are paused at a breakpoint:
- double click one of the stack frames in the stack window, this will change the active stack frame
- the top stack value might be a function, if it is you can double click it to switch it to be the active frame (this also changes the symbol viewer code to match that context)
- note: each function's execution has its own stack frame
- press Alt-V to view active instances; if there is more than one, that means that the script started another instance (commonly known as a thread in the jassing community); you can double click instance entries to switch to them
- at any time while the game is paused, press F1 to switch back to the currently executing function

Viewing referenced globals:
- press Alt-W to open the referenced globals window

Detaching:
- generally speaking you should probably not detach, but if you do, make sure the game is not paused when you try, then click detach
- note that if the debugger is closed while attached, the game will be closed too

Some other features:
- if the op limit is hit while fail.exe is attached with symbols generated, the game will be paused and the debugger will show the active script that hit the op limit
- if the game crashes due to script execution, the active script might be shown (a crash such as by calling CinematicFadeBJ with a bad path)
- the status bar at the lower right will show how many ops have been used so far, when the game is paused by the debugger (the default limit is 300000)

Miscellaneous:
- probably requires running on 64 bit windows (it is a 32 bit exe, but there is one particular winapi call that assumes the system is 64 bit; most of the functionality might still work on a 32 bit system)
- may require running as an admin, I would try without it first


Finally, some things to keep in mind:

- symbol generation works by recompiling the map script; the compiler is not the same as the game's compiler, so it will have different behavior in numerous cases ... it can fail to compile, or generate the wrong code, etc
- the game can crash at numerous points while using this tool (most often at the ems.exe hooking the game step in my experience)
- do not try to use it while online (battle.net and others)
- since the tool has stability issues, I do not recommend it for any serious use
- since the tool is just for fun on my part, I probably will not support it


In any case, give it a try if you are curious. Check out the screenshot I attached.
 

Attachments

  • publicems-17.0602-3.7z
    3.9 MB · Views: 121
  • faildebug.PNG
    faildebug.PNG
    560.3 KB · Views: 301

MindWorX

Tool Moderator
Level 20
Joined
Aug 3, 2004
Messages
709
Very interesting. How does the game handle being paused? When I was working on a debugger and paused it would result in the game playing catch up once you resumed again.
Like, if you paused for 10 seconds, the game would immediately simulate 10 seconds of gameplay once you hit resume. Similar to how it reacts to normal lag.
 
Level 5
Joined
Jun 16, 2004
Messages
108
Very interesting. How does the game handle being paused? When I was working on a debugger and paused it would result in the game playing catch up once you resumed again.
Like, if you paused for 10 seconds, the game would immediately simulate 10 seconds of gameplay once you hit resume. Similar to how it reacts to normal lag.
The tool pauses all the game's threads (except for a debug thread the debug module creates), so however the game responds to that is what will happen. Not able to test right now, but from what I remember it does skip ahead to some degree. It may work just like you describe.
Can you please upload the binaries of version 1.28.2 ("Warcraft III.exe", "game.dll" and "storm.dll")? Because I have only 1.28.1 installed here, and if I open the launcher, it will try to install 1.28.5
I will probably just update the program to work with 1.28.5.
 

MindWorX

Tool Moderator
Level 20
Joined
Aug 3, 2004
Messages
709
The tool pauses all the game's threads (except for a debug thread the debug module creates), so however the game responds to that is what will happen. Not able to test right now, but from what I remember it does skip ahead to some degree. It may work just like you describe.
Fair enough. What I was thinking about doing to solve the issue was hooking into GetTickCount and return a fake tickcount to WC3, so it doesn't see that time has passed. Maybe you'd be able to try it out?

In any case though, very awesome tool. Any idea how well it'll play with other injected systems?
 
Level 5
Joined
Jun 16, 2004
Messages
108
Updated for 1.28.5. Download is in this post. You may want to keep a copy of 1.28.5 around if you want to continue using this tool, as my motivation to update for new game versions is pretty lacking.

Fair enough. What I was thinking about doing to solve the issue was hooking into GetTickCount and return a fake tickcount to WC3, so it doesn't see that time has passed. Maybe you'd be able to try it out?

In any case though, very awesome tool. Any idea how well it'll play with other injected systems?

For the time issue, I usually test using LAN, and I am not sure if I typically see the behavior you are describing. I tried playing with a few AI just now in a melee game LAN match, and did not see obvious catch up happening after breaking for a short while.

I figure multiple tools will work as long as the things writing memory do not write over each other.

Though the only way to know for sure would be to test it, I think. This debugger + ems does do some things like overwrite existing operation IDs and introduce new ones, and it hooks into what the game does when the game hits an unknown operation.
 

Attachments

  • publicems-2017.1029.7z
    3.9 MB · Views: 97
Last edited:
Level 5
Joined
Jun 16, 2004
Messages
108
Added an updated version of the tool.
Changes:
- Stops trying to do implicit casts on return to match game behavior (the game will let you do return -1 in a real returning function, for example, and will not actually convert that -1 to a real)
- Fixed short circuiting boolean logic. The assumed behavior was incorrect before, leading to an incorrect implementation (found thanks to a post by Aniki)
- Added ForGroup and ForForce to step in logic

Interesting tool. Could you upload the source code too in case you cease the development?

In order for the debugger to be easily updatable by the community (for new game patches), I would basically need to release the source to EMS. Though if I did that then I would have no control over the toolset's existence in the wild from that point on. I do not want an unrestricted EMS rolling about because the plugin interface it provides would allow for writing some pretty trivial cheats in lua. As such, it is unlikely the source will be released.
 

Attachments

  • publicems-2018.0209.7z
    3.9 MB · Views: 73
Last edited:

MindWorX

Tool Moderator
Level 20
Joined
Aug 3, 2004
Messages
709
In order for the debugger to be easily updatable by the community (for new game patches), I would basically need to release the source to EMS. Though if I did that then I would have no control over the toolset's existence in the wild from that point on. I do not want an unrestricted EMS rolling about because the plugin interface it provides would allow for writing some pretty trivial cheats in lua. As such, it is unlikely the source will be released.
Writing cheats is already trivial with other solutions like Grimoire and SharpCraft, both of which are open source. And people that want to cheat are going to cheat, it doens't matter what tools are available. Keep in mind that people are even willing to pay for maphacks. This shouldn't be a stopping block in sharing knowledge about how we can improve the game.
 
Level 5
Joined
Jun 16, 2004
Messages
108
New version with some small additions. Most of the new stuff is shown in some small way in the screenshot in this post.

- *.j scripts are extracted automatically now, so you do not have to manually do the step of placing them in the right directories
- fixed thread_jvm.lua in the public build (was not finding jasstool.exe properly)

- added support for inline "assembly" to the compiler. This allows for using the various VM ops at a low level directly when experimenting with script changes in the debugger


assembler specifics:
Example assembly usage:
Code:
local integer result = 0
{asm
//    loadliteral integer, 55, r1
//    loadliteral integer, 12, r2
//    mod r1, r2, r2
//    writevar r2, "result"
endasm}
call BJDebugMsg("result is: " + I2S(result)) // ==> result is: 7
Limitations of the assembly:
- only usable at the function statement level (inside function ... endfunction blocks)
- jumps are currently only usable within the inline assembly block
- the syntax is written as required above, the inline assembly block begins with "{asm", ends with "endasm}", and has a commented assembly line on each line in between
- Inline assembly errors are a bit cryptic. Errors will mention two line numbers, one line number will show where the inline assembly block occurs in the script, and the other line number will be where the error is local to the inline assembly itself
- it is very well tested, in fact, I tested the above snippet and like two others!

As for some of the things it allows you to do...
- you can have the game allocate for new globals by using the global operation and putting it in a function, then running the function (additional steps are required to actually make use of the global in script)
- you can use the operations that the game's script compiler either does not emit or does not allow you to easily use (such as modulo, global, and the boolean and/or operations)

There probably is not much use for the inline assembler, but it was fun to write.
Check out format.txt (in the jasstool directory) for the list of assembly instructions. Note that all instructions are meant to be lowercase, despite how the file is written.

- added a script header editor window accessible from the script menu. This allows specifying script that basically goes above/before the scripts you might write and try to run from the script editor. Basically put global declarations in here (after having the game allocate for them by running the global op), as well as function definitions (nothing special needed for functions)

- added an "execute current script" button to the script editor. This takes what is in the script editor, wraps it in a function, then runs the function. There is also a "disable TSA" checkbox which, when active, prevents the TriggerSleepAction native from functioning. It is important that the check box be active if you run a script that calls TSA, directly or indirectly (such as through nested function calls). TSA is only safe if there is a trigger executing, such as by calling TriggerExecute. You can crash if you call TSA outside of a trigger's execution.

- the compiler is slower due to the above stuff! Enjoy maybe having a few seconds longer on the initial compile/build process to take a sip of your drink or something. Also, the inline assembly in particular caused some scary changes in the compiler that may have horrifically broken a number of things.

I will also mention that all of the commands mentioned in another thread ( loading jass functions at runtime ) are usable with this debugger release, as this debugger is basically built on top of the stuff in that post to some extent.


Writing cheats is already trivial with other solutions like Grimoire and SharpCraft, both of which are open source. And people that want to cheat are going to cheat, it doens't matter what tools are available. Keep in mind that people are even willing to pay for maphacks. This shouldn't be a stopping block in sharing knowledge about how we can improve the game.

When I say trivial, I mean someone popping open notepad and then cranking out a JASS-like script in a short time to give an unfair advantage in, say, a ladder game. This release is meant to not work in multiplayer and I want it to remain that way.
 

Attachments

  • publicems-2018.0221.7z
    3.9 MB · Views: 51
  • faildebug2.PNG
    faildebug2.PNG
    95.2 KB · Views: 85
Last edited:

MindWorX

Tool Moderator
Level 20
Joined
Aug 3, 2004
Messages
709
When I say trivial, I mean someone popping open notepad and then cranking out a JASS-like script in a short time to give an unfair advantage in, say, a ladder game. This release is meant to not work in multiplayer and I want it to remain that way.
But it's just as trivial with the SharpCraft system that powers WEX. You can inject all the JASS you'd like with very little effort. But I have a feeling anti cheating isn't the real reason, so I doubt any reasoning is going to change your mind.
 
Level 5
Joined
Jun 16, 2004
Messages
108
New version with some small additions. With this version most of the functionality I wanted in this tool will be accounted for. Besides perhaps bug fixes, not sure if anything will be forthcoming after this. I suppose it depends on how much of a pain it would be to update for 1.29.

Changes in version 2018.0226:
- hopefully fixed (or at least reduced the frequency of) the crash when EMS tries to hook into the game
- hopefully fixed (or at least reduced the frequency of) a timing error where the debugger does not properly attach to the game
- added basic save/load of window positions and sizes. The debugger tries to save the data into /fail/luabase/save/savedata.lua, so if you want to reset your save data you can delete that file. Also, you can remove the save/load functionality entirely by deleting /fail/luabase/events/shutdown/save_windows.lua and /fail/luabase/events/startup/load_windows.lua
- reduced memory leaks when replacing functions. Old functions that are replaced should now be deleted when it is possible to do so. This change increased the complexity of the replacement process/logic so it may have broken things
- added window titles/captions to most of the windows so that their purpose is more apparent
- added an "attach to" button which pops up a process list, which by default filters for processes with "war" in the name; this allows for easily attaching to the game (more so than before)
- added a new "window" menu which has options for showing the various core windows. This was added due to save/load, where the hidden windows might be permanently hidden if they were closed

- added a simple leak monitoring tool
Limitations of the leak monitor:
- it only tracks by patching creation natives and destroy natives (this means types that decay on their own will not be matched to a "destroy" by the leak monitor)
- currently, it only tracks effects, groups, locations, and timers (you can try to fiddle around with what it tracks by taking a look near the top of the /fail/luainclude/faildebug/leakconfig.lua file; creations should return the type that is created, and destroys should take one parameter for the value to be cleaned up)
- in order for leaks to be tracked, you need to first generate symbols (Debug -> Generate Symbols) and then activate the leak monitor (Leak -> Activate Leak Tracker); both of which need to happen while the debugger is attached and you are in a game
- another significant limitation is that the "activate" process actually patches bytecode, so you need to repeat the activation process every time you inject new code via the debugger

Other information about the leak monitor:
- you can open up the leak monitor window "Show Leak Window" in the leak menu to see what locations have done allocations for the configured types
- leak monitor entries show the name of the function the allocation occurs in, as well as a number (this number is the op the native call happens on, not the line)
- you can double click entries in the leak monitor to view the line that allocates that entry. After that, you can place a breakpoint near that spot if you want to see the call stack that causes the allocation

-----

2018.0227 minor update:
- step over logic improved a bit (now there should be less incidences of a step over causing a resume); step over and step in logic are both kind of silly at the moment and make assumptions about how the code is compiled, so there are likely to be more problems I have not seen yet
- leak monitor orders from greatest to least
- leak monitor now updates every 500 milliseconds to reduce spamming the pipe / improve debugger responsiveness (where there are lots of allocates/deallocates happening)
 

Attachments

  • publicems-2018.0226.7z
    4 MB · Views: 63
  • faildebug3.PNG
    faildebug3.PNG
    33.5 KB · Views: 105
  • publicems-2018.0227.7z
    4 MB · Views: 95
Last edited:
Level 5
Joined
Jun 16, 2004
Messages
108
I have not. In addition, based on some things I have heard about 1.30, I might not update this anymore.
 
Status
Not open for further replies.
Top