Перейти к содержимому
Kimapr

Защитник таблиц: tprotect

Рекомендуемые сообщения

В 24.01.2019 в 16:22, Kimapr сказал:

Бывали ли у вас когда-нибудь такие ситуации, когда необходимо защитить какую-либо таблицу от записи? Например, вы пишите операционную систему в OpenComputers,

и хотите хоть какую-то защиту от вирусов. Бедные таблицы всегда в очень большой опасности. С tprotect ваши таблицы будут в безопасности, так как другие программы вместо оригинала таблицы получат её зеркальную копию. А когда вы захотите снова в нее что-то записать, вы сможете это сделать (оригинал же у вас?). Вообщем вот ее код :

  Показать содержимое

local tprotect={}
local raw_rawset=rawset -- Сохраняем rawset для дальнейшего пользования
local raw_rawget=rawget -- Сохраняем rawget для дальнейшего пользования
local getmetatable=getmetatable --
local setmetatable=setmetatable --
local type=type                 -- Дополнительная зашыта
local error=error               --
local assert=assert             --
local protectid={}
local nextid={}
function rawget(t,k)
  if type(t)=="table" and raw_rawget(t,protectid) then
    error("СЕРЬЁЗНАЯ ПРОБЛЕМА БЕЗОПАСНОСТИ ДЕТЕКТЕД. УНИЧТОЖАЕМ ОПАСНОСТЬ...",2)
  end
  return raw_rawget(t,k)
end
local raw_next=next
-- НИКТО НЕ ДОЛЖЕН УЗНАТЬ МАСТЕР-КЛЮЧ!!!
function next(t,k)
  if type(t)=="table" and raw_rawget(t,protectid) then
    error("СЕРЬЁЗНАЯ ПРОБЛЕМА БЕЗОПАСНОСТИ ДЕТЕКТЕД. УНИЧТОЖАЕМ ОПАСНОСТЬ...",2)
  end
  local ok,k,v=xpcall(raw_next,debug.traceback,t,k)
  if not ok then
    error(k,0)
  end
  return k,v
end
local raw_ipairs=ipairs
function ipairs(...)
  local f,t,z=raw_ipairs(...)
  return function(t,k)
    if type(t)=="table" and raw_rawget(t,protectid) then
      error("СЕРЬЁЗНАЯ ПРОБЛЕМА БЕЗОПАСНОСТИ ДЕТЕКТЕД. УНИЧТОЖАЕМ ОПАСНОСТЬ...",2)
    end
    return f(t,k)
  end,t,z
