• 🏆 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!

MemHack how to detect if map has a virus?

Level 3
Joined
May 10, 2022
Messages
14
So as in title I was curious if there is anybody with knowledge how to protect myself from these viruses if I play on 1.26.
I saw some scripts that does actually install viruses on your PC, but I am not sure which wc versions were this scripts made for but they seemed very real and legit.
They were about downloading some stuff from url.
I was think about just checking maps script before playing it to detect these viruses but the point is I don't know what to search and what to expect exactly.
Is there anybody with full knowledge of what are people capable of in 1.26 patch? (knowledge about lower and higher patches would be nice too)
 
Level 3
Joined
May 10, 2022
Messages
14
Run Warcraft 3 in a sandbox or a virtual machine. While memhack is known, I am pretty sure there are dozens of undiscovered vulnerabilities in newer patches too, they didn't change too much of the core structure.
I don't know a map that has memhack with virus. Cause memhack is not always virus. Memhack is just thing found by map makers that can do very good things in maps but also u can make a virus
 
Last edited:
Level 3
Joined
May 10, 2022
Messages
14
With a sandbox/ VM you don't need to worry. They will not block memhack but if any map tries to execute commands, these will not reach your main system and data.
yes i know this all man. This is not what post is about and I already have all knowledge that u said already. Post is about how to detect memhack + virus in war3 scirpts. Cause I don't feel like running wc3 always in sandbox or virtual machine
 
Level 19
Joined
Jan 3, 2022
Messages
320
A script that exploits memhack has access to all game code and system APIs. At some point it will have to start its own payload whether by starting a thread, a process or an external program. There would be infinitely many ways to obfuscate the Jass code to hide the escape phase. Do you want to write a heuristic-based antivirus?


JASS:
function Typecast1 takes nothing returns nothing
    local integer l__Code
    local code l__Int
endfunction

function C2I takes code c returns integer
    call setCode(c)
    loop //Loop is not required, I'm using it just to fool Pjass
        return l__Code
    endloop
    return 0
endfunction

function I2C takes integer i returns code
    call setInt(i)
    loop //Loop is not required, I'm using it just to fool Pjass
        return l__Int
    endloop
    return null
endfunction

/// many lines of code

function UnlockMemory takes nothing returns nothing
    local integer array stand //The execution of this line is skipped
    call ForForce(bj_FORCE_PLAYER[0], I2C(2+C2I(function NewGlobal)))
    call ForForce(bj_FORCE_PLAYER[0], I2C(8+C2I(function SetGlobal)))
//    /*local array "stand" can now read memory, but not write.
//    The bytecode unlocks the ability to read and write memory
//    with the "Memory" array*/
    call InitArray( 0 )
    call InitArray(stand[GetArrayAddress()/4])
    call InitBytecode(stand[C2I(function ReadMemory)/4 + 13], stand[GetArrayAddress()/4+3]+4) //obtain the id of variable "Memory"
    call ForForce(bj_FORCE_PLAYER[0], I2C(stand[GetBytecodeAddress()/4+3])) //run bytecode from the array
