update to newer better version

master
rnd 2019-03-05 14:30:55 +01:00
parent ba377fb15f
commit 1bca10dc32
5 changed files with 218 additions and 69 deletions

14
README
View File

@ -1,5 +1,5 @@
OBFUSCATOR
Copyright rnd, 2017
Copyright rnd, 2019
------------------------------------------------------------------------
@ -18,10 +18,10 @@ Copyright rnd, 2017
------------------------------------------------------------------------
INSTRUCTIONS
modify last lines inside mod lua file for your own a_in.lua (original) and a_out.lua file (obfuscated)
0. use local variables all the time in your code, only use globals if absolutely necessary. all the local variables are affected by "clarity".
1.follow this guideline with the structs a = {...} :
a = {b=c,d=e, function(f) g ... } will work, so simple variables first, nested pure functions later is ok.
if you do function first it will assume you exited struct so stuff like b=c afterwards will get replaced too with v___ = v____ this will then cause execution errors!
2. dont use same variable name for variable thats local and global
obfuscator.lua contains main program. obfuscate(code) returns obfuscated code.
possible issues:
local x = 1; local table = {x=1}; print table["x"]
here 'x' will be renamed but "x" not, causing error. table.x will be renamed correctly though.
obfuscated_obfuscator.lua contains obfuscated version of obfuscator.lua.

View File