end
function rawset(t,k,v) -- Потому что в защитные копии таблиц можно было бы записывать. Хоть это бы и не отразилось бы на оригинале, но при попытке индекснуть поле защитной копии будет подложено подмененное поле в обход __index :(
  if k==protectid then
    error("СЕРЬЁЗНАЯ ПРОБЛЕМА БЕЗОПАСНОСТИ ДЕТЕКТЕД. УНИЧТОЖАЕМ ОПАСНОСТЬ...",2)
  end
  assert(type(t)=="table","bad argument #1 to rawset (table expected, got "..type(t)..")")
  assert(type(k)~="nil","bad argument #2 to rawset (table index is nil)")
  local mt=getmetatable(t)
  local no_set=raw_rawget(t,protectid) or (type(mt)=="table" and raw_rawget(mt,protectid))
  if no_set then
    error("таблица рид-онли! Аксес дэняйд!",2)
  end
  raw_rawset(t,k,v)
  return t
end
function tprotect.protect(t)
  local tcopy={[protectid]=true}
  local mto=getmetatable(t)
  local tcopy_mt=type(mto)=="table" and mto or {}
  local mt={[protectid]=true}
  function mt:__index(k)
    local x=t[k]
    if tcopy_mt.__index and not x then
      return tcopy_mt.__index(t,k)
    end
    return t[k]
  end
  function mt:__pairs(self)
    if tcopy_mt.__pairs then
      return tcopy_mt.__pairs(t)
    end
    local function iter(x,i)
      assert(x==self)
      return next(t,i)
    end
    return iter,self,nil
  end
  function mt:__ipairs(self)
    if tcopy_mt.__ipairs then
      return tcopy_mt.__ipairs(t)
    end
    local f,x,i=ipairs(self)
    local function iter(self,i)
      return f(t,i)
    end
    return iter,x,i
  end
  function mt:__newindex(k,v)
    if tcopy_mt.__newindex then -- Мы доверяем нашим клиентам!
      return tcopy_mt.__newindex(self,k,v)
    end
    error("СРЕДНЕНЬКАЯ ПРОБЛЕМА БЕЗОПАСНОСТИ ДЕТЕКТЕД. УНИЧТОЖАЕМ ОПАСНОСТЬ...",2)
  end
  mt.__metatable={"Хочешь проблем? Попытайся взломать tprotect!"}
  setmetatable(mt,{__index=function(self,i)
    local v=tcopy_mt
    if type(v)=="function" then
      return function(self,...)
        return v(t,...)
      end
    end
    return v
  end})
  setmetatable(tcopy,mt)
  return tcopy,tcopy_mt
end
local tprotect_t,tprotect_mt=tprotect.protect(tprotect) -- Защитим нашу библиотечку
return tprotect_t

А теперь документация, а то я пишу код непонятно:


function tprotect.protect(table:t):table -- Возвращает "зеркало" таблицы t и её метатаблицу (у "зеркальной" таблицы она неизменяема). "Зеркальная" таблица защищена от записи и всегда является отражением t. Если вы хотите защитить таблицу t, то на публичное (доступное для других программ, от которых вам хотелось бы защитить t) место, где вы ставите обычно таблицу t, ставьте "зеркальную" таблицу

 

есть серьезная проблема, ты подменяешь pairs/ipairs и другие функции в табличке _ENV а не в табличке _G, в openOS это разные таблички в отличии от eeprom хоть и у всех программ _ENV обшей, у демонов и в интерпретаторе lua он костюмный, и получить доступ к оригинальному pairs можно банально так _G.pairs, конечно при таком оброшении (pairs) из обычной программы будет задействоваться переопределенный pairs итд так как _ENV более приоритетнее _G но удалив pairs из _ENV будет работать оригинальный из _G, надеюсь понятно объяснил, и кста _ENV очишяеться при закрытии shell, и тебе нужно подменять функции так function _G.pairs(...) return raw_pairs(...) end, а не так function pairs(...) return raw_pairs(...) end

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
4 минуты назад, rootmaster сказал:

_ENV очишяеться при закрытии shell

По-хорошему, tprotect должен запускаться вообще до начала загрузки системы. Тогда ему будет без разницы на закрытие shell/чего-то ещё.

 

5 минут назад, rootmaster сказал:

удалив pairs из _ENV будет работать оригинальный из _G

Значит, _ENV тоже надо блокировать. Заодно не будут работать глобальные переменные - потому что не надо их использовать, лучше уж писать данные в tmpfs. (Или сделать в системе какую-то таблицу для хранения данных программ.)

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
10 минут назад, ProgramCrafter сказал:

По-хорошему, tprotect должен запускаться вообще до начала загрузки системы. Тогда ему будет без разницы на закрытие shell/чего-то ещё.

 

Значит, _ENV тоже надо блокировать. Заодно не будут работать глобальные переменные - потому что не надо их использовать, лучше уж писать данные в tmpfs. (Или сделать в системе какую-то таблицу для хранения данных программ.)

нет ты просто должен заменять в _G, твоя библиотека будет хорошо работать в Opendroid(ос которую я шас пишу) но для openOS ее надо переделать, да если подгрузить до начала загрузки то _G == _ENV и все будет нормально, но ты просто сделай как я тебе сказал это ОЧЕНЬ сильно поднимит безопасность, а глобальные переменные тоже надо создавать в _G(_G.value = 231) иначе это будет как бы глобалы, но например из демона доступны другим программам не будут(и другим демонам) а если так _G.value - 123 то будут и таким переменные нечего не страшно(кроме _G.value = nil конечно, а вот кстати так (value = nil) их не удалить потому что так обращения идет к _ENV)

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
3 часа назад, rootmaster сказал:

библиотека будет хорошо работать в Opendroid(ос которую я шас пишу)

Оооо, готовится очередная топОС от маэстро программирования :D

 

3 часа назад, rootmaster сказал:

но ты просто сделай как я тебе сказал

А ты вообще в курсе, что говоришь это НЕ автору библиотеки?

Автор тут не появлялся с 30 января 2021 года, а потому тебя скорее всего не услышит))0

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в тему...

×   Вы вставили отформатированное содержимое.   Удалить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отобразить как ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.


×
×
  • Создать...