基于c+lua漏洞扫描的实践

0x01 前言


在开发的时候参考了腾讯现有的那套据说积累了10年的漏洞扫描,基于它的原型开发。但是考虑到现有环境的特殊性,做了一些思考和改变。整个技术研发中心在定义开发语言上,有一些统一,比如标准语言java和python,这两门用的人比较多,考虑到问题的通用性,我在开发的时候也特别注意。但是终究有些蛋疼~虽然结果很好,东西出来了,马上准备上线使用,但是感觉都是坑和痛。。

0x02 摸的坑


最早考虑的方案是基于c+lua跟腾讯的那个一样,对于我来说,c到底还是不难,之前写过,有过一定的积累,相信写起来也不会特别费劲。so,直接用它来做主框架。扒拉扒拉的花了两天周末写完,调试通过。主要有几个部分:
1. 数据源(读取redis里面的爬虫数据、proxy的数据);
2. 框架层(将数据进行筛选,GET/POST分开处理);
3. 调度层(将扫描任务分发给插件模块);
4. 规则层(将扫描规则赋予到插件模块中进行深度测试);
嗯,原则上这个东西已经可以使用了,并且跟最初计划完全一致。中间碰到了以下问题,我也整理出来了。

1.1 数据切割问题

在c里面貌似没有特别合适的数据切割的库,本身数据就需要切,不然没法进行有效的分发,最悲剧的莫过于它没有split的功能,需要自己撸,痛苦的是,历史上的切割功能都有或多或少的bug,主要问题在于会有乱码,strtok()这个函数是个大坑。然后这个功能翻了下旧代码(Smart7ec-scan-console,现已经被删除,某些关系好的小伙伴有定制版)幸亏找到了,不然就悲剧了

char** str_split(char* a_str, const char a_delim)
{
    char** result    = 0;
    size_t count     = 0;
    char* tmp        = a_str;
    char* last_comma = 0;
    char delim[2];
    delim[0] = a_delim;
    delim[1] = 0;

    while (*tmp)
    {
        if (a_delim == *tmp)
        {
            count++;
            last_comma = tmp;
        }
        tmp++;
    }

    count += last_comma < (a_str + strlen(a_str) - 1);

    count++;

    result = malloc(sizeof(char*) * count);

    if (result)
    {
        size_t idx  = 0;
        char* token = strtok(a_str, delim);

        while (token)
        {
            assert(idx < count);
            *(result + idx++) = strdup(token);
            token = strtok(0, delim);
        }
        assert(idx == count - 1);
        *(result + idx) = 0;
    }

    return result;
}
1.2 C调用lua问题

这个问题就更加坑爹的了,c调用lua在百度上的案例多如牛毛,或多或少都是bug结合体,迫不得已,只能翻api看,就我那狗日的英文水平,我就呵呵了。正好把整个api底朝天的翻了一遍,刷新了我对c调用lua的理解,案例代码如下。

/**
 * @param filename    [插件名称]
 * @param module      [插件调用的模块名称]
 * @param target_info [待扫描的信息]
 */
void scanFrame_plugins(char* filename,char* module,char* target_info)
{
    char** tokens;
    tokens = str_split(target_info, '|');

    // 初始化lua
    L = luaL_newstate();
    // 加载lua基础库
    luaL_openlibs(L);
    // 加载lua脚本
    luaL_dofile(L, filename);
    // 加载lua 里面指定的模块
    lua_getglobal(L, module);

    if (tokens)
    {
        int i;
        for (i = 0; *(tokens + i); i++)
        {
            lua_pushstring(L, *(tokens + i));
            free(*(tokens + i));
        }
        // 执行这个方法,放入两个参数,返回一个值
        lua_call(L, i, 0);
        // 清理资源
        lua_pop(L,1);
        // 释放资源
        lua_close(L);
        free(tokens);
    }
}
1.3 绝对路径问题

这个就更加坑了,换了目录直接就不能执行,毕竟依赖各种插件,解决方案也坑坑挖挖的弄出来了。

/**
 * 获得绝对路径
 * @return [description]
 */
char* defpath()
{
    static char current_absolute_path[MAX_SIZE];
    //获取当前程序绝对路径
    int cnt = readlink("/proc/self/exe", current_absolute_path, MAX_SIZE);
    if (cnt < 0 || cnt >= MAX_SIZE)
    {
      printf("***Error***\n");
      exit(-1);
    }
    //获取当前目录绝对路径,即去掉程序名
    int i;
    for (i = cnt; i >=0; --i)
    {
      if (current_absolute_path[i] == '/')
      {
          current_absolute_path[i+1] = '\0';
          break;
      }
    }
    return current_absolute_path;
}

0x03 插件的模版


上面讲的那么多,撸一个插件的模版出来,自己在这基础上撸就好。

function verify(...)
    local scanid,method,url,params = ...
    print(id,method,url,params)
end

0x04 后记


讲真,lua真心学习成本高,感觉自己老了,还不如python好使,随手一扒就可以写,lua动不动就要加新的包,动不动请求的乱套。还各种屁事错误。好吧~我还是踏实撸python去。。。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Lua 5.1 参考手册 by Roberto Ierusalimschy, Luiz Henrique de F...
    苏黎九歌阅读 13,906评论 0 38
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 173,455评论 25 708
  • 受伤卧床又一天了,听着雀儿叽叽喳喳,狗狗平时是汪汪汪狂叫,今天又哼哼唧唧的撒娇,小样儿吧就你,不定打什么鬼主意...
    君不见君君阅读 182评论 1 2
  • 猜你 如同揭秘宇宙 我智慧不够 不猜 宇宙失去意义 此前的探索 沦为史前的黑洞 ——《猜宇宙》
    段童阅读 256评论 1 2
  • 当假期培训完“教室文化”这一板块后,我就一直在苦苦为了教室主题而思考。究竟叫一个什么名字好呢?冥思了一系列的...
    王玉颖简书阅读 800评论 8 2