@ -1,24 +0,0 @@
-- BEFORE: ---
local i,n
factors = function( n )
local f = {}
for i = 1, n/2 do -- here we try all the possible factors of n
if n % i == 0 then -- here we check if n is divisible by i
f[#f+1] = i -- we found factor, add it to the list
end
end
f[#f+1] = n
print("factors of " .. n .. " are : " .. table.concat(f,","))
end
factors(25)
-- AFTER : ---
v____ = function( v___ ) local v__ = {} for v_ = 1, v___/2 do if v___ % v_ == 0 then v__[#v__+1] = v_ end end v__[#v__+1] = v___ print("factors of " .. v___ .. " are : " .. table.concat(v__,",")) end v____(25)

File diff suppressed because one or more lines are too long

21
obfuscated_obfuscator.lua Normal file
View File

@ -0,0 +1,21 @@
local a = { ["for"] = true, ["else"] =true, ["if"] = true, ["then"] = true, ["not"] = true, ["end"] = true, ["in"] = true, ["return"] = true, ["or"] = true, ["and"] = true, ["local"] = true,["function"] = true,["string"] = true, ["break"]=true, ["elseif"] = true, ["false"] = true, ["nil"] = true, ["repeat"] = true, ["while"] = true, ["true"]=true, } local b = function(C) return C:gsub("%-%-%[%[.*%-%-%]%]",""):gsub("%-%-[^\n]*\n","\n") end local c = function(E) local d = 0; local e; local f; local g = string.len(E); local h = 0; local i = { {"'","'"}, {"\"","\""}, {"%[=*%[","%]=*%]"}, } local j = {} while d < g do d=d+1 local k = g+1; if h == 0 then for k=1,#i do e = string.find(E,i[k][1],d); if e and e<k then k = e h = k end end if h ~= 0 then e=k j[#j+1] = {k} end if not e then break end else f,e = string.find(E,i[h][2],d); if not e then break end if (h~=2 or (string.sub(E,e-1,e-1) ~= "\\") or string.sub(E,e-2,e-1) == "\\\\") then j[#j][2] = e h = 0 end end d=e end if h~= 0 then j[#j][2] = g end return j end local l = function(s,F) local m = 1; local n = #s; if n == 0 then return false end local o = n; while n>m+1 do o = math.floor((m+n)/2) if F<s[o][1] then n = o else m = o end end if F>s[m][2] then o = n else o = m end return s[o][1]<=F and F<=s[o][2] end local p = function(C, D, F, s) local g = string.len(C) local q = true; local d1 = F; while q do q = false local d2 = string.find(C,D,d1); if d2 then if not l(s,d2) then return d2 end q = true; d1 = d2+1; end end return nil end local r = function(C,A, B) local s = c(C); local d = 1; local g = string.len(C); local t = 0 while(d<=g) do local e1 = p(C,"[%a_]+",d, s) if e1 then local e2 = string.find(C,"[^%a_]",e1+1) or (g+1) local u = string.sub(C,e1,e2-1) d=e2+1 if not a[u] then if not A[u] and string.sub(C,e1-6,e1-2) == "local" then t=t+1;A[u] = t end end else break end end d=1 while(d<=g) do local e1 = p(C,"[%a_]+",d, s) if e1 then local e2 = string.find(C,"[^%a_]",e1+1) or (g+1) local u = string.sub(C,e1,e2-1) d=e2+1 if A[u] then B[#B+1] = {e1,e2,A[u]} end else break end end end local v = function(C,A,B) local d = 1; local z = {}; local w = {"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","z","w","x","y","z", "A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","Z","W","X","Y","Z"} local x = {}; local e = 0 local y = #w; for f,__ in pairs(A) do e=e+1 if e<=y then x[e] = w[e] elseif e<=y^2 then x[e] = w[math.floor(e/y)] .. w[(e-1)%y+1] else print("error! count exceeded " .. y^2) end end for e = 1,#B do z[#z+1] = string.sub(C,d,B[e][1]-1)..x[B[e][3]] d=B[e][2] end z[#z+1] = string.sub(C,d,string.len(C)) return table.concat(z,"") end local z = function(C) C = b(C); C = string.gsub(C,"[\n\t ]+"," ") local A = {}; local B = {};r(C,A, B) return v(C,A,B) end
print(z([=[
local i; local n
local factors = function( n )
local f = {}
for i = 1, n/2 do -- here we try all the possible factors of n
if n % i == 0 then -- here we check if n is divisible by i
f[#f+1] = i -- we found factor, add it to the list
end
end
f[#f+1] = n
print("factors of " .. n .. " are : " .. table.concat(f,","))
end
factors(25)
]=]))

190
obfuscator.lua Normal file
View File

@ -0,0 +1,190 @@
-- LUA OBFUSCATOR by rnd
-- removes all newlines, tabs and unneded spaces
-- renames all local variables to short form
local reserved_words = {
["for"] = true, ["else"] =true, ["if"] = true, ["then"] = true, ["not"] = true, ["end"] = true, ["in"] = true,
["return"] = true, ["or"] = true, ["and"] = true, ["local"] = true,["function"] = true,["string"] = true,
["break"]=true, ["elseif"] = true, ["false"] = true, ["nil"] = true, ["repeat"] = true, ["while"] = true,
["true"]=true,
}
local remove_comments = function(text)
return text:gsub("%-%-%[%[.*%-%-%]%]",""):gsub("%-%-[^\n]*\n","\n")
end
local identify_strings = function(code) -- returns list of positions {start,end} of literal strings in lua code
local i = 0; local j; local _; local length = string.len(code);
local mode = 0; -- 0: not in string, 1: in '...' string, 2: in "..." string, 3. in [==[ ... ]==] string
local modes = {
{"'","'"}, -- inside ' '
{"\"","\""}, -- inside " "
{"%[=*%[","%]=*%]"}, -- inside [=[ ]=]
}
local ret = {}
while i < length do
i=i+1
local jmin = length+1;
if mode == 0 then -- not yet inside string
for k=1,#modes do
j = string.find(code,modes[k][1],i);
if j and j<jmin then -- pick closest one
jmin = j
mode = k
end
end
if mode ~= 0 then -- found something
j=jmin
ret[#ret+1] = {jmin}
end
if not j then break end -- found nothing
else
_,j = string.find(code,modes[mode][2],i); -- search for closing pair
if not j then break end
if (mode~=2 or (string.sub(code,j-1,j-1) ~= "\\") or string.sub(code,j-2,j-1) == "\\\\") then -- not (" and not \" - but "\\" is allowed)
ret[#ret][2] = j
mode = 0
end
end
i=j -- move to next position
end
if mode~= 0 then ret[#ret][2] = length end
return ret
end
local is_inside_string = function(strings,pos) -- is position inside one of the strings?
local low = 1; local high = #strings;
if high == 0 then return false end
local mid = high;
while high>low+1 do
mid = math.floor((low+high)/2)
if pos<strings[mid][1] then high = mid else low = mid end
end
if pos>strings[low][2] then mid = high else mid = low end
return strings[mid][1]<=pos and pos<=strings[mid][2]
end
local find_outside_string = function(text, pattern, pos, strings)
local length = string.len(text)
local found = true;
local i1 = pos;
while found do
found = false
local i2 = string.find(text,pattern,i1);
if i2 then
if not is_inside_string(strings,i2) then return i2 end
found = true;
i1 = i2+1;
end
end
return nil
end
local extract_locals = function(text,locals, positions)
local strings = identify_strings(text);
local i = 1;
local length = string.len(text);
local idx = 0
while(i<=length) do
local j1 = find_outside_string(text,"[%a_]+",i, strings)
if j1 then -- find locals (local variables)
local j2 = string.find(text,"[^%a_]",j1+1) or (length+1)
local word = string.sub(text,j1,j2-1)
i=j2+1
if not reserved_words[word] then
if not locals[word] and string.sub(text,j1-6,j1-2) == "local" then -- not yet found as local and "local variable_name"
idx=idx+1;locals[word] = idx -- found new local
end
end
else
break
end
end
i=1
while(i<=length) do -- find locals positions (all of them!)
local j1 = find_outside_string(text,"[%a_]+",i, strings)
if j1 then -- find locals (local variables)
local j2 = string.find(text,"[^%a_]",j1+1) or (length+1)
local word = string.sub(text,j1,j2-1)
i=j2+1
if locals[word] then
positions[#positions+1] = {j1,j2,locals[word]} -- remember positions and local
end
else
break
end
end
end
local rename_locals = function(text,locals,positions)
local i = 1;
local out = {};
local chars = {"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","z","w","x","y","z",
"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","Z","W","X","Y","Z"}
local names = {};
local j = 0
local n = #chars;
for _,__ in pairs(locals) do -- generate new local names
j=j+1
if j<=n then
names[j] = chars[j]
elseif j<=n^2 then
names[j] = chars[math.floor(j/n)] .. chars[(j-1)%n+1]
else
print("error! count exceeded " .. n^2) -- default 54^2=2916
end
end
for j = 1,#positions do
out[#out+1] = string.sub(text,i,positions[j][1]-1)..names[positions[j][3]]
i=positions[j][2]
end
out[#out+1] = string.sub(text,i,string.len(text))
return table.concat(out,"")
end
local obfuscate = function(text)
text = remove_comments(text);
text = string.gsub(text,"[\n\t ]+"," ") -- replace newlines, tabs and multiple spaces with space
local locals = {}; local positions = {};extract_locals(text,locals, positions)
--print(serialize(locals));print(serialize(positions))
return rename_locals(text,locals,positions) -- this is final output
end
local text; local pattern; local code; local pos; local tab -- just so it gets obfuscated too when applied to itself
-- DEMO EXAMPLE
-- only variables that are local somewhere are obfuscated, like 'local variable_name'
-- possible issues: table = {x=1}; local x; res["x"]
-- here x will get renamed, but x in res["x"] not producing possible error, however res.x will be renamed correctly
text = [=[
-- BEFORE: ---
local i; local n
factors = function( n )
local f = {}
for i = 1, n/2 do -- here we try all the possible factors of n
if n % i == 0 then -- here we check if n is divisible by i
f[#f+1] = i -- we found factor, add it to the list
end
end
f[#f+1] = n
print("factors of " .. n .. " are : " .. table.concat(f,","))
end
factors(25)
]=]
print(obfuscate(text)) -- print obfuscated version