Last active
May 12, 2021 23:28
-
-
Save x4fx77x4f/248abe418dad7715d50b974e10de8627 to your computer and use it in GitHub Desktop.
Scripts relating to my string method PR for StarfallEx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- https://lua-users.org/wiki/MetatableEvents | |
local metatable = { | |
__index = true, | |
__newindex = true, | |
--__mode = true, | |
__call = true, | |
--__metatable = true, | |
--__tostring = true, | |
__len = true, -- Lua 5.2+ | |
__pairs = true, -- Lua 5.2+ | |
__ipairs = true, -- Lua 5.2+ | |
--__gc = true, | |
--__name = true, | |
--__close = true, -- Lua 5.4+ | |
__unm = true, | |
__add = true, | |
__sub = true, | |
__mul = true, | |
__div = true, | |
--__idiv = true, -- Lua 5.3 | |
__mod = true, | |
__pow = true, | |
__concat = true, | |
--__band = true, -- Lua 5.3 | |
--__bor = true, -- Lua 5.3 | |
--__bxor = true, -- Lua 5.3 | |
--__bnot = true, -- Lua 5.3 | |
--__shl = true, -- Lua 5.3 | |
--__shr = true, -- Lua 5.3 | |
__eq = true, | |
__lt = true, | |
__le = true | |
} | |
for k in pairs(metatable) do | |
local function v(...) | |
print(k, ...) | |
end | |
metatable[k] = v | |
end | |
setmetatable(string, metatable) | |
local temp | |
local str = '' | |
temp = str.index -- __index | |
pcall(function() str.newindex = true end) -- __newindex | |
pcall(str) -- __call | |
--tostring(str) -- __tostring | |
temp = #str -- __len | |
pcall(pairs, str) -- __pairs | |
pcall(ipairs, str) -- __ipairs | |
pcall(function() temp = -str end) -- __unm | |
pcall(function() temp = str+str end) -- __add | |
pcall(function() temp = str-str end) -- __sub | |
pcall(function() temp = str*str end) -- __mul | |
pcall(function() temp = str/str end) -- __div | |
pcall(function() temp = str%str end) -- __mod | |
pcall(function() temp = str^str end) -- __pow | |
pcall(function() temp = str..str end) -- __concat | |
pcall(function() temp = str==str end) -- __eq | |
pcall(function() temp = str<str end) -- __lt | |
pcall(function() temp = str<=str end) -- __le |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--@server | |
-- This isn't a great example, but you get the point. | |
function string.unfuck(str) | |
str = str | |
:gsub('//', '--') | |
:gsub('/%*', '--[[') | |
:gsub('%*/', ']]') | |
:gsub('&&', ' and ') | |
:gsub('||', ' or ') | |
--:gsub('!', ' not ') | |
return str | |
end | |
print(("/* gluaisms suck!! */"):unfuck()) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--@server | |
--@ enhancedmethods | |
-- ^ check both with and without | |
-- set up payload | |
local success = false | |
local function payload(desc, ...) | |
success = true | |
local args = {...} | |
for k, v in pairs(args) do | |
args[k] = tostring(v) | |
end | |
print(desc..table.concat(args, '\t')) | |
end | |
-- set up exploit | |
local function enthrall(func, desc) | |
desc = desc..": " | |
return function(...) | |
payload(desc, ...) | |
return func(...) | |
end | |
end | |
for k, v in pairs(string) do | |
string[k] = enthrall(v, k) | |
end | |
-- trigger exploit | |
wire.adjustInputs({"POC_9e28943"}, {'string'}) | |
-- check for success | |
print(success and "EXPLOIT SUCCESS" or "exploit failed") |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--@shared | |
local prefix = SERVER and "SERVER" or CLIENT and "CLIENT" or jit and "LuaJIT" or "Lua" | |
-- [[ | |
-- This disables numerical string indexes. | |
-- This metatable is also protected. My patch uses | |
-- debug.getmetatable, so it should not be affected | |
-- by the protected metatable. | |
setmetatable(string, { | |
__metatable = "FAIL" | |
}) | |
--]] | |
print(prefix, ("abc"):sub(1, 1)) -- should be "a" | |
print(prefix, ("abc")[2]) -- should be nil | |
print(prefix, pcall(function() return ("abc").nonexistent end)) -- should be true, nil | |
string.existent = "PASS" | |
print(prefix, pcall(function() return ("abc").existent end)) -- should be true, "PASS" | |
print(prefix, string.error) -- should be nil | |
string = nil -- won't affect string methods before or after | |
print(prefix, ("abc"):sub(3, 3)) -- should be "c" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--@name String method exploit test suite | |
--@shared | |
local testing | |
local ran, ranEver = false, false | |
local format = string.format | |
local function payload(desc) | |
ran = true | |
ranEver = true | |
print(format("%q indexed %q", testing or "[UNKNOWN]", desc)) | |
end | |
local explode = string.explode | |
local function test(k, ...) | |
if not k then | |
return | |
end | |
testing = k | |
k = explode('[.:]', k, true) | |
local v = _G | |
for _, k in ipairs(k) do | |
v = v[k] | |
if not v then | |
return | |
end | |
end | |
local success, err = pcall(v, ...) | |
if not ran then | |
if not success then | |
err = type(err) == 'table' and err.message or err | |
print(format("%q failed with %q", testing, err)) | |
else | |
print(format("%q failed", testing)) | |
end | |
end | |
testing = nil | |
ran = false | |
end | |
local haven = {} | |
for k, v in pairs(string) do | |
haven[k] = v | |
string[k] = nil | |
end | |
setmetatable(haven, getmetatable(string)) | |
setmetatable(string, { | |
__index = function(self, k) | |
payload(k) | |
return haven[k] | |
end | |
}) | |
print("## Testing") | |
local holo = CLIENT and holograms.create(Vector(), Angle(), 'models/error.mdl') | |
pcall(holo and holo.setNoDraw, holo, true) | |
local mat = CLIENT and material.create('UnlitGeneric') | |
Entity = getMethods('Entity') | |
Hologram = getMethods('Hologram') | |
Material = getMethods('Material') | |
test('Entity:setMaterial', chip(), 'foo') -- SF.CheckMaterial -> string.StripExtension -> :sub | |
test('Entity:setSubMaterial', chip(), 0, 'foo') -- SF.CheckMaterial -> string.StripExtension -> :sub | |
test(CLIENT and 'Hologram:setModel', holo, 'foo') -- string.GetExtensionFromFilename -> :match | |
test('bass.loadFile', 'foo', '', function() end) -- :match | |
test('dofile', 'foo') -- string.GetPathFromFilename -> :match | |
test('file.existsTemp', 'foo') -- checkExtension -> string.GetExtensionFromFilename -> :match, string.GetFileFromFilename -> :find, string.GetFileFromFilename -> :match | |
test('file.readTemp', 'foo', '') -- checkExtension -> string.GetExtensionFromFilename -> :match, string.GetFileFromFilename -> :find, string.GetFileFromFilename -> :match | |
test('file.write', 'foo', '') -- checkExtension -> string.GetExtensionFromFilename -> :match | |
test('file.writeTemp', 'foo', '') -- checkExtension -> string.GetExtensionFromFilename -> :match, string.GetFileFromFilename -> :find, string.GetFileFromFilename -> :match | |
test(CLIENT and 'holograms.create', nil, nil, 'foo') -- string.GetExtensionFromFilename -> :match | |
test('input.lookupBinding', '+forward') -- :upper | |
test('material.createFromImage', 'foo', '') -- string.GetExtensionFromFilename -> :match | |
test('material.load', 'foo') -- string.GetExtensionFromFilename -> :match, SF.CheckMaterial -> string.StripExtension -> :sub | |
test('render.createMaterial', 'foo') -- :find | |
test('require', 'foo') -- string.GetPathFromFilename -> :match | |
test('requiredir', 'foo') -- string.GetPathFromFilename -> :match | |
test('sounds.create', chip(), 'foo') -- :match | |
test('sql.SQLStr', 'foo', false) -- sql.SQLStr -> :gsub | |
test('wire.adjustInputs', {'Foo'}, {'string'}) -- :upper, :match | |
test('wire.adjustOutputs', {'Foo'}, {'string'}) -- :upper, :match | |
print("## Conclusion: "..(ranEver and "FAILED" or "passed")) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--@name superuser chaos | |
--@server | |
--@superuser | |
-- We can't obtain the global 'string' table, but we | |
-- can make a copy of everything in it by abusing | |
-- faulty string methods. | |
local extClone_string = { | |
Comma = true, | |
EndsWith = true, | |
Explode = true, | |
FormattedTime = true, | |
FromColor = true, | |
GetChar = true, | |
GetExtensionFromFilename = true, | |
GetFileFromFilename = true, | |
GetNormalizedFilepath = true, | |
GetPathFromFilename = true, | |
Implode = true, | |
JavascriptSafe = true, | |
Left = true, | |
NiceSize = true, | |
NiceTime = true, | |
PatternSafe = true, | |
Replace = true, | |
Right = true, | |
SetChar = true, | |
Split = true, | |
StartWith = true, | |
StripExtension = true, | |
ToColor = true, | |
ToMinutesSeconds = true, | |
ToMinutesSecondsMilliseconds = true, | |
ToTable = true, | |
Trim = true, | |
TrimLeft = true, | |
TrimRight = true, | |
byte = true, | |
char = true, | |
dump = true, | |
find = true, | |
format = true, | |
gfind = true, | |
gmatch = true, | |
gsub = true, | |
len = true, | |
lower = true, | |
match = true, | |
rep = true, | |
reverse = true, | |
sub = true, | |
upper = true | |
} | |
for k in pairs(extClone_string) do | |
extClone_string[k] = ('')[k] | |
end | |
-- Thanks to string.ToColor, we can then obtain an | |
-- external Color object. | |
local extObj_Color = extClone_string.ToColor('0 0 0 0') | |
-- And since the Color metatable is not protected, we can | |
-- just grab it like this. | |
local extMeta_Color = getmetatable(extObj_Color) | |
-- What can we do with this? Potentially a lot... but | |
-- since only superadmins can spawn superuser chips, | |
-- probably nothing they couldn't do already. | |
-- We could bypass the string.rep limits, but we can | |
-- already freeze the server/client -- we run with no | |
-- quota after all. | |
--[[ | |
local str = 'a' | |
while true do | |
str = string.rep(str, 99999) | |
end | |
--]] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local env = { | |
SF = {} | |
} | |
-- cache | |
local _G = env | |
local getfenv = getfenv | |
local SF = env.SF | |
-- common | |
local function myMetaFunc(...) end | |
local function v(...) end | |
-- original | |
local function commit_b81ce0b(...) | |
if SF.runningOps then return myMetaFunc(...) else return v(...) end | |
end | |
-- proposed (original) | |
local function commit_1af9602(...) | |
local instance = SF.runningOps | |
if instance and instance.whitelistedEnvs[getfenv(3)] then | |
return myMetaFunc(...) | |
else | |
return v(...) | |
end | |
end | |
-- proposed (simplified) | |
local function commit_xxxxxx0(...) | |
if getfenv(3) ~= _G then | |
return myMetaFunc(...) | |
else | |
return v(...) | |
end | |
end | |
-- proposed (hybrid) | |
local function commit_xxxxxx1(...) | |
if SF.runningOps and getfenv(3) ~= _G then | |
return myMetaFunc(...) | |
else | |
return v(...) | |
end | |
end | |
local SysTime = SysTime | |
local function benchmark(func, iterations, desc, ...) | |
setfenv(func, env) | |
local startTime = SysTime() | |
for i=1, iterations do | |
func(...) | |
end | |
local endTime = SysTime() | |
local totalTime = endTime-startTime | |
local avgTime = totalTime/iterations | |
print(string.format("Completed in %f seconds (%f seconds average) \t%q", totalTime, avgTime, desc or "nil")) | |
end | |
local iterations = 10000000 | |
local args = {"/* gluaisms suck!!! */", 'gsub', '/*', '--[['} | |
print("Simulating no active chip") | |
benchmark(commit_b81ce0b, iterations, "original", unpack(args)) | |
benchmark(commit_1af9602, iterations, "proposed (original)", unpack(args)) | |
benchmark(commit_xxxxxx0, iterations, "proposed (simplified)", unpack(args)) | |
benchmark(commit_xxxxxx1, iterations, "proposed (hybrid)", unpack(args)) | |
print("Simulating an active chip") | |
env.SF.runningOps = { | |
whitelistedEnvs = setmetatable({ | |
[{}] = true | |
}, {__mode = 'k'}) | |
} | |
benchmark(commit_b81ce0b, iterations, "original", unpack(args)) | |
benchmark(commit_1af9602, iterations, "proposed (original)", unpack(args)) | |
benchmark(commit_xxxxxx0, iterations, "proposed (simplified)", unpack(args)) | |
benchmark(commit_xxxxxx1, iterations, "proposed (hybrid)", unpack(args)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment