背景

想要像 cjson,gd,libinjection 一样,代码是用 c 实现的,却在 openresty 的 lua 模块中被调用。
下面以添加 ssdeep.so 为例,其中有 fuzzy_hash_buf 和 fuzzy_compare 两个接口函数。
lua 版本为 5.1.4,openresty 版本为 1.9.7.1

实践

添加头文件

//#include <lua.hpp>
#include <lauxlib.h>
//#include <lualib.h>

某些资料中显示要添加三个头,不过编译时显示lua.hpp找不到

我添加的 ssdeep 只需要 lauxlib.h 即可

修改接口函数

原有 fuzzy_hash_buf 函数如下:

char* fuzzy_hash_buf(const unsigned char *buf, uint32_t buf_len)
{
     ......
     return result;
}

现改为

int fuzzy_hash_buf_m(lua_State* L) {  //前期加上了extern "C",但是会报错
    const unsigned char *buf = (const unsigned char *)lua_tostring(L, 1);
    uint32_t buf_len = (uint32_t)lua_tonumber(L, 2); 
    char   result[FUZZY_MAX_RESULT];
    .......
    lua_pushstring(L, result); //返回result值
    return 1; //返回结果的数量
}

注解:
所有注册到 Lua 中的接口函数都具有相同的原型,该原型就是定义在 lua.h 中的 lua_CFunction:

typedef int (*lua_CFunction) (lua_State *L);

接口函数返回值表示返回结果的数量
返回值通过 lua_pushstring 或者 lua_pushnumber 注入 L 中

接口函数列表

static LuaL_reg libs[] = { //开始为LuaL_Reg会报错,原因是lua版本的问题
    {"fuzzy_hash_buf", fuzzy_hash_buf},  
    {NULL, NULL} 

};

主函数

int luaopen_ssdeep(lua_State* L)  
{  
    const char* libName = "ssdeep";    
    luaL_register(L, libName, libs);   
    return 1; 
}

luaL_register 根据给定的名称 (“ssdeep”) 创建(或复用)一个 table,并用数组 libs 中的信息填充这个 table。在 LuaL_register 返回时,会将这个 table 留在栈中。最后返回 1,表示将这个 table 返回给 lua。

编译及调用

C 模块完成后,必须将其链接到解释器。如果 Lua 解释器支持动态链接的话,那么最简便的方法就是使用动态链接机制。在这种情况中,必须将 C 代码编译成动态链接库,并将这个库放入 C 路径(LUA_CPATH)中。然后便可以用 require 从 Lua 中加载这个模块: require “ssdeep” 会将动态库 ssdeep 链接到 Lua,并会寻找 luaopen_ssdeep 函数,将其注册为一个 Lua 函数,然后调用它以打开模块。

如果解释器不支持动态链接,那么就必须用新的模块来重新编译 Lua。此外,还需要以某种方式来告诉解释器,它应在打开一个新状态的同时打开这个模块。最简单的做法是,将 luaopen_ssdeep 加到 luaL_openlibs 会打开的标准库列表中,这个列表在文件 linit.c中。

相关文章
评论
  • ipset

    ipset 安装参考文档(待整理)ipset 官方文档ipset 7.1版本链接使用参考文档 简单的流程可以用这几条命令概括使用 ipset 和 iptables 进行 IP 封禁的流程 ipset create blacklist ...

    ipset
  • 删除非目录文件

    linux 下删除一个目录下所有的隐藏文件和非目录文件 前言在 alpine 基础上编译 OpenWAF,想要达到最简,删除无用文件。 亮点rm -rf `ls -Fa | grep '^\.\w'` -- 删除隐...

    删除非目录文件
  • 在 alpine 上编译 openssl 遇到的问题

    alpine 上编译 openssl (v1.1.1) 遇到 ucontext 报错 前言今天在 alpine 基础上编译 openwaf,编到 openssl 时,报 ucontext 相关错误。 ucontext 报错编译 ope...

    在 alpine 上编译 openssl 遇到的问题
  • 批量修改或添加文件后缀名

    前言常见的是对不同文件名进行文件后缀名修改。但今天遇到同一文件名的情况。 常见windows 或 Linux 命令: ren *.jpg *.bmp # 将 jpg 后缀改为 bmp 如:1.jpg 2.txt 改后为:1.bm...

    批量修改或添加文件后缀名
  • hyperscan 安装

    1. 前言本文在 Debian8 中安装 hyperscan 5.0.0内存至少 2 G,不然编译慢而且失败 2. 依赖2.1 C/C++编译器hyperscan使用C++开发,且需要C99和C++11支持,目前支持的编译器有 GC...

    hyperscan 安装
  • linux 查看系统开机时间

    有时候需要查看Linux系统运行了多久时间,此时需要知道上次开机启动时间;有时候由于断电或供电故障突然停机,需要查看Linux开机时间/重启时间;下面总结一些查看Linux开机关机时间的方法(非常全面) 1. who 命令查看who ...

    linux 查看系统开机时间
  • GDB 多线程 (non-stop)

    1. 背景这几天在扩展 ngx_lua 模块,但 gdb 定位时,提示:Thread debugging using libthread_db enabled。 2. GDB non-stop 配置把以下3行添加到 ~/.gdbini...

    GDB 多线程 (non-stop)
  • suricata 从 0 开始

    背景OpenWAF 是在 openresty 基础上发布的,但安全不仅仅是针对 HTTP 协议的防护,而是全方位立体化的防护。因此,为了防护更多的协议,开始接触 suricata,用熟后,争取将 OpenWAF 集成到 suricat...

    suricata 从 0 开始
  • clear: command not found 命令无法找到

    1. 安装 ncurses-binsudo apt-get install ncurses-bin 此时尝试执行 ‘clear’ 命令,若失败,执行第二步(重新安装 ncurses-bin) 2. 重新安装 ncurses-binsu...

    clear: command not found 命令无法找到
  • svn 游记

    前言公司之前用 svn 管理项目代码,我一直用的 windows 版本 近期想要搭建知识库云平台,需要在 linux 上使用 svn 管理代码,因此做些笔记 直接使用公司搭建好的 svn服务器 1. 客户端安装yum install ...

    svn 游记