签名的字节码加载

因此,我正在研究如何为 Lua 的“load”函数加载字节码进行安全处理。目前,我的代码如下:

local nativeload = load
load = function(chunk, chunkname, mode, ...)
  if mode == nil then
    mode = "bt"
  elseif not (mode == "b" or mode == "t" or mode == "bt") then
    error("无效模式")
  end
  local targetenv = [[snip]]
  if select('#', ...) > 0 then targetenv = ... end
  if mode == "t" then
    return nativeload(chunk, chunkname, mode, targetenv)
  elseif type(chunk) == "string" then
    if chunk:sub(1,4) == "\27Lua" then
      local code = chunk:sub(1,-33)
      if HMAC_SHA256(code, getkey()) == chunk:sub(-32) then
        return nativeload(code, chunkname, mode, targetenv)
      else
        error("无效签名")
      end
    else
      return nativeload(chunk, chunkname, mode, targetenv)
    end
  elseif type(chunk) == "function" then
    -- 我该怎么做?!
  end
end

虽然处理文本模式和字符串块相当简单,但我不知道如何处理函数块。

我应该如何将所有内容收集到字符串中,然后进行 HMAC 处理并用此字符串调用“nativeload”?但是,这样做就不能加载大文件(例如 2GB 的文件),否则程序会崩溃(使用函数编译文件时,每次以 8KB 的增量编译文件,并且当文件大部分是空行时,这意味着在编译过程中只需要几 KB 的空间 - 而将整个文件加载到一个字符串中显然会使用 2GB 的 RAM)。

我该怎么做?

点赞
用户6834680
用户6834680
local function extract_code(data)
   local code = data:sub(1,-33)
   assert(HMAC_SHA256(code, getkey()) == data:sub(-32), "Invalid signature")
   return code
end

local nativeload = load
load = function(chunk, chunkname, mode, ...)
   local targetenv = [[snip]]
   if select('#', ...) ~= 0 then targetenv = ... end
   local new_chunk
   if type(chunk) == "string" then
      new_chunk = chunk:match"^\27Lua" and extract_code(chunk) or chunk
   elseif type(chunk) == "function" then
      local buffer = ""
      repeat
         local next_part = chunk() or ""
         buffer = buffer..next_part
      until next_part == "" or #buffer >= 4
      if buffer:match"^\27Lua" then -- Bytecode can't be very large, collect it in a string
         local t = {buffer}
         while t[#t] ~= "" do t[#t+1] = chunk() or "" end
         new_chunk = extract_code(table.concat(t))
      else                          -- Source code can be very large, use a function
         local function f()
            f = chunk
            return buffer
         end
         function new_chunk()
            return f()
         end
      end
   end
   return nativeload(new_chunk, chunkname, mode, targetenv)
end

这段代码实现了 Lua 脚本的加载和运行,支持对加密脚本的解密和验证签名。

其中 extract_code 函数用于提取加密的脚本内容,并验证签名的有效性。如果签名无效则会触发错误。

load 函数是对 loadin 函数的扩展,在加载脚本前对其进行处理,如果是加密的脚本则先进行解密,否则直接加载。同时支持加载字节码和源代码,如果是字节码则会将其转化为字符串进行解密,如果是源代码则会用一个函数来加载。

这段代码的作用是保护 Lua 脚本的安全性,防止源码泄漏以及篡改。

2016-11-02 10:33:07