This is a read only copy without any forum functionality of the old Modcraft forum.
If there is anything that you would like to have removed, message me on Discord via Kaev#5208.
Big thanks to Alastor for making this copy!

Menu

Author Topic: [LUA] Modifying secure variables without taint  (Read 1561 times)

Grymskvll

  • Registred Member
  • Polygonshifter
  • *****
  • Posts: 65
    • View Profile
[LUA] Modifying secure variables without taint
« on: August 03, 2016, 08:27:59 pm »
If there's a better solution, or if there are any improvements to be made to this, please let me know.

I was working on a custom secondary class resource system (demo here: ) and ran into the phenomenon of interface taint (more info here: http://wowwiki.wikia.com/wiki/Secure_Ex ... d_Tainting).

From what I understand, normally when you're modding the interface for addons, you don't necessarily need to directly change the return value of API functions. However, I needed to change the return value of certain secure functions based on custom conditions (like checking custom resource values to see if a spell is usable).

The problem is that directly changing secure functions will taint them, causing interface errors (or at least it causes ugly notifications to be printed in the chat window). The good news is there's apparently a way to modify secure variables (including functions).

Here's how:


1) Requires a patched Wow.exe to load modified interface files (see http://www.ownedcore.com/forums/world-o ... mover.html).

2) Find the most up-to-date FrameXML.toc (GlueXML.toc should work too) in your client. For the standard WotLK 3.3.5 version, it should be in [your-WoW-folder]Data[locale]patch-[locale]-3.MPQ
Full path:
InterfaceFrameXMLFrameXML.toc

3) Extract FrameXML.toc to [your-WoW-folder]InterfaceFrameXML, or make a new MPQ for it. Either should work.

4) Open it up in any text editor and add this new line at the bottom (the path and filename are arbitrary, change it if you feel like it):
Code: [Select]
..CustomSecureVarsCustomSecureVars.lua
5) Create a new folder in [your-WoW-folder]Interface, name it CustomSecureVars. In the new folder, create a text file called CustomSecureVars.lua. This file will hold all the new secure variables you need. Feel free to edit secure functions all you want, they'll still be secure so long as you don't taint them by accessing any tainted variables.

Top tips for keeping variables secure:


If you want to call a (potentially) tainted function, use the "securecall" API function (see http://wowwiki.wikia.com/wiki/API_securecall).

If you need to provide a tainted variable as an argument from a modified secure function, provide it as a string and have the called function resolve the string to a global variable. That way the secure function stays secure, and only the called function needs to deal with taint.

For debugging, you can check individual variables with "issecurevariable" (see http://wowwiki.wikia.com/wiki/API_issecurevariable)

You can also enable taint logging (http://wow.gamepedia.com/CVar_taintLog). Any time your chat window shows "Interface action failed because of an AddOn", it'll write a report in WoWLogstaint.log. Remember to delete your taint.log in between tests for convenience! And remember to turn off logging after your tests!

I don't always get an interface error when accessing a tainted variable from a secure function, I'm not entirely sure how it works. Specific lines of code seem consistent, but different modifications don't always cause an error.

Example:


Lets say you have a tainted variable:
Code: [Select]
TaintedVar = "hi I'm a tainted variable"
You can't keep it secure because it's managed by an AIO script or addon. You also want to check TaintedVar inside the secure GetShapeshiftFormInfo API function, so you hook it:
Code: [Select]
local origGetShapeshiftFormInfo = GetShapeshiftFormInfo;
GetShapeshiftFormInfo = function(...)
local texture, name, isActive, isCastable = origGetShapeshiftFormInfo(...)

if (TaintedVar) then print(TaintedVar) end -- oops, we're accessing a tainted variable!

return texture, name, isActive, isCastable
end

Testing this on a character with a shapeshift/stances bar, I get "Interface action failed because of an AddOn" during combat. The solution is to make a new function that's allowed to get tainted (because it's not used by the official UI), the new function will return the tainted value we want to check. We'll call the new function using securecall, providing the name of the tainted value we want to check.

Code: [Select]
local function GetTaintedVar(varname)
-- _G[variable name] retrieves a global variable
return _G[varname]
end

local origGetShapeshiftFormInfo = GetShapeshiftFormInfo;
GetShapeshiftFormInfo = function(...)
local texture, name, isActive, isCastable = origGetShapeshiftFormInfo(...)

-- Even if GetTaintedVar is tainted, secure status is restored after the call
local SecureVar = securecall(GetTaintedVar, "TaintedVar")
if (SecureVar) then print(SecureVar) end

return texture, name, isActive, isCastable
end

The key here is that the function that has to stay secure (GetShapeshiftFormInfo) doesn't access any tainted variables, except the GetTaintedVar function, which it provides as an argument for securecall, but thanks to the magic of securecall, secure status is restored after the call to securecall. TaintedVar is just provided as a variable name string, and then checked by the function that we're allowing to get tainted. It seems that the function being called by securecall is allowed to be tainted, but not any arguments provided along with it, thus the need to provide the name of the variable as a string.
« Last Edit: January 01, 1970, 01:00:00 am by Admin »