endfunction
From here: Memory hack (warning, the page loads a lot of code and that's very slow even on PC)

Here's an example of memhack being used. ForForce takes a code/function type as a second argument. There are more functions like ForForce that take it, however I don't know if they are exploitable too. If you wanted to "just checking maps script before playing" then you would need to audit the entirety of code that uses memhack, the other functions I don't know about (or none) and make sure its not passing some exploit vectors into ForForce.

I think this approach is certainly not what you want to do for each map you are gonna play (run MPQEditor, extract war3map.j, inspect it) that's why I didn't start with this (XY Problem).
 
Level 9
Joined
Jul 20, 2018
Messages
176
If you afraid of viruses, you should at first do not run WC3 with admin rights. If for some reason WC3 requires you to run with admin right, most likely it is inside program files or other restricted directory. Move WC3 from it to other place.
 
Level 3
Joined
May 10, 2022
Messages
14
A script that exploits memhack has access to all game code and system APIs. At some point it will have to start its own payload whether by starting a thread, a process or an external program. There would be infinitely many ways to obfuscate the Jass code to hide the escape phase. Do you want to write a heuristic-based antivirus?


JASS:
function Typecast1 takes nothing returns nothing
    local integer l__Code
    local code l__Int
endfunction

function C2I takes code c returns integer
    call setCode(c)
    loop //Loop is not required, I'm using it just to fool Pjass
        return l__Code
    endloop
    return 0
endfunction

function I2C takes integer i returns code
    call setInt(i)
    loop //Loop is not required, I'm using it just to fool Pjass
        return l__Int
    endloop
    return null
endfunction

/// many lines of code

function UnlockMemory takes nothing returns nothing
    local integer array stand //The execution of this line is skipped
    call ForForce(bj_FORCE_PLAYER[0], I2C(2+C2I(function NewGlobal)))
    call ForForce(bj_FORCE_PLAYER[0], I2C(8+C2I(function SetGlobal)))
//    /*local array "stand" can now read memory, but not write.
//    The bytecode unlocks the ability to read and write memory
//    with the "Memory" array*/
    call InitArray( 0 )
    call InitArray(stand[GetArrayAddress()/4])
    call InitBytecode(stand[C2I(function ReadMemory)/4 + 13], stand[GetArrayAddress()/4+3]+4) //obtain the id of variable "Memory"
    call ForForce(bj_FORCE_PLAYER[0], I2C(stand[GetBytecodeAddress()/4+3])) //run bytecode from the array
endfunction
From here: Memory hack (warning, the page loads a lot of code and that's very slow even on PC)

Here's an example of memhack being used. ForForce takes a code/function type as a second argument. There are more functions like ForForce that take it, however I don't know if they are exploitable too. If you wanted to "just checking maps script before playing" then you would need to audit the entirety of code that uses memhack, the other functions I don't know about (or none) and make sure its not passing some exploit vectors into ForForce.

I think this approach is certainly not what you want to do for each map you are gonna play (run MPQEditor, extract war3map.j, inspect it) that's why I didn't start with this (XY Problem).
yeah nice, but I mean there is some group of functions globals or whatever (I didn't really started learing jass so I don't know how it's called) that allows memhack. And this way you could detect if scripts file has those >stable names< used to allow memhack at all.
The same as there are certain commands to detect if players write something on chat like GetEventPlayerChatString TriggerRegisterPlayerChatEvent
 
Level 3
Joined
May 10, 2022
Messages
14
If you afraid of viruses, you should at first do not run WC3 with admin rights. If for some reason WC3 requires you to run with admin right, most likely it is inside program files or other restricted directory. Move WC3 from it to other place.
yeah my wc doesn't run with admins rights I belive at least I don't have to confirm anything and it doesn't have shield icon
 
Memhack is just thing found by map makers that can do very good things in maps but also u can make a virus
I think for each person, it may be up to the user to consider: does the good outweigh the bad?

For me, it doesn't. I don't ever want to play a memhack map. The time necessary to audit it for security would be greater than my attention span, and the necessity for auditing is extremely high. Memhack is commonly achieved through Jass, and Jass executes to create the Player Lobby, so a memhack virus could in theory infect you while browsing your map list in single player, even if you do not click "Play" on the map, simply as a result of clicking to see its lobby ingame.

yeah nice, but I mean there is some group of functions globals or whatever (I didn't really started learing jass so I don't know how it's called) that allows memhack. And this way you could detect if scripts file has those >stable names< used to allow memhack at all.
As @Luashine indicated, the answer to your question is absolutely not. The entire idea of memhack is dependent on breaking the game as using its code in ways outside of the original programming intention. So by definition there are not consistent rules how to break the game. And so there are not consistent names used for memhack, especially not if the developer is making a virus and therefore incentivised to choose different names.

You could try to make a map scanner that looks for many common known memhack paradigms, but it would always be possible that someone might know more than you and get around it. It would become like a technological arms race rather than a one-and-for-all solution, in theory.

In 2016 when leandrotp discovered 1.26 was still vulnerable, I replied to his thread saying that means we should rewrite the game to escape this problem. I wanted to be as far away from memhack as possible.

In the 7 years since that time, I have amassed technology and attempted to create a LibGDX Java game protected by Java's standardized memory exceptions (IndexOutOfBoundsException) that is making progress towards being able to simulate the Warcraft 3 experience in an external program so that we do not need to play the real one. My work is not done, and sometimes like recently I go for months at a time without doing productive work on this hobby, but at one point I did attempt to launch DotA for 1.26 inside of my LibGDX game that simulates Warcraft 3. Inside the JVM, when the memory hack system came online in Jass, it was unable to escape and started senselessly printing that its attempts to read memory were all returning 0's and it dumped out a URL where it wanted me to report the problem to its creators. Of course, I did not report it. The LibGDX game is invulnerable to memhack anyway.

But you could imagine how a JASS interpreter with memory protection like Java could in theory be used as a component of a map checker, maybe. But again, that would be the technology arms race situation unless you were actually intending to play the LibGDX game and not Warcraft 3.
 
Level 3
Joined
May 10, 2022
Messages
14
I think for each person, it may be up to the user to consider: does the good outweigh the bad?

For me, it doesn't. I don't ever want to play a memhack map. The time necessary to audit it for security would be greater than my attention span, and the necessity for auditing is extremely high. Memhack is commonly achieved through Jass, and Jass executes to create the Player Lobby, so a memhack virus could in theory infect you while browsing your map list in single player, even if you do not click "Play" on the map, simply as a result of clicking to see its lobby ingame.


As @Luashine indicated, the answer to your question is absolutely not. The entire idea of memhack is dependent on breaking the game as using its code in ways outside of the original programming intention. So by definition there are not consistent rules how to break the game. And so there are not consistent names used for memhack, especially not if the developer is making a virus and therefore incentivised to choose different names.

You could try to make a map scanner that looks for many common known memhack paradigms, but it would always be possible that someone might know more than you and get around it. It would become like a technological arms race rather than a one-and-for-all solution, in theory.

In 2016 when leandrotp discovered 1.26 was still vulnerable, I replied to his thread saying that means we should rewrite the game to escape this problem. I wanted to be as far away from memhack as possible.

In the 7 years since that time, I have amassed technology and attempted to create a LibGDX Java game protected by Java's standardized memory exceptions (IndexOutOfBoundsException) that is making progress towards being able to simulate the Warcraft 3 experience in an external program so that we do not need to play the real one. My work is not done, and sometimes like recently I go for months at a time without doing productive work on this hobby, but at one point I did attempt to launch DotA for 1.26 inside of my LibGDX game that simulates Warcraft 3. Inside the JVM, when the memory hack system came online in Jass, it was unable to escape and started senselessly printing that its attempts to read memory were all returning 0's and it dumped out a URL where it wanted me to report the problem to its creators. Of course, I did not report it. The LibGDX game is invulnerable to memhack anyway.

But you could imagine how a JASS interpreter with memory protection like Java could in theory be used as a component of a map checker, maybe. But again, that would be the technology arms race situation unless you were actually intending to play the LibGDX game and not Warcraft 3.
oh wow I didn't know it can do so as well while browsing lol.
I agree with you mostly.
But I got one thing, there has to be some way to implement Memhack, and no matter what purpose of this Memhack would be but somehow map maker has to say IN JASS, to call functions or whatever that trigger Memhack. And I am not saying that there is just one way of calling out Memhack to take place at all but my point is to detect all the things that can trigger Memhack at all. Which I mean for example.
All possible commands to detect if players typed something on chat are: GetEventPlayerChatString and TriggerRegisterPlayerChatEvent (i don't know if there are only true but let's say there are just as an example) so this way we can detect if map has any function to detect players chat messages. And this way we can detect the unwanted thing for example.

Maybe I don't understand something but to use memhack at all you have to first make code in JASS that will trigger MemHack and this memhack will do whatever doesn't matter what.
So this way we can detect by JASS functions or calls or whatever I don't know how is it called but we can detect if any gateway for Memhack has been written, it might not be memhack but it doesn't matter, what matters is there is a chance for memhack to take place.
It would be just bascially the same as you would detect if map has player's chat detection which is just searching files for GetEventPlayerChatString and TriggerRegisterPlayerChatEvent. If you can't do this for memhack then tell me why and give me a few examples of how memhack is implemented
 
If you can't do this for memhack then tell me why and give me a few examples of how memhack is implemented
I don't implement memhack, personally. My understanding of it is only rudimentary. But here is my (fairly uninformed) understanding -- and maybe someone else later will describe more, better, and in more detail:

The premise of memhack is to hack the computer by modifying computer memory that was not meant to be modifiable. To modify computer memory for which there is no JASS function to modify, we must break the system itself and cause it to perform operations that were not originally intended. In order to break the system itself, ideally it is beneficial to understand the system itself to an extraordinary degree.

When the ability to break the system itself was first discovered, the most obvious flaw in the system was called I2C. This naming convention was inspired by default functions in JASS, but is not the same. For example, there is a JASS function available on Warcraft 3 by default called I2S. The idea of the I2S function is that it is an "integer to string" (abbreviated as "integer 2 string") conversion. So, if we provide the numeric value 3 to the default I2S function, it will return the text string "3" that we can display on screen or in a floating text object.

But there is a function that we do not have on Warcraft III -- the I2C function -- and we do not have this function for a good reason. So, when users hacked the game and added the I2C function, the idea was to create "integer to code" as a conversion.

I can take a minute to explain what "code" means in this context, because that is less obvious than a text string. Specifically in the JASS language, there is a variable type code that is supported by default which allows us to wrap a function as a variable. As an example, we might do something like this to kill all units in an area:

JASS:
function CodeToRunForEachUnit takes nothing returns nothing
    call KillUnit(GetEnumUnit())
endfunction

function KillAllUnitsInArea takes rect whichArea returns nothing
    local group myGroup = CreateGroup()
    call EnumUnitsInRect(myGroup, rect, null)
    call ForGroup(myGroup, function CodeToRunForEachUnit)
    call DestroyGroup(myGroup)
endfunction

So, if you can loosely understand the code above -- even if you might not be super proficient in JASS -- the idea is a simple description of a custom function KillAllUnitsInArea that takes a rect as input and then uses the ForGroup function to run code on every unit in the group of units in that area that we create -- and in so doing, the function that is named CodeToRunForEachUnit executes repeatedly, once for each unit that was in the rectangular area given to us.

Kill all the units in a rectangular area like this would be one of the expected use-cases for the Warcraft III game and its JASS language. To achieve this expected use-case, the developers of Warcraft III had to somehow describe the built-in function named ForGroup which repeats code on every unit in the group that we selected. To do this, it is necessary to be able to call a function where one of the variables passed into that function is actually a reference to some other function to execute.

For this reason, the built-in definition of ForGroup in the game looks something like this:

JASS:
native ForGroup takes group whichGroup, code func returns nothing

In this case, along with a group type variable this function also takes a code type variable, and that is how I passed the special syntax function CodeToRunForEachUnit into this built-in ForGroup function when I called it.

But the original simplest way to break this concept apart that was discovered back around the days of Patch 1.21 was to construct a function that would convert an integer into a code in this way. In other words, we would have the following function:

JASS:
function I2C takes integer x returns code
    return x // the type of "x" was integer, but the return type of this function is "code"
endfunction

The syntax for this exploit was not very different from the above, although it was not this exactly. It turns out, in the original versions of Frozen Throne, there was no type-checking on the value that is passed back by a function to the outside, and so it was possible to arbitrarily convert a variable of one type to another type. And that meant that in this case, we could convert an integer into a code reference.

In practice, what this meant was that a user could tell the computer to start running code from anywhere in any way. As a hopefully somewhat straightforward example, suppose we do the following

JASS:
function I2C takes integer x returns code
    return x // the type of "x" was integer, but the return type of this function is "code"
endfunction

function C2I takes code x returns integer
    return x // the type of "x" was code, but the return type of this function is "integer"
endfunction

function CodeToRunForEachUnit takes nothing returns nothing
    call KillUnit(GetEnumUnit())
    call BJDebugMsg("We killed the unit named " + GetUnitName(GetEnumUnit()))
endfunction

function KillAllUnitsInArea takes rect whichArea returns nothing
    local group myGroup = CreateGroup()
    call EnumUnitsInRect(myGroup, rect, null)
    call ForGroup(myGroup, I2C(C2I(function CodeToRunForEachUnit)+1))
    call DestroyGroup(myGroup)
endfunction

This is not a tested example, and probably has some typos and oversights that will cause it not to run, but it combines our two previous examples and hopefully can be used to explain what's going on. I added a function C2I as well, so that now I can not only convert integer to code -- which is useful -- but likewise convert code back to integer. Converting code back to integer is great because we can do it first to get a reference point to where the valid code is.

So, in my example, now instead of killing every unit in the area I am calling ForGroup(myGroup, I2C(C2I(function CodeToRunForEachUnit)+1)) which is doing the bizarre behavior of not executing the CodeToRunForEachUnit function, but is instead executing this function offset by +1 forward. So, if we think of the function as a number that represents where the contents of that function are inside the computer machine, I am telling the program to run the contents +1 ahead of that numeric place instead of the place itself.

Conceptually, if each number referred to a line of code, you would image that since the definition of CodeToRunForEachUnit is to:
(1) - kill the unit
(2) - print a debug message saying that we killed the unit

Given that the original function was (1) above, by adding one, maybe I would land on the computer memory for (2) and so what my ForGroup call would do is to print the debug messages for each unit, but not actually kill them. If you understand this numeric jump forward and the idea that we would still execute code for every unit, but only print the debug message for that unit and not kill it, then you understand the idea of mathematical indexing for the contents of a function as the way to define it as a code number, and what it means to offset from that code number.

Now, in reality, my example would not work as given because each line of code is most likely going to be about 4 numeric indices and not 1 index spanning between them. So if you actually wanted to run this code on Patch 1.21 and actually wanted to see it print the debug message for each unit but not kill the unit, you might need to use +4 instead of the +1 for example, corresponding to your computer hardware and the size of a JASS instruction or whatever -- which are details that I do not bother myself to memorize.

Now, again, from my layman understanding of memhack (as someone who never actually intentionally did it myself, but only read about it) the second stage of this exploit once we have a means to jump to have the computer run any JASS code that we desire, from anywhere, even if it is not labelled with a function name and is not code that was intended to be runnable, was to then execute JASS code that has no visual written equivalent but is capable of doing things that we cannot express in the written JASS code. For example, the actual example that I recall looking at years ago looked something like this:

Java:
globals
    integer array MyArray
endglobals

function Setup takes nothing returns nothing
    set MyArray[0] = $234234523
    set MyArray[1] = $567334563
    set MyArray[2] = $659756754
    set MyArray[3] = $374568456
    set MyArray[4] = $883223565
    set MyArray[5] = $845672345
endfunction

function RunSpecialBinaryCode takes nothing returns nothing
    call ForGroup(someGroup, I2C(A2I(MyArray)))
endfunction

Now, the intuition here is that when the system is working properly, we can create an "array" of numbers. Again, I do not know if you are familiar with this idea, but it is really nothing special. In the typical use case, if we were going to build a custom map with an array of numbers, they might serve a purpose like counting the remaining lives that each player had in a hero RPG. Maybe if there are 12 players, we could create an array where we could set PlayerLives[10] = 47 to say that Player 10 (Light Blue) has 47 lives remaining. The integer arrays are a basic programming concept included in JASS so that we can load a list of numbers under a single name, where each number is given a "bin" to place it in.

But, in the stupid/bizarre example that I have constructed above, we use the previously mentioned I2C exploit so that now we instruct the system to execute MyArray as though it were a function, even though it is not. When this happens, the JASS system starts running the numeric value $234234523 as the first line of JASS code to run. But there is no JASS equivalent for this number -- no where in our file do we have the written code of what this was -- and yet the computer doesn't know the difference because of the bug/exploit, and starts running this number as though it was meaningful code.

At this point, the people who constructed this exploit fill the numbers with code that roughly would translate to an example like:

JASS:
set MyOtherArray = 100000

And in this case, setting MyOtherArray to be 100000 is not a legal JASS line of code because we can only use the "set" command on an array to set the contents of one of its "bins"! Indeed, how else would it make sense to set the array at all?

But it turns out, due to a bug in JASS, using the set command on the array alone with a pre-defined value like 100000 allows us to glitch the "array" concept itself, so that referring to MyOtherArray[10] will not refer to "bin 10" of some list of numbers in the game scripts, but instead to "bin 10" of anything in the computer itself, anywhere. And that's why they choose some pre-defined value that might be 100000, which in reality might be the offset where the Warcraft III game itself is stored, and not the map data executing inside of the game.

A common theme that I saw people doing on the few occasions that I looked into this issue was that instead of MyOtherArray, they would name this exploited array that referred to the contents of the Warcraft III game itself in the computer with the name Memory for that array, so that they could use the syntax set Memory[50] = myThing as a means to try to pretend that they were using some well-defined API or that any of the steps that I have described up to this point were anything but an insane failure of computer security and technology design. But, this name "Memory" is not a requirement of the exploit, and indeed if someone did not want you to know what they were doing, they could just as soon name this second array "FireballDamageTimer" and yet it would be no less capable of tampering with your computer itself, whether that be your running Windows installation, or your Warcraft III game, or whatever else. The same map that I looked at to try to understand this issue years ago, for example, jumped through the hoops described above and then did a few more steps that I did not bother to analyze, so that as an end result they would Open the Windows Command Prompt as Administrator and echo inside the command window the text, "Got you!". But this could have just as soon installed any kind of malware or anything that they wanted, and the computer instructions doing the installation would be the Warcraft III game itself and not a separate program, and so your antimalware virus protection would 99% likelihood not notice and not protect you as far as I understand.

And so you ask the age-old question "we can detect if any gateway for Memhack has been written, it might not be memhack but it doesn't matter" and of course, Blizzard Entertainment was forced to ask themselves this same question multiple times. Because as soon as this exploit was publicly well known, the computer security of Warcraft III became a laughing stock. The simple act of joining a Battle.net game lobby could instantly delete all the files on your computer, and your virus protection would probably not even intervene in the slightest -- seeing it as a normal function of the Warcraft III program that you supposedly ran yourself.

And this is the way that modding died.

When I was a kid back in 2009 I did not know any of the stuff that I just described to you. I did not understand how that worked, but what I did understand is that I had tried for 5 or 6 years to work on a very cool Warcraft III mod that I was making, and that the only way to store data for each unit was to use something the modders were calling "Return Bug" to get a magic number for the unit, and use this number for a bin designation of where to put data for that unit. In other words, given some systems that are already inside of the Trigger Editor that allowed us to store some data with a name at the time, it was possible for me to do something like:

JASS:
function SetUnitKillCounter takes unit whichUnit, integer killCounter returns nothing
    call StoreValue(I2S(H2I(whichUnit)), "KillCounter", killCounter)
endfunction

function GetUnitKillCounter takes unit whichUnit returns integer
    return LoadValue(I2S(H2I(whichUnit)), "KillCounter")
endfunction

And this incredibly, incredibly useful tool for modding that I have shown above would let me store any data in a per-unit fashion that I wanted, which is a feature otherwise greatly lacking from Trigger Editor! But it all depended on ONE thing that the Warcraft III game did not actually have -- the function H2I (meaning "handle to integer") to basically convert any "handle" (or game object) into a number, so that we could store data against it based on a unique name. Even if you had 5 footmen, and they all would give you the text "Footman" if you called the function GetUnitName on them, the magic H2I function would give you a distinct value for each of the 5 footmen!

But after the I2C bug was reported publicly, and Blizzard Entertainment was forced to act on the issue, it was more important to them to have a polished game that kept running than to maintain support for existing custom maps. And that's why a lot of the custom maps died at this cutoff point in 2009, and then old versions quit working, because I2C forced Blizzard's hand and forced them to do something.

And they decided that the answer to your original question, regarding how we detect this problem, was to cut the problem off at its source. Once they had someone in the office who understood the sequence of exploits that I described above, their conclusion was that the whole entire thing was bad and should eradicated to the best extent possible. To do this, the "Return Bug" was removed, wherein it was no longer possible to make a function that takes an input of one kind of thing, but returns output of a different kind of thing, and still works. In my opinion, this was a fairly logical solution to the problem, but I hated it at the time because it felt like some stupid hackers broke my mod and made all the things that I had been working on quit working, and from 2009 to 2011 this was very frustrating for me and I felt that Warcraft III had lost something great not because I cared about the specifics on H2I but because of all the existing, non-malicious map files that I had collected on my hard drive which now unilaterally were not playable if they stored unit-specific data after the patch.

The saving grace of the patch at that time was that the Activision merger had only just happened. Blizzard under the pressure to release this patch that would kill off most of the custom maps for Warcraft III, apparently still cared just enough... and reached out to a technical minority of Warcraft III modders at the time (probably Vexorian himself) and asked how they could serve us to provide a system that would let us store the unit-specific data in the way that I described above, while also completely eradicating this security problem because it's freaking horrible. The solution that these folks under time pressure to release a patch and go back to focusing on WoW and money making things... the solution those wonderful folks arrived at... was the hashtable type that was added to Warcraft III, and a function GetHandleId which is a built-in function and not a hack to convert any object (such as a unit) into a numeric index that corresponds to it.

The new hashtable type of variable is -- quite simply -- a more complex data table that lets us store information per a numeric index of any kind. It solves the legitimate use-case problem that maps were depending on in 2009, while offering none of the crazy buggy mess that would have been available by still allowing users to convert numbers into functions or do other arbitrary type conversions without limit.

And this is how Patch 1.26 came to be. It was the end of a patch cycle in 2009-2011 that was made in a hurry by Blizzard folks after the Activision merger, primarily for the sole and express purpose of coming back to Warcraft III to solve the grotesque security vulnerability that you people now call "memhack." And, they sought to solve the problem without destroying the modding community by inadvertently removing necessary functionality.

Unfortunately, as it happens, after about 5 years of relative stability a new user came to Hive Workshop and posted a new thread claiming that he had found a new but similar way to poke a hole in the game system, and cause the game system to begin executing code from somewhere in the computer that was not intended. As it turns out, what he discovered was that although Blizzard had removed the lowest-level base case for converting between types by writing a simple function in the form that I expressed previously, there was a new and different bug that could achieve the same end result. This time, as it turned out, the system would break if the user would name a local variable and a global variable by the same name, but gave them different types.

So, the implementation might look something like this:

JASS:
globals
    integer my_variable = 0
endglobals

function SetMyVar takes integer i returns nothing
    set my_variable = i
endfunction

function Typecast takes nothing returns nothing
    local code my_variable
endfunction

function I2C takes integer x returns code
    call SetMyVar(x)
    return my_variable
endfunction

Again, this glosses over some details, but the basic premise here is that we can construct a function that goes nuts and allows us to return a variable type as code based on a previous local variable with the same name, but in reality this thing is returning a global variable by that name and the end result is that the type on the variable is swapped. And so, again, the exploit becomes available. And thus it is so that Blizzard Entertainment's actual attempt to patch the game to avoid a catastrophic security vulnerability failed and the problem is still present on the Patch 1.26.

It was at this point, in 2016, when this problem again became known, that the guy who discovered it suggested publicly that maybe he should make a "good virus" of sorts that would use this exploit to travel from map to map inside of user computers, spreading itself into all the computers and patching them so that everyone who played 1.26 but knew less than him would have a free upgrade, including the ability to host custom maps larger than 8 MB, as well as a patch to this security vulnerability so that only his virus would effect everyone. From my standpoint, when a person goes mad with power like that and starts to espouse that kind of idea, more than anything it indicates that we have a problem. I replied to his post here on Hive advocating that if he was serious about what he was saying, he should make his virus-induced patch to Warcraft III game client option for users, with some kind of informational popup that required the user to press "OK" with regards to what it was doing.

I don't think he ever followed through with that, but when Blizzard released the Patch 1.27 several months later and did not fix the issue at all, he probably realized that this company did not really maybe take it that seriously anymore now that it was Activision-run. A couple of years went by, and Activision's new team was making patches to prepare for Reforged, and eventually they removed this "duplicate global variable names" issue a few patches down the line to resolve the matters of security.

Of course, in the meantime, the fellow who discovered the bug on Patch 1.26 tried to advocate to Blizzard the absurd idea that Blizzard should patch-away the "second" stage of the hack that I described above -- essentially allowing users to execute a large binary number array as though it was code, but then blocking the assignment of an array named Memory to anywhere in the computer -- but this came from him going mad with power and desiring to have the ridiculous ability to convert code to and from numbers, which was never and intended use case on Warcraft III. He wanted to believe that he could somehow perform this conversion in a "safe" or restricted way, but in my opinion that is obviously stupid and should not be allowed. So, by the time of Patch 1.29, the local/global variable names conflicting thing was fixed so that that was no longer possible.

And this is where we have the interesting problem. If you agree with the sort of propaganda of the "memhack" name -- giving this technology any name that isn't synonymous with "evil stupid virus hack" -- then you recreate the situation of my childhood and the immense suffering, wherein all your progress eventually has to get reset because the thing you are building has to be patched away, because it is a tremendous security violation. Plus, we already knew that would be how this would go, since that was already how this went in 2009-2011 the first time it was found. So, to me it feels like the people who built memhack did this knowingly, because it was not the first time using a return-bug based thing for modding and so they should have known better. It felt to me as if it was manipulated by something bad -- perhaps a vocal bad actor trying to train users to accept the idea of maps having free-for-all ability to run any code on the user computer -- because I don't think maps should do any of these hacks at all.

And these personal opinions of mine are why I do not see eye-to-eye with people from the 2016 group who split off and tried to "build systems based on memhack" that were rooted in this way of thinking that the insane insecure exploits were anything but bad. From my perspective, they appear to ascribe to the "I can therefore I shall" method of thinking -- which is admittedly quite similar to how I approach Warcraft III modding at times -- but they do it in a way that is destined not to last, because it is based on a brittle and bizarre exploit of a particular Warcraft III version, which will be doomed not to last, just like my favorite versions when I had the most fun back on Patch 1.21/1.22 that was really the defining moments of my Warcraft III childhood and why I am still here.

And I don't really think that people should make things that were doomed not to last, or at least I would like to avoid that, but of course Reforged teaches us that all of Warcraft III is doomed not to last, so maybe I am talking myself in circles. But you can see, I have a bias, and that bias is that with the information and experiences that I have, I think that people should not use memhack.

Other people disagree with me. Those people want the memhack to be a legitimate use case. They believe that downloading a Warcraft III map and playing it should always be the same level of security threat as downloading an EXE binary program on Windows and running that program as administrator [except that there is no virus protection for it].

And, the thing is, despite being mad for power, people like that... they're smart. One of them told me that they have a new, third way to kick off the exploits above and convert numbers to functions and back and that it still works on into the future patches and even on Reforged, making Reforged likewise vulnerable. But the people who are hungry for power in this way realized that there are guys like me who just want to play Warcraft 3. What they do has to be secret, because it is based in the idea that whoever has the smartest hack should have the power, and therefore accordingly that because they know how to hack your game therefore they should be allowed to do it. And that creates an incentive for them not to publish it online nor to tell it to people like me who might report it to Blizzard, so that Blizzard doesn't create a detector like you're talking about to stop them from doing it again.

In this ridiculous arms race -- a mad quest for power between apathetic, oligarchic evil WoW developers and some deeply enthusiastic Warcraft 3 fans who just want to make better DotA map versions -- I decided that I do not want to be a part of that arms race, and instead would like to simulate the Warcraft III game from the outside using a separate program built in Java, which has built-in memory protections so the arms race described above will never happen, because it is all simulated in a way that it cannot break outside of.

So, I see myself as kind of a bystander in the stupid, stupid battle that you are facing. And that is why I can share with you all the knowledge that I have, to the best of my ability, and yet lose nothing by doing it. Because whenever I go mad with power from World Editor, I am doing that in simulation and not with the real thing, so I get to feel good but it is not at anyone else's expense.

By contrast, the people in the arms race on the quest for power -- for example, if you implement a detector for global variables and local variables with the overlapping names -- would just move on to their next form of their technology, and find another way to glitch between the execution of code and the numeric representation of numbers, because those designs are how the computers work at the lowest level.

Now I have spent far more of my time than what this topic is worth, and I hope that I have enlightened you, and I hope that you will see that although you may create a detector for the exploits of today, eventually the people who are hungry for power would simply move to the next phase of their arms race in order to retain control even if your detector was very successful.
 
Last edited:
the entire game needs to be rewritten.
And in order to do that, the easiest way is if they give me the code so I can go mad with power and rewrite it, which is why it is fun for me to post trolling videos like this or this or this or even this
 
Level 3
Joined
May 10, 2022
Messages
14
hm yeah from these few examples I see some ways to detect at least the ones you have mentioned, but we would have to know all the ways to detect memhack better. Thing with names overlapping was a nice try at least.
Also I asked Irina admin and he told me that he used pjass to detect memhack but there were some false positives at first revision which makes totally sense for me since I saw it too coming when reading your post. And also with what you said- pjass might not detect all of memhack.

But yeah I see now why this is so difficult to protect against, because it BREAKS JASS within it's most basic definitions/functions, right xD?

And Nice story you wrote here;
and conlusion of it all would be that blizzard made very insecure JASS enviroment and it is just broken and never got fixed properly. Blizzard sucks but the game and what community made is great.
The simplest way is to just put it all on VM but I don't think amount of maps with viruses is big enough to make me go play on VM
 
Top