Is it possible to read the following from the local variable in Lua?
local t = os.execute("echo 'test'")
print(t)
I just want to achieve this: whenever os.execute returns any value, I would like to use it in Lua - for example echo 'test' will output test in the bash command line - is that possible to get the returned value (test in this case) to the Lua local variable?
You can use io.popen() instead. This returns a file handle you can use to read the output of the command. Something like the following may work:
local handle = io.popen(command)
local result = handle:read("*a")
handle:close()
Note that this will include the trailing newline (if any) that the command emits.
function GetFiles(mask)
local files = {}
local tmpfile = '/tmp/stmp.txt'
os.execute('ls -1 '..mask..' > '..tmpfile)
local f = io.open(tmpfile)
if not f then return files end
local k = 1
for line in f:lines() do
files[k] = line
k = k + 1
end
f:close()
return files
end
Lua's os.capture returns all standard output, thus it will be returned into that variable.
Example:
local result = os.capture("echo hallo")
print(result)
Printing:
hallo
Sorry,
but this is impossible.
If the echo programm exit with success it will return 0. This returncode is what the os.execute() function get and returned too.
if 0 == os.execute("echo 'test'") then
local t = "test"
end
This is a way to get what you want, i hope it helps you.
Another Tip for getting the return code of a function is the Lua reference.
Lua-Reference/Tutorial
Related
Here I have a loadstring but attacker can just hook it and steal it's content like bellow. I want to make a anti hook so that it can be prevented.
-- Save copies of orignal functions
local o_load = _G["load"]
local o_loadstring = _G["loadstring"]
local o_unpack = _G["unpack"]
local o_pairs = _G["pairs"]
local o_writefile = _G["writefile"]
local o_print = _G["print"]
local o_tostring = _G["tostring"]
-- Dynamic function names
local load_name = tostring(_G["load"])
local loadstring_name = tostring(_G["loadstring"])
local tostring_name = tostring(_G["tostring"])
-- For multiple instances of loadstring or load being used
local files_loadstring = 1
local files_load = 1
-- Hide function names
_G["tostring"] = function(...)
local args = {...}
local arg = o_unpack(args)
if arg == _G["tostring"] then
return tostring_name
end
if arg == _G["loadstring"] then
return loadstring_name
end
if arg == _G["load"] then
return load_name
end
local ret = { o_tostring(o_unpack(args)) }
local value = o_unpack(ret)
return value
end
-- Hook loadstring
_G["loadstring"] = function(...)
local args = {...}
o_print("loadstring called")
local str = ""
for k, v in o_pairs(args) do
str = str .. o_tostring(v) .. " "
end
o_writefile("hook_loadstring"..o_tostring(files_loadstring)..".lua", str)
o_print("file written to hook_loadstring"..o_tostring(files_loadstring)..".lua")
files_loadstring = files_loadstring +1
local ret = { o_loadstring(o_unpack(args)) }
str = ""
for k, v in o_pairs(ret) do
str = str .. o_tostring(v) .. " "
end
return o_unpack(ret)
end
-- Hook load
_G["load"] = function(...)
local args = {...}
o_print("load called")
local str = ""
for k, v in o_pairs(args) do
str = str .. o_tostring(v) .. " "
end
o_writefile("hook_load"..o_tostring(files_load)..".lua", str)
o_print("file written to hook_load"..o_tostring(files_load)..".lua")
files_load = files_load +1
local ret = { o_load(o_unpack(args)) }
str = ""
for k, v in o_pairs(ret) do
str = str .. o_tostring(v) .. " "
end
return o_unpack(ret)
end
-- bellow is the loadstring function with a lua and all it's content is getting hooked and writen in a file
loadstring("local a = 1;")()`
I tried using tostring(loadstring) to compare the function name to check if it's real or fake but attacker can just hook tostring as well and give original function name so my anti hook won't work at all. Also I can't do writefile = nil or print = nil so attacker can't print or write the file since he saved a copy of these functions on top of the file so his code will work always. How can I prevent my loadstring from getting hooked like this. Please help.
I just want my content inside loadstring not to be stolen.
loadstring being hooked implies that the attacker's code runs before your code and in the same environment. This implies that all functions of the global environment may be hooked - from loadstring over tostring and including the debug library. Thus, the only thing you may rely on (and even that is uncertain, depending on which software is interpreting your Lua) are "hard-wired" (e.g. syntactical) Lua language features. You can take a look at the complete syntax of Lua. Notice that all these are basic constructs that won't help you at all; everything advanced in Lua uses function calls and the global environment, which may be hooked.
Whatever loads these scripts would need to be patched to either (1) load everything in a separate, clean environment (2) protect the global environment or at least a few selected functions, but even then the "loader" could be tampered with to remove these "protections".
In conclusion, you can't reliably prevent or detect loadstring being hooked. If you are providing someone with code for them to run, that code inevitably has to run at some point, and at that point they will be able to "steal" it. The "best" you can do is obfuscate your code so that there is little benefit from stealing it.
Bottom line: As long as your software runs "on-premise" (on their machines) rather than "as a service" (on your machines), they will always be able to steal and analyze your code; all you can do is make it harder e.g. through obfuscation or checks (which may be circumvented however).
It's me again
I'm trying to make a Terminal program in Lua since it's my best language I know, I'm making the calculator program in it and I'm trying to make it so if the user types "exit" the program will restart and will go back to the terminal, but I don't know how to reset the program through the code. if anyone can help that be deeply appreciated.
This is the code:
io.write("Terminal is starting up --- done!")
io.write("Making sure everything works --- Done!")
cmd = io.read()
io.write(">")
if cmd == "" then
io.write(">\n")
end
if cmd == "cal"then
io.write("Calculator Terminal Program v1.0")
io.write("what operation?/n")
op = io.read()
if op == "exit"then
io.write("Exiting")
end
end
To answer your question directly, I don't think it's possible to "restart the program". However, by taking advantage of loops, you can achieve the same result.
For instance, this code probably does what you want:
print('Terminal is starting up --- done!')
print('Making sure everything works --- Done!')
repeat
io.write('>')
cmd = io.read()
if cmd == 'cal' then
print('Calculator Terminal Program v1.0')
repeat
io.write('Operation: ')
op = io.read()
until op == 'exit'
print('Exiting')
elseif cmd == 'command' then
--another command
else
print('Unknown command.')
end
until cmd == 'exit'
Other tips:
You should take advantage of elseif instead of writing multiple separate if statements to improve readability.
Consider using the print function when you want a new line after writing some text for a better Terminal experience. You could also use io.write('\n').
You probably want os.exit(), which terminates the entire program.
i think this might work through creative use of load() and coroutines
this gonna stop restarting itself when 3 total error has occured
if innerProgram == nil then --innerProgram will set to true when it load itself
local filename = nil
local errorLimit = 3 --Change this to any value to enable this code to restart itself when error occur until this amount of time set zero or below to exit instantly when error occur
local errors = 0
local filename = function()
local str = debug.getinfo(2, "S").source:sub(2)
return str:match("^.*/(.*)") or str
end
filename = filename()
local src_h = io.open(filename, "r") --open in read mode
local src = src_h:read("*a")
src_h:close()
local G = _G
local quit = false --set true when you want to exit instead restart
local code = nil
local request = false
local restart = false --set true when you want restart
local program
local yield = coroutine.yield --Incase when coroutine get removed in your calculator code for no reason
local running = coroutine.running
local exit = os.exit
function G.restart()
restart = true --Always refer to restart variable above
request = true
yield() --Always refer to yield above
end
function G.os.exit(exitcode) --Replace os.exit with this
quit = true --Always refer to quit variable above
reuqest = true
code = exitcode or nil
yield() --Always refer to yield above
end
function G.coroutine.yield()
if running() == program and request == false then --Emulating coroutine.yield when it not run inside coroutine
error("attempt to yield from outside a coroutine")
end
end
G.innerProgram = true --So the inner program not keep loading itself forever
function copy(obj, seen)
if type(obj) ~= 'table' then return obj end --got from https://stackoverflow.com/questions/640642/how-do-you-copy-a-lua-table-by-value for us to clone _G variable without reference to original _G thus we can do total restart without using same _G
if seen and seen[obj] then return seen[obj] end
local s = seen or {}
local res = setmetatable({}, getmetatable(obj))
s[obj] = res
for k, v in pairs(obj) do res[copy(k, s)] = copy(v, s) end
return res
end
print("Loading "..filename)
program = coroutine.create(load(src, filename, "bt", copy(G)))
while errors < errorLimit do
restart = false
local status, err = coroutine.resume(program)
if restart == true then
print("Restarting...")
program = coroutine.create(load(src, filename, "bt", copy(G)))
--Put errors = errors + 1 if you want errors counter to reset every time the program request restart
end
if status == false and restart ~= true then
print(filename.." errored with "..err.."\nRestarting...")
program = coroutine.create(load(src, filename, "bt", copy(G)))
errors = errors + 1
elseif restart ~= true then
print(filename.." done executing.")
exit()
end
end
return
else
innerProgram = nil --Nil-ing the variable
end
Features
Auto exit when 3 total errors has occur (configure errorLimit variable)
_G is not shared (same _G as start of the program but not linked with the actual _G)
Emulating yielding outside of coroutine
Replaced os.exit so it yield then the self-loader run the os.exit
How to use
put the code i give above to very first line of your code
Feature Number 1 and 3 test
it error with the a content the value will be different in each error restart
if a == nil then --Only set a when a equal nil so if _G was shared the error value will be same
a = math.random() --Set global a to a random value
end
error(a) --Error with number a
os.exit()
So I use a program where I script mods in lua, the lua is in a sandbox state, meaning most functions are blocked like IO and OS, I can't even use REQUIRE to add libs.
I need to have a function that unzips files in one of my mods and I don't seem to find a way.
Is there anyway to do it?
If it's not possible in an easy way, is it possible to hack the program .exe or dlls to re-enable those functions in the lua?
Thank you in advance, Regards
There are decompression librarys in pure Lua, you should be able to embed these in any environment that allows loading Lua scripts: http://lua-users.org/wiki/CompressionAndArchiving
If you can't access any files at all, you could try a simple packer:
#!/usr/bin/env lua
local files = arg
local w = io.write
local function pack(...) return {...} end
w("files = {\n")
for i, filename in ipairs(arg) do
w('\t["' ..filename .. '"] = "')
local file = assert(io.open(filename, "r"), "Can't open file!")
local data = file:read("*a")
data = data:gsub("\a", "\\a")
:gsub("\\", "\\\\")
:gsub("\f", "\\f")
:gsub("\n", "\\n")
:gsub("\r", "\\r")
:gsub("\t", "\\t")
:gsub("\v", "\\v")
:gsub('"', '\\"')
:gsub("'", "\\'")
w(data, '",\n')
end
w("}\n")
w([[
function require(path)
local data = assert(files[path..".lua"], "file not found")
local func = assert(loadstring(data))
local _, ret = assert(pcall(func))
return ret
end
]])
w('require("', arg[1]:match("^(.-)%.lua$"),'")\n')
This should create a script like this:
$ ./packer.lua init.lua
files = {
["init.lua"] = "for k,v in pairs(arg) do\n\tprint(k,v)\nend\n",
}
function require(path)
local data = assert(files[path..".lua"], "file not found")
local func = assert(loadstring(data))
local _, ret = assert(pcall(func))
return ret
end
require("init")
I am using Lua with the luaposix library to get the the output of some commands, and sometimes send some too. I am using this code, or variants of this to do my work, but I sometimes get stuck at posix.wait(cpid) or sometimes the command doesn't seem to finish.
-- returns true on connected, else false
function wifi.wpa_supplicant_status()
-- iw dev wlan0-1 link
local r,w = posix.pipe()
local cpid = posix.fork()
if cpid == 0 then --child writes to pipe
--close unused read end
local devnull = posix.open("/dev/null", posix.O_RDWR)
posix.close(r)
posix.dup2(devnull, 0)
posix.dup2(w, 1)
posix.dup2(devnull, 2)
local dir = wifi.wpa_supplicant_dir()
local iface = posix.basename(dir)
iface = string.gsub(iface, "wpa_supplicant%-",'')
posix.exec('/usr/sbin/iw', {'dev', iface, 'link'})
posix._exit(-1)
elseif cpid > 0 then
--parent reads from pipe, close write end
posix.close(w)
local buf = ''
while true do
local tmp = posix.read(r, 100)
if tmp ~= nil and #tmp > 0 then
buf = buf .. tmp
else
break
end
end
-- TODO, check exit value, to see if entry exists or not
while posix.wait(cpid) ~= cpid do print("waiting in wpa_supplicant_status") end
print("status is "..buf)
if string.find(buf, "Connected to", 1, true) then
return true
else
return false
end
end
end
This is what I understand what I have to do(to just get output):
create a single pipe
fork
if child,
close read end of pipe
dup2(write_end, stdout)
exec() to desired process
if parent
close write end of pipe
do blocking reads to read end of pipe, till you get a 0 byte read, which means the child process has terminated, closing the pipe
Am I missing something?
You should have a look at the answers in this question How do you construct a read-write pipe with lua?
to get an idea of the difficulties to implement this. One thing that strikes me is that nobody seems to be able to get it to work with only one child process.
However, In the example you give, it seems you only want to get the output of the command, so I would suggest simply doing this:
function os.capture(cmd)
local f = assert(io.popen(cmd, 'r'))
local s = assert(f:read('*a'))
f:close()
return s
end
function wifi.wpa_supplicant_status()
local dir = wifi.wpa_supplicant_dir()
local iface = posix.basename(dir):gsub("wpa_supplicant%-",'')
local cmd = ('/usr/sbin/iw dev %s link'):format(iface)
local buf = os.capture(cmd)
return buf:find("Connected to", 1, true) ~= nil
end
This is not even tested, but you should get the idea.
When call a lua function like
PrintMe(MyVariableName)
I would like to be able to actually print "MyVariableName" and not it's value(well, for demo purposes).
Obviously I could just pass the string but that requires extra quotes and I also would like to print it's value.
e.g.,
MyVariable = 4
PrintVariable(MyVariable)
Would print "MyVariable is 4" or whatever
I do not want to have to duplicate the name and variable like
PrintVariable(MyVariable, "MyVariable")
as this is unnecessary duplication.
Can lua handle it?
What I'm doing now is passing the variable name in quotes and using loadstring to get the value but I would like to just pass the variable directly without the extra unnecessary quotes(which I thought debug.getlocal did but it ends up returning the value instead of the name).
Here is mock example
function printme1(var, val)
print(var.." = "..val)
end
function printme2(v)
local r
loadstring("r = "..v)() -- equivalent to r = a but must be used since v is a string representing a and not the object a
print(v.." = "..tostring(r))
end
function printme3(v)
-- unknown
end
a = 3
printme1("a", a)
printme2("a")
printme3(a)
In this case all 3 should print the same thing. printme3 obviously is the most convenient.
You can't say PrintVariable(MyVariable), because Lua gives you no way of determining which variable (if any; a constant could have been used) was used to pass an argument to your function. However, you can say PrintVariable('MyVariable') then used the debug API to look for a local variable in the caller's scope which has that name:
function PrintVariable(name)
-- default to showing the global with that name, if any
local value = _G[name]
-- see if we can find a local in the caller's scope with that name
for i=1,math.huge do
local localname, localvalue = debug.getlocal(2,i,1)
if not localname then
break -- no more locals to check
elseif localname == name then
value = localvalue
end
end
if value then
print(string.format("%s = %s", name, tostring(value)))
else
print(string.format("No variable named '%s' found.", name))
end
end
Now you can say:
PrintVariable('MyVariable')
While in this case will print "MyVariable = 4".
Not, if you really want to do this without the quotes, you could check the caller's locals for variables that have a supplied value, but that's occasionally going to give you the wrong variable name if there is more than one variable in the caller's scope with a given value. With that said, here's how you'd do that:
function PrintVariable(value)
local name
-- see if we can find a local in the caller's scope with the given value
for i=1,math.huge do
local localname, localvalue = debug.getlocal(2,i,1)
if not localname then
break
elseif localvalue == value then
name = localname
end
end
-- if we couldn't find a local, check globals
if not name then
for globalname, globalvalue in pairs(_G) do
if globalvalue == value then
name = globalname
end
end
end
if name then
print(string.format("%s = %s", name, tostring(value)))
else
print(string.format("No variable found for the value '%s'.", tostring(value)))
end
end
Now you can say PrintVariable(MyVariable), but if there happened to be another variable in the caller's scope with the value 4, and it occurred before MyVariable, it's that variable name that will be printed.
you can do stuff like this with the debug library... something like this does what you seem to be looking for:
function a_func(arg1, asdf)
-- if this function doesn't use an argument... it shows up as (*temporary) in
-- calls to debug.getlocal() because they aren't used...
if arg1 == "10" then end
if asdf == 99 then end
-- does stuff with arg1 and asdf?
end
-- just a function to dump variables in a user-readable format
function myUnpack(tbl)
if type(tbl) ~= "table" then
return ""
end
local ret = ""
for k,v in pairs(tbl) do
if tostring(v) ~= "" then
ret = ret.. tostring(k).. "=".. tostring(v).. ", "
end
end
return string.gsub(ret, ", $", "")
end
function hook()
-- passing 2 to to debug.getinfo means 'give me info on the function that spawned
-- this call to this function'. level 1 is the C function that called the hook.
local info = debug.getinfo(2)
if info ~= nil and info.what == "Lua" then
local i, variables = 1, {""}
-- now run through all the local variables at this level of the lua stack
while true do
local name, value = debug.getlocal(2, i)
if name == nil then
break
end
-- this just skips unused variables
if name ~= "(*temporary)" then
variables[tostring(name)] = value
end
i = i + 1
end
-- this is what dumps info about a function thats been called
print((info.name or "unknown").. "(".. myUnpack(variables).. ")")
end
end
-- tell the debug library to call lua function 'hook 'every time a function call
-- is made...
debug.sethook(hook, "c")
-- call a function to try it out...
a_func("some string", 2012)
this results in the output:
a_func(asdf=2012, arg1=some string)
you can do fancier stuff to pretty this up, but this basically covers how to do what you're asking.
I have bad news, my friend. You can access function parameter names as they appear at the top of the function, but the data to access exactly what they were named in the calling function does not exist. See the following:
function PrintVariable(VariableToPrint)
--we can use debug.getinfo() to determine the name 'VariableToPrint'
--we cannot determine the name 'MyVariable' without some really convoluted stuff (see comment by VBRonPaulFan on his own answer)
print(VariableToPrint);
end
MyVariable = 4
PrintVariable(MyVariable)
To illustrate this, imagine if we had done:
x = 4
MyVariable = x
MyOtherVariable = x
x = nil
PrintVariable(MyVariable)
Now if you were Lua, what name would you attach in the metadata to the variable that ends up getting passed to the function? Yes, you could walk up the stack with debug.getint() looking for the variable that was passed in, but you may find several references.
Also consider:
PrintVariable("StringLiteral")
What would you call that variable? It has a value but no name.
You could just use this form:
local parms = { "MyVariable" }
local function PrintVariable(vars)
print(parms[1]..": "..vars[1])
end
local MyVariable = "bar"
PrintVariable{MyVariable}
Which gives:
MyVariable: bar
It isn't generic, but it is simple. You avoid the debug library and loadstring by doing it this way. If your editor is any good, you could write a macro to do it.
Another possible solution is add this facility your self.
The Lua C API and source is pretty simple and extendable.
I/we don't know the context of your project/work but if you ARE making/embedding your own Lua build you could extend the debug library with something to do this.
Lua passes it's values by reference, but unknown offhand if these contain a string name in them and if so if easily accessible.
In your example the value declaration is the same as:
_G["MyVariable"] = 4
Since it's global. If it were declared local then like others stated here you can enumerate those via debug.getlocal(). But again in the C context of the actual reference context it might not matter.
Implement a debug.getargumentinfo(...) that extends the argument table with name key, value pairs.
This is quite an old topic and I apologize for bringing it back to life.
In my experience with lua, the closest I know to what the OP asked for is something like this:
PrintVariable = {}
setmetatable(PrintVariable, {__index = function (self, k, v) return string.format('%s = %s', k, _G[k]) end})
VAR = 0
VAR2 = "Hello World"
print(PrintVariable.VAR, PrintVariable.VAR2)
-- Result: VAR = 0 VAR2 = Hello World
I do not give more explanation, because the code is quite readable, however:
What happens here is simple, you only set a metatable to the PrintVariable variable and add the __index metamethod that is called when the table is forced to search for a value in its index, thanks to this functionality you can achieve what you see in the example.
Reference: https://www.lua.org/manual/5.1/manual.html
I hope that future and new visitors will find this helpful.