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去。。。