- Joined
- Jan 3, 2022
- Messages
- 364
The topic has come up recently again where people cannot retrieve all of the file names of a broken MPQ map archive when using MPQEditor. Why is the situation so bad though?
I tried MPQEditor's W3X Name Scanner on a legit optimized map: 129 files remained unknown. I wrote my own tiny tool but it was barely better: 127 files remained unknown. More on that later.
MPQEditor also had run the "Name Breaker" project in the past, the goal was to bruteforce the names by trying all combinations. That was useful for Blizzard's original MPQs without list files, where it was possible to make a lot of assumptions about the name structure. It is not practical for maps where file names can be very long...
...unless someone creates a GPU-accelerated bruteforcer similar to what hashcat does
You'd either get the original name by bruteforcing with so much power or a hash collision (a random name that would work the same)
RMPQEx surprised me, it recognized 10-12 more files than MPQEditor.
Anything that you see in-game must be referenced in 2nd group's files. A custom unit will load the custom texture and model by file name, so these strings will be inside the map somewhere. Basically, the methods of RMPQEx and MPQEditor to detect names must be improved upon to recover all unknown files.
This is what I tried:
Further, based on my previous research there're more "secret" paths used by Reforged where files could be hidden (localization and _hd.mod folders): Multilanguage map prototype (Translation Tutorial) - this trick was previously used to hide ./war3map.j inside ./scripts/war3map.j and it took some time until deprotectors figured it out.
I'm eager to try it out and improve the script above when I get time. Until then, I'd like to hear some input from people who know this stuff better than me
Explanation
(if you know how listfiles and MPQEditor work, can skip reading this)An MPQ archive normally has all file names stored in a (listfile) file. Map protectors/optimizers usually delete the file because it's not needed for the map to work. At the same time it makes modifying/working on the map in WE nearly impossible: you need the file to be normal, to have a name. MPQEditor has an automatic name detection feature under "Tools" -> "W3X Name Scanner". In one mode, it injects into the game to intercept file loading calls and save them to a list file (only worked in old WC3 versions). In second mode, it scans the map files for text strings and checks if any of those strings are a valid file name; it also has a bundled "default" listfile for Warcraft's own MPQ archives.
The injection method obviously no longer works and the second search method is imperfect.
The injection method obviously no longer works and the second search method is imperfect.
Other methods
RMPQEx Map Extractor (by Riv) too has a scanner for unknown names (called "Auto Search"). Tested: 117 files remain unknown.MPQEditor also had run the "Name Breaker" project in the past, the goal was to bruteforce the names by trying all combinations. That was useful for Blizzard's original MPQs without list files, where it was possible to make a lot of assumptions about the name structure. It is not practical for maps where file names can be very long...
...unless someone creates a GPU-accelerated bruteforcer similar to what hashcat does
RMPQEx surprised me, it recognized 10-12 more files than MPQEditor.
Do It Yourself
Nonetheless, the (listfile) must be fully recoverable for all the files the map actually uses. The war3 maps consist of two groups of files: 1) needed for WorldEdit only 2) needed for map to run.Anything that you see in-game must be referenced in 2nd group's files. A custom unit will load the custom texture and model by file name, so these strings will be inside the map somewhere. Basically, the methods of RMPQEx and MPQEditor to detect names must be improved upon to recover all unknown files.
Lua:
#!/usr/bin/env lua
-- takes ... any amount of files, extracts all unique strings that are
-- encased in double-quotes:
-- "extracted_string"
-- RUN AS:
-- lua extract-strings.lua ability.ini war3map.j someother.ini > random-strings-for-listfile.txt
-- v1.0 (just a little test version)
-- Results:
-- MPQEditor: 129 unrecognized files
-- This script using w3xlni export: 127 files
-- RMPQEx: 117 files
function processFile(filePath, intoTable)
local file = assert(io.open(filePath, "r"))
for line in file:lines() do
-- strings can only be single-line, always inside "quotes"
local raw = line:match('%b""')
-- exclude empty strings
-- and |r color codes (which would also be invalid file names on WIN)
if raw and raw ~= '""' and not raw:find("|", 1, true) then
-- cut double-quotes and remove escaped backslashes
local str = raw:sub(2,-2):gsub("\\\\", "\\")
if not intoTable[str] then
io.stderr:write(str .. "\n")
intoTable[str] = true
-- some values are comma-separated, just add them without lookup:
for csv in str:gmatch("[^,]+") do
io.stderr:write(csv .. "\n")
intoTable[csv] = true
end
end
end
end
end
function main(args)
local stringTable = {}
for i = 1, #args do
processFile(args[i], stringTable)
end
-- print stringTable to STDOUT
for str, _ in pairs(stringTable) do
print(str)
end
end
main(args or {...})
- Use w3x2lni to extract map data to .ini files (actually only w2l CLI version worked, with 2 unspecified errors)
- Use my tiny script above to extract every text from /table/*.ini (w3x2lni output files) and war3map.j, and use that later as file name
- Take the output file from previous step and add it as a Listfile in MPQEditor
- ???
- PROFIT
- w3x2lni doesn't export everything as .ini files and some file names are inside other files
- w3x2lni's errors I encountered are actually errors, that resulted in incomplete output
- Jass
Further, based on my previous research there're more "secret" paths used by Reforged where files could be hidden (localization and _hd.mod folders): Multilanguage map prototype (Translation Tutorial) - this trick was previously used to hide ./war3map.j inside ./scripts/war3map.j and it took some time until deprotectors figured it out.
I'm eager to try it out and improve the script above when I get time. Until then, I'd like to hear some input from people who know this stuff better than me

- Are RMPQEx, MPQEditor just bad at scanning?
- Of course, in case of JASS code, the process cannot be automatic:
string textureName = "path/to/texture." + variableExtension
- here the tool should print all suspicious lines for the human to figure it out, a manual process
- Of course, in case of JASS code, the process cannot be automatic:
- If the map has imported unused files, will there remain any info after an optimization/protection process?
- How much of the 117-127 unrecognized files are actually used by the map (in my case)?
- (I don't want to summon the Devil but): Novel map protection techniques that'd rename files automatically to use names not allowed on Windows (e.g. | character) - THIS IS A PATENTED TECHNOLOGY, YOU OWE ME $9000 IF YOU USE IT IN YOUR PROTECTOR. Please don't hamper creativity. - Something like this would force you to also modify all file references to rename the invalid file name.
Last edited: