Advertisement
PaymentOption

Protected Program Executer

May 16th, 2013
160
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 11.21 KB | None | 0 0
  1. --[[
  2.     Protected Execute       Trystan Cannon
  3.                             16 May 2013
  4.                            
  5.     This program allows for users to run other
  6.     programs without the risk of potentially
  7.     malicious functions to execute without their
  8.     allowing so. Currently, this program only
  9.     prevents unauthorized 'fs' and 'os' calls.
  10.    
  11.     Version: 1.0 Updated 16 May 2013
  12. --]]
  13.  
  14. -- Variables ------------------------------------
  15. local NATIVE_TERMINAL = term.native -- A reference to the native terminal functions.
  16. _G.screenBuffer       = {} -- A table containing the visual contents of the screen.
  17.  
  18. local WARNING_BOX_WIDTH, WARNING_BOX_HEIGHT = 25, 7 -- The width and height of every warning box that is drawn.
  19. local oldFunctions                          = {}
  20. -- Variables ------------------------------------
  21.  
  22. -- Screen Buffer Functions ------------------------------------
  23. -- Checks if the given color is a valid color on the computer. Returns true or false depending on the aforementioned condition.
  24. local function isColorValid (color)
  25.     for colorIndex, colorValue in pairs (colors) do
  26.         if colorValue == color and type (colorValue) == "number" then
  27.             return true
  28.         end
  29.     end
  30.    
  31.     return false
  32. end
  33.  
  34. -- Initializes the global table 'screenBuffer' table to keep track of the screen's contents. Also, this method redirects the terminal
  35. -- to write to the screen buffer and the screen.
  36. local function initScreenBuffer()
  37.     -- Initialize the screen buffer to be an empty canvas of cells whose text color is white and background color is black.
  38.     screenBuffer.currentTextColor       = colors.white
  39.     screenBuffer.currentBackgroundColor = colors.black
  40.    
  41.     local screenWidth, screenHeight = term.getSize()
  42.     for height = 1, screenHeight do
  43.         screenBuffer[height] = {}
  44.        
  45.         for width = 1, screenWidth do
  46.             screenBuffer[height][width] = {text = ' ', textColor = colors.white, backgroundColor = colors.black}
  47.         end
  48.     end
  49.    
  50.     -- Create a new terminal table which will have all of the native functions with some edited functionality.
  51.     local terminal = {}
  52.     for functionName, functionObject in pairs (NATIVE_TERMINAL) do
  53.         terminal[functionName] = functionObject
  54.     end
  55.    
  56.     -- Overrides the term.write method to write to the screen buffer and the screen.
  57.     terminal.write = function (text)
  58.         local cursorX, cursorY = term.getCursorPos()
  59.        
  60.         if cursorX < 1 or cursorX > screenWidth or cursorY < 1 or cursorY > screenHeight then
  61.             return NATIVE_TERMINAL.write (text)
  62.         end
  63.        
  64.         for charIndex = 1, text:len() do
  65.             screenBuffer[cursorY][cursorX].text            = text:sub (charIndex, charIndex)
  66.             screenBuffer[cursorY][cursorX].textColor       = screenBuffer.currentTextColor
  67.             screenBuffer[cursorY][cursorX].backgroundColor = screenBuffer.currentBackgroundColor
  68.             cursorX = cursorX + 1
  69.            
  70.             if cursorX > screenWidth then
  71.                 break
  72.             end
  73.         end
  74.        
  75.         return NATIVE_TERMINAL.write (text)
  76.     end
  77.    
  78.     -- Overrides the term.setTextColor method to set the current text color of the screen buffer and the terminal.
  79.     terminal.setTextColor = function (textColor)
  80.         if isColorValid (textColor) then
  81.             screenBuffer.currentTextColor = textColor
  82.         end
  83.        
  84.         return NATIVE_TERMINAL.setTextColor (textColor)
  85.     end
  86.    
  87.     -- Overrides the term.setBackgroundColor method to set the current background color of the screen buffer and the terminal.
  88.     terminal.setBackgroundColor = function (backgroundColor)
  89.         if isColorValid (backgroundColor) then
  90.             screenBuffer.currentBackgroundColor = backgroundColor
  91.         end
  92.        
  93.         return NATIVE_TERMINAL.setBackgroundColor (backgroundColor)
  94.     end
  95.    
  96.     -- Overrides the term.clear method to clear out the entire buffer and the terminal.
  97.     terminal.clear = function()
  98.         for line = 1, screenHeight do
  99.             for width = 1, screenWidth do
  100.                 local cell = screenBuffer[line][width]
  101.                
  102.                 cell.text            = ' '
  103.                 cell.textColor       = screenBuffer.currentTextColor
  104.                 cell.backgroundColor = screenBuffer.currentBackgroundColor
  105.             end
  106.         end
  107.        
  108.         return NATIVE_TERMINAL.clear()
  109.     end
  110.    
  111.     -- Overrides the term.clearLine method to clear out only the current line in the buffer and terminal.
  112.     terminal.cearLine = function()
  113.         local _, currentLine = term.getCursorPos()
  114.        
  115.         if currentLine > 0 and currentLine <= screenHeight then
  116.             for width = 1, screenWidth do
  117.                 local cell = screenBuffer[currentLine][width]
  118.                
  119.                 cell.text            = ' '
  120.                 cell.textColor       = screenBuffer.currentTextColor
  121.                 cell.backgroundColor = screenBuffer.currentBackgroundColor
  122.             end
  123.         end
  124.        
  125.         return NATIVE_TERMINAL.clearLine()
  126.     end
  127.    
  128.     term.redirect (terminal)
  129. end
  130.  
  131. -- Kills the screen buffer by emptying the buffer and restoring the terminal to its native functionality.
  132. local function killScreenBuffer()
  133.     screenBuffer = {}
  134.     term.redirect (NATIVE_TERMINAL)
  135. end
  136. -- Screen Buffer Functions ------------------------------------
  137.  
  138. -- Anti Virus Functions ------------------------------------
  139. -- Prompts the user if a program being executed is trying to execute a malicious function. The user
  140. -- will be asked if they want the program to be allowed to execute the function. However, if the user says
  141. -- no, then the program might not work properly. Returns true or false depending on the Y/N value of the
  142. -- user's input.
  143. local function promptUserOfMaliciousFunctionCall (functionName)
  144.     local cursorX, cursorY          = term.getCursorPos()
  145.     local screenWidth, screenHeight = term.getSize()
  146.     local MAX_MESSAGE_WIDTH         = WARNING_BOX_WIDTH - 4
  147.    
  148.     -- Draws a string in the center of the screen.
  149.     local function drawCentered (myString, line)
  150.         term.setCursorPos (screenWidth / 2 - myString:len() / 2, line)
  151.         NATIVE_TERMINAL.write (myString)
  152.     end
  153.    
  154.     -- Draw a simple black and white box in the middle of the screen which describes the situation.
  155.     local currentTextColor, currentBackgroundColor = screenBuffer.currentTextColor, screenBuffer.currentBackgroundColor
  156.     term.setTextColor (colors.white)
  157.     term.setBackgroundColor (colors.black)
  158.    
  159.     drawCentered ('+' .. string.rep ('-', WARNING_BOX_WIDTH - 2) .. '+', screenHeight / 2 - WARNING_BOX_HEIGHT / 2)
  160.     for line = 1, WARNING_BOX_HEIGHT do
  161.         drawCentered ('|' .. string.rep (' ', WARNING_BOX_WIDTH - 2) .. '|', line + screenHeight / 2 - WARNING_BOX_HEIGHT / 2)
  162.     end
  163.     drawCentered ('+' .. string.rep ('-', WARNING_BOX_WIDTH - 2) .. '+', screenHeight / 2 + WARNING_BOX_HEIGHT / 2)
  164.    
  165.     drawCentered ("Malicious call:", screenHeight / 2 - WARNING_BOX_HEIGHT / 2 + 1)
  166.     drawCentered (functionName:sub (1, MAX_MESSAGE_WIDTH), screenHeight / 2 - WARNING_BOX_HEIGHT / 2 + 3)
  167.     drawCentered ("Allow call? Y \\ N?", screenHeight / 2 - WARNING_BOX_HEIGHT / 2 + 5)
  168.    
  169.     -- Wait for the user to press 'Y' or 'N' signaling their answer.
  170.     local char = nil
  171.     while not (char == 'y' or char == 'n') do
  172.         _, char = oldFunctions.os.pullEvent ("char")
  173.     end
  174.    
  175.     -- Restore the screen to the way it was.
  176.     for lineNumber = 1, screenHeight do
  177.         for cellNumber = 1, screenWidth do
  178.             local cell = screenBuffer[lineNumber][cellNumber]
  179.            
  180.             NATIVE_TERMINAL.setTextColor (cell.textColor)
  181.             NATIVE_TERMINAL.setBackgroundColor (cell.backgroundColor)
  182.             NATIVE_TERMINAL.setCursorPos (cellNumber, lineNumber)
  183.             NATIVE_TERMINAL.write (cell.text)
  184.         end
  185.     end
  186.     NATIVE_TERMINAL.setCursorPos (cursorX, cursorY)
  187.     NATIVE_TERMINAL.setTextColor (screenBuffer.currentTextColor)
  188.     NATIVE_TERMINAL.setBackgroundColor (screenBuffer.currentBackgroundColor)
  189.    
  190.     return char == 'y'
  191. end
  192.  
  193. -- Secures all of the functions in the APIs specified in 'maliciousAPIs' to prompt the user if they want to allow some program to execute
  194. -- a potentially malicious function.
  195. -- Returns all of the old functions in a table.
  196. local function secureMaliciousAPIs()
  197.     local oldFunctions = {}
  198.    
  199.     -- Secure the os API.
  200.     oldFunctions.os = {}
  201.     for functionName, functionObject in pairs (os) do
  202.         oldFunctions.os[functionName] = functionObject
  203.        
  204.         os[functionName] = function (...)
  205.             if promptUserOfMaliciousFunctionCall ("os." .. functionName) then
  206.                 return oldFunctions.os[functionName] (...)
  207.             else
  208.                 return nil
  209.             end
  210.         end
  211.     end
  212.    
  213.     -- Clean up the exceptions for the os API.
  214.     os.startTimer   = oldFunctions.os.startTimer
  215.     os.pullEvent    = oldFunctions.os.pullEvent
  216.     os.pullEventRaw = oldFunctions.os.pullEventRaw
  217.    
  218.     -- Secure the fs API.
  219.     oldFunctions.fs = {}
  220.     for functionName, functionObject in pairs (fs) do
  221.         oldFunctions.fs[functionName] = functionObject
  222.        
  223.         fs[functionName] = function (...)
  224.             if promptUserOfMaliciousFunctionCall ("fs." .. functionName) then
  225.                 return oldFunctions.fs[functionName] (...)
  226.             else
  227.                 return nil
  228.             end
  229.         end
  230.     end
  231.    
  232.     -- Clean up the exceptions for the fs API.
  233.     fs.isDir      = oldFunctions.fs.isDir
  234.     fs.exists     = oldFunctions.fs.exists
  235.     fs.combine    = oldFunctions.fs.combine
  236.     fs.getName    = oldFunctions.fs.getName
  237.     fs.list       = oldFunctions.fs.list
  238.     fs.isReadOnly = oldFunctions.fs.isReadOnly
  239.    
  240.     return oldFunctions
  241. end
  242.  
  243. -- Restores all of the secured APIs to their previous states given a table containing the states of all of the malicious APIs.
  244. local function restoreMaliciousAPIs (oldFunctions)
  245.     for apiName, api in pairs (oldFunctions) do
  246.         for functionName, functionObject in pairs (api) do
  247.             local currentEnvironment = getfenv (1)
  248.            
  249.             if _G[apiName] ~= nil then
  250.                 _G[apiName][functionName] = functionObject
  251.             elseif currentEnvironment[apiName] ~= nil then
  252.                 currentEnvironment[apiName][functionName] = functionObject
  253.             end
  254.         end
  255.     end
  256. end
  257. -- Anti Virus Functions ------------------------------------
  258.  
  259. -- 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.
  260. local tArgs       = { ... }
  261. local path        = (tArgs[1] ~= nil) and shell.resolve (tArgs[1]) or ""
  262. local currentPath = shell.resolve (shell.getRunningProgram())
  263.  
  264. if path ~= currentPath and fs.exists (path) and not fs.isDir (path) then
  265.     initScreenBuffer()
  266.     oldFunctions = secureMaliciousAPIs()
  267.    
  268.     local success, errorMessage = pcall (dofile, path)
  269.     restoreMaliciousAPIs (oldFunctions)
  270.     killScreenBuffer()
  271. else
  272.     print ("Usage: " .. fs.getName (currentPath) .. " <filePath>.")
  273. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement