Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --[[
- Protected Execute Trystan Cannon
- 16 May 2013
- This program allows for users to run other
- programs without the risk of potentially
- malicious functions to execute without their
- allowing so. Currently, this program only
- prevents unauthorized 'fs' and 'os' calls.
- Version: 1.0 Updated 16 May 2013
- --]]
- -- Variables ------------------------------------
- local NATIVE_TERMINAL = term.native -- A reference to the native terminal functions.
- _G.screenBuffer = {} -- A table containing the visual contents of the screen.
- local WARNING_BOX_WIDTH, WARNING_BOX_HEIGHT = 25, 7 -- The width and height of every warning box that is drawn.
- local oldFunctions = {}
- -- Variables ------------------------------------
- -- Screen Buffer Functions ------------------------------------
- -- Checks if the given color is a valid color on the computer. Returns true or false depending on the aforementioned condition.
- local function isColorValid (color)
- for colorIndex, colorValue in pairs (colors) do
- if colorValue == color and type (colorValue) == "number" then
- return true
- end
- end
- return false
- end
- -- Initializes the global table 'screenBuffer' table to keep track of the screen's contents. Also, this method redirects the terminal
- -- to write to the screen buffer and the screen.
- local function initScreenBuffer()
- -- Initialize the screen buffer to be an empty canvas of cells whose text color is white and background color is black.
- screenBuffer.currentTextColor = colors.white
- screenBuffer.currentBackgroundColor = colors.black
- local screenWidth, screenHeight = term.getSize()
- for height = 1, screenHeight do
- screenBuffer[height] = {}
- for width = 1, screenWidth do
- screenBuffer[height][width] = {text = ' ', textColor = colors.white, backgroundColor = colors.black}
- end
- end
- -- Create a new terminal table which will have all of the native functions with some edited functionality.
- local terminal = {}
- for functionName, functionObject in pairs (NATIVE_TERMINAL) do
- terminal[functionName] = functionObject
- end
- -- Overrides the term.write method to write to the screen buffer and the screen.
- terminal.write = function (text)
- local cursorX, cursorY = term.getCursorPos()
- if cursorX < 1 or cursorX > screenWidth or cursorY < 1 or cursorY > screenHeight then
- return NATIVE_TERMINAL.write (text)
- end
- for charIndex = 1, text:len() do
- screenBuffer[cursorY][cursorX].text = text:sub (charIndex, charIndex)
- screenBuffer[cursorY][cursorX].textColor = screenBuffer.currentTextColor
- screenBuffer[cursorY][cursorX].backgroundColor = screenBuffer.currentBackgroundColor
- cursorX = cursorX + 1
- if cursorX > screenWidth then
- break
- end
- end
- return NATIVE_TERMINAL.write (text)
- end
- -- Overrides the term.setTextColor method to set the current text color of the screen buffer and the terminal.
- terminal.setTextColor = function (textColor)
- if isColorValid (textColor) then
- screenBuffer.currentTextColor = textColor
- end
- return NATIVE_TERMINAL.setTextColor (textColor)
- end
- -- Overrides the term.setBackgroundColor method to set the current background color of the screen buffer and the terminal.
- terminal.setBackgroundColor = function (backgroundColor)
- if isColorValid (backgroundColor) then
- screenBuffer.currentBackgroundColor = backgroundColor
- end
- return NATIVE_TERMINAL.setBackgroundColor (backgroundColor)
- end
- -- Overrides the term.clear method to clear out the entire buffer and the terminal.
- terminal.clear = function()
- for line = 1, screenHeight do
- for width = 1, screenWidth do
- local cell = screenBuffer[line][width]
- cell.text = ' '
- cell.textColor = screenBuffer.currentTextColor
- cell.backgroundColor = screenBuffer.currentBackgroundColor
- end
- end
- return NATIVE_TERMINAL.clear()
- end
- -- Overrides the term.clearLine method to clear out only the current line in the buffer and terminal.
- terminal.cearLine = function()
- local _, currentLine = term.getCursorPos()
- if currentLine > 0 and currentLine <= screenHeight then
- for width = 1, screenWidth do
- local cell = screenBuffer[currentLine][width]
- cell.text = ' '
- cell.textColor = screenBuffer.currentTextColor
- cell.backgroundColor = screenBuffer.currentBackgroundColor
- end
- end
- return NATIVE_TERMINAL.clearLine()
- end
- term.redirect (terminal)
- end
- -- Kills the screen buffer by emptying the buffer and restoring the terminal to its native functionality.
- local function killScreenBuffer()
- screenBuffer = {}
- term.redirect (NATIVE_TERMINAL)
- end
- -- Screen Buffer Functions ------------------------------------
- -- Anti Virus Functions ------------------------------------
- -- Prompts the user if a program being executed is trying to execute a malicious function. The user
- -- will be asked if they want the program to be allowed to execute the function. However, if the user says
- -- no, then the program might not work properly. Returns true or false depending on the Y/N value of the
- -- user's input.
- local function promptUserOfMaliciousFunctionCall (functionName)
- local cursorX, cursorY = term.getCursorPos()
- local screenWidth, screenHeight = term.getSize()
- local MAX_MESSAGE_WIDTH = WARNING_BOX_WIDTH - 4
- -- Draws a string in the center of the screen.
- local function drawCentered (myString, line)
- term.setCursorPos (screenWidth / 2 - myString:len() / 2, line)
- NATIVE_TERMINAL.write (myString)
- end
- -- Draw a simple black and white box in the middle of the screen which describes the situation.
- local currentTextColor, currentBackgroundColor = screenBuffer.currentTextColor, screenBuffer.currentBackgroundColor
- term.setTextColor (colors.white)
- term.setBackgroundColor (colors.black)
- drawCentered ('+' .. string.rep ('-', WARNING_BOX_WIDTH - 2) .. '+', screenHeight / 2 - WARNING_BOX_HEIGHT / 2)
- for line = 1, WARNING_BOX_HEIGHT do
- drawCentered ('|' .. string.rep (' ', WARNING_BOX_WIDTH - 2) .. '|', line + screenHeight / 2 - WARNING_BOX_HEIGHT / 2)
- end
- drawCentered ('+' .. string.rep ('-', WARNING_BOX_WIDTH - 2) .. '+', screenHeight / 2 + WARNING_BOX_HEIGHT / 2)
- drawCentered ("Malicious call:", screenHeight / 2 - WARNING_BOX_HEIGHT / 2 + 1)
- drawCentered (functionName:sub (1, MAX_MESSAGE_WIDTH), screenHeight / 2 - WARNING_BOX_HEIGHT / 2 + 3)
- drawCentered ("Allow call? Y \\ N?", screenHeight / 2 - WARNING_BOX_HEIGHT / 2 + 5)
- -- Wait for the user to press 'Y' or 'N' signaling their answer.
- local char = nil
- while not (char == 'y' or char == 'n') do
- _, char = oldFunctions.os.pullEvent ("char")
- end
- -- Restore the screen to the way it was.
- for lineNumber = 1, screenHeight do
- for cellNumber = 1, screenWidth do
- local cell = screenBuffer[lineNumber][cellNumber]
- NATIVE_TERMINAL.setTextColor (cell.textColor)
- NATIVE_TERMINAL.setBackgroundColor (cell.backgroundColor)
- NATIVE_TERMINAL.setCursorPos (cellNumber, lineNumber)
- NATIVE_TERMINAL.write (cell.text)
- end
- end
- NATIVE_TERMINAL.setCursorPos (cursorX, cursorY)
- NATIVE_TERMINAL.setTextColor (screenBuffer.currentTextColor)
- NATIVE_TERMINAL.setBackgroundColor (screenBuffer.currentBackgroundColor)
- return char == 'y'
- end
- -- Secures all of the functions in the APIs specified in 'maliciousAPIs' to prompt the user if they want to allow some program to execute
- -- a potentially malicious function.
- -- Returns all of the old functions in a table.
- local function secureMaliciousAPIs()
- local oldFunctions = {}
- -- Secure the os API.
- oldFunctions.os = {}
- for functionName, functionObject in pairs (os) do
- oldFunctions.os[functionName] = functionObject
- os[functionName] = function (...)
- if promptUserOfMaliciousFunctionCall ("os." .. functionName) then
- return oldFunctions.os[functionName] (...)
- else
- return nil
- end
- end
- end
- -- Clean up the exceptions for the os API.
- os.startTimer = oldFunctions.os.startTimer
- os.pullEvent = oldFunctions.os.pullEvent
- os.pullEventRaw = oldFunctions.os.pullEventRaw
- -- Secure the fs API.
- oldFunctions.fs = {}
- for functionName, functionObject in pairs (fs) do
- oldFunctions.fs[functionName] = functionObject
- fs[functionName] = function (...)
- if promptUserOfMaliciousFunctionCall ("fs." .. functionName) then
- return oldFunctions.fs[functionName] (...)
- else
- return nil
- end
- end
- end
- -- Clean up the exceptions for the fs API.
- fs.isDir = oldFunctions.fs.isDir
- fs.exists = oldFunctions.fs.exists
- fs.combine = oldFunctions.fs.combine
- fs.getName = oldFunctions.fs.getName
- fs.list = oldFunctions.fs.list
- fs.isReadOnly = oldFunctions.fs.isReadOnly
- return oldFunctions
- end
- -- Restores all of the secured APIs to their previous states given a table containing the states of all of the malicious APIs.
- local function restoreMaliciousAPIs (oldFunctions)
- for apiName, api in pairs (oldFunctions) do
- for functionName, functionObject in pairs (api) do
- local currentEnvironment = getfenv (1)
- if _G[apiName] ~= nil then
- _G[apiName][functionName] = functionObject
- elseif currentEnvironment[apiName] ~= nil then
- currentEnvironment[apiName][functionName] = functionObject
- end
- end
- end
- end
- -- Anti Virus Functions ------------------------------------
- -- Get the potential file path that we need to check for malicious calls. If there wasn't a valid file path then print the program usage instructions.
- local tArgs = { ... }
- local path = (tArgs[1] ~= nil) and shell.resolve (tArgs[1]) or ""
- local currentPath = shell.resolve (shell.getRunningProgram())
- if path ~= currentPath and fs.exists (path) and not fs.isDir (path) then
- initScreenBuffer()
- oldFunctions = secureMaliciousAPIs()
- local success, errorMessage = pcall (dofile, path)
- restoreMaliciousAPIs (oldFunctions)
- killScreenBuffer()
- else
- print ("Usage: " .. fs.getName (currentPath) .. " <filePath>.")
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement